/**----------------------------------------------------------------------- * 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 #define NO_SUB_PRAGMAS #include #include "bitio.h" /* custom includes */ /**----------------------------------------------------------------------- * Bloque de constantes 'NEMOTECNICAS' para una mejor simplicidad * de csdigo, lo siento si alguien cree que tengo demasiada tendencia * a las palabras de origen sajsn, pero no puedo sufrir versiones * castellanas ni catalanas. Sera la costumbre. * **/ #define TRUE 1 #define FALSE 0 #define NIL 0 #define UNUSED 0 #define CONTROL 0L /* Indicador de que control */ #define END_OF_FILE 0L /* Indic. fin de fichero */ #define BITS_CHARS 8 /* 8 order-0 ; 16 order-1 ... */ #define WIND_BITS 14 #define WIND_SIZE ( 1 << WIND_BITS ) #define WIND_MASK ( WIND_SIZE - 1 ) #define MOD_WIN( a ) ( ( a ) & WIND_MASK ) #define INIT_BIT_BUMP 8 #define BITS_LOOKAHEAD 4 #define RAW_LOOKAHEAD ( 1 << BITS_LOOKAHEAD ) #define MIN_MATCH 3 /* No lo toques o no funciona */ #define MAX_MATCH (RAW_LOOKAHEAD + MIN_MATCH -1 ) #define HASH_BITS 15 /* Sugiero mmnimo de 12 pero llega a 10 */ #define HASH_SIZE (unsigned)(1<= 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 inpmask; UBYTE outmask; register CHARS *inpb; CHARS *endinp; register CHARS *outb; CHARS *endout; ULONG ioaux; /* tambien se usa en BestMach */ /* varialbles utilizadas en BestMach */ CHARS scanend; CHARS *strend; 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; 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 ); } memset( head , NIL , HASH_SIZE*sizeof( UWORD ) ); /* head */ xpar->Sub[0]=(long)prev; xpar->Sub[1]=(long)head; } /* previous y wwindow se autoinilizalizan */ InitOutput(); InitInput(); 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 ); OutputBits( (long )*actp , BITS_CHARS ); } else { replace=matchlen; if( actp > bumpcode ) { bitcount++; bumpcode = xparinbuf + (1<