/* * @(#) arcoder.c - Arithmetic byte compressor/decompressor. * (c) 1998 Ivan Maidanski http://ivmai.chat.ru * Freeware program source. All rights reserved. ** * Language: ANSI C * Tested with: Microsoft Visual C++ (R) v4.2, Borland C/C++ v3.1 * Last modified: 1998-08-04 13:20:00 GMT+04:00 */ /* Notes: declare own ARITHPCK_VALUE_TYPE macro to override predefined encoded/decoded value type, declare own ARITHPCK_SYM_TYPE macro to override predefined symbol/index type, declare own ARITHPCK_FREQ_TYPE macro to override predefined frequence type, declare own ARITHPCK_FREQ_MAX macro to override predefined maximum frequence constant, declare own SYMSCALE macro to override predefined char update scale constant. */ #include "arithpck.h" /* ARITHPCK_SYM_TYPE, ARITHPCK_FREQ_TYPE */ /* ARITHPCK_VALUE_TYPE, ARITHSTART() */ /* arithinitinput(), arithpacksym(), arithunpacksym() */ /* arithoutput(), ARITHOUTFINISH(), arithflushfinish() */ /* FREQMODELALLOC(), freqmodelstart(), FREQMODELFREE() */ #include /* NULL, malloc(), free() */ #include /* FILE, SEEK_SET, SEEK_END */ /* puts(), fopen(), fclose(), fseek(), ftell() */ /* getc(), putc() */ #ifndef SYMSCALE #define SYMSCALE 4 /* frequence model char (symbol) update scale */ #endif void packfile(FILE *destfile, FILE *srcfile, long srclen, ARITHPCK_SYM_TYPE symtbl[], ARITHPCK_FREQ_TYPE freqtbl[], ARITHPCK_VALUE_TYPE maxcum) { unsigned char outcode=0; ARITHPCK_VALUE_TYPE low,high; ARITHSTART(low,high); while ((srclen--)>0) for (arithpacksym(&low,&high,(ARITHPCK_SYM_TYPE)getc(srcfile), symtbl,freqtbl,SYMSCALE,&maxcum); arithoutput(&outcode,NULL,NULL,&low,&high,maxcum);outcode=0) putc(outcode,destfile); for (;ARITHOUTFINISH(&outcode,NULL,NULL,&low,&high);outcode=0) putc(outcode,destfile); if (arithflushfinish(&outcode,NULL,NULL)) putc(outcode,destfile); } void unpackfile(FILE *destfile, FILE *srcfile, long destlen, ARITHPCK_SYM_TYPE symtbl[], ARITHPCK_FREQ_TYPE freqtbl[], ARITHPCK_VALUE_TYPE maxcum) { ARITHPCK_VALUE_TYPE low,high,input=0; unsigned char incode,outcode=0; while (arithinitinput(&input,(unsigned char)getc(srcfile))); incode=(unsigned char)getc(srcfile); ARITHSTART(low,high); while ((destlen--)>0) for (putc(arithunpacksym(&low,&high,input, symtbl,freqtbl,SYMSCALE,&maxcum),destfile); arithoutput(&outcode,&input,&incode,&low,&high,maxcum);outcode=0) incode=(unsigned char)getc(srcfile); /* for (;ARITHOUTFINISH(&outcode,&input,&incode,&low,&high);outcode=0) incode=(unsigned char)getc(srcfile); if (arithflushfinish(&outcode,&input,&incode)) incode=(unsigned char)getc(srcfile); */ } void fputlong(long value, FILE *f) { int cnt=sizeof(long); unsigned char *p=(unsigned char *)&value+cnt; while ((cnt--)>0) putc(*--p,f); } long fgetlong(FILE *f) { long value=0; unsigned char *p=(unsigned char *)&value; *p=(unsigned char)1; p+=sizeof(long); while (!*--p) *p=(unsigned char)getc(f); *p=(unsigned char)getc(f); return value; } int packunpackfile(char *destfname, char *srcfname, int compression) { long srclen; FILE *srcfile,*destfile; ARITHPCK_SYM_TYPE *symtbl; ARITHPCK_FREQ_TYPE *freqtbl; ARITHPCK_VALUE_TYPE maxcum; if ((srcfile=fopen(srcfname,"rb"))==NULL) return 2; if (FREQMODELALLOC(symtbl,freqtbl,(unsigned char)~0)<0) { fclose(srcfile); return 1; } if ((destfile=fopen(destfname,"wb"))==NULL) { FREQMODELFREE(symtbl,freqtbl); fclose(srcfile); return 3; } freqmodelstart(symtbl,freqtbl,&maxcum,(unsigned char)~0); if (compression) { fseek(srcfile,0L,SEEK_END); srclen=ftell(srcfile); fseek(srcfile,0L,SEEK_SET); fputlong(srclen,destfile); packfile(destfile,srcfile,srclen,symtbl,freqtbl,maxcum); } else unpackfile(destfile,srcfile,fgetlong(srcfile),symtbl,freqtbl,maxcum); fclose(destfile); FREQMODELFREE(symtbl,freqtbl); fclose(srcfile); return 0; } int main(int argc, char *argv[]) { if (argc!=4 || !(argc=argv[1][0]=='E' || argv[1][0]=='e') && !(argv[1][0]=='D' || argv[1][0]=='d')) { puts("Arithmetic byte compressor/decompressor\n" "Usage parameters: E|D \n"); return -1; } argc=packunpackfile(argv[3],argv[2],argc); switch (argc) { case 1: puts("Error: not enough memory."); break; case 2: puts("Error: cannot open source file."); break; case 3: puts("Error: cannot open destination file."); } return argc; }