/******************************************************************************* * * * JAC.C May 1992 * * * * Written in Borland C++ 2.0 under MS-DOS 5.0 * * Memory model = medium * * * *******************************************************************************/ #include typedef struct chardata { short charnum; // which character to be encoded short frequency; // frequency of occurance, }; #define input fgetc(infile) #define output(i) fputc(i,outfile) #define FALSE 0 #define TRUE !FALSE struct chardata *table[256]; struct chardata *temp; FILE *infile; // file ptr to original file (uncompressed) FILE *outfile; // file ptr to output fiel (compressed) char *infile_name; // ptr to name of input file char *outfile_name; // ptr to name of output file int n=0,S=0; int sort(short); int frequency_16_char(short); int timeout(void); int main(int argc, char **argv) { enum { QUAD, NO_QUAD } encode_state = NO_QUAD; register short c,quad_high,X; // a character if (argc < 3) { // check command line arguments puts("'jac file1 file2 [S] ' encode_s file1 into file2."); return 1; } puts("Jac by TT, 1992"); infile_name = argv[1]; outfile_name = argv[2]; if (argc == 3) S=atoi(argv[3]); for (c=0; c < 256; c++) // initialize decode table { if ((table[c] = (struct chardata *)malloc(sizeof (struct chardata)))== NULL) { printf("Unable to allocate space for %dth table node.",c); return 1; } table[c]->charnum = c; // need to know who we are after sort table[c]->frequency = 1; } if ((infile=fopen(infile_name, "rb")) == NULL) // open the input file { printf("Unable to open %s.\n", infile_name); return 1; } outfile=fopen(outfile_name,"wb"); while (!timeout()) // get character distribution data { c = input; if (!timeout()) { X=0; while(table[X]->charnum != c || X==256) X++; switch (encode_state) { case NO_QUAD: { if (X < S) // check if quad is 4-bit character { quad_high=(X << 4); // save character S=sort(X); // sort table encode_state=QUAD; break; } else if (X > 255 - 16 * S) { output(0xf0+(X>>4)); S=sort(X); quad_high=X<<4; encode_state=QUAD; break; } else { output(X+15*S); encode_state=NO_QUAD; S=sort(X); break; } } case QUAD: { if (X 255 - 16*S) { output(quad_high+0x0f); output(X); S=sort(X); encode_state=NO_QUAD; break; } else { output(quad_high+((X+15*S)>>4)); quad_high=(X+15*S)<<4; S=sort(X); encode_state=QUAD; break; } } default: break; } // switch (deco.... } if (timeout() && encode_state==QUAD) // fill end of file with quad + 1111 { printf("filling"); output(quad_high+0x0f); } } fclose(infile); // Close files fclose(outfile); // close files return 0; } // Function makes limited short // if function has been called 128 times // it calcultes new value for S int sort(short x) { int c,b; table[x]->frequency++; // update frequency // printf("%c",table[x]->charnum); if (x<16) c=0; else c=x-16; while((table[c]->frequency >= table[x]->frequency) || c==x) c++; // printf("c=%d\n",c); // If new frequency greater than value(s) above change places if (cfrequency >= table[b]->frequency) { table[x]=table[b]; // store original value to X place table[b]=temp; // replace new value to b temp=table[x]; // restore original value to temp } } table[x]=temp; } // Check is it time to calculate S set n++; // increment counter if (n==128) // Time to check SET S { // calculate best S value S=0; for (c=0;c<16;c++) if ((table[c]->frequency) > frequency_16_char(256-(c+1)*16)) S=c; printf("S=%d \t",S); // divide by two the original character count for (c=0;c<256;c++) table[c]->frequency >>=1; // set n to zero for next calculation n=0; } return S; } // Calculates total frequency of 16 characters starting from charcter c int frequency_16_char(short c) { int v,val=0; for(v=c;vfrequency; return val; } // Returns TRUE if timeout occurs // In this case timeout is only true if end of file infile int timeout(void) { if(!feof(infile)) return FALSE; else return TRUE; }