- /* Ordenamos inicialmente la inputlist para tomar las dos freqs min */
- while (lastsymbol > list) {
- /* Ordeno la lista por frecuencia descendente */
- qsort(list,listcount,sizeof(HUFFNODE),compnode);
- /* Tomo los ultimos dos elementos, generando dos nodos del arbol */
- node1 = (HUFFNODE*)malloc(sizeof(HUFFNODE));
- node2 = (HUFFNODE*)malloc(sizeof(HUFFNODE));
- cpynode(node1,lastsymbol-1);
- cpynode(node2,lastsymbol);
- lastsymbol -= 1;
- /* Nodo ficticio con la suma de las probs y los ptros a childs */
- lastsymbol->symbol = 256;
- lastsymbol->freq = node1->freq + node2->freq;
- lastsymbol->lchild = node1;
- lastsymbol->rchild = node2;
- --listcount;
+/** Prepara las estructuras de datos necesarias para una compresion */
+int shuff_encode_file(HUFF_STATE *shuff)
+{
+ /* Locals */
+ SHUFFCODE *codetable = (SHUFFCODE*)malloc(sizeof(SHUFFCODE)*256);
+
+ /* Veo si debo armar una freqtable o si esta preloaded */
+ if ((!shuff->canonic) && (!shuff->bychunk))
+ if (!shuff_scanfreq(shuff->sourcefile,shuff->freqtable)) return 0;
+
+ /* Genero el arbol de huffman */
+ shuff->codetree = shuff_buildtree(shuff->freqtable);
+
+ /* Armo la tabla de codigos prefijos para el encoder */
+ shuff_zerocodes(codetable);
+ shuff_buildcodes(codetable,shuff->codetree,0,0);
+ /*shuff_printcodes(codetable,shuff->freqtable);*/
+
+ /* Encodeo byte per byte */
+ shuff_encode_symbols(shuff,codetable);
+
+ /* Free up memory baby yeah */
+ free(codetable);
+
+ return 1;
+}
+
+/** Decodifica una serie de bits en un symbolo y lo devuelve */
+SHUFFNODE *shuff_decode_symbols(SHUFFNODE *entrynode, unsigned long int buffer,
+ int *bitsleft, unsigned short int *symbol)
+{
+ char bit = 0;
+
+ /* Levanto el symbolo y si es uno valido, devuelvo */
+ *symbol = entrynode->symbol;
+ if (*symbol != 256) return entrynode;
+ if (*bitsleft == 0) return entrynode;
+
+ /* Obtengo otro bit a procesar y me muevo en el arbol */
+ bit = (buffer >> ((*bitsleft)-1)) & 1;
+ --(*bitsleft);
+ if (bit == 0) return shuff_decode_symbols(entrynode->lchild,buffer,bitsleft,symbol);
+ else return shuff_decode_symbols(entrynode->rchild,buffer,bitsleft,symbol);
+}
+
+/** Decodifica chunksize symbolos y los devuelve en un chunk de datos */
+int shuff_decode_chunk(HUFF_STATE *shuff, char *chunk, int chunksize, unsigned long int *decodedbytes)
+{
+ SHUFFNODE *currnode = shuff->codetree;
+ unsigned short int decoded_symbol;
+ *decodedbytes = 0;
+
+ while (!vfeof(shuff->decoderfp) && (shuff->bytesleft > 0) && (*decodedbytes < chunksize)) {
+
+ /* Leo un buffer de 32 bits si es que quedo vacio el anterior */
+ if (shuff->bitsleft == 0) {
+ if (vfread(&(shuff->codebuffer),sizeof(unsigned long int),1,shuff->decoderfp) != 1) continue;
+ shuff->bitsleft = sizeof(unsigned long int) * 8;
+ }
+
+ /* Proceso el buffer sacando simbolos till se me agote el buffer, file o chunk */
+ while ((shuff->bitsleft > 0) && (shuff->bytesleft > 0) && (*decodedbytes < chunksize)) {
+ currnode = shuff_decode_symbols(currnode,shuff->codebuffer,&(shuff->bitsleft),&decoded_symbol);
+ /* Si obtuve un symbolo valido lo emito*/
+ if (decoded_symbol != 256) {
+ chunk[(*decodedbytes)++] = decoded_symbol;
+ currnode = shuff->codetree;
+ --(shuff->bytesleft);
+ }
+ }