ENH: reorder code to remove forward declarations
This commit is contained in:
parent
3a44f2a47e
commit
d4ae4849f7
|
@ -67,9 +67,6 @@ static const char_type magic_header[] = { "\037\235" }; /* 1F 9D */
|
||||||
#define FIRST 257 /* first free entry */
|
#define FIRST 257 /* first free entry */
|
||||||
#define CLEAR 256 /* table clear output code */
|
#define CLEAR 256 /* table clear output code */
|
||||||
|
|
||||||
static void cl_hash(struct cmcompress_stream* cdata, count_int hsize); /* reset code table */
|
|
||||||
static int cl_block (struct cmcompress_stream* cdata); /* table clear for block compress */
|
|
||||||
static int output(struct cmcompress_stream* cdata, code_int code);
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static void prratio( FILE *stream, long int num, long int den);
|
static void prratio( FILE *stream, long int num, long int den);
|
||||||
#endif
|
#endif
|
||||||
|
@ -92,230 +89,6 @@ int cmcompress_compress_initialize(struct cmcompress_stream* cdata)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* compress stdin to stdout
|
|
||||||
*
|
|
||||||
* Algorithm: use open addressing double hashing (no chaining) on the
|
|
||||||
* prefix code / next character combination. We do a variant of Knuth's
|
|
||||||
* algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
|
|
||||||
* secondary probe. Here, the modular division first probe is gives way
|
|
||||||
* to a faster exclusive-or manipulation. Also do block compression with
|
|
||||||
* an adaptive reset, whereby the code table is cleared when the compression
|
|
||||||
* ratio decreases, but after the table fills. The variable-length output
|
|
||||||
* codes are re-sized at this point, and a special CLEAR code is generated
|
|
||||||
* for the decompressor. Late addition: construct the table according to
|
|
||||||
* file size for noticeable speed improvement on small files. Please direct
|
|
||||||
* questions about this implementation to ames!jaw.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int cmcompress_compress_start(struct cmcompress_stream* cdata)
|
|
||||||
{
|
|
||||||
#ifndef COMPATIBLE
|
|
||||||
if (cdata->nomagic == 0)
|
|
||||||
{
|
|
||||||
char headLast = (char)(cdata->maxbits | cdata->block_compress);
|
|
||||||
cdata->output_stream(cdata, (const char*)magic_header, 2);
|
|
||||||
cdata->output_stream(cdata, &headLast, 1);
|
|
||||||
if(ferror(stdout))
|
|
||||||
{
|
|
||||||
printf("Error...\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* COMPATIBLE */
|
|
||||||
|
|
||||||
cdata->offset = 0;
|
|
||||||
cdata->bytes_out = 3; /* includes 3-byte header mojo */
|
|
||||||
cdata->out_count = 0;
|
|
||||||
cdata->clear_flg = 0;
|
|
||||||
cdata->ratio = 0;
|
|
||||||
cdata->in_count = 1;
|
|
||||||
cdata->checkpoint = CHECK_GAP;
|
|
||||||
cdata->maxcode = MAXCODE(cdata->n_bits = INIT_BITS);
|
|
||||||
cdata->free_ent = ((cdata->block_compress) ? FIRST : 256 );
|
|
||||||
|
|
||||||
cdata->first_pass = 1;
|
|
||||||
|
|
||||||
cdata->hshift = 0;
|
|
||||||
for ( cdata->fcode = (long) cdata->hsize; cdata->fcode < 65536L; cdata->fcode *= 2L )
|
|
||||||
{
|
|
||||||
cdata->hshift++;
|
|
||||||
}
|
|
||||||
cdata->hshift = 8 - cdata->hshift; /* set hash code range bound */
|
|
||||||
|
|
||||||
cdata->hsize_reg = cdata->hsize;
|
|
||||||
cl_hash(cdata, (count_int) cdata->hsize_reg); /* clear hash table */
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cmcompress_compress(struct cmcompress_stream* cdata, void* buff, size_t n)
|
|
||||||
{
|
|
||||||
register code_int i;
|
|
||||||
register int c;
|
|
||||||
register int disp;
|
|
||||||
|
|
||||||
unsigned char* input_buffer = (unsigned char*)buff;
|
|
||||||
|
|
||||||
size_t cc;
|
|
||||||
|
|
||||||
/*printf("cmcompress_compress(%p, %p, %d)\n", cdata, buff, n);*/
|
|
||||||
|
|
||||||
if ( cdata->first_pass )
|
|
||||||
{
|
|
||||||
cdata->ent = input_buffer[0];
|
|
||||||
++ input_buffer;
|
|
||||||
-- n;
|
|
||||||
cdata->first_pass = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( cc = 0; cc < n; ++ cc )
|
|
||||||
{
|
|
||||||
c = input_buffer[cc];
|
|
||||||
cdata->in_count++;
|
|
||||||
cdata->fcode = (long) (((long) c << cdata->maxbits) + cdata->ent);
|
|
||||||
i = ((c << cdata->hshift) ^ cdata->ent); /* xor hashing */
|
|
||||||
|
|
||||||
if ( htabof (i) == cdata->fcode )
|
|
||||||
{
|
|
||||||
cdata->ent = codetabof (i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if ( (long)htabof (i) < 0 ) /* empty slot */
|
|
||||||
{
|
|
||||||
goto nomatch;
|
|
||||||
}
|
|
||||||
disp = cdata->hsize_reg - i; /* secondary hash (after G. Knott) */
|
|
||||||
if ( i == 0 )
|
|
||||||
{
|
|
||||||
disp = 1;
|
|
||||||
}
|
|
||||||
probe:
|
|
||||||
if ( (i -= disp) < 0 )
|
|
||||||
{
|
|
||||||
i += cdata->hsize_reg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( htabof (i) == cdata->fcode )
|
|
||||||
{
|
|
||||||
cdata->ent = codetabof (i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ( (long)htabof (i) > 0 )
|
|
||||||
{
|
|
||||||
goto probe;
|
|
||||||
}
|
|
||||||
nomatch:
|
|
||||||
if ( !output(cdata, (code_int) cdata->ent ) )
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
cdata->out_count++;
|
|
||||||
cdata->ent = c;
|
|
||||||
if (
|
|
||||||
#ifdef SIGNED_COMPARE_SLOW
|
|
||||||
(unsigned) cdata->free_ent < (unsigned) cdata->maxmaxcode
|
|
||||||
#else
|
|
||||||
cdata->free_ent < cdata->maxmaxcode
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
codetabof (i) = (unsigned short)(cdata->free_ent++); /* code -> hashtable */
|
|
||||||
htabof (i) = cdata->fcode;
|
|
||||||
}
|
|
||||||
else if ( (count_int)cdata->in_count >= cdata->checkpoint && cdata->block_compress )
|
|
||||||
{
|
|
||||||
if ( !cl_block (cdata) )
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cmcompress_compress_finalize(struct cmcompress_stream* cdata)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Put out the final code.
|
|
||||||
*/
|
|
||||||
if ( !output(cdata, (code_int)cdata->ent ) )
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
cdata->out_count++;
|
|
||||||
if ( !output(cdata, (code_int)-1 ) )
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(cdata->bytes_out > cdata->in_count) /* exit(2) if no savings */
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cl_block (struct cmcompress_stream* cdata) /* table clear for block compress */
|
|
||||||
{
|
|
||||||
register long int rat;
|
|
||||||
|
|
||||||
cdata->checkpoint = cdata->in_count + CHECK_GAP;
|
|
||||||
#ifdef DEBUG
|
|
||||||
if ( cdata->debug )
|
|
||||||
{
|
|
||||||
fprintf ( stderr, "count: %ld, ratio: ", cdata->in_count );
|
|
||||||
prratio ( stderr, cdata->in_count, cdata->bytes_out );
|
|
||||||
fprintf ( stderr, "\n");
|
|
||||||
}
|
|
||||||
#endif /* DEBUG */
|
|
||||||
|
|
||||||
if(cdata->in_count > 0x007fffff)
|
|
||||||
{ /* shift will overflow */
|
|
||||||
rat = cdata->bytes_out >> 8;
|
|
||||||
if(rat == 0)
|
|
||||||
{ /* Don't divide by zero */
|
|
||||||
rat = 0x7fffffff;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rat = cdata->in_count / rat;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rat = (cdata->in_count << 8) / cdata->bytes_out; /* 8 fractional bits */
|
|
||||||
}
|
|
||||||
if ( rat > cdata->ratio )
|
|
||||||
{
|
|
||||||
cdata->ratio = rat;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cdata->ratio = 0;
|
|
||||||
#ifdef DEBUG
|
|
||||||
if(cdata->verbose)
|
|
||||||
{
|
|
||||||
dump_tab(); /* dump string table */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
cl_hash (cdata, (count_int) cdata->hsize );
|
|
||||||
cdata->free_ent = FIRST;
|
|
||||||
cdata->clear_flg = 1;
|
|
||||||
if ( !output (cdata, (code_int) CLEAR ) )
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#ifdef DEBUG
|
|
||||||
if(cdata->debug)
|
|
||||||
{
|
|
||||||
fprintf ( stderr, "clear\n" );
|
|
||||||
}
|
|
||||||
#endif /* DEBUG */
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cl_hash(struct cmcompress_stream* cdata, count_int hsize) /* reset code table */
|
static void cl_hash(struct cmcompress_stream* cdata, count_int hsize) /* reset code table */
|
||||||
{
|
{
|
||||||
register count_int *htab_p = cdata->htab+hsize;
|
register count_int *htab_p = cdata->htab+hsize;
|
||||||
|
@ -350,28 +123,6 @@ static void cl_hash(struct cmcompress_stream* cdata, count_int hsize) /* rese
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(DEBUG)
|
|
||||||
static void prratio(FILE *stream, long int num, long int den)
|
|
||||||
{
|
|
||||||
register int q; /* Doesn't need to be long */
|
|
||||||
|
|
||||||
if(num > 214748L)
|
|
||||||
{ /* 2147483647/10000 */
|
|
||||||
q = num / (den / 10000L);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
q = 10000L * num / den; /* Long calculations, though */
|
|
||||||
}
|
|
||||||
if (q < 0)
|
|
||||||
{
|
|
||||||
putc('-', stream);
|
|
||||||
q = -q;
|
|
||||||
}
|
|
||||||
fprintf(stream, "%d.%02d%%", q / 100, q % 100);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Output the given code.
|
* Output the given code.
|
||||||
* Inputs:
|
* Inputs:
|
||||||
|
@ -549,3 +300,252 @@ static int output(struct cmcompress_stream* cdata, code_int code)
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* compress stdin to stdout
|
||||||
|
*
|
||||||
|
* Algorithm: use open addressing double hashing (no chaining) on the
|
||||||
|
* prefix code / next character combination. We do a variant of Knuth's
|
||||||
|
* algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
|
||||||
|
* secondary probe. Here, the modular division first probe is gives way
|
||||||
|
* to a faster exclusive-or manipulation. Also do block compression with
|
||||||
|
* an adaptive reset, whereby the code table is cleared when the compression
|
||||||
|
* ratio decreases, but after the table fills. The variable-length output
|
||||||
|
* codes are re-sized at this point, and a special CLEAR code is generated
|
||||||
|
* for the decompressor. Late addition: construct the table according to
|
||||||
|
* file size for noticeable speed improvement on small files. Please direct
|
||||||
|
* questions about this implementation to ames!jaw.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int cmcompress_compress_start(struct cmcompress_stream* cdata)
|
||||||
|
{
|
||||||
|
#ifndef COMPATIBLE
|
||||||
|
if (cdata->nomagic == 0)
|
||||||
|
{
|
||||||
|
char headLast = (char)(cdata->maxbits | cdata->block_compress);
|
||||||
|
cdata->output_stream(cdata, (const char*)magic_header, 2);
|
||||||
|
cdata->output_stream(cdata, &headLast, 1);
|
||||||
|
if(ferror(stdout))
|
||||||
|
{
|
||||||
|
printf("Error...\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* COMPATIBLE */
|
||||||
|
|
||||||
|
cdata->offset = 0;
|
||||||
|
cdata->bytes_out = 3; /* includes 3-byte header mojo */
|
||||||
|
cdata->out_count = 0;
|
||||||
|
cdata->clear_flg = 0;
|
||||||
|
cdata->ratio = 0;
|
||||||
|
cdata->in_count = 1;
|
||||||
|
cdata->checkpoint = CHECK_GAP;
|
||||||
|
cdata->maxcode = MAXCODE(cdata->n_bits = INIT_BITS);
|
||||||
|
cdata->free_ent = ((cdata->block_compress) ? FIRST : 256 );
|
||||||
|
|
||||||
|
cdata->first_pass = 1;
|
||||||
|
|
||||||
|
cdata->hshift = 0;
|
||||||
|
for ( cdata->fcode = (long) cdata->hsize; cdata->fcode < 65536L; cdata->fcode *= 2L )
|
||||||
|
{
|
||||||
|
cdata->hshift++;
|
||||||
|
}
|
||||||
|
cdata->hshift = 8 - cdata->hshift; /* set hash code range bound */
|
||||||
|
|
||||||
|
cdata->hsize_reg = cdata->hsize;
|
||||||
|
cl_hash(cdata, (count_int) cdata->hsize_reg); /* clear hash table */
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cl_block (struct cmcompress_stream* cdata) /* table clear for block compress */
|
||||||
|
{
|
||||||
|
register long int rat;
|
||||||
|
|
||||||
|
cdata->checkpoint = cdata->in_count + CHECK_GAP;
|
||||||
|
#ifdef DEBUG
|
||||||
|
if ( cdata->debug )
|
||||||
|
{
|
||||||
|
fprintf ( stderr, "count: %ld, ratio: ", cdata->in_count );
|
||||||
|
prratio ( stderr, cdata->in_count, cdata->bytes_out );
|
||||||
|
fprintf ( stderr, "\n");
|
||||||
|
}
|
||||||
|
#endif /* DEBUG */
|
||||||
|
|
||||||
|
if(cdata->in_count > 0x007fffff)
|
||||||
|
{ /* shift will overflow */
|
||||||
|
rat = cdata->bytes_out >> 8;
|
||||||
|
if(rat == 0)
|
||||||
|
{ /* Don't divide by zero */
|
||||||
|
rat = 0x7fffffff;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rat = cdata->in_count / rat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rat = (cdata->in_count << 8) / cdata->bytes_out; /* 8 fractional bits */
|
||||||
|
}
|
||||||
|
if ( rat > cdata->ratio )
|
||||||
|
{
|
||||||
|
cdata->ratio = rat;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cdata->ratio = 0;
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(cdata->verbose)
|
||||||
|
{
|
||||||
|
dump_tab(); /* dump string table */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
cl_hash (cdata, (count_int) cdata->hsize );
|
||||||
|
cdata->free_ent = FIRST;
|
||||||
|
cdata->clear_flg = 1;
|
||||||
|
if ( !output (cdata, (code_int) CLEAR ) )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
if(cdata->debug)
|
||||||
|
{
|
||||||
|
fprintf ( stderr, "clear\n" );
|
||||||
|
}
|
||||||
|
#endif /* DEBUG */
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int cmcompress_compress(struct cmcompress_stream* cdata, void* buff, size_t n)
|
||||||
|
{
|
||||||
|
register code_int i;
|
||||||
|
register int c;
|
||||||
|
register int disp;
|
||||||
|
|
||||||
|
unsigned char* input_buffer = (unsigned char*)buff;
|
||||||
|
|
||||||
|
size_t cc;
|
||||||
|
|
||||||
|
/*printf("cmcompress_compress(%p, %p, %d)\n", cdata, buff, n);*/
|
||||||
|
|
||||||
|
if ( cdata->first_pass )
|
||||||
|
{
|
||||||
|
cdata->ent = input_buffer[0];
|
||||||
|
++ input_buffer;
|
||||||
|
-- n;
|
||||||
|
cdata->first_pass = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( cc = 0; cc < n; ++ cc )
|
||||||
|
{
|
||||||
|
c = input_buffer[cc];
|
||||||
|
cdata->in_count++;
|
||||||
|
cdata->fcode = (long) (((long) c << cdata->maxbits) + cdata->ent);
|
||||||
|
i = ((c << cdata->hshift) ^ cdata->ent); /* xor hashing */
|
||||||
|
|
||||||
|
if ( htabof (i) == cdata->fcode )
|
||||||
|
{
|
||||||
|
cdata->ent = codetabof (i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if ( (long)htabof (i) < 0 ) /* empty slot */
|
||||||
|
{
|
||||||
|
goto nomatch;
|
||||||
|
}
|
||||||
|
disp = cdata->hsize_reg - i; /* secondary hash (after G. Knott) */
|
||||||
|
if ( i == 0 )
|
||||||
|
{
|
||||||
|
disp = 1;
|
||||||
|
}
|
||||||
|
probe:
|
||||||
|
if ( (i -= disp) < 0 )
|
||||||
|
{
|
||||||
|
i += cdata->hsize_reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( htabof (i) == cdata->fcode )
|
||||||
|
{
|
||||||
|
cdata->ent = codetabof (i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( (long)htabof (i) > 0 )
|
||||||
|
{
|
||||||
|
goto probe;
|
||||||
|
}
|
||||||
|
nomatch:
|
||||||
|
if ( !output(cdata, (code_int) cdata->ent ) )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cdata->out_count++;
|
||||||
|
cdata->ent = c;
|
||||||
|
if (
|
||||||
|
#ifdef SIGNED_COMPARE_SLOW
|
||||||
|
(unsigned) cdata->free_ent < (unsigned) cdata->maxmaxcode
|
||||||
|
#else
|
||||||
|
cdata->free_ent < cdata->maxmaxcode
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
codetabof (i) = (unsigned short)(cdata->free_ent++); /* code -> hashtable */
|
||||||
|
htabof (i) = cdata->fcode;
|
||||||
|
}
|
||||||
|
else if ( (count_int)cdata->in_count >= cdata->checkpoint && cdata->block_compress )
|
||||||
|
{
|
||||||
|
if ( !cl_block (cdata) )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmcompress_compress_finalize(struct cmcompress_stream* cdata)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Put out the final code.
|
||||||
|
*/
|
||||||
|
if ( !output(cdata, (code_int)cdata->ent ) )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cdata->out_count++;
|
||||||
|
if ( !output(cdata, (code_int)-1 ) )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cdata->bytes_out > cdata->in_count) /* exit(2) if no savings */
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(DEBUG)
|
||||||
|
static void prratio(FILE *stream, long int num, long int den)
|
||||||
|
{
|
||||||
|
register int q; /* Doesn't need to be long */
|
||||||
|
|
||||||
|
if(num > 214748L)
|
||||||
|
{ /* 2147483647/10000 */
|
||||||
|
q = num / (den / 10000L);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
q = 10000L * num / den; /* Long calculations, though */
|
||||||
|
}
|
||||||
|
if (q < 0)
|
||||||
|
{
|
||||||
|
putc('-', stream);
|
||||||
|
q = -q;
|
||||||
|
}
|
||||||
|
fprintf(stream, "%d.%02d%%", q / 100, q % 100);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue