extern const ct_data static_ltree[L_CODES+2];
extern const ct_data static_dtree[D_CODES];
+#define QUICK_START_BLOCK(s, last) { \
+ zng_tr_emit_tree(s, STATIC_TREES, last); \
+ s->block_open = 1; \
+ s->block_start = s->strstart; \
+}
+
+#define QUICK_END_BLOCK(s, last) { \
+ if (s->block_open) { \
+ zng_tr_emit_end_block(s, static_ltree, last); \
+ s->block_open = 0; \
+ s->block_start = s->strstart; \
+ } \
+}
+
ZLIB_INTERNAL block_state deflate_quick(deflate_state *s, int flush) {
Pos hash_head;
unsigned dist, match_len, last;
- if (s->block_open == 0) {
- last = (flush == Z_FINISH) ? 1 : 0;
- zng_tr_emit_tree(s, STATIC_TREES, last);
- s->block_open = 1;
- }
-
do {
- if (s->pending + ((BIT_BUF_SIZE + 7) >> 3) >= s->pending_buf_size) {
- flush_pending(s->strm);
- if (s->strm->avail_in == 0 && flush != Z_FINISH) {
- return need_more;
- }
- }
-
if (s->lookahead < MIN_LOOKAHEAD) {
fill_window(s);
if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
- zng_tr_emit_end_block(s, static_ltree, 0);
- s->block_open = 0;
- s->block_start = s->strstart;
- flush_pending(s->strm);
+ /* Always emit end block, in case next call is with Z_FINISH,
+ and we need to emit start of last block */
+ QUICK_END_BLOCK(s, 0);
return need_more;
}
if (s->lookahead == 0)
break;
}
+ if (s->pending + ((BIT_BUF_SIZE + 7) >> 3) >= s->pending_buf_size) {
+ flush_pending(s->strm);
+ if (s->strm->avail_out == 0 && flush != Z_FINISH) {
+ /* Break to emit end block and return need_more */
+ break;
+ }
+ }
+
+ if (s->block_open == 0) {
+ /* Start new block when we have lookahead data, so that if no
+ input data is given an empty block will not be written */
+ last = (flush == Z_FINISH) ? 1 : 0;
+ QUICK_START_BLOCK(s, last);
+ }
+
if (s->lookahead >= MIN_MATCH) {
hash_head = functable.quick_insert_string(s, s->strstart);
dist = s->strstart - hash_head;
s->lookahead--;
} while (s->strm->avail_out != 0);
- if (s->strm->avail_out == 0 && flush != Z_FINISH)
- return need_more;
-
s->insert = s->strstart < MIN_MATCH - 1 ? s->strstart : MIN_MATCH-1;
last = (flush == Z_FINISH) ? 1 : 0;
- zng_tr_emit_end_block(s, static_ltree, last);
- s->block_open = 0;
- s->block_start = s->strstart;
+ QUICK_END_BLOCK(s, last);
flush_pending(s->strm);
if (last) {