#include "freeze.h" #include "lz.h" /*----------------------------------------------------------------------*/ /* */ /* LZSS ENCODING */ /* */ /*----------------------------------------------------------------------*/ uc_t text_buf[N2 + F2 - 1]; /* cyclic buffer with an overlay */ us_t match_position, match_length; /* current characteristics of a matched pattern */ us_t chain_length; /* max_chain_length == CHAIN_THRESHOLD / greedy */ /* next[N+1..] is used as hash table, the rest of next is a link down, prev is a link up. */ hash_t prev[N2 + 1]; #ifndef __XENIX__ #ifdef __TURBOC__ us_t huge * next = (us_t huge *) NULL; #else /* __TURBOC__ */ us_t next[array_size]; /* a VERY large array :-) */ #endif /* __TURBOC__ */ #else /* __XENIX__ */ #if parts == 2 us_t next0[32768L], next1[8193]; #else us_t next0[32768L], next1[32768L], next2[8193]; #endif /* parts */ /* A list of `next's parts */ us_t *next[parts] = { next0, next1 #if parts > 2 ,next2 #endif }; #endif /* __XENIX__ */ #ifdef GATHER_STAT long node_steps, node_matches; #endif /* GATHER_STAT */ /* Initialize the data structures and allocate memory, if needed. Although there is no more trees in the LZ algorithm implementation, routine name is kept intact :-) */ void InitTree () { long i; #ifdef GATHER_STAT node_steps = node_matches = 0; #endif /* GATHER_STAT */ #ifdef __TURBOC__ if (!next && (next = (us_t huge *) farmalloc( (ul_t)array_size * sizeof(us_t))) == NULL) { fprintf(stderr, "Not enough memory (%luK wanted)\n", (ul_t)array_size * sizeof(us_t) / 1024); exit(3); } #endif /* __TURBOC__ */ for (i = N2 + 1; i < array_size; i++ ) nextof(i) = NIL; for (i = 0; i < sizeof(prev)/sizeof(*prev); i++ ) prev[i] = NIL; chain_length = greedy ? CHAIN_THRESHOLD / greedy : 0; } /* Get the longest (longer than `match_length' when entering in subroutine) nearest match of the string beginning in text_buf[r] to the cyclic buffer. Result (length & position) is returned in correspondent global variables (`match_length' & `match_position'). Unchanged `match_length' denotes failure. */ #ifndef FAST void get_next_match (r) us_t r; { register us_t p = r; register int m; register uc_t *key FIX_SI, *pattern FIX_DI; int chain_count = chain_length; #ifdef GATHER_STAT node_matches++; #endif key = text_buf + r; do { do { /* From ZIP 1.0 by J.-L. Gailly et al. */ if ((p = nextof(p)) == NIL || (greedy && !chain_count--)) return; pattern = text_buf + p; MATCHING; } while NOT_YET; #ifdef GATHER_STAT node_steps++; #endif for (m = match_length; ++m < F2 && key[m] == pattern[m]; ); match_length = m; match_position = ((r - p) & (N2 - 1)) - 1; } while (m < F2); /* There are two equal F-char sequences, the oldest one must be deleted from the list. */ #ifdef DEBUG if (verbose) fprintf(stderr, "Replacing node: %d -> %d\n", p, r); #endif nextof(prev[p]) = nextof(p); prev[nextof(p)] = prev[p]; prev[p] = NIL; /* remove p, it is further than r */ return; } #endif