home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HAM Radio 1
/
HamRadio.cdr
/
tech
/
pcbsrcs2
/
pcbpak2.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-07
|
5KB
|
160 lines
/*
** 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 );
}