0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 #include <linux/module.h>
0052 #include <linux/zutil.h>
0053 #include "defutil.h"
0054
0055
0056 #ifdef CONFIG_ZLIB_DFLTCC
0057 # include "../zlib_dfltcc/dfltcc.h"
0058 #else
0059 #define DEFLATE_RESET_HOOK(strm) do {} while (0)
0060 #define DEFLATE_HOOK(strm, flush, bstate) 0
0061 #define DEFLATE_NEED_CHECKSUM(strm) 1
0062 #define DEFLATE_DFLTCC_ENABLED() 0
0063 #endif
0064
0065
0066
0067
0068
0069 typedef block_state (*compress_func) (deflate_state *s, int flush);
0070
0071
0072 static void fill_window (deflate_state *s);
0073 static block_state deflate_stored (deflate_state *s, int flush);
0074 static block_state deflate_fast (deflate_state *s, int flush);
0075 static block_state deflate_slow (deflate_state *s, int flush);
0076 static void lm_init (deflate_state *s);
0077 static void putShortMSB (deflate_state *s, uInt b);
0078 static int read_buf (z_streamp strm, Byte *buf, unsigned size);
0079 static uInt longest_match (deflate_state *s, IPos cur_match);
0080
0081 #ifdef DEBUG_ZLIB
0082 static void check_match (deflate_state *s, IPos start, IPos match,
0083 int length);
0084 #endif
0085
0086
0087
0088
0089
0090 #define NIL 0
0091
0092
0093 #ifndef TOO_FAR
0094 # define TOO_FAR 4096
0095 #endif
0096
0097
0098 #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
0099
0100
0101
0102
0103
0104 typedef struct deflate_workspace {
0105
0106 deflate_state deflate_memory;
0107 #ifdef CONFIG_ZLIB_DFLTCC
0108
0109 struct dfltcc_state dfltcc_memory;
0110 #endif
0111 Byte *window_memory;
0112 Pos *prev_memory;
0113 Pos *head_memory;
0114 char *overlay_memory;
0115 } deflate_workspace;
0116
0117 #ifdef CONFIG_ZLIB_DFLTCC
0118
0119 static_assert(offsetof(struct deflate_workspace, dfltcc_memory) % 8 == 0);
0120 #endif
0121
0122
0123
0124
0125
0126
0127 typedef struct config_s {
0128 ush good_length;
0129 ush max_lazy;
0130 ush nice_length;
0131 ush max_chain;
0132 compress_func func;
0133 } config;
0134
0135 static const config configuration_table[10] = {
0136
0137 {0, 0, 0, 0, deflate_stored},
0138 {4, 4, 8, 4, deflate_fast},
0139 {4, 5, 16, 8, deflate_fast},
0140 {4, 6, 32, 32, deflate_fast},
0141
0142 {4, 4, 16, 16, deflate_slow},
0143 {8, 16, 32, 32, deflate_slow},
0144 {8, 16, 128, 128, deflate_slow},
0145 {8, 32, 128, 256, deflate_slow},
0146 {32, 128, 258, 1024, deflate_slow},
0147 {32, 258, 258, 4096, deflate_slow}};
0148
0149
0150
0151
0152
0153
0154 #define EQUAL 0
0155
0156
0157
0158
0159
0160
0161
0162
0163 #define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174 #define INSERT_STRING(s, str, match_head) \
0175 (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
0176 s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \
0177 s->head[s->ins_h] = (Pos)(str))
0178
0179
0180
0181
0182
0183 #define CLEAR_HASH(s) \
0184 s->head[s->hash_size-1] = NIL; \
0185 memset((char *)s->head, 0, (unsigned)(s->hash_size-1)*sizeof(*s->head));
0186
0187
0188 int zlib_deflateInit2(
0189 z_streamp strm,
0190 int level,
0191 int method,
0192 int windowBits,
0193 int memLevel,
0194 int strategy
0195 )
0196 {
0197 deflate_state *s;
0198 int noheader = 0;
0199 deflate_workspace *mem;
0200 char *next;
0201
0202 ush *overlay;
0203
0204
0205
0206
0207 if (strm == NULL) return Z_STREAM_ERROR;
0208
0209 strm->msg = NULL;
0210
0211 if (level == Z_DEFAULT_COMPRESSION) level = 6;
0212
0213 mem = (deflate_workspace *) strm->workspace;
0214
0215 if (windowBits < 0) {
0216 noheader = 1;
0217 windowBits = -windowBits;
0218 }
0219 if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
0220 windowBits < 9 || windowBits > 15 || level < 0 || level > 9 ||
0221 strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
0222 return Z_STREAM_ERROR;
0223 }
0224
0225
0226
0227
0228
0229 next = (char *) mem;
0230 next += sizeof(*mem);
0231 #ifdef CONFIG_ZLIB_DFLTCC
0232
0233
0234
0235
0236 mem->window_memory = (Byte *) PTR_ALIGN(next, PAGE_SIZE);
0237 #else
0238 mem->window_memory = (Byte *) next;
0239 #endif
0240 next += zlib_deflate_window_memsize(windowBits);
0241 mem->prev_memory = (Pos *) next;
0242 next += zlib_deflate_prev_memsize(windowBits);
0243 mem->head_memory = (Pos *) next;
0244 next += zlib_deflate_head_memsize(memLevel);
0245 mem->overlay_memory = next;
0246
0247 s = (deflate_state *) &(mem->deflate_memory);
0248 strm->state = (struct internal_state *)s;
0249 s->strm = strm;
0250
0251 s->noheader = noheader;
0252 s->w_bits = windowBits;
0253 s->w_size = 1 << s->w_bits;
0254 s->w_mask = s->w_size - 1;
0255
0256 s->hash_bits = memLevel + 7;
0257 s->hash_size = 1 << s->hash_bits;
0258 s->hash_mask = s->hash_size - 1;
0259 s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
0260
0261 s->window = (Byte *) mem->window_memory;
0262 s->prev = (Pos *) mem->prev_memory;
0263 s->head = (Pos *) mem->head_memory;
0264
0265 s->lit_bufsize = 1 << (memLevel + 6);
0266
0267 overlay = (ush *) mem->overlay_memory;
0268 s->pending_buf = (uch *) overlay;
0269 s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
0270
0271 s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
0272 s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
0273
0274 s->level = level;
0275 s->strategy = strategy;
0276 s->method = (Byte)method;
0277
0278 return zlib_deflateReset(strm);
0279 }
0280
0281
0282 int zlib_deflateReset(
0283 z_streamp strm
0284 )
0285 {
0286 deflate_state *s;
0287
0288 if (strm == NULL || strm->state == NULL)
0289 return Z_STREAM_ERROR;
0290
0291 strm->total_in = strm->total_out = 0;
0292 strm->msg = NULL;
0293 strm->data_type = Z_UNKNOWN;
0294
0295 s = (deflate_state *)strm->state;
0296 s->pending = 0;
0297 s->pending_out = s->pending_buf;
0298
0299 if (s->noheader < 0) {
0300 s->noheader = 0;
0301 }
0302 s->status = s->noheader ? BUSY_STATE : INIT_STATE;
0303 strm->adler = 1;
0304 s->last_flush = Z_NO_FLUSH;
0305
0306 zlib_tr_init(s);
0307 lm_init(s);
0308
0309 DEFLATE_RESET_HOOK(strm);
0310
0311 return Z_OK;
0312 }
0313
0314
0315
0316
0317
0318
0319 static void putShortMSB(
0320 deflate_state *s,
0321 uInt b
0322 )
0323 {
0324 put_byte(s, (Byte)(b >> 8));
0325 put_byte(s, (Byte)(b & 0xff));
0326 }
0327
0328
0329 int zlib_deflate(
0330 z_streamp strm,
0331 int flush
0332 )
0333 {
0334 int old_flush;
0335 deflate_state *s;
0336
0337 if (strm == NULL || strm->state == NULL ||
0338 flush > Z_FINISH || flush < 0) {
0339 return Z_STREAM_ERROR;
0340 }
0341 s = (deflate_state *) strm->state;
0342
0343 if ((strm->next_in == NULL && strm->avail_in != 0) ||
0344 (s->status == FINISH_STATE && flush != Z_FINISH)) {
0345 return Z_STREAM_ERROR;
0346 }
0347 if (strm->avail_out == 0) return Z_BUF_ERROR;
0348
0349 s->strm = strm;
0350 old_flush = s->last_flush;
0351 s->last_flush = flush;
0352
0353
0354 if (s->status == INIT_STATE) {
0355
0356 uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
0357 uInt level_flags = (s->level-1) >> 1;
0358
0359 if (level_flags > 3) level_flags = 3;
0360 header |= (level_flags << 6);
0361 if (s->strstart != 0) header |= PRESET_DICT;
0362 header += 31 - (header % 31);
0363
0364 s->status = BUSY_STATE;
0365 putShortMSB(s, header);
0366
0367
0368 if (s->strstart != 0) {
0369 putShortMSB(s, (uInt)(strm->adler >> 16));
0370 putShortMSB(s, (uInt)(strm->adler & 0xffff));
0371 }
0372 strm->adler = 1L;
0373 }
0374
0375
0376 if (s->pending != 0) {
0377 flush_pending(strm);
0378 if (strm->avail_out == 0) {
0379
0380
0381
0382
0383
0384
0385 s->last_flush = -1;
0386 return Z_OK;
0387 }
0388
0389
0390
0391
0392
0393 } else if (strm->avail_in == 0 && flush <= old_flush &&
0394 flush != Z_FINISH) {
0395 return Z_BUF_ERROR;
0396 }
0397
0398
0399 if (s->status == FINISH_STATE && strm->avail_in != 0) {
0400 return Z_BUF_ERROR;
0401 }
0402
0403
0404
0405 if (strm->avail_in != 0 || s->lookahead != 0 ||
0406 (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
0407 block_state bstate;
0408
0409 bstate = DEFLATE_HOOK(strm, flush, &bstate) ? bstate :
0410 (*(configuration_table[s->level].func))(s, flush);
0411
0412 if (bstate == finish_started || bstate == finish_done) {
0413 s->status = FINISH_STATE;
0414 }
0415 if (bstate == need_more || bstate == finish_started) {
0416 if (strm->avail_out == 0) {
0417 s->last_flush = -1;
0418 }
0419 return Z_OK;
0420
0421
0422
0423
0424
0425
0426
0427 }
0428 if (bstate == block_done) {
0429 if (flush == Z_PARTIAL_FLUSH) {
0430 zlib_tr_align(s);
0431 } else if (flush == Z_PACKET_FLUSH) {
0432
0433
0434 zlib_tr_stored_type_only(s);
0435 } else {
0436 zlib_tr_stored_block(s, (char*)0, 0L, 0);
0437
0438
0439
0440 if (flush == Z_FULL_FLUSH) {
0441 CLEAR_HASH(s);
0442 }
0443 }
0444 flush_pending(strm);
0445 if (strm->avail_out == 0) {
0446 s->last_flush = -1;
0447 return Z_OK;
0448 }
0449 }
0450 }
0451 Assert(strm->avail_out > 0, "bug2");
0452
0453 if (flush != Z_FINISH) return Z_OK;
0454 if (s->noheader) return Z_STREAM_END;
0455
0456
0457 putShortMSB(s, (uInt)(strm->adler >> 16));
0458 putShortMSB(s, (uInt)(strm->adler & 0xffff));
0459 flush_pending(strm);
0460
0461
0462
0463 s->noheader = -1;
0464 return s->pending != 0 ? Z_OK : Z_STREAM_END;
0465 }
0466
0467
0468 int zlib_deflateEnd(
0469 z_streamp strm
0470 )
0471 {
0472 int status;
0473 deflate_state *s;
0474
0475 if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR;
0476 s = (deflate_state *) strm->state;
0477
0478 status = s->status;
0479 if (status != INIT_STATE && status != BUSY_STATE &&
0480 status != FINISH_STATE) {
0481 return Z_STREAM_ERROR;
0482 }
0483
0484 strm->state = NULL;
0485
0486 return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
0487 }
0488
0489
0490
0491
0492
0493
0494
0495
0496 static int read_buf(
0497 z_streamp strm,
0498 Byte *buf,
0499 unsigned size
0500 )
0501 {
0502 unsigned len = strm->avail_in;
0503
0504 if (len > size) len = size;
0505 if (len == 0) return 0;
0506
0507 strm->avail_in -= len;
0508
0509 if (!DEFLATE_NEED_CHECKSUM(strm)) {}
0510 else if (!((deflate_state *)(strm->state))->noheader) {
0511 strm->adler = zlib_adler32(strm->adler, strm->next_in, len);
0512 }
0513 memcpy(buf, strm->next_in, len);
0514 strm->next_in += len;
0515 strm->total_in += len;
0516
0517 return (int)len;
0518 }
0519
0520
0521
0522
0523 static void lm_init(
0524 deflate_state *s
0525 )
0526 {
0527 s->window_size = (ulg)2L*s->w_size;
0528
0529 CLEAR_HASH(s);
0530
0531
0532
0533 s->max_lazy_match = configuration_table[s->level].max_lazy;
0534 s->good_match = configuration_table[s->level].good_length;
0535 s->nice_match = configuration_table[s->level].nice_length;
0536 s->max_chain_length = configuration_table[s->level].max_chain;
0537
0538 s->strstart = 0;
0539 s->block_start = 0L;
0540 s->lookahead = 0;
0541 s->match_length = s->prev_length = MIN_MATCH-1;
0542 s->match_available = 0;
0543 s->ins_h = 0;
0544 }
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558 static uInt longest_match(
0559 deflate_state *s,
0560 IPos cur_match
0561 )
0562 {
0563 unsigned chain_length = s->max_chain_length;
0564 register Byte *scan = s->window + s->strstart;
0565 register Byte *match;
0566 register int len;
0567 int best_len = s->prev_length;
0568 int nice_match = s->nice_match;
0569 IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
0570 s->strstart - (IPos)MAX_DIST(s) : NIL;
0571
0572
0573
0574 Pos *prev = s->prev;
0575 uInt wmask = s->w_mask;
0576
0577 #ifdef UNALIGNED_OK
0578
0579
0580
0581 register Byte *strend = s->window + s->strstart + MAX_MATCH - 1;
0582 register ush scan_start = *(ush*)scan;
0583 register ush scan_end = *(ush*)(scan+best_len-1);
0584 #else
0585 register Byte *strend = s->window + s->strstart + MAX_MATCH;
0586 register Byte scan_end1 = scan[best_len-1];
0587 register Byte scan_end = scan[best_len];
0588 #endif
0589
0590
0591
0592
0593 Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
0594
0595
0596 if (s->prev_length >= s->good_match) {
0597 chain_length >>= 2;
0598 }
0599
0600
0601
0602 if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
0603
0604 Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
0605
0606 do {
0607 Assert(cur_match < s->strstart, "no future");
0608 match = s->window + cur_match;
0609
0610
0611
0612
0613 #if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
0614
0615
0616
0617 if (*(ush*)(match+best_len-1) != scan_end ||
0618 *(ush*)match != scan_start) continue;
0619
0620
0621
0622
0623
0624
0625
0626
0627
0628
0629 Assert(scan[2] == match[2], "scan[2]?");
0630 scan++, match++;
0631 do {
0632 } while (*(ush*)(scan+=2) == *(ush*)(match+=2) &&
0633 *(ush*)(scan+=2) == *(ush*)(match+=2) &&
0634 *(ush*)(scan+=2) == *(ush*)(match+=2) &&
0635 *(ush*)(scan+=2) == *(ush*)(match+=2) &&
0636 scan < strend);
0637
0638
0639
0640 Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
0641 if (*scan == *match) scan++;
0642
0643 len = (MAX_MATCH - 1) - (int)(strend-scan);
0644 scan = strend - (MAX_MATCH-1);
0645
0646 #else
0647
0648 if (match[best_len] != scan_end ||
0649 match[best_len-1] != scan_end1 ||
0650 *match != *scan ||
0651 *++match != scan[1]) continue;
0652
0653
0654
0655
0656
0657
0658
0659 scan += 2, match++;
0660 Assert(*scan == *match, "match[2]?");
0661
0662
0663
0664
0665 do {
0666 } while (*++scan == *++match && *++scan == *++match &&
0667 *++scan == *++match && *++scan == *++match &&
0668 *++scan == *++match && *++scan == *++match &&
0669 *++scan == *++match && *++scan == *++match &&
0670 scan < strend);
0671
0672 Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
0673
0674 len = MAX_MATCH - (int)(strend - scan);
0675 scan = strend - MAX_MATCH;
0676
0677 #endif
0678
0679 if (len > best_len) {
0680 s->match_start = cur_match;
0681 best_len = len;
0682 if (len >= nice_match) break;
0683 #ifdef UNALIGNED_OK
0684 scan_end = *(ush*)(scan+best_len-1);
0685 #else
0686 scan_end1 = scan[best_len-1];
0687 scan_end = scan[best_len];
0688 #endif
0689 }
0690 } while ((cur_match = prev[cur_match & wmask]) > limit
0691 && --chain_length != 0);
0692
0693 if ((uInt)best_len <= s->lookahead) return best_len;
0694 return s->lookahead;
0695 }
0696
0697 #ifdef DEBUG_ZLIB
0698
0699
0700
0701 static void check_match(
0702 deflate_state *s,
0703 IPos start,
0704 IPos match,
0705 int length
0706 )
0707 {
0708
0709 if (memcmp((char *)s->window + match,
0710 (char *)s->window + start, length) != EQUAL) {
0711 fprintf(stderr, " start %u, match %u, length %d\n",
0712 start, match, length);
0713 do {
0714 fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
0715 } while (--length != 0);
0716 z_error("invalid match");
0717 }
0718 if (z_verbose > 1) {
0719 fprintf(stderr,"\\[%d,%d]", start-match, length);
0720 do { putc(s->window[start++], stderr); } while (--length != 0);
0721 }
0722 }
0723 #else
0724 # define check_match(s, start, match, length)
0725 #endif
0726
0727
0728
0729
0730
0731
0732
0733
0734
0735
0736
0737 static void fill_window(
0738 deflate_state *s
0739 )
0740 {
0741 register unsigned n, m;
0742 register Pos *p;
0743 unsigned more;
0744 uInt wsize = s->w_size;
0745
0746 do {
0747 more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
0748
0749
0750 if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
0751 more = wsize;
0752
0753 } else if (more == (unsigned)(-1)) {
0754
0755
0756
0757 more--;
0758
0759
0760
0761
0762 } else if (s->strstart >= wsize+MAX_DIST(s)) {
0763
0764 memcpy((char *)s->window, (char *)s->window+wsize,
0765 (unsigned)wsize);
0766 s->match_start -= wsize;
0767 s->strstart -= wsize;
0768 s->block_start -= (long) wsize;
0769
0770
0771
0772
0773
0774
0775
0776 n = s->hash_size;
0777 p = &s->head[n];
0778 do {
0779 m = *--p;
0780 *p = (Pos)(m >= wsize ? m-wsize : NIL);
0781 } while (--n);
0782
0783 n = wsize;
0784 p = &s->prev[n];
0785 do {
0786 m = *--p;
0787 *p = (Pos)(m >= wsize ? m-wsize : NIL);
0788
0789
0790
0791 } while (--n);
0792 more += wsize;
0793 }
0794 if (s->strm->avail_in == 0) return;
0795
0796
0797
0798
0799
0800
0801
0802
0803
0804
0805
0806
0807 Assert(more >= 2, "more < 2");
0808
0809 n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
0810 s->lookahead += n;
0811
0812
0813 if (s->lookahead >= MIN_MATCH) {
0814 s->ins_h = s->window[s->strstart];
0815 UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
0816 #if MIN_MATCH != 3
0817 Call UPDATE_HASH() MIN_MATCH-3 more times
0818 #endif
0819 }
0820
0821
0822
0823
0824 } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
0825 }
0826
0827
0828
0829
0830
0831 #define FLUSH_BLOCK_ONLY(s, eof) { \
0832 zlib_tr_flush_block(s, (s->block_start >= 0L ? \
0833 (char *)&s->window[(unsigned)s->block_start] : \
0834 NULL), \
0835 (ulg)((long)s->strstart - s->block_start), \
0836 (eof)); \
0837 s->block_start = s->strstart; \
0838 flush_pending(s->strm); \
0839 Tracev((stderr,"[FLUSH]")); \
0840 }
0841
0842
0843 #define FLUSH_BLOCK(s, eof) { \
0844 FLUSH_BLOCK_ONLY(s, eof); \
0845 if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
0846 }
0847
0848
0849
0850
0851
0852
0853
0854
0855
0856
0857 static block_state deflate_stored(
0858 deflate_state *s,
0859 int flush
0860 )
0861 {
0862
0863
0864
0865 ulg max_block_size = 0xffff;
0866 ulg max_start;
0867
0868 if (max_block_size > s->pending_buf_size - 5) {
0869 max_block_size = s->pending_buf_size - 5;
0870 }
0871
0872
0873 for (;;) {
0874
0875 if (s->lookahead <= 1) {
0876
0877 Assert(s->strstart < s->w_size+MAX_DIST(s) ||
0878 s->block_start >= (long)s->w_size, "slide too late");
0879
0880 fill_window(s);
0881 if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
0882
0883 if (s->lookahead == 0) break;
0884 }
0885 Assert(s->block_start >= 0L, "block gone");
0886
0887 s->strstart += s->lookahead;
0888 s->lookahead = 0;
0889
0890
0891 max_start = s->block_start + max_block_size;
0892 if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
0893
0894 s->lookahead = (uInt)(s->strstart - max_start);
0895 s->strstart = (uInt)max_start;
0896 FLUSH_BLOCK(s, 0);
0897 }
0898
0899
0900
0901 if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
0902 FLUSH_BLOCK(s, 0);
0903 }
0904 }
0905 FLUSH_BLOCK(s, flush == Z_FINISH);
0906 return flush == Z_FINISH ? finish_done : block_done;
0907 }
0908
0909
0910
0911
0912
0913
0914
0915
0916 static block_state deflate_fast(
0917 deflate_state *s,
0918 int flush
0919 )
0920 {
0921 IPos hash_head = NIL;
0922 int bflush;
0923
0924 for (;;) {
0925
0926
0927
0928
0929
0930 if (s->lookahead < MIN_LOOKAHEAD) {
0931 fill_window(s);
0932 if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
0933 return need_more;
0934 }
0935 if (s->lookahead == 0) break;
0936 }
0937
0938
0939
0940
0941 if (s->lookahead >= MIN_MATCH) {
0942 INSERT_STRING(s, s->strstart, hash_head);
0943 }
0944
0945
0946
0947
0948 if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
0949
0950
0951
0952
0953 if (s->strategy != Z_HUFFMAN_ONLY) {
0954 s->match_length = longest_match (s, hash_head);
0955 }
0956
0957 }
0958 if (s->match_length >= MIN_MATCH) {
0959 check_match(s, s->strstart, s->match_start, s->match_length);
0960
0961 bflush = zlib_tr_tally(s, s->strstart - s->match_start,
0962 s->match_length - MIN_MATCH);
0963
0964 s->lookahead -= s->match_length;
0965
0966
0967
0968
0969 if (s->match_length <= s->max_insert_length &&
0970 s->lookahead >= MIN_MATCH) {
0971 s->match_length--;
0972 do {
0973 s->strstart++;
0974 INSERT_STRING(s, s->strstart, hash_head);
0975
0976
0977
0978 } while (--s->match_length != 0);
0979 s->strstart++;
0980 } else {
0981 s->strstart += s->match_length;
0982 s->match_length = 0;
0983 s->ins_h = s->window[s->strstart];
0984 UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
0985 #if MIN_MATCH != 3
0986 Call UPDATE_HASH() MIN_MATCH-3 more times
0987 #endif
0988
0989
0990
0991 }
0992 } else {
0993
0994 Tracevv((stderr,"%c", s->window[s->strstart]));
0995 bflush = zlib_tr_tally (s, 0, s->window[s->strstart]);
0996 s->lookahead--;
0997 s->strstart++;
0998 }
0999 if (bflush) FLUSH_BLOCK(s, 0);
1000 }
1001 FLUSH_BLOCK(s, flush == Z_FINISH);
1002 return flush == Z_FINISH ? finish_done : block_done;
1003 }
1004
1005
1006
1007
1008
1009
1010 static block_state deflate_slow(
1011 deflate_state *s,
1012 int flush
1013 )
1014 {
1015 IPos hash_head = NIL;
1016 int bflush;
1017
1018
1019 for (;;) {
1020
1021
1022
1023
1024
1025 if (s->lookahead < MIN_LOOKAHEAD) {
1026 fill_window(s);
1027 if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
1028 return need_more;
1029 }
1030 if (s->lookahead == 0) break;
1031 }
1032
1033
1034
1035
1036 if (s->lookahead >= MIN_MATCH) {
1037 INSERT_STRING(s, s->strstart, hash_head);
1038 }
1039
1040
1041
1042 s->prev_length = s->match_length, s->prev_match = s->match_start;
1043 s->match_length = MIN_MATCH-1;
1044
1045 if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
1046 s->strstart - hash_head <= MAX_DIST(s)) {
1047
1048
1049
1050
1051 if (s->strategy != Z_HUFFMAN_ONLY) {
1052 s->match_length = longest_match (s, hash_head);
1053 }
1054
1055
1056 if (s->match_length <= 5 && (s->strategy == Z_FILTERED ||
1057 (s->match_length == MIN_MATCH &&
1058 s->strstart - s->match_start > TOO_FAR))) {
1059
1060
1061
1062
1063 s->match_length = MIN_MATCH-1;
1064 }
1065 }
1066
1067
1068
1069 if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
1070 uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
1071
1072
1073 check_match(s, s->strstart-1, s->prev_match, s->prev_length);
1074
1075 bflush = zlib_tr_tally(s, s->strstart -1 - s->prev_match,
1076 s->prev_length - MIN_MATCH);
1077
1078
1079
1080
1081
1082
1083 s->lookahead -= s->prev_length-1;
1084 s->prev_length -= 2;
1085 do {
1086 if (++s->strstart <= max_insert) {
1087 INSERT_STRING(s, s->strstart, hash_head);
1088 }
1089 } while (--s->prev_length != 0);
1090 s->match_available = 0;
1091 s->match_length = MIN_MATCH-1;
1092 s->strstart++;
1093
1094 if (bflush) FLUSH_BLOCK(s, 0);
1095
1096 } else if (s->match_available) {
1097
1098
1099
1100
1101 Tracevv((stderr,"%c", s->window[s->strstart-1]));
1102 if (zlib_tr_tally (s, 0, s->window[s->strstart-1])) {
1103 FLUSH_BLOCK_ONLY(s, 0);
1104 }
1105 s->strstart++;
1106 s->lookahead--;
1107 if (s->strm->avail_out == 0) return need_more;
1108 } else {
1109
1110
1111
1112 s->match_available = 1;
1113 s->strstart++;
1114 s->lookahead--;
1115 }
1116 }
1117 Assert (flush != Z_NO_FLUSH, "no flush?");
1118 if (s->match_available) {
1119 Tracevv((stderr,"%c", s->window[s->strstart-1]));
1120 zlib_tr_tally (s, 0, s->window[s->strstart-1]);
1121 s->match_available = 0;
1122 }
1123 FLUSH_BLOCK(s, flush == Z_FINISH);
1124 return flush == Z_FINISH ? finish_done : block_done;
1125 }
1126
1127 int zlib_deflate_workspacesize(int windowBits, int memLevel)
1128 {
1129 if (windowBits < 0)
1130 windowBits = -windowBits;
1131
1132
1133 BUG_ON(memLevel < 1 || memLevel > MAX_MEM_LEVEL || windowBits < 9 ||
1134 windowBits > 15);
1135
1136 return sizeof(deflate_workspace)
1137 + zlib_deflate_window_memsize(windowBits)
1138 + zlib_deflate_prev_memsize(windowBits)
1139 + zlib_deflate_head_memsize(memLevel)
1140 + zlib_deflate_overlay_memsize(memLevel);
1141 }
1142
1143 int zlib_deflate_dfltcc_enabled(void)
1144 {
1145 return DEFLATE_DFLTCC_ENABLED();
1146 }