• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  #ifndef TREES_EMIT_H_
2  #define TREES_EMIT_H_
3  
4  #include "zbuild.h"
5  #include "trees.h"
6  
7  #ifdef ZLIB_DEBUG
8  #  include <ctype.h>
9  #  include <inttypes.h>
10  #  include <stdint.h>
11  #endif
12  
13  
14  /* trees.h */
15  extern Z_INTERNAL const ct_data static_ltree[L_CODES+2];
16  extern Z_INTERNAL const ct_data static_dtree[D_CODES];
17  
18  extern const unsigned char Z_INTERNAL zng_dist_code[DIST_CODE_LEN];
19  extern const unsigned char Z_INTERNAL zng_length_code[MAX_MATCH-MIN_MATCH+1];
20  
21  extern Z_INTERNAL const int base_length[LENGTH_CODES];
22  extern Z_INTERNAL const int base_dist[D_CODES];
23  
24  /* Bit buffer and deflate code stderr tracing */
25  #ifdef ZLIB_DEBUG
26  #  define send_bits_trace(s, value, length) { \
27          Tracevv((stderr, " l %2d v %4llx ", (int)(length), (long long)(value))); \
28          Assert(length > 0 && length <= BIT_BUF_SIZE, "invalid length"); \
29      }
30  #  define send_code_trace(s, c) \
31      if (z_verbose > 2) { \
32          fprintf(stderr, "\ncd %3d ", (c)); \
33      }
34  #else
35  #  define send_bits_trace(s, value, length)
36  #  define send_code_trace(s, c)
37  #endif
38  
39  /* If not enough room in bi_buf, use (valid) bits from bi_buf and
40   * (64 - bi_valid) bits from value, leaving (width - (64-bi_valid))
41   * unused bits in value.
42   */
43  #define send_bits(s, t_val, t_len, bi_buf, bi_valid) {\
44      uint64_t val = (uint64_t)t_val;\
45      uint32_t len = (uint32_t)t_len;\
46      uint32_t total_bits = bi_valid + len;\
47      send_bits_trace(s, val, len);\
48      sent_bits_add(s, len);\
49      if (total_bits < BIT_BUF_SIZE) {\
50          bi_buf |= val << bi_valid;\
51          bi_valid = total_bits;\
52      } else if (bi_valid == BIT_BUF_SIZE) {\
53          put_uint64(s, bi_buf);\
54          bi_buf = val;\
55          bi_valid = len;\
56      } else {\
57          bi_buf |= val << bi_valid;\
58          put_uint64(s, bi_buf);\
59          bi_buf = val >> (BIT_BUF_SIZE - bi_valid);\
60          bi_valid = total_bits - BIT_BUF_SIZE;\
61      }\
62  }
63  
64  /* Send a code of the given tree. c and tree must not have side effects */
65  #ifdef ZLIB_DEBUG
66  #  define send_code(s, c, tree, bi_buf, bi_valid) { \
67      send_code_trace(s, c); \
68      send_bits(s, tree[c].Code, tree[c].Len, bi_buf, bi_valid); \
69  }
70  #else
71  #  define send_code(s, c, tree, bi_buf, bi_valid) \
72      send_bits(s, tree[c].Code, tree[c].Len, bi_buf, bi_valid)
73  #endif
74  
75  /* ===========================================================================
76   * Flush the bit buffer and align the output on a byte boundary
77   */
bi_windup(deflate_state * s)78  static void bi_windup(deflate_state *s) {
79      if (s->bi_valid > 56) {
80          put_uint64(s, s->bi_buf);
81      } else {
82          if (s->bi_valid > 24) {
83              put_uint32(s, (uint32_t)s->bi_buf);
84              s->bi_buf >>= 32;
85              s->bi_valid -= 32;
86          }
87          if (s->bi_valid > 8) {
88              put_short(s, (uint16_t)s->bi_buf);
89              s->bi_buf >>= 16;
90              s->bi_valid -= 16;
91          }
92          if (s->bi_valid > 0) {
93              put_byte(s, s->bi_buf);
94          }
95      }
96      s->bi_buf = 0;
97      s->bi_valid = 0;
98  }
99  
100  /* ===========================================================================
101   * Emit literal code
102   */
zng_emit_lit(deflate_state * s,const ct_data * ltree,unsigned c)103  static inline uint32_t zng_emit_lit(deflate_state *s, const ct_data *ltree, unsigned c) {
104      uint32_t bi_valid = s->bi_valid;
105      uint64_t bi_buf = s->bi_buf;
106  
107      send_code(s, c, ltree, bi_buf, bi_valid);
108  
109      s->bi_valid = bi_valid;
110      s->bi_buf = bi_buf;
111  
112      Tracecv(isgraph(c), (stderr, " '%c' ", c));
113  
114      return ltree[c].Len;
115  }
116  
117  /* ===========================================================================
118   * Emit match distance/length code
119   */
zng_emit_dist(deflate_state * s,const ct_data * ltree,const ct_data * dtree,uint32_t lc,uint32_t dist)120  static inline uint32_t zng_emit_dist(deflate_state *s, const ct_data *ltree, const ct_data *dtree,
121      uint32_t lc, uint32_t dist) {
122      uint32_t c, extra;
123      uint8_t code;
124      uint64_t match_bits;
125      uint32_t match_bits_len;
126      uint32_t bi_valid = s->bi_valid;
127      uint64_t bi_buf = s->bi_buf;
128  
129      /* Send the length code, len is the match length - MIN_MATCH */
130      code = zng_length_code[lc];
131      c = code+LITERALS+1;
132      Assert(c < L_CODES, "bad l_code");
133      send_code_trace(s, c);
134  
135      match_bits = ltree[c].Code;
136      match_bits_len = ltree[c].Len;
137      extra = extra_lbits[code];
138      if (extra != 0) {
139          lc -= base_length[code];
140          match_bits |= ((uint64_t)lc << match_bits_len);
141          match_bits_len += extra;
142      }
143  
144      dist--; /* dist is now the match distance - 1 */
145      code = d_code(dist);
146      Assert(code < D_CODES, "bad d_code");
147      send_code_trace(s, code);
148  
149      /* Send the distance code */
150      match_bits |= ((uint64_t)dtree[code].Code << match_bits_len);
151      match_bits_len += dtree[code].Len;
152      extra = extra_dbits[code];
153      if (extra != 0) {
154          dist -= base_dist[code];
155          match_bits |= ((uint64_t)dist << match_bits_len);
156          match_bits_len += extra;
157      }
158  
159      send_bits(s, match_bits, match_bits_len, bi_buf, bi_valid);
160  
161      s->bi_valid = bi_valid;
162      s->bi_buf = bi_buf;
163  
164      return match_bits_len;
165  }
166  
167  /* ===========================================================================
168   * Emit end block
169   */
zng_emit_end_block(deflate_state * s,const ct_data * ltree,const int last)170  static inline void zng_emit_end_block(deflate_state *s, const ct_data *ltree, const int last) {
171      uint32_t bi_valid = s->bi_valid;
172      uint64_t bi_buf = s->bi_buf;
173      send_code(s, END_BLOCK, ltree, bi_buf, bi_valid);
174      s->bi_valid = bi_valid;
175      s->bi_buf = bi_buf;
176      Tracev((stderr, "\n+++ Emit End Block: Last: %u Pending: %u Total Out: %" PRIu64 "\n",
177          last, s->pending, (uint64_t)s->strm->total_out));
178      (void)last;
179  }
180  
181  /* ===========================================================================
182   * Emit literal and count bits
183   */
zng_tr_emit_lit(deflate_state * s,const ct_data * ltree,unsigned c)184  static inline void zng_tr_emit_lit(deflate_state *s, const ct_data *ltree, unsigned c) {
185      cmpr_bits_add(s, zng_emit_lit(s, ltree, c));
186  }
187  
188  /* ===========================================================================
189   * Emit match and count bits
190   */
zng_tr_emit_dist(deflate_state * s,const ct_data * ltree,const ct_data * dtree,uint32_t lc,uint32_t dist)191  static inline void zng_tr_emit_dist(deflate_state *s, const ct_data *ltree, const ct_data *dtree,
192      uint32_t lc, uint32_t dist) {
193      cmpr_bits_add(s, zng_emit_dist(s, ltree, dtree, lc, dist));
194  }
195  
196  /* ===========================================================================
197   * Emit start of block
198   */
zng_tr_emit_tree(deflate_state * s,int type,const int last)199  static inline void zng_tr_emit_tree(deflate_state *s, int type, const int last) {
200      uint32_t bi_valid = s->bi_valid;
201      uint64_t bi_buf = s->bi_buf;
202      uint32_t header_bits = (type << 1) + last;
203      send_bits(s, header_bits, 3, bi_buf, bi_valid);
204      cmpr_bits_add(s, 3);
205      s->bi_valid = bi_valid;
206      s->bi_buf = bi_buf;
207      Tracev((stderr, "\n--- Emit Tree: Last: %u\n", last));
208  }
209  
210  /* ===========================================================================
211   * Align bit buffer on a byte boundary and count bits
212   */
zng_tr_emit_align(deflate_state * s)213  static inline void zng_tr_emit_align(deflate_state *s) {
214      bi_windup(s); /* align on byte boundary */
215      sent_bits_align(s);
216  }
217  
218  /* ===========================================================================
219   * Emit an end block and align bit buffer if last block
220   */
zng_tr_emit_end_block(deflate_state * s,const ct_data * ltree,const int last)221  static inline void zng_tr_emit_end_block(deflate_state *s, const ct_data *ltree, const int last) {
222      zng_emit_end_block(s, ltree, last);
223      cmpr_bits_add(s, 7);
224      if (last)
225          zng_tr_emit_align(s);
226  }
227  
228  #endif
229