123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929 |
- #define __DEFLATE_C
- #include "zip.h"
- #ifndef USE_ZLIB
- #ifdef SMALL_MEM
- # define HASH_BITS 13
- #endif
- #ifdef MEDIUM_MEM
- # define HASH_BITS 14
- #endif
- #ifndef HASH_BITS
- # define HASH_BITS 15
-
- #endif
- #define HASH_SIZE (unsigned)(1<<HASH_BITS)
- #define HASH_MASK (HASH_SIZE-1)
- #define WMASK (WSIZE-1)
- #define NIL 0
- #define FAST 4
- #define SLOW 2
- #ifndef TOO_FAR
- # define TOO_FAR 4096
- #endif
- #if (defined(ASMV) && !defined(MSDOS16) && defined(DYN_ALLOC))
- error: DYN_ALLOC not yet supported in match.S or match32.asm
- #endif
- #ifdef MEMORY16
- # define MAXSEG_64K
- #endif
- #if defined(MMAP) || defined(BIG_MEM)
- typedef unsigned Pos;
- #else
- typedef ush Pos;
- #endif
- typedef unsigned IPos;
- #ifndef DYN_ALLOC
- uch window[2L*WSIZE];
-
- Pos prev[WSIZE];
-
- Pos head[HASH_SIZE];
-
- #else
- uch far * near window = NULL;
- Pos far * near prev = NULL;
- Pos far * near head;
- #endif
- ulg window_size;
- long block_start;
- local int sliding;
- local unsigned ins_h;
- #define H_SHIFT ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH)
- unsigned int near prev_length;
- unsigned near strstart;
- unsigned near match_start;
- local int eofile;
- local unsigned lookahead;
- unsigned near max_chain_length;
- local unsigned int max_lazy_match;
- #define max_insert_length max_lazy_match
- unsigned near good_match;
- #ifdef FULL_SEARCH
- # define nice_match MAX_MATCH
- #else
- int near nice_match;
- #endif
- typedef struct config {
- ush good_length;
- ush max_lazy;
- ush nice_length;
- ush max_chain;
- } config;
- local config configuration_table[10] = {
- {0, 0, 0, 0},
- {4, 4, 8, 4},
- {4, 5, 16, 8},
- {4, 6, 32, 32},
- {4, 4, 16, 16},
- {8, 16, 32, 32},
- {8, 16, 128, 128},
- {8, 32, 128, 256},
- {32, 128, 258, 1024},
- {32, 258, 258, 4096}};
- #define EQUAL 0
- local void fill_window OF((void));
- local uzoff_t deflate_fast OF((void));
- int longest_match OF((IPos cur_match));
- #if defined(ASMV) && !defined(RISCOS)
- void match_init OF((void));
- #endif
- #ifdef DEBUG
- local void check_match OF((IPos start, IPos match, int length));
- #endif
- #define UPDATE_HASH(h,c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK)
- #define INSERT_STRING(s, match_head) \
- (UPDATE_HASH(ins_h, window[(s) + (MIN_MATCH-1)]), \
- prev[(s) & WMASK] = match_head = head[ins_h], \
- head[ins_h] = (s))
- void lm_init (pack_level, flags)
- int pack_level;
- ush *flags;
- {
- register unsigned j;
- if (pack_level < 1 || pack_level > 9) error("bad pack level");
-
- sliding = 0;
- if (window_size == 0L) {
- sliding = 1;
- window_size = (ulg)2L*WSIZE;
- }
-
- #ifdef DYN_ALLOC
- if (window == NULL) {
- window = (uch far *) zcalloc(WSIZE, 2*sizeof(uch));
- if (window == NULL) ziperr(ZE_MEM, "window allocation");
- }
- if (prev == NULL) {
- prev = (Pos far *) zcalloc(WSIZE, sizeof(Pos));
- head = (Pos far *) zcalloc(HASH_SIZE, sizeof(Pos));
- if (prev == NULL || head == NULL) {
- ziperr(ZE_MEM, "hash table allocation");
- }
- }
- #endif
-
- head[HASH_SIZE-1] = NIL;
- memset((char*)head, NIL, (unsigned)(HASH_SIZE-1)*sizeof(*head));
-
- max_lazy_match = configuration_table[pack_level].max_lazy;
- good_match = configuration_table[pack_level].good_length;
- #ifndef FULL_SEARCH
- nice_match = configuration_table[pack_level].nice_length;
- #endif
- max_chain_length = configuration_table[pack_level].max_chain;
- if (pack_level <= 2) {
- *flags |= FAST;
- } else if (pack_level >= 8) {
- *flags |= SLOW;
- }
-
- strstart = 0;
- block_start = 0L;
- #if defined(ASMV) && !defined(RISCOS)
- match_init();
- #endif
- j = WSIZE;
- #ifndef MAXSEG_64K
- if (sizeof(int) > 2) j <<= 1;
- #endif
- lookahead = (*read_buf)((char*)window, j);
- if (lookahead == 0 || lookahead == (unsigned)EOF) {
- eofile = 1, lookahead = 0;
- return;
- }
- eofile = 0;
-
- if (lookahead < MIN_LOOKAHEAD) fill_window();
- ins_h = 0;
- for (j=0; j<MIN_MATCH-1; j++) UPDATE_HASH(ins_h, window[j]);
-
- }
- void lm_free()
- {
- #ifdef DYN_ALLOC
- if (window != NULL) {
- zcfree(window);
- window = NULL;
- }
- if (prev != NULL) {
- zcfree(prev);
- zcfree(head);
- prev = head = NULL;
- }
- #endif
- }
- #ifndef ASMV
- int longest_match(cur_match)
- IPos cur_match;
- {
- unsigned chain_length = max_chain_length;
- register uch far *scan = window + strstart;
- register uch far *match;
- register int len;
- int best_len = prev_length;
- IPos limit = strstart > (IPos)MAX_DIST ? strstart - (IPos)MAX_DIST : NIL;
-
- #if HASH_BITS < 8 || MAX_MATCH != 258
- error: Code too clever
- #endif
- #ifdef UNALIGNED_OK
-
- register uch far *strend = window + strstart + MAX_MATCH - 1;
- register ush scan_start = *(ush far *)scan;
- register ush scan_end = *(ush far *)(scan+best_len-1);
- #else
- register uch far *strend = window + strstart + MAX_MATCH;
- register uch scan_end1 = scan[best_len-1];
- register uch scan_end = scan[best_len];
- #endif
-
- if (prev_length >= good_match) {
- chain_length >>= 2;
- }
- Assert(strstart <= window_size-MIN_LOOKAHEAD, "insufficient lookahead");
- do {
- Assert(cur_match < strstart, "no future");
- match = window + cur_match;
-
- #if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
-
- if (*(ush far *)(match+best_len-1) != scan_end ||
- *(ush far *)match != scan_start) continue;
-
- scan++, match++;
- do {
- } while (*(ush far *)(scan+=2) == *(ush far *)(match+=2) &&
- *(ush far *)(scan+=2) == *(ush far *)(match+=2) &&
- *(ush far *)(scan+=2) == *(ush far *)(match+=2) &&
- *(ush far *)(scan+=2) == *(ush far *)(match+=2) &&
- scan < strend);
-
-
- Assert(scan <= window+(unsigned)(window_size-1), "wild scan");
- if (*scan == *match) scan++;
- len = (MAX_MATCH - 1) - (int)(strend-scan);
- scan = strend - (MAX_MATCH-1);
- #else
- if (match[best_len] != scan_end ||
- match[best_len-1] != scan_end1 ||
- *match != *scan ||
- *++match != scan[1]) continue;
-
- scan += 2, match++;
-
- do {
- } while (*++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- scan < strend);
- Assert(scan <= window+(unsigned)(window_size-1), "wild scan");
- len = MAX_MATCH - (int)(strend - scan);
- scan = strend - MAX_MATCH;
- #endif
- if (len > best_len) {
- match_start = cur_match;
- best_len = len;
- if (len >= nice_match) break;
- #ifdef UNALIGNED_OK
- scan_end = *(ush far *)(scan+best_len-1);
- #else
- scan_end1 = scan[best_len-1];
- scan_end = scan[best_len];
- #endif
- }
- } while ((cur_match = prev[cur_match & WMASK]) > limit
- && --chain_length != 0);
- return best_len;
- }
- #endif
- #ifdef DEBUG
- local void check_match(start, match, length)
- IPos start, match;
- int length;
- {
-
- if (memcmp((char*)window + match,
- (char*)window + start, length) != EQUAL) {
- fprintf(mesg,
- " start %d, match %d, length %d\n",
- start, match, length);
- error("invalid match");
- }
- if (verbose > 1) {
- fprintf(mesg,"\\[%d,%d]", start-match, length);
- #ifndef WINDLL
- do { putc(window[start++], mesg); } while (--length != 0);
- #else
- do { fprintf(stdout,"%c",window[start++]); } while (--length != 0);
- #endif
- }
- }
- #else
- # define check_match(start, match, length)
- #endif
- #define FLUSH_BLOCK(eof) \
- flush_block(block_start >= 0L ? (char*)&window[(unsigned)block_start] : \
- (char*)NULL, (ulg)strstart - (ulg)block_start, (eof))
- local void fill_window()
- {
- register unsigned n, m;
- unsigned more;
- do {
- more = (unsigned)(window_size - (ulg)lookahead - (ulg)strstart);
-
- if (more == (unsigned)EOF) {
-
- more--;
-
- } else if (strstart >= WSIZE+MAX_DIST && sliding) {
- #ifdef FORCE_METHOD
-
- if (level <= 2) FLUSH_BLOCK(0), block_start = strstart;
- #endif
-
- memcpy((char*)window, (char*)window+WSIZE, (unsigned)WSIZE);
- match_start -= WSIZE;
- strstart -= WSIZE;
- block_start -= (long) WSIZE;
- for (n = 0; n < HASH_SIZE; n++) {
- m = head[n];
- head[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL);
- }
- for (n = 0; n < WSIZE; n++) {
- m = prev[n];
- prev[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL);
-
- }
- more += WSIZE;
- if (dot_size > 0 && !display_globaldots) {
-
- if (noisy && dot_count == -1) {
- #ifndef WINDLL
- putc(' ', mesg);
- fflush(mesg);
- #else
- fprintf(stdout,"%c",' ');
- #endif
- dot_count++;
- }
- dot_count++;
- if (dot_size <= (dot_count + 1) * WSIZE) dot_count = 0;
- }
- if ((verbose || noisy) && dot_size && !dot_count) {
- #ifndef WINDLL
- putc('.', mesg);
- fflush(mesg);
- #else
- fprintf(stdout,"%c",'.');
- #endif
- mesg_line_started = 1;
- }
- }
- if (eofile) return;
-
- Assert(more >= 2, "more < 2");
- n = (*read_buf)((char*)window+strstart+lookahead, more);
- if (n == 0 || n == (unsigned)EOF) {
- eofile = 1;
- } else {
- lookahead += n;
- }
- } while (lookahead < MIN_LOOKAHEAD && !eofile);
- }
- local uzoff_t deflate_fast()
- {
- IPos hash_head = NIL;
- int flush;
- unsigned match_length = 0;
- prev_length = MIN_MATCH-1;
- while (lookahead != 0) {
-
- #ifndef DEFL_UNDETERM
- if (lookahead >= MIN_MATCH)
- #endif
- INSERT_STRING(strstart, hash_head);
-
- if (hash_head != NIL && strstart - hash_head <= MAX_DIST) {
-
- #ifndef HUFFMAN_ONLY
- # ifndef DEFL_UNDETERM
-
- if ((unsigned)nice_match > lookahead) nice_match = (int)lookahead;
- # endif
- match_length = longest_match (hash_head);
-
- if (match_length > lookahead) match_length = lookahead;
- #endif
- }
- if (match_length >= MIN_MATCH) {
- check_match(strstart, match_start, match_length);
- flush = ct_tally(strstart-match_start, match_length - MIN_MATCH);
- lookahead -= match_length;
-
- if (match_length <= max_insert_length
- #ifndef DEFL_UNDETERM
- && lookahead >= MIN_MATCH
- #endif
- ) {
- match_length--;
- do {
- strstart++;
- INSERT_STRING(strstart, hash_head);
-
- #ifdef DEFL_UNDETERM
-
- #endif
- } while (--match_length != 0);
- strstart++;
- } else {
- strstart += match_length;
- match_length = 0;
- ins_h = window[strstart];
- UPDATE_HASH(ins_h, window[strstart+1]);
- #if MIN_MATCH != 3
- Call UPDATE_HASH() MIN_MATCH-3 more times
- #endif
- }
- } else {
-
- Tracevv((stderr,"%c",window[strstart]));
- flush = ct_tally (0, window[strstart]);
- lookahead--;
- strstart++;
- }
- if (flush) FLUSH_BLOCK(0), block_start = strstart;
-
- if (lookahead < MIN_LOOKAHEAD) fill_window();
- }
- return FLUSH_BLOCK(1);
- }
- uzoff_t deflate()
- {
- IPos hash_head = NIL;
- IPos prev_match;
- int flush;
- int match_available = 0;
- register unsigned match_length = MIN_MATCH-1;
- #ifdef DEBUG
- extern uzoff_t isize;
- #endif
- if (level <= 3) return deflate_fast();
-
- while (lookahead != 0) {
-
- #ifndef DEFL_UNDETERM
- if (lookahead >= MIN_MATCH)
- #endif
- INSERT_STRING(strstart, hash_head);
-
- prev_length = match_length, prev_match = match_start;
- match_length = MIN_MATCH-1;
- if (hash_head != NIL && prev_length < max_lazy_match &&
- strstart - hash_head <= MAX_DIST) {
-
- #ifndef HUFFMAN_ONLY
- # ifndef DEFL_UNDETERM
-
- if ((unsigned)nice_match > lookahead) nice_match = (int)lookahead;
- # endif
- match_length = longest_match (hash_head);
-
- if (match_length > lookahead) match_length = lookahead;
- #endif
- #ifdef FILTERED
-
- if (match_length <= 5) {
- #else
-
- if (match_length == MIN_MATCH && strstart-match_start > TOO_FAR){
- #endif
-
- match_length = MIN_MATCH-1;
- }
- }
-
- if (prev_length >= MIN_MATCH && match_length <= prev_length) {
- #ifndef DEFL_UNDETERM
- unsigned max_insert = strstart + lookahead - MIN_MATCH;
- #endif
- check_match(strstart-1, prev_match, prev_length);
- flush = ct_tally(strstart-1-prev_match, prev_length - MIN_MATCH);
-
- lookahead -= prev_length-1;
- prev_length -= 2;
- #ifndef DEFL_UNDETERM
- do {
- if (++strstart <= max_insert) {
- INSERT_STRING(strstart, hash_head);
-
- }
- } while (--prev_length != 0);
- strstart++;
- #else
- do {
- strstart++;
- INSERT_STRING(strstart, hash_head);
-
- } while (--prev_length != 0);
- strstart++;
- #endif
- match_available = 0;
- match_length = MIN_MATCH-1;
- if (flush) FLUSH_BLOCK(0), block_start = strstart;
- } else if (match_available) {
-
- Tracevv((stderr,"%c",window[strstart-1]));
- if (ct_tally (0, window[strstart-1])) {
- FLUSH_BLOCK(0), block_start = strstart;
- }
- strstart++;
- lookahead--;
- } else {
-
- match_available = 1;
- strstart++;
- lookahead--;
- }
- Assert(strstart <= isize && lookahead <= isize, "a bit too far");
-
- if (lookahead < MIN_LOOKAHEAD) fill_window();
- }
- if (match_available) ct_tally (0, window[strstart-1]);
- return FLUSH_BLOCK(1);
- }
- #endif
|