/**----------------------------------------------------------------------- * Bloque de includes, por fin me ocupan menos de una pagina de * impresisn, lo que hay que hacer para tener todos los prototipos.. * **/ #include #include #include #include #include #define NO_SUB_PRAGMAS #include #include "cbitio.h" /* custom includes */ #include "ilzr.h" /**----------------------------------------------------------------------- * Prototipos para todas estas paridas necesarias para compilar. * **/ /**----------------------------------------------------------------------- * En un principio utilizaba la funcisn de HASH del COMRESS de GNU en * UNIX, pero por motivos de eficiencia he tenido que cambiarla. La forma * actual se inspira en el algoritmo de Rabin & Karp ( En el libro : * "Algorithms" de Sedgewick de Addison-Wesley p.252 ) * **/ #define BestMatch( scan , matchpos , bestlen ) \ { \ if( (xparinbuf + matchpos) <= scan ) \ { \ ioaux = 0; \ bestlen = MIN_MATCH - 1; \ scanend = scan[ bestlen ]; \ strend = scan + MAX_MATCH; \ current = matchpos; \ lastmatch= matchpos; \ while( current != NIL && lastmatch >= current ) \ { \ match = xparinbuf + current; \ if( match[ bestlen ] != scanend || \ *match != *scan || \ *++match != scan[1] ) \ { \ lastmatch = current; \ current = prev[ current ]; \ ioaux++; \ if( ioaux > MAX_HASH_COL ) \ break; \ continue; \ } \ scan+=2; /* do not try to put in the if condition */ \ match++; \ do \ { \ }while( *++scan == *++match && *++scan == *++match && \ *++scan == *++match && *++scan == *++match && \ *++scan == *++match && *++scan == *++match && \ *++scan == *++match && *++scan == *++match && \ scan < strend ); /* Estraqo pero mejor codigo */ \ conta = MAX_MATCH - (UBYTE)(strend - scan); /* len para ahorrar */\ scan = strend - MAX_MATCH; \ if( conta > bestlen ) \ { \ bestlen = conta; \ matchpos = current; \ if( conta >= MAX_MATCH ) \ break; \ scanend = scan[ bestlen ]; \ } \ lastmatch = current; \ current = prev[ current ]; \ } \ } \ } /**----------------------------------------------------------------------- * En pocas lineas se adentrara al nucleo de todo el sistema de * compresisn de datos, aunque parezca mentira intentare que el * sistema mantenga el coste ideal mmnimo, coste LINEAL??. * Esto son las mejores intenciones, ya veremos en que se nos queda. * **/ long __saveds __asm XpksPackChunk( REG __a0 XPARAMS *xpar ) { /* variables para input - output */ register UBYTE outmask; register CHARS *inpb; CHARS *endinp; register CHARS *outb; CHARS *endout; ULONG ioaux; /* tambien se usa en BestMach */ UBYTE endoffile; /* varialbles utilizadas en BestMach */ CHARS scanend; CHARS *strend; register CHARS *match; UWORD current; UWORD lastmatch; /* bloque general de compres */ UBYTE lookahead; /* siempre RAW_LOOKAHEAD < 255 */ UBYTE matchlen; /* siempre RAW_LOOKAHEAD < 255 */ UBYTE replace; /* cuanto se ha de ampliar "lookahead" */ UBYTE conta; /* tambien se usa en BestMach */ long bitcount; /* es un LONG para compatibilidad */ CHARS *bumpcode; long temp; CHARS *xparinbuf; /* todo el mundo la utiliza */ UWORD hash_key; /* actual hash value */ UWORD matchpos; /* position of matchlen */ register CHARS *actp; /* posicion en wwindow fich */ register UWORD *head; /* dictionary */ register UWORD *prev; /* previous in the hash line */ /** * Bloque de inicializacsn + reserva de memoria para las tablas * **/ if( !xpar->Sub[0] ) { if( !(head = malloc( sizeof( UWORD ) * HASH_SIZE )) ) return( XPKERR_NOMEM ); if( !(prev = malloc( sizeof( UWORD ) * (WIND_SIZE+MAX_MATCH) ) ) ) { free( head ); return( XPKERR_NOMEM ); } xpar->Sub[0]=(long)prev; xpar->Sub[1]=(long)head; } else { prev= (UWORD *)xpar->Sub[0]; head= (UWORD *)xpar->Sub[1]; } /* previous y wwindow se autoinilizalizan */ memset( head , NIL , HASH_SIZE*sizeof( UWORD ) ); /* head */ InitOutput(); InitInput(); endoffile = 0; temp = xpar->InLen; OutputBits( temp , 16 ); /* NEED store the long of this block */ xparinbuf = xpar->InBuf; bitcount = INIT_BIT_BUMP; bumpcode = xparinbuf+(1< 3 ) { REHASH( hash_key , actp[1] ); REHASH( hash_key , actp[2] ); } /** * Comienzo del bucle principal para la compresisn de datos * **/ while( lookahead > 0 ) { if( matchlen > lookahead ) matchlen = lookahead; if( matchlen < MIN_MATCH ) /* Sale a cuenta 2 bloque ? */ { replace=1; OutputBit( 1 ); temp=(long)*actp; OutputBits( temp , BITS_CHARS ); } else { replace=matchlen; if( actp > bumpcode ) { bitcount++; bumpcode = xparinbuf + (1<OutLen = (long)outb - (long)xpar->OutBuf + 1; /* CUrIosO */ return( 0 ); } /************************** End of ILZR.C *************************/