+/** Inicializa un descompresor de huffman */
+HUFF_STATE *shuff_init_decoder(char *inputfile, char *outputfile)
+{
+ /* Locals */
+ HUFF_STATE *shuff = (HUFF_STATE*)malloc(sizeof(HUFF_STATE));
+ shuff->freqtable = (t_freq*)malloc(sizeof(t_freq)*256);
+
+ /* Init fields */
+ shuff->codebuffer = 0;
+ shuff->bitsleft = 0;
+ shuff->coderfp = NULL;
+ shuff->targetfile = NULL;
+ shuff->sourcefile = (char*)malloc(sizeof(char)*(strlen(inputfile)+1));
+ strcpy(shuff->sourcefile,inputfile);
+ if (outputfile != NULL) {
+ shuff->targetfile = (char*)malloc(sizeof(char)*(strlen(outputfile)+1));
+ strcpy(shuff->targetfile,outputfile);
+ }
+
+ /* Levanto cuantos bytes debo decodificar y la freqtable */
+ if ((shuff->decoderfp = vfopen(shuff->sourcefile,"r",0)) == NULL) return NULL;
+ vfread(&(shuff->bytesleft),sizeof(unsigned long int),1,shuff->decoderfp);
+ vfread(shuff->freqtable,sizeof(t_freq),256,shuff->decoderfp);
+ /* Armo el arbol de huffman que uso para decodificar */
+ shuff->codetree = shuff_buildtree(shuff->freqtable);
+
+ return shuff;
+}
+
+/** Inicializa compresor de huffman por archivo */
+HUFF_STATE *shuff_init_encoder_byfile(char *inputfile, char *outputfile, long volsize)
+{
+ /* Locals */
+ HUFF_STATE *fshuff = (HUFF_STATE*)malloc(sizeof(HUFF_STATE));
+ int i;
+
+ /* Inicializo la estructura para trabajar con Huff Static by File */
+ fshuff->coderfp = NULL;
+ fshuff->decoderfp = NULL;
+ fshuff->sourcefile = (char*)malloc(sizeof(char)*(strlen(inputfile)+1));
+ fshuff->targetfile = (char*)malloc(sizeof(char)*(strlen(outputfile)+1));
+ strcpy(fshuff->sourcefile,inputfile);
+ strcpy(fshuff->targetfile,outputfile);
+ fshuff->volsize = volsize;
+ fshuff->bychunk = 0;
+ fshuff->canonic = 0;
+ fshuff->freqtable = (t_freq*)malloc(sizeof(t_freq)*256);
+ for (i = 0; i < 256; ++i) fshuff->freqtable[i] = 0;
+ fshuff->sumfreq = 0;
+ fshuff->codetree = NULL;
+
+ return fshuff;
+}
+
+/** Inicializa compresor de huffman de a chunks */
+HUFF_STATE *shuff_init_encoder_bychunk(char *outputfile, long volsize)
+{
+ /* Locals */
+ HUFF_STATE *cshuff = (HUFF_STATE*)malloc(sizeof(HUFF_STATE));
+ int i;
+
+ /* Inicializo la estructura para trabajar con Huff Static by Chunks */
+ cshuff->decoderfp = NULL;
+ cshuff->sourcefile = (char*)malloc(sizeof(char)*(strlen(outputfile)+2));
+ cshuff->targetfile = (char*)malloc(sizeof(char)*(strlen(outputfile)+1));
+ strcpy(cshuff->targetfile,outputfile);
+ strcpy(cshuff->sourcefile,outputfile);
+ strcat(cshuff->sourcefile,"~");
+ cshuff->volsize = volsize;
+ cshuff->bychunk = 1;
+ cshuff->canonic = 0;
+ cshuff->freqtable = (t_freq*)malloc(sizeof(t_freq)*256);
+ for (i = 0; i < 256; ++i) cshuff->freqtable[i] = 0;
+ cshuff->sumfreq = 0;
+ cshuff->codetree = NULL;
+
+ /* Abrimos un archivo temporal para ir tirando los chunks */
+ if ((cshuff->coderfp = fopen(cshuff->sourcefile,"w")) == NULL) return NULL;
+
+ return cshuff;
+}
+
+/** Carga un modelo estadistico para huffman */
+int shuff_loadmodel(HUFF_STATE *shuff, char *modelfile) {
+
+ FILE *fp;
+
+ if ((shuff) && (shuff->freqtable) && (modelfile)) {
+ /* Cargo el modelo de disco */
+ if ((fp = fopen(modelfile,"r")) == NULL) return 0;
+ if (fread(shuff->freqtable,sizeof(t_freq),256,fp) != 256) return 0;
+ shuff->canonic = 1;
+ if (fp) fclose(fp);
+ return 1;
+ }
+ return 0;
+}
+
+/** Graba un modelo estadístico de huffman */
+int shuff_savemodel(HUFF_STATE *shuff) {
+
+ FILE *fp;
+ char *auxfilename;
+ char *stopchar;
+
+ if ((shuff) && (shuff->targetfile) && (shuff->freqtable)) {
+ /* Preparo el nombre del archivo con la tabla */
+ auxfilename = (char*)malloc(strlen(shuff->targetfile)+1);
+ stopchar = strrchr(shuff->targetfile,'.');
+ strncpy(auxfilename,shuff->targetfile,stopchar - shuff->targetfile);
+ auxfilename[stopchar - shuff->targetfile] = 0;
+ strcat(auxfilename,".ftb");
+
+ /* Lo creamos y dumpeamos la tabla de frecuencias (modelo) */
+ if ((fp = fopen(auxfilename,"w")) == NULL) return 0;
+ fwrite(shuff->freqtable,sizeof(t_freq),256,fp);
+ if (fp) fclose(fp);
+
+ return 1;
+ }
+ return 0;
+}
+
+/** Desinicializa un compresor de huffman */
+void shuff_deinit_encoder(HUFF_STATE *shuff)
+{
+ /* Libero mallocs y cierro archivos */
+ if (shuff->freqtable) free(shuff->freqtable);
+ if (shuff->coderfp) fclose(shuff->coderfp);
+ if (shuff->bychunk) unlink(shuff->sourcefile);
+ if (shuff->sourcefile) free(shuff->sourcefile);
+ if (shuff->targetfile) free(shuff->targetfile);
+
+ /* Destruyo recursivamente el arbol de codigos */
+ if (shuff->codetree) shuff_destroy_tree(shuff->codetree);
+}
+
+/** Desinicializa un descompresor de huffman */
+void shuff_deinit_decoder(HUFF_STATE *shuff)
+{
+ /* Libero mallocs y cierro archivos */
+ if (shuff->freqtable) free(shuff->freqtable);
+ if (shuff->sourcefile != NULL) free(shuff->sourcefile);
+ if (shuff->targetfile != NULL) free(shuff->targetfile);
+ if (shuff->decoderfp != NULL) vfclose(shuff->decoderfp);
+
+ /* Destruyo recursivamente el arbol de codigos */
+ if (shuff->codetree) shuff_destroy_tree(shuff->codetree);
+}