ENH: reorder code to remove forward declarations

This commit is contained in:
Ken Martin 2006-08-17 12:04:26 -04:00
parent 3a44f2a47e
commit d4ae4849f7
1 changed files with 249 additions and 249 deletions

View File

@ -67,9 +67,6 @@ static const char_type magic_header[] = { "\037\235" }; /* 1F 9D */
#define FIRST 257 /* first free entry */
#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
static void prratio( FILE *stream, long int num, long int den);
#endif
@ -92,230 +89,6 @@ int cmcompress_compress_initialize(struct cmcompress_stream* cdata)
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 */
{
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.
* Inputs:
@ -549,3 +300,252 @@ static int output(struct cmcompress_stream* cdata, code_int code)
}
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