123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611 |
- /*
- THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
- SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
- END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
- ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
- IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
- SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
- FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
- CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
- AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
- COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
- */
- /*
- * $Source: f:/miner/source/cfile/rcs/cfile.c $
- * $Revision: 1.7 $
- * $Author: matt $
- * $Date: 1994/04/13 23:44:59 $
- *
- * Functions for accessing compressed files.
- *
- * $Log: cfile.c $
- * Revision 1.7 1994/04/13 23:44:59 matt
- * When file cannot be opened, free up the buffer for that file.
- *
- * Revision 1.6 1994/02/18 12:38:20 john
- * Optimized a bit
- *
- * Revision 1.5 1994/02/15 18:13:20 john
- * Fixed more bugs.
- *
- * Revision 1.4 1994/02/15 13:27:58 john
- * Works ok...
- *
- * Revision 1.3 1994/02/15 12:51:57 john
- * Crappy inbetween version
- *
- * Revision 1.2 1994/02/14 20:12:29 john
- * First version working with new cfile stuff.
- *
- * Revision 1.1 1994/02/14 15:51:33 john
- * Initial revision
- *
- * Revision 1.1 1994/02/10 15:45:12 john
- * Initial revision
- *
- *
- */
- #pragma off (unreferenced)
- static char rcsid[] = "$Id: cfile.c 1.7 1994/04/13 23:44:59 matt Exp $";
- #pragma on (unreferenced)
- #include <time.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <stdarg.h>
- #include <conio.h>
- #include <dos.h>
- #include <fcntl.h>
- #include <io.h>
- #include <sys\types.h>
- #include <sys\stat.h>
- #include <errno.h>
- #include <string.h>
- #include "mem.h"
- #include "error.h"
- #include "cfile.h"
- #define BITS 15
- #define MAX_CODE ( ( 1 << BITS ) - 1 )
- #define TABLE_SIZE 35023L
- #define END_OF_STREAM 256
- #define BUMP_CODE 257
- #define FLUSH_CODE 258
- #define FIRST_CODE 259
- #define UNUSED -1
- extern FILE * LibraryGetFileInfo( char *filename, int * others_use, int * lib_offset, int * file_size, int * org_size, int * compressed, char * buffer );
- int raw_seek( CFILE * cfile, int pos )
- {
- int i;
- cfile->raw_position = pos;
- //printf( "Seeking to %d + %d\n", cfile->lib_offset, cfile->raw_position );
- i = fseek( cfile->file, cfile->lib_offset+cfile->raw_position, SEEK_SET );
- if (i) Int3();
- return i;
- }
- int raw_getc( CFILE * cfile )
- {
- int c;
- // if (cfile->others_use)
- // fseek( cfile->file, cfile->lib_offset+cfile->raw_position, SEEK_SET );
- if (cfile->raw_position >= cfile->org_size ) return EOF;
- c = getc( cfile->file );
- if (c!=EOF)
- cfile->raw_position++;
- // Assert( cfile->raw_position==(ftell(cfile->file)-cfile->lib_offset) );
- return c;
- }
- int raw_putc( int c, CFILE * cfile )
- {
- int r;
- if (cfile->others_use)
- fseek( cfile->file, cfile->lib_offset+cfile->raw_position, SEEK_SET );
- r = fputc( c, cfile->file );
- if (r!=EOF)
- cfile->raw_position++;
- Assert( cfile->raw_position==(ftell(cfile->file)-cfile->lib_offset) );
- return r;
- }
- void compress_init_dict( CFILE * cfile )
- {
- unsigned int i;
- for ( i = 0 ; i < TABLE_SIZE ; i++ )
- cfile->dict[i].code_value = UNUSED;
- cfile->next_code = FIRST_CODE;
- cfile->current_code_bits = 9;
- cfile->next_bump_code = 511;
- }
- void compress_init_storage( CFILE * cfile )
- {
- MALLOC( cfile->dict, DICTIONARY, TABLE_SIZE );
- MALLOC( cfile->decode_stack, char, TABLE_SIZE );
- }
- void compress_free_storage( CFILE * cfile )
- {
- free(cfile->dict);
- free(cfile->decode_stack);
- }
- unsigned int compress_find_child_node( CFILE * cfile, int parent_code, int child_character ) {
- unsigned int index;
- int offset;
- index = ( child_character << ( BITS - 8 ) ) ^ parent_code;
- if ( index == 0 )
- offset = 1;
- else
- offset = TABLE_SIZE - index;
- for ( ; ; ) {
- if ( cfile->dict[ index ].code_value == UNUSED )
- return( (unsigned int) index );
- if ( cfile->dict[ index ].parent_code == parent_code &&
- cfile->dict[ index ].character == (char) child_character )
- return( index );
- if ( (int) index >= offset )
- index -= offset;
- else
- index += TABLE_SIZE - offset;
- }
- }
- unsigned int compress_decode_string( CFILE * cfile, unsigned int count, unsigned int code ) {
- while ( code > 255 ) {
- cfile->decode_stack[ count++ ] = cfile->dict[ code ].character;
- code = cfile->dict[ code ].parent_code;
- }
- cfile->decode_stack[ count++ ] = (char) code;
- return( count );
- }
- void compress_output_bit( CFILE *bit_file, int bit ) {
- if ( bit )
- bit_file->rack |= bit_file->mask;
- bit_file->mask >>= 1;
- if ( bit_file->mask == 0 ) {
- if ( raw_putc(bit_file->rack, bit_file ) != bit_file->rack )
- Error( "Error in compress_output_bit" );
- bit_file->rack = 0;
- bit_file->mask = 0x80;
- }
- }
- void compress_output_bits( CFILE *bit_file, unsigned int code, int count ) {
- unsigned int mask;
- mask = 1L << ( count - 1 );
- while ( mask != 0) {
- if ( mask & code )
- bit_file->rack |= bit_file->mask;
- bit_file->mask >>= 1;
- if ( bit_file->mask == 0 ) {
- if ( raw_putc(bit_file->rack, bit_file ) != bit_file->rack )
- Error( "Error in compress_output_bits" );
- bit_file->rack = 0;
- bit_file->mask = 0x80;
- }
- mask >>= 1;
- }
- }
- int compress_input_bit( CFILE *bit_file ) {
- int value;
- if ( bit_file->mask == 0x80 ) {
- bit_file->rack = raw_getc( bit_file );
- if ( bit_file->rack == EOF )
- return END_OF_STREAM;
- //Error( "Fatal error in compress_input_bit!" );
- }
- value = bit_file->rack & bit_file->mask;
- bit_file->mask >>= 1;
- if ( bit_file->mask == 0 )
- bit_file->mask = 0x80;
- return( value ? 1 : 0 );
- }
- unsigned int compress_input_bits( CFILE *bit_file, int bit_count ) {
- unsigned int mask;
- unsigned int return_value;
- mask = 1L << ( bit_count - 1 );
- return_value = 0;
- while ( mask != 0) {
- if ( bit_file->mask == 0x80 ) {
- bit_file->rack = raw_getc( bit_file );
- if ( bit_file->rack == EOF )
- return END_OF_STREAM;
- //Error( "Fatal error in compress_input_bit!" );
- }
- if ( bit_file->rack & bit_file->mask )
- return_value |= mask;
- mask >>= 1;
- bit_file->mask >>= 1;
- if ( bit_file->mask == 0 )
- bit_file->mask = 0x80;
- }
- return( return_value );
- }
- CFILE * cfopen(char * filename, char * mode ) {
- CFILE *cfile;
- char signature[3] = "CF";
- MALLOC(cfile, CFILE, 1);
- cfile->rack = 0;
- cfile->mask = 0x80;
- MALLOC(cfile->buffer,char,4096*2);
-
- if (strcmpi( mode, "rc")==0 ) {
- cfile->file = LibraryGetFileInfo( filename, &cfile->others_use, &cfile->lib_offset, &cfile->compressed_size, &cfile->org_size, &cfile->compressed, cfile->buffer );
- if (cfile->file==NULL ) {
- free(cfile->buffer);
- free(cfile);
- return NULL;
- }
- raw_seek( cfile, 0 );
- if (!cfile->compressed) {
- cfile->position = 0;
- cfile->readonly=1; // Read
- return cfile;
- }
- compress_init_storage(cfile);
- compress_init_dict(cfile);
- cfile->old_code = UNUSED;
- cfile->readonly=1; // Read
- cfile->position = 0;
- cfile->count = 0;
- //printf( "File is %d bytes, orginal is %d bytes\n", cfile->compressed_size, cfile->org_size );
- return cfile;
- } else if (strcmpi( mode, "wc")==0 ) {
- compress_init_storage(cfile);
- compress_init_dict(cfile);
- cfile->old_code = UNUSED;
- cfile->readonly=0; // Write
- cfile->compressed=1;
- cfile->string_code = -1;
- cfile->position = 0;
- cfile->count = 0;
- cfile->compressed_size = 0;
- cfile->file=fopen( filename, "wb" );
- setvbuf( cfile->file, cfile->buffer, _IOFBF, 4096*2 );
- cfile->others_use = 0;
- cfile->lib_offset = 6;
- cfile->org_size = 0;
- fwrite( &signature, 2, sizeof(char), cfile->file );
- fwrite( &cfile->org_size, sizeof(int), 1, cfile->file );
- raw_seek( cfile, 0 );
- return cfile;
- }
- cfile->file = fopen( filename, mode );
- setvbuf( cfile->file, cfile->buffer, _IOFBF, 4096*2 );
- cfile->org_size = filelength( fileno( cfile->file ));
- cfile->compressed_size = cfile->org_size;
- cfile->readonly=0;
- cfile->position = 0;
- cfile->raw_position = 0;
- cfile->compressed = 0;
- cfile->lib_offset = 0;
- cfile->others_use = 0;
- return cfile;
- }
- int cfilelength( CFILE *fp )
- {
- if ( fp->org_size < fp->position )
- return fp->position;
- else
- return fp->org_size;
- }
- int cfputc( int c, CFILE *fp )
- {
- int character;
- unsigned int index;
- if (!fp->compressed)
- return raw_putc( c, fp );
- character = c & 0xFF;
- if (fp->string_code < 0 ) {
- fp->string_code = character;
- fp->position++;
- return character;
- }
-
- fp->position++;
- index = compress_find_child_node( fp, fp->string_code, character );
- if ( fp->dict[ index ].code_value != - 1 )
- fp->string_code = fp->dict[ index ].code_value;
- else {
- fp->dict[ index ].code_value = fp->next_code++;
- fp->dict[ index ].parent_code = fp->string_code;
- fp->dict[ index ].character = (char) character;
- compress_output_bits( fp, (unsigned long)fp->string_code, fp->current_code_bits );
- fp->string_code = character;
- if ( fp->next_code > MAX_CODE ) {
- compress_output_bits( fp,(unsigned long)FLUSH_CODE, fp->current_code_bits );
- compress_init_dict(fp);
- } else if ( fp->next_code > fp->next_bump_code ) {
- compress_output_bits( fp,(unsigned long)BUMP_CODE, fp->current_code_bits );
- fp->current_code_bits++;
- fp->next_bump_code <<= 1;
- fp->next_bump_code |= 1;
- }
- }
- return character;
- }
- int cfgetc( CFILE * fp ) {
- int new_character;
- if ( !fp->compressed )
- return raw_getc( fp );
- if (fp->position >= fp->org_size )
- return EOF;
- if ( fp->old_code == UNUSED ) {
- fp->old_code = (unsigned int) compress_input_bits( fp, fp->current_code_bits );
- if ( fp->old_code == END_OF_STREAM ) {
- fp->position = fp->org_size;
- return EOF;
- }
- fp->count = 0;
- fp->character = fp->old_code;
- fp->position++;
- return fp->character;
- }
- if ( fp->count > 0 ) {
- new_character = ( unsigned char )fp->decode_stack[ --fp->count ];
- fp->position++;
- if (fp->count==0 ) {
- fp->dict[ fp->next_code ].parent_code = fp->old_code;
- fp->dict[ fp->next_code ].character = (char) fp->character;
- fp->next_code++;
- fp->old_code = fp->new_code;
- }
- return new_character;
- }
- for ( ; ; ) {
- fp->new_code = (unsigned int) compress_input_bits( fp, fp->current_code_bits );
- switch( fp->new_code )
- {
- case END_OF_STREAM:
- fp->position = fp->org_size;
- return EOF;
-
- case FLUSH_CODE:
- compress_init_dict(fp);
- fp->old_code = (unsigned int) compress_input_bits( fp, fp->current_code_bits );
- if ( fp->old_code == END_OF_STREAM ) {
- fp->position = fp->org_size;
- return EOF;
- }
- fp->count = 0;
- fp->character = fp->old_code;
- fp->position++;
- return fp->character;
-
- case BUMP_CODE:
- fp->current_code_bits++;
- break;
- default:
- if ( fp->new_code >= fp->next_code ) {
- fp->decode_stack[ 0 ] = (char) fp->character;
- fp->count = compress_decode_string( fp, 1, fp->old_code );
- } else {
- fp->count = compress_decode_string( fp, 0, fp->new_code );
- }
-
- fp->character = fp->decode_stack[ fp->count - 1 ];
- new_character = ( unsigned char )fp->decode_stack[ --fp->count ];
- fp->position++;
- if (fp->count==0 ) {
- fp->dict[ fp->next_code ].parent_code = fp->old_code;
- fp->dict[ fp->next_code ].character = (char) fp->character;
- fp->next_code++;
- fp->old_code = fp->new_code;
- }
- return new_character;
- }
- }
- }
- size_t cfread( void * buf, size_t elsize, size_t nelem, CFILE * fp )
- {
- int c, i = 0;
- unsigned char * buffer = (unsigned char *)buf;
- if ( !fp->compressed ) {
- //if ((cfile->raw_position+(elsize*nelem)) > cfile->org_size ) return EOF;
- //i = fread( buf, elsize, nelem, fp->file );
- //fp->raw_position += i*elsize;
- // return i;
- //return raw_fread( buf, elsize, nelem, fp->file );
-
- for ( i=0; i<(elsize*nelem); i++ )
- {
- c = raw_getc( fp );
- if ( c==EOF) return i/elsize;
- *buffer++ = c;
- }
- return nelem;
- }
- //printf( "Reading %d compressed bytes..\n", elsize*nelem );
- for ( i=0; i<(elsize*nelem); i++ )
- {
- c = cfgetc( fp );
- if ( c==EOF) return i/elsize;
- *buffer++ = c;
- }
- return nelem;
- }
-
- size_t cfwrite( const void * buf, size_t elsize, size_t nelem, CFILE *fp )
- {
- int c, i = 0;
- unsigned char * buffer = (unsigned char *)buf;
- if ( !fp->compressed ) {
- //return fwrite( buf, elsize, nelem, fp->file );
- for ( i=0; i<(elsize*nelem); i++ )
- {
- c = *buffer++;
- if (raw_putc( c, fp )!=c)
- return i/elsize;
- }
- return nelem;
- }
-
- for ( i=0; i<(elsize*nelem); i++ )
- {
- c = *buffer++;
- if (cfputc( c, fp )!=c)
- return i/elsize;
- }
- return nelem;
- }
- int cftell( CFILE *fp ) {
- if ( !fp->compressed )
- return fp->raw_position;
- return fp->position;
- }
- int cfseek( CFILE *fp, long int offset, int where )
- {
- int c, goal_position;
- if ( !fp->readonly && fp->compressed ) return 3; // Can only seek on readonly files.
- switch( where )
- {
- case SEEK_SET:
- goal_position = offset;
- break;
- case SEEK_CUR:
- if (fp->compressed)
- goal_position = fp->position+offset;
- else
- goal_position = fp->raw_position+offset;
- break;
- case SEEK_END:
- goal_position = fp->org_size+offset;
- break;
- default:
- return 1;
- }
- if ( !fp->compressed ) {
- c = fseek( fp->file, fp->lib_offset + goal_position, SEEK_SET );
- fp->raw_position = ftell(fp->file)-fp->lib_offset;
- return c;
- }
-
- if ( (goal_position<0) || (goal_position>=fp->org_size) )
- return 1;
- if ( goal_position == fp->position )
- return 0; // Already there!
-
- if ( goal_position < fp->position ) {
- // We need to back track...
- compress_init_dict(fp);
- fp->old_code = UNUSED;
- fp->position = 0;
- fp->raw_position = 0;
- fp->count = 0;
- fp->rack = 0;
- fp->mask = 0x80;
- raw_seek( fp, 0 );
- //fread( &signature, sizeof(unsigned int), 1, fp->file );
- //if (signature != 0xCFCF ) return 1;
- //fread( &fp->compressed_size, sizeof(int), 1, fp->file );
- }
-
- // Read forward to goal_position...
- while( fp->position < goal_position )
- {
- c = cfgetc( fp );
- if (c==EOF) return 2;
- }
- return 0;
- }
- void cfclose( CFILE * fp ) {
- char signature[3] = "CF";
- Assert( fp!=NULL );
- if (!fp->compressed) {
- if ( !fp->others_use )
- fclose(fp->file);
- if (fp->buffer) free(fp->buffer);
- free(fp);
- return;
- }
- if (!fp->readonly) {
- compress_output_bits( fp, (unsigned long) fp->string_code, fp->current_code_bits );
- compress_output_bits( fp, (unsigned long) END_OF_STREAM, fp->current_code_bits);
- if ( fp->mask != 0x80 ) {
- if ( putc( fp->rack, fp->file ) != fp->rack )
- Error( "Fatal error in CloseBitFile" );
- }
- fp->org_size = fp->position;
- fseek( fp->file, 0L, SEEK_SET );
- fwrite( signature, 2, sizeof(char), fp->file );
- fwrite( &fp->org_size, 1, sizeof(int), fp->file );
- //printf( "File wrote is %d bytes originally\n", fp->org_size );
- }
- if (!fp->others_use )
- fclose(fp->file);
- compress_free_storage(fp);
- if (fp->buffer) free(fp->buffer);
- free(fp);
- }
|