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 */
15extern Z_INTERNAL const ct_data static_ltree[L_CODES+2];
16extern Z_INTERNAL const ct_data static_dtree[D_CODES];
17
18extern const unsigned char Z_INTERNAL zng_dist_code[DIST_CODE_LEN];
19extern const unsigned char Z_INTERNAL zng_length_code[MAX_MATCH-MIN_MATCH+1];
20
21extern Z_INTERNAL const int base_length[LENGTH_CODES];
22extern 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 */
78static void bi_windup(deflate_state *s) {
79 if (s->bi_valid > 56) {
80 put_uint64(s, lld: s->bi_buf);
81 } else {
82 if (s->bi_valid > 24) {
83 put_uint32(s, dw: (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, w: (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 */
103static 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 & 0xff), (stderr, " '%c' ", c));
113
114 return ltree[c].Len;
115}
116
117/* ===========================================================================
118 * Emit match distance/length code
119 */
120static 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 */
170static 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 Z_UNUSED(last);
179}
180
181/* ===========================================================================
182 * Emit literal and count bits
183 */
184static 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 */
191static 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 */
199static 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 */
213static 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 */
221static 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