/src/zlib-ng/trees_emit.h
Line | Count | Source |
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 | | #endif |
11 | | |
12 | | |
13 | | /* trees.h */ |
14 | | extern Z_INTERNAL const ct_data static_ltree[L_CODES+2]; |
15 | | extern Z_INTERNAL const ct_data static_dtree[D_CODES]; |
16 | | |
17 | | extern Z_INTERNAL const unsigned char zng_dist_code[DIST_CODE_LEN]; |
18 | | extern Z_INTERNAL const unsigned char zng_length_code[STD_MAX_MATCH-STD_MIN_MATCH+1]; |
19 | | |
20 | | /* Combined mask + extra_bits tables for single-lookup optimization */ |
21 | | extern Z_INTERNAL const uint16_t lmask_extra[LENGTH_CODES]; |
22 | | extern Z_INTERNAL const uint32_t dmask_extra[D_CODES]; |
23 | | |
24 | | /* Bit buffer and deflate code stderr tracing */ |
25 | | #ifdef ZLIB_DEBUG |
26 | | # define trace_bits(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 trace_code(c) \ |
31 | | if (z_verbose > 2) { \ |
32 | | fprintf(stderr, "\ncd %3d ", (c)); \ |
33 | | } |
34 | | #else |
35 | | # define trace_bits(s, value, length) |
36 | | # define trace_code(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 | 93.8k | #define send_bits(s, t_val, t_len, bi_buf, bi_valid) do {\ |
44 | 93.8k | Assert(bi_valid <= 64, "Too many bits in bi_valid");\ |
45 | 93.8k | uint64_t val = (uint64_t)t_val;\ |
46 | 93.8k | uint32_t len = (uint32_t)t_len;\ |
47 | 93.8k | uint32_t total_bits = bi_valid + len;\ |
48 | 93.8k | trace_bits(s, val, len);\ |
49 | 93.8k | sent_bits_add(s, len);\ |
50 | 93.8k | \ |
51 | 93.8k | /* Unconditionally shift and merge values into the buffer */\ |
52 | 93.8k | bi_buf |= val << bi_valid;\ |
53 | 93.8k | \ |
54 | 93.8k | /* Check if the 64-bit boundary was crossed */\ |
55 | 93.8k | if (total_bits >= 64) {\ |
56 | 2.46k | total_bits -= 64;\ |
57 | 2.46k | put_uint64(s, bi_buf);\ |
58 | 2.46k | \ |
59 | 2.46k | /* Secure shift: prevent Undefined Behavior when bi_valid is 0 */\ |
60 | 2.46k | /* If bi_valid is 0, we shift by 0 (via the mask) and overwrite bi_buf completely */\ |
61 | 2.46k | bi_buf = (val >> 1) >> (~bi_valid & 63);\ |
62 | 2.46k | }\ |
63 | 93.8k | bi_valid = total_bits;\ |
64 | 93.8k | } while (0) |
65 | | |
66 | | /* Merge bits into the bit buffer without flushing. The caller must guarantee room, |
67 | | * i.e. bi_valid + len <= 64. Pair with send_bits_flush, which leaves at most 7 bits. */ |
68 | 1.72M | #define send_bits_merge(s, t_val, t_len, bi_buf, bi_valid) do { \ |
69 | 1.72M | Assert((bi_valid) + (uint32_t)(t_len) <= 64, "bit buffer overflow"); \ |
70 | 1.72M | trace_bits(s, (uint64_t)(t_val), (uint32_t)(t_len)); \ |
71 | 1.72M | sent_bits_add(s, t_len); \ |
72 | 1.72M | bi_buf |= (uint64_t)(t_val) << (bi_valid); \ |
73 | 1.72M | bi_valid += (uint32_t)(t_len); \ |
74 | 1.72M | } while (0) |
75 | | |
76 | | /* Store the bit buffer unconditionally and consume its complete bytes, leaving at most |
77 | | * 7 valid bits. The unconditional 8-byte store reaches up to 7 bytes past the logical |
78 | | * output position, which the pending buffer layout must reserve room for |
79 | | * (see PENDING_BUF_PAD in deflate.c). */ |
80 | 1.72M | #define send_bits_flush(s, bi_buf, bi_valid, pending) do { \ |
81 | 1.72M | zng_memwrite_8((s)->pending_buf + (pending), Z_U64_TO_LE(bi_buf)); \ |
82 | 1.72M | pending += (bi_valid) >> 3; \ |
83 | 1.72M | bi_buf >>= ((bi_valid) & ~7U); \ |
84 | 1.72M | bi_valid &= 7; \ |
85 | 1.72M | } while (0) |
86 | | |
87 | | /* Send a code of the given tree. c and tree must not have side effects */ |
88 | | #ifdef ZLIB_DEBUG |
89 | | # define send_code(s, c, tree, bi_buf, bi_valid) { \ |
90 | | trace_code(c); \ |
91 | | send_bits(s, tree[c].Code, tree[c].Len, bi_buf, bi_valid); \ |
92 | | } |
93 | | #else |
94 | | # define send_code(s, c, tree, bi_buf, bi_valid) \ |
95 | 27.3k | send_bits(s, tree[c].Code, tree[c].Len, bi_buf, bi_valid) |
96 | | #endif |
97 | | |
98 | | /* Merge a code of the given tree without flushing. c and tree must not have side effects */ |
99 | | #ifdef ZLIB_DEBUG |
100 | | # define send_code_merge(s, c, tree, bi_buf, bi_valid) { \ |
101 | | trace_code(c); \ |
102 | | send_bits_merge(s, tree[c].Code, tree[c].Len, bi_buf, bi_valid); \ |
103 | | } |
104 | | #else |
105 | | # define send_code_merge(s, c, tree, bi_buf, bi_valid) \ |
106 | 3.79k | send_bits_merge(s, tree[c].Code, tree[c].Len, bi_buf, bi_valid) |
107 | | #endif |
108 | | |
109 | | /* =========================================================================== |
110 | | * Flush the bit buffer and align the output on a byte boundary |
111 | | */ |
112 | 3.07k | static inline void bi_windup(deflate_state *s) { |
113 | 3.07k | if (s->bi_valid > 56) { |
114 | 0 | put_uint64(s, s->bi_buf); |
115 | 3.07k | } else { |
116 | 3.07k | if (s->bi_valid > 24) { |
117 | 259 | put_uint32(s, (uint32_t)s->bi_buf); |
118 | 259 | s->bi_buf >>= 32; |
119 | 259 | s->bi_valid -= 32; |
120 | 259 | } |
121 | 3.07k | if (s->bi_valid > 8) { |
122 | 1.36k | put_short(s, (uint16_t)s->bi_buf); |
123 | 1.36k | s->bi_buf >>= 16; |
124 | 1.36k | s->bi_valid -= 16; |
125 | 1.36k | } |
126 | 3.07k | if (s->bi_valid > 0) { |
127 | 1.53k | put_byte(s, s->bi_buf); |
128 | 1.53k | } |
129 | 3.07k | } |
130 | 3.07k | s->bi_used = ((s->bi_valid - 1) & 7) + 1; |
131 | 3.07k | s->bi_buf = 0; |
132 | 3.07k | s->bi_valid = 0; |
133 | 3.07k | } Unexecuted instantiation: deflate_quick.c:bi_windup Line | Count | Source | 112 | 3.07k | static inline void bi_windup(deflate_state *s) { | 113 | 3.07k | if (s->bi_valid > 56) { | 114 | 0 | put_uint64(s, s->bi_buf); | 115 | 3.07k | } else { | 116 | 3.07k | if (s->bi_valid > 24) { | 117 | 259 | put_uint32(s, (uint32_t)s->bi_buf); | 118 | 259 | s->bi_buf >>= 32; | 119 | 259 | s->bi_valid -= 32; | 120 | 259 | } | 121 | 3.07k | if (s->bi_valid > 8) { | 122 | 1.36k | put_short(s, (uint16_t)s->bi_buf); | 123 | 1.36k | s->bi_buf >>= 16; | 124 | 1.36k | s->bi_valid -= 16; | 125 | 1.36k | } | 126 | 3.07k | if (s->bi_valid > 0) { | 127 | 1.53k | put_byte(s, s->bi_buf); | 128 | 1.53k | } | 129 | 3.07k | } | 130 | 3.07k | s->bi_used = ((s->bi_valid - 1) & 7) + 1; | 131 | 3.07k | s->bi_buf = 0; | 132 | 3.07k | s->bi_valid = 0; | 133 | 3.07k | } |
|
134 | | |
135 | | /* =========================================================================== |
136 | | * Emit literal code |
137 | | */ |
138 | | Z_FORCEINLINE static void zng_emit_lit(deflate_state *s, const ct_data *ltree, unsigned c, |
139 | 0 | uint64_t *bi_buf, uint32_t *bi_valid) { |
140 | 0 | send_code(s, c, ltree, *bi_buf, *bi_valid); |
141 | 0 | Tracecv(isgraph(c & 0xff), (stderr, " '%c' ", c)); |
142 | 0 | } Unexecuted instantiation: deflate_quick.c:zng_emit_lit Unexecuted instantiation: trees.c:zng_emit_lit |
143 | | |
144 | | /* =========================================================================== |
145 | | * Assemble a match's length code + extra bits + distance code + extra bits into |
146 | | * a single bit string, at most 48 bits. Returns the bits, length via *bits_len. |
147 | | */ |
148 | 1.72M | Z_FORCEINLINE static uint64_t zng_assemble_dist(const ct_data *ltree, const ct_data *dtree, uint32_t lc, uint32_t dist, uint32_t *bits_len) { |
149 | 1.72M | uint64_t match_bits; |
150 | 1.72M | uint32_t match_bits_len; |
151 | 1.72M | uint32_t mask_ext; // Contains both mask and extra, can safely be used directly as mask |
152 | | // due to extra bits being outside the range of lc and dist data. |
153 | 1.72M | uint32_t c, extra; |
154 | 1.72M | uint8_t code; |
155 | | |
156 | | /* 1. Process Length Code */ |
157 | 1.72M | code = zng_length_code[lc]; |
158 | 1.72M | c = code + LITERALS + 1; |
159 | 1.72M | Assert(c < L_CODES, "bad l_code"); |
160 | 1.72M | trace_code(c); |
161 | | |
162 | | /* Send length code, len is the match length - STD_MIN_MATCH */ |
163 | 1.72M | match_bits = ltree[c].Code; |
164 | 1.72M | match_bits_len = ltree[c].Len; |
165 | | |
166 | | /* 2. Get extra bits count and mask */ |
167 | 1.72M | mask_ext = lmask_extra[code]; |
168 | 1.72M | extra = mask_ext >> 8; |
169 | | |
170 | | /* Send length extra bits */ |
171 | 1.72M | match_bits |= (uint64_t)(lc & mask_ext) << match_bits_len; |
172 | 1.72M | match_bits_len += extra; |
173 | | |
174 | | /* 3. Process Distance Code */ |
175 | 1.72M | dist--; /* dist is now the match distance - 1 */ |
176 | 1.72M | code = d_code(dist); |
177 | 1.72M | Assert(code < D_CODES, "bad d_code"); |
178 | 1.72M | trace_code(code); |
179 | | |
180 | | /* Send distance code */ |
181 | 1.72M | match_bits |= ((uint64_t)dtree[code].Code << match_bits_len); |
182 | 1.72M | match_bits_len += dtree[code].Len; |
183 | | |
184 | | /* 4. Get extra bits count and mask */ |
185 | 1.72M | mask_ext = dmask_extra[code]; |
186 | 1.72M | extra = mask_ext >> 16; |
187 | | |
188 | | /* Send dist extra bits */ |
189 | 1.72M | match_bits |= ((uint64_t)(dist & mask_ext) << match_bits_len); |
190 | 1.72M | match_bits_len += extra; |
191 | | |
192 | 1.72M | *bits_len = match_bits_len; |
193 | 1.72M | return match_bits; |
194 | 1.72M | } Unexecuted instantiation: deflate_quick.c:zng_assemble_dist trees.c:zng_assemble_dist Line | Count | Source | 148 | 1.72M | Z_FORCEINLINE static uint64_t zng_assemble_dist(const ct_data *ltree, const ct_data *dtree, uint32_t lc, uint32_t dist, uint32_t *bits_len) { | 149 | 1.72M | uint64_t match_bits; | 150 | 1.72M | uint32_t match_bits_len; | 151 | 1.72M | uint32_t mask_ext; // Contains both mask and extra, can safely be used directly as mask | 152 | | // due to extra bits being outside the range of lc and dist data. | 153 | 1.72M | uint32_t c, extra; | 154 | 1.72M | uint8_t code; | 155 | | | 156 | | /* 1. Process Length Code */ | 157 | 1.72M | code = zng_length_code[lc]; | 158 | 1.72M | c = code + LITERALS + 1; | 159 | 1.72M | Assert(c < L_CODES, "bad l_code"); | 160 | 1.72M | trace_code(c); | 161 | | | 162 | | /* Send length code, len is the match length - STD_MIN_MATCH */ | 163 | 1.72M | match_bits = ltree[c].Code; | 164 | 1.72M | match_bits_len = ltree[c].Len; | 165 | | | 166 | | /* 2. Get extra bits count and mask */ | 167 | 1.72M | mask_ext = lmask_extra[code]; | 168 | 1.72M | extra = mask_ext >> 8; | 169 | | | 170 | | /* Send length extra bits */ | 171 | 1.72M | match_bits |= (uint64_t)(lc & mask_ext) << match_bits_len; | 172 | 1.72M | match_bits_len += extra; | 173 | | | 174 | | /* 3. Process Distance Code */ | 175 | 1.72M | dist--; /* dist is now the match distance - 1 */ | 176 | 1.72M | code = d_code(dist); | 177 | 1.72M | Assert(code < D_CODES, "bad d_code"); | 178 | 1.72M | trace_code(code); | 179 | | | 180 | | /* Send distance code */ | 181 | 1.72M | match_bits |= ((uint64_t)dtree[code].Code << match_bits_len); | 182 | 1.72M | match_bits_len += dtree[code].Len; | 183 | | | 184 | | /* 4. Get extra bits count and mask */ | 185 | 1.72M | mask_ext = dmask_extra[code]; | 186 | 1.72M | extra = mask_ext >> 16; | 187 | | | 188 | | /* Send dist extra bits */ | 189 | 1.72M | match_bits |= ((uint64_t)(dist & mask_ext) << match_bits_len); | 190 | 1.72M | match_bits_len += extra; | 191 | | | 192 | 1.72M | *bits_len = match_bits_len; | 193 | 1.72M | return match_bits; | 194 | 1.72M | } |
|
195 | | |
196 | | /* =========================================================================== |
197 | | * Emit match distance/length code |
198 | | */ |
199 | | static inline uint32_t zng_emit_dist(deflate_state *s, const ct_data *ltree, const ct_data *dtree, |
200 | 0 | uint32_t lc, uint32_t dist, uint64_t *bi_buf, uint32_t *bi_valid) { |
201 | 0 | uint32_t match_bits_len; |
202 | 0 | uint64_t match_bits = zng_assemble_dist(ltree, dtree, lc, dist, &match_bits_len); |
203 | |
|
204 | 0 | send_bits(s, match_bits, match_bits_len, *bi_buf, *bi_valid); |
205 | |
|
206 | 0 | return match_bits_len; |
207 | 0 | } Unexecuted instantiation: deflate_quick.c:zng_emit_dist Unexecuted instantiation: trees.c:zng_emit_dist |
208 | | |
209 | | /* =========================================================================== |
210 | | * Emit end block |
211 | | */ |
212 | | static inline void zng_emit_end_block(deflate_state *s, const ct_data *ltree, const int last, |
213 | 3.07k | uint64_t *bi_buf, uint32_t *bi_valid) { |
214 | 3.07k | send_code(s, END_BLOCK, ltree, *bi_buf, *bi_valid); |
215 | 3.07k | Tracev((stderr, "\n+++ Emit End Block: Last: %u Pending: %u Total Out: %" PRIu64 "\n", |
216 | 3.07k | last, s->pending, (uint64_t)s->strm->total_out)); |
217 | 3.07k | Z_UNUSED(last); |
218 | 3.07k | } Unexecuted instantiation: deflate_quick.c:zng_emit_end_block trees.c:zng_emit_end_block Line | Count | Source | 213 | 3.07k | uint64_t *bi_buf, uint32_t *bi_valid) { | 214 | 3.07k | send_code(s, END_BLOCK, ltree, *bi_buf, *bi_valid); | 215 | 3.07k | Tracev((stderr, "\n+++ Emit End Block: Last: %u Pending: %u Total Out: %" PRIu64 "\n", | 216 | 3.07k | last, s->pending, (uint64_t)s->strm->total_out)); | 217 | 3.07k | Z_UNUSED(last); | 218 | 3.07k | } |
|
219 | | |
220 | | /* =========================================================================== |
221 | | * Emit literal and count bits |
222 | | */ |
223 | 0 | static inline void zng_tr_emit_lit(deflate_state *s, const ct_data *ltree, unsigned c) { |
224 | 0 | uint64_t bi_buf = s->bi_buf; |
225 | 0 | uint32_t bi_valid = s->bi_valid; |
226 | 0 | zng_emit_lit(s, ltree, c, &bi_buf, &bi_valid); |
227 | 0 | s->bi_buf = bi_buf; |
228 | 0 | s->bi_valid = bi_valid; |
229 | 0 | cmpr_bits_add(s, ltree[c].Len); |
230 | 0 | } Unexecuted instantiation: deflate_quick.c:zng_tr_emit_lit Unexecuted instantiation: trees.c:zng_tr_emit_lit |
231 | | |
232 | | /* =========================================================================== |
233 | | * Emit match and count bits |
234 | | */ |
235 | | static inline void zng_tr_emit_dist(deflate_state *s, const ct_data *ltree, const ct_data *dtree, |
236 | 0 | uint32_t lc, uint32_t dist) { |
237 | 0 | uint64_t bi_buf = s->bi_buf; |
238 | 0 | uint32_t bi_valid = s->bi_valid; |
239 | 0 | uint32_t bits = zng_emit_dist(s, ltree, dtree, lc, dist, &bi_buf, &bi_valid); |
240 | 0 | s->bi_buf = bi_buf; |
241 | 0 | s->bi_valid = bi_valid; |
242 | 0 | cmpr_bits_add(s, bits); |
243 | 0 | } Unexecuted instantiation: deflate_quick.c:zng_tr_emit_dist Unexecuted instantiation: trees.c:zng_tr_emit_dist |
244 | | |
245 | | /* =========================================================================== |
246 | | * Emit start of block |
247 | | */ |
248 | 4.61k | static inline void zng_tr_emit_tree(deflate_state *s, int type, const int last) { |
249 | 4.61k | uint32_t bi_valid = s->bi_valid; |
250 | 4.61k | uint64_t bi_buf = s->bi_buf; |
251 | 4.61k | uint32_t header_bits = (type << 1) + last; |
252 | 4.61k | send_bits(s, header_bits, 3, bi_buf, bi_valid); |
253 | 4.61k | cmpr_bits_add(s, 3); |
254 | 4.61k | s->bi_valid = bi_valid; |
255 | 4.61k | s->bi_buf = bi_buf; |
256 | 4.61k | Tracev((stderr, "\n--- Emit Tree: Last: %u\n", last)); |
257 | 4.61k | } Unexecuted instantiation: deflate_quick.c:zng_tr_emit_tree Line | Count | Source | 248 | 4.61k | static inline void zng_tr_emit_tree(deflate_state *s, int type, const int last) { | 249 | 4.61k | uint32_t bi_valid = s->bi_valid; | 250 | 4.61k | uint64_t bi_buf = s->bi_buf; | 251 | 4.61k | uint32_t header_bits = (type << 1) + last; | 252 | 4.61k | send_bits(s, header_bits, 3, bi_buf, bi_valid); | 253 | 4.61k | cmpr_bits_add(s, 3); | 254 | 4.61k | s->bi_valid = bi_valid; | 255 | 4.61k | s->bi_buf = bi_buf; | 256 | 4.61k | Tracev((stderr, "\n--- Emit Tree: Last: %u\n", last)); | 257 | 4.61k | } |
|
258 | | |
259 | | /* =========================================================================== |
260 | | * Align bit buffer on a byte boundary and count bits |
261 | | */ |
262 | 3.07k | static inline void zng_tr_emit_align(deflate_state *s) { |
263 | 3.07k | bi_windup(s); /* align on byte boundary */ |
264 | 3.07k | sent_bits_align(s); |
265 | 3.07k | } Unexecuted instantiation: deflate_quick.c:zng_tr_emit_align trees.c:zng_tr_emit_align Line | Count | Source | 262 | 3.07k | static inline void zng_tr_emit_align(deflate_state *s) { | 263 | 3.07k | bi_windup(s); /* align on byte boundary */ | 264 | 3.07k | sent_bits_align(s); | 265 | 3.07k | } |
|
266 | | |
267 | | /* =========================================================================== |
268 | | * Emit an end block and align bit buffer if last block |
269 | | */ |
270 | 0 | static inline void zng_tr_emit_end_block(deflate_state *s, const ct_data *ltree, const int last) { |
271 | 0 | uint64_t bi_buf = s->bi_buf; |
272 | 0 | uint32_t bi_valid = s->bi_valid; |
273 | 0 | zng_emit_end_block(s, ltree, last, &bi_buf, &bi_valid); |
274 | 0 | s->bi_buf = bi_buf; |
275 | 0 | s->bi_valid = bi_valid; |
276 | 0 | cmpr_bits_add(s, 7); |
277 | 0 | if (last) |
278 | 0 | zng_tr_emit_align(s); |
279 | 0 | } Unexecuted instantiation: deflate_quick.c:zng_tr_emit_end_block Unexecuted instantiation: trees.c:zng_tr_emit_end_block |
280 | | |
281 | | #endif |