00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 #include "deflate.h"
00053 
00054 const char deflate_copyright[] =
00055    " deflate 1.1.3 Copyright 1995-1998 Jean-loup Gailly ";
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 typedef enum {
00067     need_more,      
00068     block_done,     
00069     finish_started, 
00070     finish_done     
00071 } block_state;
00072 
00073 typedef block_state (*compress_func) OF((deflate_state *s, int flush));
00074 
00075 
00076 local void fill_window    OF((deflate_state *s));
00077 local block_state deflate_stored OF((deflate_state *s, int flush));
00078 local block_state deflate_fast   OF((deflate_state *s, int flush));
00079 local block_state deflate_slow   OF((deflate_state *s, int flush));
00080 local void lm_init        OF((deflate_state *s));
00081 local void putShortMSB    OF((deflate_state *s, uInt b));
00082 local void flush_pending  OF((z_streamp strm));
00083 local int read_buf        OF((z_streamp strm, Bytef *buf, unsigned size));
00084 #ifdef ASMV
00085       void match_init OF((void)); 
00086       uInt longest_match  OF((deflate_state *s, IPos cur_match));
00087 #else
00088 local uInt longest_match  OF((deflate_state *s, IPos cur_match));
00089 #endif
00090 
00091 #ifdef DEBUG
00092 local  void check_match OF((deflate_state *s, IPos start, IPos match,
00093                             int length));
00094 #endif
00095 
00096 
00097 
00098 
00099 
00100 #define NIL 0
00101 
00102 
00103 #ifndef TOO_FAR
00104 #  define TOO_FAR 4096
00105 #endif
00106 
00107 
00108 #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
00109 
00110 
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 typedef struct config_s {
00119    ush good_length; 
00120    ush max_lazy;    
00121    ush nice_length; 
00122    ush max_chain;
00123    compress_func func;
00124 } config;
00125 
00126 local const config configuration_table[10] = {
00127 
00128  {0,    0,  0,    0, deflate_stored},  
00129  {4,    4,  8,    4, deflate_fast}, 
00130  {4,    5, 16,    8, deflate_fast},
00131  {4,    6, 32,   32, deflate_fast},
00132 
00133  {4,    4, 16,   16, deflate_slow},  
00134  {8,   16, 32,   32, deflate_slow},
00135  {8,   16, 128, 128, deflate_slow},
00136  {8,   32, 128, 256, deflate_slow},
00137  {32, 128, 258, 1024, deflate_slow},
00138  {32, 258, 258, 4096, deflate_slow}}; 
00139 
00140 
00141 
00142 
00143 
00144 
00145 #define EQUAL 0
00146 
00147 
00148 struct static_tree_desc_s {int dummy;}; 
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 #define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
00157 
00158 
00159 
00160 
00161 
00162 
00163 
00164 
00165 
00166 
00167 
00168 
00169 #ifdef FASTEST
00170 #define INSERT_STRING(s, str, match_head) \
00171    (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
00172     match_head = s->head[s->ins_h], \
00173     s->head[s->ins_h] = (Pos)(str))
00174 #else
00175 #define INSERT_STRING(s, str, match_head) \
00176    (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
00177     s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \
00178     s->head[s->ins_h] = (Pos)(str))
00179 #endif
00180 
00181 
00182 
00183 
00184 
00185 #define CLEAR_HASH(s) \
00186     s->head[s->hash_size-1] = NIL; \
00187     zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
00188 
00189 
00190 int ZEXPORT deflateInit_(strm, level, version, stream_size)
00191     z_streamp strm;
00192     int level;
00193     const char *version;
00194     int stream_size;
00195 {
00196     return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
00197                          Z_DEFAULT_STRATEGY, version, stream_size);
00198     
00199 }
00200 
00201 
00202 int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
00203                   version, stream_size)
00204     z_streamp strm;
00205     int  level;
00206     int  method;
00207     int  windowBits;
00208     int  memLevel;
00209     int  strategy;
00210     const char *version;
00211     int stream_size;
00212 {
00213     deflate_state *s;
00214     int noheader = 0;
00215     static const char* my_version = ZLIB_VERSION;
00216 
00217     ushf *overlay;
00218     
00219 
00220 
00221 
00222     if (version == Z_NULL || version[0] != my_version[0] ||
00223         stream_size != sizeof(z_stream)) {
00224         return Z_VERSION_ERROR;
00225     }
00226     if (strm == Z_NULL) return Z_STREAM_ERROR;
00227 
00228     strm->msg = Z_NULL;
00229     if (strm->zalloc == Z_NULL) {
00230         strm->zalloc = zcalloc;
00231         strm->opaque = (voidpf)0;
00232     }
00233     if (strm->zfree == Z_NULL) strm->zfree = zcfree;
00234 
00235     if (level == Z_DEFAULT_COMPRESSION) level = 6;
00236 #ifdef FASTEST
00237     level = 1;
00238 #endif
00239 
00240     if (windowBits < 0) { 
00241         noheader = 1;
00242         windowBits = -windowBits;
00243     }
00244     if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
00245         windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
00246         strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
00247         return Z_STREAM_ERROR;
00248     }
00249     s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
00250     if (s == Z_NULL) return Z_MEM_ERROR;
00251     strm->state = (struct internal_state FAR *)s;
00252     s->strm = strm;
00253 
00254     s->noheader = noheader;
00255     s->w_bits = windowBits;
00256     s->w_size = 1 << s->w_bits;
00257     s->w_mask = s->w_size - 1;
00258 
00259     s->hash_bits = memLevel + 7;
00260     s->hash_size = 1 << s->hash_bits;
00261     s->hash_mask = s->hash_size - 1;
00262     s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
00263 
00264     s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
00265     s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
00266     s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
00267 
00268     s->lit_bufsize = 1 << (memLevel + 6); 
00269 
00270     overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
00271     s->pending_buf = (uchf *) overlay;
00272     s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
00273 
00274     if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
00275         s->pending_buf == Z_NULL) {
00276         strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
00277         deflateEnd (strm);
00278         return Z_MEM_ERROR;
00279     }
00280     s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
00281     s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
00282 
00283     s->level = level;
00284     s->strategy = strategy;
00285     s->method = (Byte)method;
00286 
00287     return deflateReset(strm);
00288 }
00289 
00290 
00291 int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
00292     z_streamp strm;
00293     const Bytef *dictionary;
00294     uInt  dictLength;
00295 {
00296     deflate_state *s;
00297     uInt length = dictLength;
00298     uInt n;
00299     IPos hash_head = 0;
00300 
00301     if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
00302         strm->state->status != INIT_STATE) return Z_STREAM_ERROR;
00303 
00304     s = strm->state;
00305     strm->adler = adler32(strm->adler, dictionary, dictLength);
00306 
00307     if (length < MIN_MATCH) return Z_OK;
00308     if (length > MAX_DIST(s)) {
00309         length = MAX_DIST(s);
00310 #ifndef USE_DICT_HEAD
00311         dictionary += dictLength - length; 
00312 #endif
00313     }
00314     zmemcpy(s->window, dictionary, length);
00315     s->strstart = length;
00316     s->block_start = (long)length;
00317 
00318     
00319 
00320 
00321 
00322     s->ins_h = s->window[0];
00323     UPDATE_HASH(s, s->ins_h, s->window[1]);
00324     for (n = 0; n <= length - MIN_MATCH; n++) {
00325         INSERT_STRING(s, n, hash_head);
00326     }
00327     if (hash_head) hash_head = 0;  
00328     return Z_OK;
00329 }
00330 
00331 
00332 int ZEXPORT deflateReset (strm)
00333     z_streamp strm;
00334 {
00335     deflate_state *s;
00336     
00337     if (strm == Z_NULL || strm->state == Z_NULL ||
00338         strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR;
00339 
00340     strm->total_in = strm->total_out = 0;
00341     strm->msg = Z_NULL; 
00342     strm->data_type = Z_UNKNOWN;
00343 
00344     s = (deflate_state *)strm->state;
00345     s->pending = 0;
00346     s->pending_out = s->pending_buf;
00347 
00348     if (s->noheader < 0) {
00349         s->noheader = 0; 
00350     }
00351     s->status = s->noheader ? BUSY_STATE : INIT_STATE;
00352     strm->adler = 1;
00353     s->last_flush = Z_NO_FLUSH;
00354 
00355     _tr_init(s);
00356     lm_init(s);
00357 
00358     return Z_OK;
00359 }
00360 
00361 
00362 int ZEXPORT deflateParams(strm, level, strategy)
00363     z_streamp strm;
00364     int level;
00365     int strategy;
00366 {
00367     deflate_state *s;
00368     compress_func func;
00369     int err = Z_OK;
00370 
00371     if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
00372     s = strm->state;
00373 
00374     if (level == Z_DEFAULT_COMPRESSION) {
00375         level = 6;
00376     }
00377     if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
00378         return Z_STREAM_ERROR;
00379     }
00380     func = configuration_table[s->level].func;
00381 
00382     if (func != configuration_table[level].func && strm->total_in != 0) {
00383         
00384         err = deflate(strm, Z_PARTIAL_FLUSH);
00385     }
00386     if (s->level != level) {
00387         s->level = level;
00388         s->max_lazy_match   = configuration_table[level].max_lazy;
00389         s->good_match       = configuration_table[level].good_length;
00390         s->nice_match       = configuration_table[level].nice_length;
00391         s->max_chain_length = configuration_table[level].max_chain;
00392     }
00393     s->strategy = strategy;
00394     return err;
00395 }
00396 
00397 
00398 
00399 
00400 
00401 
00402 local void putShortMSB (s, b)
00403     deflate_state *s;
00404     uInt b;
00405 {
00406     put_byte(s, (Byte)(b >> 8));
00407     put_byte(s, (Byte)(b & 0xff));
00408 }   
00409 
00410 
00411 
00412 
00413 
00414 
00415 
00416 local void flush_pending(strm)
00417     z_streamp strm;
00418 {
00419     unsigned len = strm->state->pending;
00420 
00421     if (len > strm->avail_out) len = strm->avail_out;
00422     if (len == 0) return;
00423 
00424     zmemcpy(strm->next_out, strm->state->pending_out, len);
00425     strm->next_out  += len;
00426     strm->state->pending_out  += len;
00427     strm->total_out += len;
00428     strm->avail_out  -= len;
00429     strm->state->pending -= len;
00430     if (strm->state->pending == 0) {
00431         strm->state->pending_out = strm->state->pending_buf;
00432     }
00433 }
00434 
00435 
00436 int ZEXPORT deflate (strm, flush)
00437     z_streamp strm;
00438     int flush;
00439 {
00440     int old_flush; 
00441     deflate_state *s;
00442 
00443     if (strm == Z_NULL || strm->state == Z_NULL ||
00444         flush > Z_FINISH || flush < 0) {
00445         return Z_STREAM_ERROR;
00446     }
00447     s = strm->state;
00448 
00449     if (strm->next_out == Z_NULL ||
00450         (strm->next_in == Z_NULL && strm->avail_in != 0) ||
00451         (s->status == FINISH_STATE && flush != Z_FINISH)) {
00452         ERR_RETURN(strm, Z_STREAM_ERROR);
00453     }
00454     if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
00455 
00456     s->strm = strm; 
00457     old_flush = s->last_flush;
00458     s->last_flush = flush;
00459 
00460     
00461     if (s->status == INIT_STATE) {
00462 
00463         uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
00464         uInt level_flags = (s->level-1) >> 1;
00465 
00466         if (level_flags > 3) level_flags = 3;
00467         header |= (level_flags << 6);
00468         if (s->strstart != 0) header |= PRESET_DICT;
00469         header += 31 - (header % 31);
00470 
00471         s->status = BUSY_STATE;
00472         putShortMSB(s, header);
00473 
00474         
00475         if (s->strstart != 0) {
00476             putShortMSB(s, (uInt)(strm->adler >> 16));
00477             putShortMSB(s, (uInt)(strm->adler & 0xffff));
00478         }
00479         strm->adler = 1L;
00480     }
00481 
00482     
00483     if (s->pending != 0) {
00484         flush_pending(strm);
00485         if (strm->avail_out == 0) {
00486             
00487 
00488 
00489 
00490 
00491 
00492             s->last_flush = -1;
00493             return Z_OK;
00494         }
00495 
00496     
00497 
00498 
00499 
00500     } else if (strm->avail_in == 0 && flush <= old_flush &&
00501                flush != Z_FINISH) {
00502         ERR_RETURN(strm, Z_BUF_ERROR);
00503     }
00504 
00505     
00506     if (s->status == FINISH_STATE && strm->avail_in != 0) {
00507         ERR_RETURN(strm, Z_BUF_ERROR);
00508     }
00509 
00510     
00511 
00512     if (strm->avail_in != 0 || s->lookahead != 0 ||
00513         (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
00514         block_state bstate;
00515 
00516         bstate = (*(configuration_table[s->level].func))(s, flush);
00517 
00518         if (bstate == finish_started || bstate == finish_done) {
00519             s->status = FINISH_STATE;
00520         }
00521         if (bstate == need_more || bstate == finish_started) {
00522             if (strm->avail_out == 0) {
00523                 s->last_flush = -1; 
00524             }
00525             return Z_OK;
00526             
00527 
00528 
00529 
00530 
00531 
00532 
00533         }
00534         if (bstate == block_done) {
00535             if (flush == Z_PARTIAL_FLUSH) {
00536                 _tr_align(s);
00537             } else { 
00538                 _tr_stored_block(s, (char*)0, 0L, 0);
00539                 
00540 
00541 
00542                 if (flush == Z_FULL_FLUSH) {
00543                     CLEAR_HASH(s);             
00544                 }
00545             }
00546             flush_pending(strm);
00547             if (strm->avail_out == 0) {
00548               s->last_flush = -1; 
00549               return Z_OK;
00550             }
00551         }
00552     }
00553     Assert(strm->avail_out > 0, "bug2");
00554 
00555     if (flush != Z_FINISH) return Z_OK;
00556     if (s->noheader) return Z_STREAM_END;
00557 
00558     
00559     putShortMSB(s, (uInt)(strm->adler >> 16));
00560     putShortMSB(s, (uInt)(strm->adler & 0xffff));
00561     flush_pending(strm);
00562     
00563 
00564 
00565     s->noheader = -1; 
00566     return s->pending != 0 ? Z_OK : Z_STREAM_END;
00567 }
00568 
00569 
00570 int ZEXPORT deflateEnd (strm)
00571     z_streamp strm;
00572 {
00573     int status;
00574 
00575     if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
00576 
00577     status = strm->state->status;
00578     if (status != INIT_STATE && status != BUSY_STATE &&
00579         status != FINISH_STATE) {
00580       return Z_STREAM_ERROR;
00581     }
00582 
00583     
00584     TRY_FREE(strm, strm->state->pending_buf);
00585     TRY_FREE(strm, strm->state->head);
00586     TRY_FREE(strm, strm->state->prev);
00587     TRY_FREE(strm, strm->state->window);
00588 
00589     ZFREE(strm, strm->state);
00590     strm->state = Z_NULL;
00591 
00592     return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
00593 }
00594 
00595 
00596 
00597 
00598 
00599 
00600 int ZEXPORT deflateCopy (dest, source)
00601     z_streamp dest;
00602     z_streamp source;
00603 {
00604 #ifdef MAXSEG_64K
00605     return Z_STREAM_ERROR;
00606 #else
00607     deflate_state *ds;
00608     deflate_state *ss;
00609     ushf *overlay;
00610 
00611 
00612     if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
00613         return Z_STREAM_ERROR;
00614     }
00615 
00616     ss = source->state;
00617 
00618     *dest = *source;
00619 
00620     ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
00621     if (ds == Z_NULL) return Z_MEM_ERROR;
00622     dest->state = (struct internal_state FAR *) ds;
00623     *ds = *ss;
00624     ds->strm = dest;
00625 
00626     ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
00627     ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));
00628     ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));
00629     overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
00630     ds->pending_buf = (uchf *) overlay;
00631 
00632     if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
00633         ds->pending_buf == Z_NULL) {
00634         deflateEnd (dest);
00635         return Z_MEM_ERROR;
00636     }
00637     
00638     zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
00639     zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
00640     zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
00641     zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
00642 
00643     ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
00644     ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
00645     ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
00646 
00647     ds->l_desc.dyn_tree = ds->dyn_ltree;
00648     ds->d_desc.dyn_tree = ds->dyn_dtree;
00649     ds->bl_desc.dyn_tree = ds->bl_tree;
00650 
00651     return Z_OK;
00652 #endif
00653 }
00654 
00655 
00656 
00657 
00658 
00659 
00660 
00661 
00662 local int read_buf(strm, buf, size)
00663     z_streamp strm;
00664     Bytef *buf;
00665     unsigned size;
00666 {
00667     unsigned len = strm->avail_in;
00668 
00669     if (len > size) len = size;
00670     if (len == 0) return 0;
00671 
00672     strm->avail_in  -= len;
00673 
00674     if (!strm->state->noheader) {
00675         strm->adler = adler32(strm->adler, strm->next_in, len);
00676     }
00677     zmemcpy(buf, strm->next_in, len);
00678     strm->next_in  += len;
00679     strm->total_in += len;
00680 
00681     return (int)len;
00682 }
00683 
00684 
00685 
00686 
00687 local void lm_init (s)
00688     deflate_state *s;
00689 {
00690     s->window_size = (ulg)2L*s->w_size;
00691 
00692     CLEAR_HASH(s);
00693 
00694     
00695 
00696     s->max_lazy_match   = configuration_table[s->level].max_lazy;
00697     s->good_match       = configuration_table[s->level].good_length;
00698     s->nice_match       = configuration_table[s->level].nice_length;
00699     s->max_chain_length = configuration_table[s->level].max_chain;
00700 
00701     s->strstart = 0;
00702     s->block_start = 0L;
00703     s->lookahead = 0;
00704     s->match_length = s->prev_length = MIN_MATCH-1;
00705     s->match_available = 0;
00706     s->ins_h = 0;
00707 #ifdef ASMV
00708     match_init(); 
00709 #endif
00710 }
00711 
00712 
00713 
00714 
00715 
00716 
00717 
00718 
00719 
00720 
00721 #ifndef ASMV
00722 
00723 
00724 
00725 #ifndef FASTEST
00726 local uInt longest_match(s, cur_match)
00727     deflate_state *s;
00728     IPos cur_match;                             
00729 {
00730     unsigned chain_length = s->max_chain_length;
00731     register Bytef *scan = s->window + s->strstart; 
00732     register Bytef *match;                       
00733     register int len;                           
00734     int best_len = s->prev_length;              
00735     int nice_match = s->nice_match;             
00736     IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
00737         s->strstart - (IPos)MAX_DIST(s) : NIL;
00738     
00739 
00740 
00741     Posf *prev = s->prev;
00742     uInt wmask = s->w_mask;
00743 
00744 #ifdef UNALIGNED_OK
00745     
00746 
00747 
00748     register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
00749     register ush scan_start = *(ushf*)scan;
00750     register ush scan_end   = *(ushf*)(scan+best_len-1);
00751 #else
00752     register Bytef *strend = s->window + s->strstart + MAX_MATCH;
00753     register Byte scan_end1  = scan[best_len-1];
00754     register Byte scan_end   = scan[best_len];
00755 #endif
00756 
00757     
00758 
00759 
00760     Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
00761 
00762     
00763     if (s->prev_length >= s->good_match) {
00764         chain_length >>= 2;
00765     }
00766     
00767 
00768 
00769     if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
00770 
00771     Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
00772 
00773     do {
00774         Assert(cur_match < s->strstart, "no future");
00775         match = s->window + cur_match;
00776 
00777         
00778 
00779 
00780 #if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
00781         
00782 
00783 
00784         if (*(ushf*)(match+best_len-1) != scan_end ||
00785             *(ushf*)match != scan_start) continue;
00786 
00787         
00788 
00789 
00790 
00791 
00792 
00793 
00794 
00795 
00796         Assert(scan[2] == match[2], "scan[2]?");
00797         scan++, match++;
00798         do {
00799         } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
00800                  *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
00801                  *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
00802                  *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
00803                  scan < strend);
00804         
00805 
00806         
00807         Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
00808         if (*scan == *match) scan++;
00809 
00810         len = (MAX_MATCH - 1) - (int)(strend-scan);
00811         scan = strend - (MAX_MATCH-1);
00812 
00813 #else 
00814 
00815         if (match[best_len]   != scan_end  ||
00816             match[best_len-1] != scan_end1 ||
00817             *match            != *scan     ||
00818             *++match          != scan[1])      continue;
00819 
00820         
00821 
00822 
00823 
00824 
00825 
00826         scan += 2, match++;
00827         Assert(*scan == *match, "match[2]?");
00828 
00829         
00830 
00831 
00832         do {
00833         } while (*++scan == *++match && *++scan == *++match &&
00834                  *++scan == *++match && *++scan == *++match &&
00835                  *++scan == *++match && *++scan == *++match &&
00836                  *++scan == *++match && *++scan == *++match &&
00837                  scan < strend);
00838 
00839         Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
00840 
00841         len = MAX_MATCH - (int)(strend - scan);
00842         scan = strend - MAX_MATCH;
00843 
00844 #endif 
00845 
00846         if (len > best_len) {
00847             s->match_start = cur_match;
00848             best_len = len;
00849             if (len >= nice_match) break;
00850 #ifdef UNALIGNED_OK
00851             scan_end = *(ushf*)(scan+best_len-1);
00852 #else
00853             scan_end1  = scan[best_len-1];
00854             scan_end   = scan[best_len];
00855 #endif
00856         }
00857     } while ((cur_match = prev[cur_match & wmask]) > limit
00858              && --chain_length != 0);
00859 
00860     if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
00861     return s->lookahead;
00862 }
00863 
00864 #else 
00865 
00866 
00867 
00868 local uInt longest_match(s, cur_match)
00869     deflate_state *s;
00870     IPos cur_match;                             
00871 {
00872     register Bytef *scan = s->window + s->strstart; 
00873     register Bytef *match;                       
00874     register int len;                           
00875     register Bytef *strend = s->window + s->strstart + MAX_MATCH;
00876 
00877     
00878 
00879 
00880     Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
00881 
00882     Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
00883 
00884     Assert(cur_match < s->strstart, "no future");
00885 
00886     match = s->window + cur_match;
00887 
00888     
00889 
00890     if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
00891 
00892     
00893 
00894 
00895 
00896 
00897 
00898     scan += 2, match += 2;
00899     Assert(*scan == *match, "match[2]?");
00900 
00901     
00902 
00903 
00904     do {
00905     } while (*++scan == *++match && *++scan == *++match &&
00906              *++scan == *++match && *++scan == *++match &&
00907              *++scan == *++match && *++scan == *++match &&
00908              *++scan == *++match && *++scan == *++match &&
00909              scan < strend);
00910 
00911     Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
00912 
00913     len = MAX_MATCH - (int)(strend - scan);
00914 
00915     if (len < MIN_MATCH) return MIN_MATCH - 1;
00916 
00917     s->match_start = cur_match;
00918     return len <= s->lookahead ? len : s->lookahead;
00919 }
00920 #endif 
00921 #endif 
00922 
00923 #ifdef DEBUG
00924 
00925 
00926 
00927 local void check_match(s, start, match, length)
00928     deflate_state *s;
00929     IPos start, match;
00930     int length;
00931 {
00932     
00933     if (zmemcmp(s->window + match,
00934                 s->window + start, length) != EQUAL) {
00935         fprintf(stderr, " start %u, match %u, length %d\n",
00936                 start, match, length);
00937         do {
00938             fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
00939         } while (--length != 0);
00940         z_error("invalid match");
00941     }
00942     if (z_verbose > 1) {
00943         fprintf(stderr,"\\[%d,%d]", start-match, length);
00944         do { putc(s->window[start++], stderr); } while (--length != 0);
00945     }
00946 }
00947 #else
00948 #  define check_match(s, start, match, length)
00949 #endif
00950 
00951 
00952 
00953 
00954 
00955 
00956 
00957 
00958 
00959 
00960 
00961 local void fill_window(s)
00962     deflate_state *s;
00963 {
00964     register unsigned n, m;
00965     register Posf *p;
00966     unsigned more;    
00967     uInt wsize = s->w_size;
00968 
00969     do {
00970         more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
00971 
00972         
00973         if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
00974             more = wsize;
00975 
00976         } else if (more == (unsigned)(-1)) {
00977             
00978 
00979 
00980             more--;
00981 
00982         
00983 
00984 
00985         } else if (s->strstart >= wsize+MAX_DIST(s)) {
00986 
00987             zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
00988             s->match_start -= wsize;
00989             s->strstart    -= wsize; 
00990             s->block_start -= (long) wsize;
00991 
00992             
00993 
00994 
00995 
00996 
00997 
00998             n = s->hash_size;
00999             p = &s->head[n];
01000             do {
01001                 m = *--p;
01002                 *p = (Pos)(m >= wsize ? m-wsize : NIL);
01003             } while (--n);
01004 
01005             n = wsize;
01006 #ifndef FASTEST
01007             p = &s->prev[n];
01008             do {
01009                 m = *--p;
01010                 *p = (Pos)(m >= wsize ? m-wsize : NIL);
01011                 
01012 
01013 
01014             } while (--n);
01015 #endif
01016             more += wsize;
01017         }
01018         if (s->strm->avail_in == 0) return;
01019 
01020         
01021 
01022 
01023 
01024 
01025 
01026 
01027 
01028 
01029 
01030 
01031         Assert(more >= 2, "more < 2");
01032 
01033         n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
01034         s->lookahead += n;
01035 
01036         
01037         if (s->lookahead >= MIN_MATCH) {
01038             s->ins_h = s->window[s->strstart];
01039             UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
01040 #if MIN_MATCH != 3
01041             Call UPDATE_HASH() MIN_MATCH-3 more times
01042 #endif
01043         }
01044         
01045 
01046 
01047 
01048     } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
01049 }
01050 
01051 
01052 
01053 
01054 
01055 #define FLUSH_BLOCK_ONLY(s, eof) { \
01056    _tr_flush_block(s, (s->block_start >= 0L ? \
01057                    (charf *)&s->window[(unsigned)s->block_start] : \
01058                    (charf *)Z_NULL), \
01059                 (ulg)((long)s->strstart - s->block_start), \
01060                 (eof)); \
01061    s->block_start = s->strstart; \
01062    flush_pending(s->strm); \
01063    Tracev((stderr,"[FLUSH]")); \
01064 }
01065 
01066 
01067 #define FLUSH_BLOCK(s, eof) { \
01068    FLUSH_BLOCK_ONLY(s, eof); \
01069    if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
01070 }
01071 
01072 
01073 
01074 
01075 
01076 
01077 
01078 
01079 
01080 
01081 local block_state deflate_stored(s, flush)
01082     deflate_state *s;
01083     int flush;
01084 {
01085     
01086 
01087 
01088     ulg max_block_size = 0xffff;
01089     ulg max_start;
01090 
01091     if (max_block_size > s->pending_buf_size - 5) {
01092         max_block_size = s->pending_buf_size - 5;
01093     }
01094 
01095     
01096     for (;;) {
01097         
01098         if (s->lookahead <= 1) {
01099 
01100             Assert(s->strstart < s->w_size+MAX_DIST(s) ||
01101                    s->block_start >= (long)s->w_size, "slide too late");
01102 
01103             fill_window(s);
01104             if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
01105 
01106             if (s->lookahead == 0) break; 
01107         }
01108         Assert(s->block_start >= 0L, "block gone");
01109 
01110         s->strstart += s->lookahead;
01111         s->lookahead = 0;
01112 
01113         
01114         max_start = s->block_start + max_block_size;
01115         if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
01116             
01117             s->lookahead = (uInt)(s->strstart - max_start);
01118             s->strstart = (uInt)max_start;
01119             FLUSH_BLOCK(s, 0);
01120         }
01121         
01122 
01123 
01124         if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
01125             FLUSH_BLOCK(s, 0);
01126         }
01127     }
01128     FLUSH_BLOCK(s, flush == Z_FINISH);
01129     return flush == Z_FINISH ? finish_done : block_done;
01130 }
01131 
01132 
01133 
01134 
01135 
01136 
01137 
01138 
01139 local block_state deflate_fast(s, flush)
01140     deflate_state *s;
01141     int flush;
01142 {
01143     IPos hash_head = NIL; 
01144     int bflush;           
01145 
01146     for (;;) {
01147         
01148 
01149 
01150 
01151 
01152         if (s->lookahead < MIN_LOOKAHEAD) {
01153             fill_window(s);
01154             if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
01155                 return need_more;
01156             }
01157             if (s->lookahead == 0) break; 
01158         }
01159 
01160         
01161 
01162 
01163         if (s->lookahead >= MIN_MATCH) {
01164             INSERT_STRING(s, s->strstart, hash_head);
01165         }
01166 
01167         
01168 
01169 
01170         if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
01171             
01172 
01173 
01174 
01175             if (s->strategy != Z_HUFFMAN_ONLY) {
01176                 s->match_length = longest_match (s, hash_head);
01177             }
01178             
01179         }
01180         if (s->match_length >= MIN_MATCH) {
01181             check_match(s, s->strstart, s->match_start, s->match_length);
01182 
01183             _tr_tally_dist(s, s->strstart - s->match_start,
01184                            s->match_length - MIN_MATCH, bflush);
01185 
01186             s->lookahead -= s->match_length;
01187 
01188             
01189 
01190 
01191 #ifndef FASTEST
01192             if (s->match_length <= s->max_insert_length &&
01193                 s->lookahead >= MIN_MATCH) {
01194                 s->match_length--; 
01195                 do {
01196                     s->strstart++;
01197                     INSERT_STRING(s, s->strstart, hash_head);
01198                     
01199 
01200 
01201                 } while (--s->match_length != 0);
01202                 s->strstart++; 
01203             } else
01204 #endif
01205             {
01206                 s->strstart += s->match_length;
01207                 s->match_length = 0;
01208                 s->ins_h = s->window[s->strstart];
01209                 UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
01210 #if MIN_MATCH != 3
01211                 Call UPDATE_HASH() MIN_MATCH-3 more times
01212 #endif
01213                 
01214 
01215 
01216             }
01217         } else {
01218             
01219             Tracevv((stderr,"%c", s->window[s->strstart]));
01220             _tr_tally_lit (s, s->window[s->strstart], bflush);
01221             s->lookahead--;
01222             s->strstart++; 
01223         }
01224         if (bflush) FLUSH_BLOCK(s, 0);
01225     }
01226     FLUSH_BLOCK(s, flush == Z_FINISH);
01227     return flush == Z_FINISH ? finish_done : block_done;
01228 }
01229 
01230 
01231 
01232 
01233 
01234 
01235 local block_state deflate_slow(s, flush)
01236     deflate_state *s;
01237     int flush;
01238 {
01239     IPos hash_head = NIL;    
01240     int bflush;              
01241 
01242     
01243     for (;;) {
01244         
01245 
01246 
01247 
01248 
01249         if (s->lookahead < MIN_LOOKAHEAD) {
01250             fill_window(s);
01251             if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
01252                 return need_more;
01253             }
01254             if (s->lookahead == 0) break; 
01255         }
01256 
01257         
01258 
01259 
01260         if (s->lookahead >= MIN_MATCH) {
01261             INSERT_STRING(s, s->strstart, hash_head);
01262         }
01263 
01264         
01265 
01266         s->prev_length = s->match_length, s->prev_match = s->match_start;
01267         s->match_length = MIN_MATCH-1;
01268 
01269         if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
01270             s->strstart - hash_head <= MAX_DIST(s)) {
01271             
01272 
01273 
01274 
01275             if (s->strategy != Z_HUFFMAN_ONLY) {
01276                 s->match_length = longest_match (s, hash_head);
01277             }
01278             
01279 
01280             if (s->match_length <= 5 && (s->strategy == Z_FILTERED ||
01281                  (s->match_length == MIN_MATCH &&
01282                   s->strstart - s->match_start > TOO_FAR))) {
01283 
01284                 
01285 
01286 
01287                 s->match_length = MIN_MATCH-1;
01288             }
01289         }
01290         
01291 
01292 
01293         if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
01294             uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
01295             
01296 
01297             check_match(s, s->strstart-1, s->prev_match, s->prev_length);
01298 
01299             _tr_tally_dist(s, s->strstart -1 - s->prev_match,
01300                            s->prev_length - MIN_MATCH, bflush);
01301 
01302             
01303 
01304 
01305 
01306 
01307             s->lookahead -= s->prev_length-1;
01308             s->prev_length -= 2;
01309             do {
01310                 if (++s->strstart <= max_insert) {
01311                     INSERT_STRING(s, s->strstart, hash_head);
01312                 }
01313             } while (--s->prev_length != 0);
01314             s->match_available = 0;
01315             s->match_length = MIN_MATCH-1;
01316             s->strstart++;
01317 
01318             if (bflush) FLUSH_BLOCK(s, 0);
01319 
01320         } else if (s->match_available) {
01321             
01322 
01323 
01324 
01325             Tracevv((stderr,"%c", s->window[s->strstart-1]));
01326             _tr_tally_lit(s, s->window[s->strstart-1], bflush);
01327             if (bflush) {
01328                 FLUSH_BLOCK_ONLY(s, 0);
01329             }
01330             s->strstart++;
01331             s->lookahead--;
01332             if (s->strm->avail_out == 0) return need_more;
01333         } else {
01334             
01335 
01336 
01337             s->match_available = 1;
01338             s->strstart++;
01339             s->lookahead--;
01340         }
01341     }
01342     Assert (flush != Z_NO_FLUSH, "no flush?");
01343     if (s->match_available) {
01344         Tracevv((stderr,"%c", s->window[s->strstart-1]));
01345         _tr_tally_lit(s, s->window[s->strstart-1], bflush);
01346         s->match_available = 0;
01347     }
01348     FLUSH_BLOCK(s, flush == Z_FINISH);
01349     return flush == Z_FINISH ? finish_done : block_done;
01350 }