home *** CD-ROM | disk | FTP | other *** search
- /*
- ** general purpose file packer, Copyright (C) Randy Nevin 1989, 1990.
- **
- ** you may give this software to anyone, make as many copies as you like, and
- ** post it on public computer bulletin boards and file servers. you may not
- ** sell it or charge any fee for distribution (except for media and postage),
- ** remove this comment or the copyright notice from the code, or claim that
- ** you wrote this code or anything derived from it. you may modify the code as
- ** much as you want (please document clearly with comments, and maintain the
- ** coding style), but programs which are derived from this one are subject to
- ** the conditions stated here. i am providing this code so that people can
- ** learn from it, so if you distribute it, please include source code, not
- ** just executables. contact me to report bugs or suggest enhancements; i do
- ** not guarantee support, but i will make an effort to help you, and i want to
- ** act as a central clearing house for future versions. you should contact me
- ** before undertaking a significant development effort, to avoid reinventing
- ** the wheel. if you come up with an enhancement you consider particularly
- ** useful, i would appreciate being informed so that it can be incorporated in
- ** future versions. my address is: Randy Nevin, 1731 211th PL NE, Redmond,
- ** WA 98053, USA. this code is available directly from the author; just send a
- ** 360k floppy and a self-addressed floppy mailer with sufficient postage.
- **
- ** HISTORY
- ** (name date description)
- ** ----------------------------------------------------
- ** randy nevin 8/6/89 initial version
- ** randy nevin 8/15/89 released version 1.00
- */
-
- /* BUGBUG: doesn't handle files with only one byte value */
-
- /*
- ** use run-length encoding to compress runs of identical bytes. do this by
- ** scanning the input file once, counting the number of times each byte
- ** occurs. then pick the one that occurs least frequently (ideally not at all)
- ** as the encoding byte. put the encoding type (2) and the encoding byte in
- ** the output file. then scan the input file again, writing out the encoded
- ** input to the output file. encode by looking for runs of 3 or more identical
- ** bytes. for runs, output the encoding byte, the byte count, and the byte
- ** value. for non-runs, just output the byte values. be careful if the
- ** encoding byte occurs in the input file; a byte count of 0 means just put
- ** out one (literal) encoding byte.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- long table[0x100]; /* frequency table */
-
- void main( int, char *[] );
-
- void main ( argc, argv )
- int argc;
- char *argv[];
- {
- char *self, *t;
- int c, i, enc, val;
- FILE *fin, *fout;
-
- printf( "Copyright (C) Randy Nevin, 1989, 1990. Version 1.00\n" );
- printf( "See source code for rights granted.\n\n" );
- self = argv[0];
- /* get rid of initial part of path */
- if ((t = strrchr( self, '\\' )) || (t = strrchr( self, ':' )))
- self = ++t;
- /* get rid of extension */
- if ((t = strrchr( self, '.' )) && !stricmp( t, ".EXE" ))
- *t = 0;
- if (argc != 3) { /* need infile and outfile */
- fprintf( stderr, "usage: %s infile outfile\n", self );
- exit( -1 );
- }
- if (!(fin = fopen( argv[1], "rb" ))) {
- fprintf( stderr, "can't open %s\n", argv[1] );
- exit( -1 );
- }
- if (!(fout = fopen( argv[2], "wb" ))) {
- fprintf( stderr, "can't open %s\n", argv[2] );
- exit( -1 );
- }
- /* initialize the byte count table */
- for (i = 0; i < 0x100; i++)
- table[i] = 0;
- /* scan the input bytes */
- for (c = getc( fin ); c != EOF; c = getc( fin ))
- table[c] += 1L;
- /* determine the encoding byte */
- for (enc = 0, i = 1; i < 0x100; i++)
- if (table[i] < table[enc])
- enc = i;
- putc( 2, fout ); /* encoding type (2=run-length) */
- putc( (char)enc, fout ); /* identify encoding byte */
- fseek( fin, 0L, SEEK_SET ); /* rewind input file for second pass */
- i = 0; /* use i as byte count */
- while ((c = getc( fin )) != EOF) { /* encode input file */
- if (!i) {
- val = c;
- i = 1;
- }
- else if (c == val)
- i++;
- else { /* flush val */
- if (i >= 3) { /* encode it */
- putc( (char)enc, fout );
- putc( (char)i, fout );
- putc( (char)val, fout );
- }
- else if (i == 2) { /* do separately */
- putc( (char)val, fout );
- if (val == enc) {
- putc( 0, fout );
- putc( (char)val, fout );
- putc( 0, fout );
- }
- else
- putc( (char)val, fout );
- }
- else if (i == 1) { /* do separately */
- putc( (char)val, fout );
- if (val == enc)
- putc( 0, fout );
- }
- val = c;
- i = 1;
- }
- if (i == 0xFF) { /* force a flush to avoid count overflow */
- putc( (char)enc, fout );
- putc( (char)i, fout );
- putc( (char)val, fout );
- i = 0;
- }
- } /* end while */
- /* flush val */
- if (i >= 3) { /* encode it */
- putc( (char)enc, fout );
- putc( (char)i, fout );
- putc( (char)val, fout );
- }
- else if (i == 2) { /* do separately */
- putc( (char)val, fout );
- if (val == enc) {
- putc( 0, fout );
- putc( (char)val, fout );
- putc( 0, fout );
- }
- else
- putc( (char)val, fout );
- }
- else if (i == 1) { /* do separately */
- putc( (char)val, fout );
- if (val == enc)
- putc( 0, fout );
- }
- if (ferror( fout ))
- fprintf( stderr, "output error; disk might be full\n" );
- fclose( fout );
- exit( 0 );
- }
-