home *** CD-ROM | disk | FTP | other *** search
-
-
- /**-----------------------------------------------------------------------
- * Bloque de includes, por fin me ocupan menos de una pagina de
- * impresisn, lo que hay que hacer para tener todos los prototipos..
- *
- **/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
-
- #define NO_SUB_PRAGMAS
- #include <libraries/xpksub.h>
-
- #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<<HASH_BITS)
- #define HASH_MASK ( HASH_SIZE - 1)
- #define HASH_SHIFT (( HASH_BITS + MIN_MATCH -1 )/MIN_MATCH) /* 5 */
-
- #define MAX_HASH_COL 128
-
- #define REHASH( h , c ) h = (( (( h )<<HASH_SHIFT) ^ ( c )) & HASH_MASK )
-
-
- /**-----------------------------------------------------------------------
- * Aqum se encuentran las variables globales, espero que no quede nada
- * pues en caso contrario uno no puede hacer residente el codigo
- *
- **/
-
-
- /**-----------------------------------------------------------------------
- * Definicisn de tipos a causa de mi vagancia al escribir, tambien
- * simplifica considerablemente el entendimiento de los parametros.
- *
- **/
-
- typedef unsigned char CHARS; /* Por si en el futuro amplio a order-1 */
- /* El 1.8 Speedup , 14% compresion-down( text ) */
-
- /**-----------------------------------------------------------------------
- * 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 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<<INIT_BIT_BUMP);
-
- matchpos = 0; /* No hace falta pero evita un WARNING */
- matchlen = 0;
- actp = xparinbuf;
- hash_key = 0;
-
- /**
- * Bloque de la precarga necesaria para poder empezar el bucle
- *
- **/
-
- for( conta = 1 ; conta <= MAX_MATCH && EndOfFile() ; conta++ )
- InputByte( );
-
- lookahead = conta-2;
-
- if( conta > 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<<bitcount);
- }
- OutputBit( 0 );
- OutputBits( (long)matchpos , bitcount );
- OutputBits( (long)( matchlen - MIN_MATCH ) , BITS_LOOKAHEAD );
- }
-
- for( conta = 0 ; conta < replace ; conta++ )
- {
- if( EndOfFile() )
- lookahead--;
- else
- InputByte( );
-
- actp++;
-
- REHASH( hash_key , actp[ MIN_MATCH -1 ] );
-
- prev[ actp - xparinbuf ] = matchpos = head [ hash_key ];
- head[ hash_key ] = actp - xparinbuf;
- }
-
- BestMatch( actp , matchpos , matchlen ); /* potente macro eh !! */
- }
-
- /**
- * No hace falta indicador de final de fichero pues se siempre
- * la longitud, tampoco libero los recursos, de esto se encarga
- * XpkPackFree
- *
- **/
- return( 0 );
- }
-
- /************************** End of ILZR.C *************************/
-