/* huffman-decode.c */ /* This file is part of the AVR-Huffman. Copyright (C) 2009 Daniel Otte (daniel.otte@rub.de) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #define V_NODE (-2) #define V_EOF (-1) #define PREFIX_SIZE_B 32 #define ALLOC_ERROR {fprintf(stderr,"failed to alloc memory in %s @ %d !\n",__FILE__, __LINE__); exit(-1);} #define DEBUG 0 typedef struct { int16_t value; void* left; void* right; } node_t; node_t* tree=NULL; uint16_t tree_index; void prefix_increment(uint8_t* prefix){ uint8_t i; for(i=0; i>7; prefix[i]<<=1; ci ^= 1; prefix[i]|=c[ci]; } } uint8_t append_tree(int16_t value, uint16_t depth){ static uint8_t prefix[PREFIX_SIZE_B]; static uint8_t cdepth=0; node_t* current=tree; int8_t i,t; for(;cdepth=0; --i){ t=(prefix[i/8])&(1<<(i%8)); if(t==0){ if(current->left==NULL){ // current->left=calloc(1, sizeof(node_t)); current->left=&(tree[tree_index++]); ((node_t*)(current->left))->value = V_NODE; } current = current->left; } else { if(current->right==NULL){ // current->right=calloc(1, sizeof(node_t)); current->right=&(tree[tree_index++]); ((node_t*)(current->right))->value = V_NODE; } current = current->right; } } if(current==NULL) ALLOC_ERROR current->value=value; prefix_increment(prefix); return prefix[depth/8]&(1<<(depth%8)); } void set_last_to_eof(void){ node_t* current=tree; while(current->value==V_NODE) current=current->right; current->value=V_EOF; } void build_tree(FILE* f){ uint16_t treesize; uint16_t x1, x2; x1 =fgetc(f); x2 =fgetc(f); if(x1!=0xc0 || (x2&0xFE)!=0xde){ fprintf(stderr,"No magic values found!\n"); } treesize= fgetc(f); if(treesize>0xff){ fprintf(stderr,"You are trying to uncompress an empty file!\n"); exit(-3); } treesize = 2*(((x2&1)<<8)+treesize)-1; //printf("Using treesize=%i with size of %i\n", treesize, sizeof(node_t)); tree = calloc(treesize, sizeof(node_t)); if(tree==NULL) ALLOC_ERROR tree->value = V_NODE; tree_index=1; uint16_t depth=0; uint16_t count=0; uint8_t v; do{ while(count==0){ depth++; count= fgetc(f); if(count==255) count += fgetc(f); } v = fgetc(f); --count; }while(!append_tree(v, depth)); set_last_to_eof(); } void free_tree(node_t* node){ free(node); } FILE* outfile; FILE* infile; void write_char(uint8_t v){ fputc(v, outfile); } uint8_t read_bit(void){ static uint8_t buffer; static uint8_t index=0; uint8_t t; if(index==0){ buffer = fgetc(infile); if(feof(infile)) return 0xFF; } t=buffer>>7; buffer<<=1; index = (index+1)%8; return t; } uint16_t decompress_byte(void){ node_t* current=tree; uint8_t t; while(current->value==V_NODE){ t=read_bit(); if(t==0xFF) return EOF; if(t==0){ current=current->left; } else { current=current->right; } if(current==NULL){ fprintf(stderr, "Tree damaged!\n"); exit(-4); } } return current->value; } void decompress(void){ uint16_t t; for(;;){ t=decompress_byte(); if(t==(uint16_t)EOF) return; write_char(t); } } int main(int argc, char** argv){ int i; FILE* fin; FILE* fg; // outfile=stdout; for(i=1;i