/* Program Name : ENDECODE.C */ /* Original Author : C. K. Hung */ /* Date : 1-JUN-1990 */ /* Program Description : This file contains routines for compress */ /* and expand files. */ /* : */ /* Revision History follows */ #include "global.h" #include "endecode.h" /* ** ** INTERNAL GLOBAL DECLARATIONS ** **/ static int input_bit_count; static unsigned long input_bit_buffer; static int output_bit_count; static unsigned long output_bit_buffer; int compress (FILE *input, FILE *output) { unsigned int next_code; unsigned int character; unsigned int string_code; unsigned int index; register int i; output_bit_count = 0; output_bit_buffer = 0; next_code = 256; for (i = 0; i < TABLE_SIZE; i++) code_value[i] = -1; string_code = getc(input); while ((character = getc(input)) != EOF) { index = find_match (string_code, character); if (code_value[index] != -1) string_code = code_value[index]; else { if (next_code <= MAX_CODE) { code_value[index] = next_code++; prefix_code[index] = string_code; append_character[index] = character; } output_code(output, string_code); string_code = character; } } output_code(output, string_code); output_code(output, MAX_VALUE); output_code(output, 0); return DX__NORMAL; } int find_match (int hash_prefix, unsigned int hash_character) { register int index; int offset; index = (hash_character << HASHING_SHIFT) ^ hash_prefix; offset = (index == 0? 1 : TABLE_SIZE-index); while (1) { if (code_value[index] == -1) { return index; } if (prefix_code[index] == hash_prefix && append_character[index] == hash_character) { return index; } index -= offset; if (index < 0) { index += TABLE_SIZE; } } } int output_code (FILE *output, unsigned int code) { output_bit_buffer |= (unsigned long) code << (32-BITS-output_bit_count); output_bit_count += BITS; while (output_bit_count >= 8) { putc(output_bit_buffer >> 24, output); output_bit_buffer <<= 8; output_bit_count -= 8; } return DX__NORMAL; } int expand(char *errmsg, FILE *input, FILE *output) { unsigned int next_code; unsigned int new_code; unsigned int old_code; int character; unsigned char *string; input_bit_count = 0; input_bit_buffer = 0; next_code = 256; old_code = input_code(input); character = old_code; putc(old_code, output); while ((new_code = input_code(input)) != MAX_VALUE) { if (new_code >= next_code) { *decode_stack = character; if ((string = decode_string(errmsg, decode_stack+1, old_code)) == -1) return -1; } else if ((string = decode_string(errmsg, decode_stack, new_code)) == -1) return -1; character = *string; while (string >= decode_stack) putc(*string--, output); if (next_code <= MAX_CODE) { prefix_code[next_code] = old_code; append_character[next_code] = character; next_code++; } old_code = new_code; } return 1; } char *decode_string(char *errmsg, unsigned char *buffer, unsigned int code) { register int i; i = 0; while (code > 255) { *buffer++ = append_character[code]; code = prefix_code[code]; if (i++ >= 4000) { sprintf(errmsg, "Exceeded quota during code expandion"); return -1; } } *buffer = code; return buffer; } int input_code(FILE *input) { unsigned int return_value; unsigned int character; while (input_bit_count <= 24) { input_bit_buffer |= (unsigned long) getc(input) << (24-input_bit_count); input_bit_count += 8; } return_value = input_bit_buffer >> (32-BITS); input_bit_buffer <<= BITS; input_bit_count -= BITS; return return_value; }