/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(s, 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(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 | 27.0M | #define send_bits(s, t_val, t_len, bi_buf, bi_valid) do {\ |
44 | 27.0M | Assert(bi_valid <= 64, "Too many bits in bi_valid");\ |
45 | 27.0M | uint64_t val = (uint64_t)t_val;\ |
46 | 27.0M | uint32_t len = (uint32_t)t_len;\ |
47 | 27.0M | uint32_t total_bits = bi_valid + len;\ |
48 | 27.0M | trace_bits(s, val, len);\ |
49 | 27.0M | sent_bits_add(s, len);\ |
50 | 27.0M | \ |
51 | 27.0M | /* Unconditionally shift and merge values into the buffer */\ |
52 | 27.0M | bi_buf |= val << bi_valid;\ |
53 | 27.0M | \ |
54 | 27.0M | /* Check if the 64-bit boundary was crossed */\ |
55 | 27.0M | if (total_bits >= 64) {\ |
56 | 11.3M | total_bits -= 64;\ |
57 | 11.3M | put_uint64(s, bi_buf);\ |
58 | 11.3M | \ |
59 | 11.3M | /* Secure shift: prevent Undefined Behavior when bi_valid is 0 */\ |
60 | 11.3M | /* If bi_valid is 0, we shift by 0 (via the mask) and overwrite bi_buf completely */\ |
61 | 11.3M | bi_buf = (val >> 1) >> (~bi_valid & 63);\ |
62 | 11.3M | }\ |
63 | 27.0M | bi_valid = total_bits;\ |
64 | 27.0M | } while (0) |
65 | | |
66 | | /* Send a code of the given tree. c and tree must not have side effects */ |
67 | | #ifdef ZLIB_DEBUG |
68 | | # define send_code(s, c, tree, bi_buf, bi_valid) { \ |
69 | | trace_code(s, c); \ |
70 | | send_bits(s, tree[c].Code, tree[c].Len, bi_buf, bi_valid); \ |
71 | | } |
72 | | #else |
73 | | # define send_code(s, c, tree, bi_buf, bi_valid) \ |
74 | 1.02M | send_bits(s, tree[c].Code, tree[c].Len, bi_buf, bi_valid) |
75 | | #endif |
76 | | |
77 | | /* =========================================================================== |
78 | | * Flush the bit buffer and align the output on a byte boundary |
79 | | */ |
80 | 5.34k | static inline void bi_windup(deflate_state *s) { |
81 | 5.34k | if (s->bi_valid > 56) { |
82 | 315 | put_uint64(s, s->bi_buf); |
83 | 5.03k | } else { |
84 | 5.03k | if (s->bi_valid > 24) { |
85 | 1.54k | put_uint32(s, (uint32_t)s->bi_buf); |
86 | 1.54k | s->bi_buf >>= 32; |
87 | 1.54k | s->bi_valid -= 32; |
88 | 1.54k | } |
89 | 5.03k | if (s->bi_valid > 8) { |
90 | 1.80k | put_short(s, (uint16_t)s->bi_buf); |
91 | 1.80k | s->bi_buf >>= 16; |
92 | 1.80k | s->bi_valid -= 16; |
93 | 1.80k | } |
94 | 5.03k | if (s->bi_valid > 0) { |
95 | 3.31k | put_byte(s, s->bi_buf); |
96 | 3.31k | } |
97 | 5.03k | } |
98 | 5.34k | s->bi_used = ((s->bi_valid - 1) & 7) + 1; |
99 | 5.34k | s->bi_buf = 0; |
100 | 5.34k | s->bi_valid = 0; |
101 | 5.34k | } Unexecuted instantiation: deflate_quick.c:bi_windup Line | Count | Source | 80 | 5.34k | static inline void bi_windup(deflate_state *s) { | 81 | 5.34k | if (s->bi_valid > 56) { | 82 | 315 | put_uint64(s, s->bi_buf); | 83 | 5.03k | } else { | 84 | 5.03k | if (s->bi_valid > 24) { | 85 | 1.54k | put_uint32(s, (uint32_t)s->bi_buf); | 86 | 1.54k | s->bi_buf >>= 32; | 87 | 1.54k | s->bi_valid -= 32; | 88 | 1.54k | } | 89 | 5.03k | if (s->bi_valid > 8) { | 90 | 1.80k | put_short(s, (uint16_t)s->bi_buf); | 91 | 1.80k | s->bi_buf >>= 16; | 92 | 1.80k | s->bi_valid -= 16; | 93 | 1.80k | } | 94 | 5.03k | if (s->bi_valid > 0) { | 95 | 3.31k | put_byte(s, s->bi_buf); | 96 | 3.31k | } | 97 | 5.03k | } | 98 | 5.34k | s->bi_used = ((s->bi_valid - 1) & 7) + 1; | 99 | 5.34k | s->bi_buf = 0; | 100 | 5.34k | s->bi_valid = 0; | 101 | 5.34k | } |
|
102 | | |
103 | | /* =========================================================================== |
104 | | * Emit literal code |
105 | | */ |
106 | | Z_FORCEINLINE static void zng_emit_lit(deflate_state *s, const ct_data *ltree, unsigned c, |
107 | 0 | uint64_t *bi_buf, uint32_t *bi_valid) { |
108 | 0 | send_code(s, c, ltree, *bi_buf, *bi_valid); |
109 | 0 | Tracecv(isgraph(c & 0xff), (stderr, " '%c' ", c)); |
110 | 0 | } Unexecuted instantiation: deflate_quick.c:zng_emit_lit Unexecuted instantiation: trees.c:zng_emit_lit |
111 | | |
112 | | /* =========================================================================== |
113 | | * Emit match distance/length code |
114 | | */ |
115 | | static inline uint32_t zng_emit_dist(deflate_state *s, const ct_data *ltree, const ct_data *dtree, |
116 | 1.91M | uint32_t lc, uint32_t dist, uint64_t *bi_buf, uint32_t *bi_valid) { |
117 | 1.91M | uint64_t match_bits; |
118 | 1.91M | uint32_t match_bits_len; |
119 | 1.91M | uint32_t mask_ext; // Contains both mask and extra, can safely be used directly as mask |
120 | | // due to extra bits being outside the range of lc and dist data. |
121 | 1.91M | uint32_t c, extra; |
122 | 1.91M | uint8_t code; |
123 | | |
124 | | /* 1. Process Length Code */ |
125 | 1.91M | code = zng_length_code[lc]; |
126 | 1.91M | c = code + LITERALS + 1; |
127 | 1.91M | Assert(c < L_CODES, "bad l_code"); |
128 | 1.91M | trace_code(s, c); |
129 | | |
130 | | /* Send length code, len is the match length - STD_MIN_MATCH */ |
131 | 1.91M | match_bits = ltree[c].Code; |
132 | 1.91M | match_bits_len = ltree[c].Len; |
133 | | |
134 | | /* 2. Get extra bits count and mask */ |
135 | 1.91M | mask_ext = lmask_extra[code]; |
136 | 1.91M | extra = mask_ext >> 8; |
137 | | |
138 | | /* Send length extra bits */ |
139 | 1.91M | match_bits |= (uint64_t)(lc & mask_ext) << match_bits_len; |
140 | 1.91M | match_bits_len += extra; |
141 | | |
142 | | /* 3. Process Distance Code */ |
143 | 1.91M | dist--; /* dist is now the match distance - 1 */ |
144 | 1.91M | code = d_code(dist); |
145 | 1.91M | Assert(code < D_CODES, "bad d_code"); |
146 | 1.91M | trace_code(s, code); |
147 | | |
148 | | /* Send distance code */ |
149 | 1.91M | match_bits |= ((uint64_t)dtree[code].Code << match_bits_len); |
150 | 1.91M | match_bits_len += dtree[code].Len; |
151 | | |
152 | | /* 4. Get extra bits count and mask */ |
153 | 1.91M | mask_ext = dmask_extra[code]; |
154 | 1.91M | extra = mask_ext >> 16; |
155 | | |
156 | | /* Send dist extra bits */ |
157 | 1.91M | match_bits |= ((uint64_t)(dist & mask_ext) << match_bits_len); |
158 | 1.91M | match_bits_len += extra; |
159 | | |
160 | 1.91M | send_bits(s, match_bits, match_bits_len, *bi_buf, *bi_valid); |
161 | | |
162 | 1.91M | return match_bits_len; |
163 | 1.91M | } Unexecuted instantiation: deflate_quick.c:zng_emit_dist Line | Count | Source | 116 | 1.91M | uint32_t lc, uint32_t dist, uint64_t *bi_buf, uint32_t *bi_valid) { | 117 | 1.91M | uint64_t match_bits; | 118 | 1.91M | uint32_t match_bits_len; | 119 | 1.91M | uint32_t mask_ext; // Contains both mask and extra, can safely be used directly as mask | 120 | | // due to extra bits being outside the range of lc and dist data. | 121 | 1.91M | uint32_t c, extra; | 122 | 1.91M | uint8_t code; | 123 | | | 124 | | /* 1. Process Length Code */ | 125 | 1.91M | code = zng_length_code[lc]; | 126 | 1.91M | c = code + LITERALS + 1; | 127 | 1.91M | Assert(c < L_CODES, "bad l_code"); | 128 | 1.91M | trace_code(s, c); | 129 | | | 130 | | /* Send length code, len is the match length - STD_MIN_MATCH */ | 131 | 1.91M | match_bits = ltree[c].Code; | 132 | 1.91M | match_bits_len = ltree[c].Len; | 133 | | | 134 | | /* 2. Get extra bits count and mask */ | 135 | 1.91M | mask_ext = lmask_extra[code]; | 136 | 1.91M | extra = mask_ext >> 8; | 137 | | | 138 | | /* Send length extra bits */ | 139 | 1.91M | match_bits |= (uint64_t)(lc & mask_ext) << match_bits_len; | 140 | 1.91M | match_bits_len += extra; | 141 | | | 142 | | /* 3. Process Distance Code */ | 143 | 1.91M | dist--; /* dist is now the match distance - 1 */ | 144 | 1.91M | code = d_code(dist); | 145 | 1.91M | Assert(code < D_CODES, "bad d_code"); | 146 | 1.91M | trace_code(s, code); | 147 | | | 148 | | /* Send distance code */ | 149 | 1.91M | match_bits |= ((uint64_t)dtree[code].Code << match_bits_len); | 150 | 1.91M | match_bits_len += dtree[code].Len; | 151 | | | 152 | | /* 4. Get extra bits count and mask */ | 153 | 1.91M | mask_ext = dmask_extra[code]; | 154 | 1.91M | extra = mask_ext >> 16; | 155 | | | 156 | | /* Send dist extra bits */ | 157 | 1.91M | match_bits |= ((uint64_t)(dist & mask_ext) << match_bits_len); | 158 | 1.91M | match_bits_len += extra; | 159 | | | 160 | 1.91M | send_bits(s, match_bits, match_bits_len, *bi_buf, *bi_valid); | 161 | | | 162 | 1.91M | return match_bits_len; | 163 | 1.91M | } |
|
164 | | |
165 | | /* =========================================================================== |
166 | | * Emit end block |
167 | | */ |
168 | | static inline void zng_emit_end_block(deflate_state *s, const ct_data *ltree, const int last, |
169 | 8.97k | uint64_t *bi_buf, uint32_t *bi_valid) { |
170 | 8.97k | send_code(s, END_BLOCK, ltree, *bi_buf, *bi_valid); |
171 | 8.97k | Tracev((stderr, "\n+++ Emit End Block: Last: %u Pending: %u Total Out: %" PRIu64 "\n", |
172 | 8.97k | last, s->pending, (uint64_t)s->strm->total_out)); |
173 | 8.97k | Z_UNUSED(last); |
174 | 8.97k | } Unexecuted instantiation: deflate_quick.c:zng_emit_end_block trees.c:zng_emit_end_block Line | Count | Source | 169 | 8.97k | uint64_t *bi_buf, uint32_t *bi_valid) { | 170 | 8.97k | send_code(s, END_BLOCK, ltree, *bi_buf, *bi_valid); | 171 | 8.97k | Tracev((stderr, "\n+++ Emit End Block: Last: %u Pending: %u Total Out: %" PRIu64 "\n", | 172 | 8.97k | last, s->pending, (uint64_t)s->strm->total_out)); | 173 | 8.97k | Z_UNUSED(last); | 174 | 8.97k | } |
|
175 | | |
176 | | /* =========================================================================== |
177 | | * Emit literal and count bits |
178 | | */ |
179 | 0 | static inline void zng_tr_emit_lit(deflate_state *s, const ct_data *ltree, unsigned c) { |
180 | 0 | uint64_t bi_buf = s->bi_buf; |
181 | 0 | uint32_t bi_valid = s->bi_valid; |
182 | 0 | zng_emit_lit(s, ltree, c, &bi_buf, &bi_valid); |
183 | 0 | s->bi_buf = bi_buf; |
184 | 0 | s->bi_valid = bi_valid; |
185 | 0 | cmpr_bits_add(s, ltree[c].Len); |
186 | 0 | } Unexecuted instantiation: deflate_quick.c:zng_tr_emit_lit Unexecuted instantiation: trees.c:zng_tr_emit_lit |
187 | | |
188 | | /* =========================================================================== |
189 | | * Emit match and count bits |
190 | | */ |
191 | | static inline void zng_tr_emit_dist(deflate_state *s, const ct_data *ltree, const ct_data *dtree, |
192 | 0 | uint32_t lc, uint32_t dist) { |
193 | 0 | uint64_t bi_buf = s->bi_buf; |
194 | 0 | uint32_t bi_valid = s->bi_valid; |
195 | 0 | uint32_t bits = zng_emit_dist(s, ltree, dtree, lc, dist, &bi_buf, &bi_valid); |
196 | 0 | s->bi_buf = bi_buf; |
197 | 0 | s->bi_valid = bi_valid; |
198 | 0 | cmpr_bits_add(s, bits); |
199 | 0 | } Unexecuted instantiation: deflate_quick.c:zng_tr_emit_dist Unexecuted instantiation: trees.c:zng_tr_emit_dist |
200 | | |
201 | | /* =========================================================================== |
202 | | * Emit start of block |
203 | | */ |
204 | 10.5k | static inline void zng_tr_emit_tree(deflate_state *s, int type, const int last) { |
205 | 10.5k | uint32_t bi_valid = s->bi_valid; |
206 | 10.5k | uint64_t bi_buf = s->bi_buf; |
207 | 10.5k | uint32_t header_bits = (type << 1) + last; |
208 | 10.5k | send_bits(s, header_bits, 3, bi_buf, bi_valid); |
209 | 10.5k | cmpr_bits_add(s, 3); |
210 | 10.5k | s->bi_valid = bi_valid; |
211 | 10.5k | s->bi_buf = bi_buf; |
212 | 10.5k | Tracev((stderr, "\n--- Emit Tree: Last: %u\n", last)); |
213 | 10.5k | } Unexecuted instantiation: deflate_quick.c:zng_tr_emit_tree Line | Count | Source | 204 | 10.5k | static inline void zng_tr_emit_tree(deflate_state *s, int type, const int last) { | 205 | 10.5k | uint32_t bi_valid = s->bi_valid; | 206 | 10.5k | uint64_t bi_buf = s->bi_buf; | 207 | 10.5k | uint32_t header_bits = (type << 1) + last; | 208 | 10.5k | send_bits(s, header_bits, 3, bi_buf, bi_valid); | 209 | 10.5k | cmpr_bits_add(s, 3); | 210 | 10.5k | s->bi_valid = bi_valid; | 211 | 10.5k | s->bi_buf = bi_buf; | 212 | 10.5k | Tracev((stderr, "\n--- Emit Tree: Last: %u\n", last)); | 213 | 10.5k | } |
|
214 | | |
215 | | /* =========================================================================== |
216 | | * Align bit buffer on a byte boundary and count bits |
217 | | */ |
218 | 5.34k | static inline void zng_tr_emit_align(deflate_state *s) { |
219 | 5.34k | bi_windup(s); /* align on byte boundary */ |
220 | 5.34k | sent_bits_align(s); |
221 | 5.34k | } Unexecuted instantiation: deflate_quick.c:zng_tr_emit_align trees.c:zng_tr_emit_align Line | Count | Source | 218 | 5.34k | static inline void zng_tr_emit_align(deflate_state *s) { | 219 | 5.34k | bi_windup(s); /* align on byte boundary */ | 220 | 5.34k | sent_bits_align(s); | 221 | 5.34k | } |
|
222 | | |
223 | | /* =========================================================================== |
224 | | * Emit an end block and align bit buffer if last block |
225 | | */ |
226 | 0 | static inline void zng_tr_emit_end_block(deflate_state *s, const ct_data *ltree, const int last) { |
227 | 0 | uint64_t bi_buf = s->bi_buf; |
228 | 0 | uint32_t bi_valid = s->bi_valid; |
229 | 0 | zng_emit_end_block(s, ltree, last, &bi_buf, &bi_valid); |
230 | 0 | s->bi_buf = bi_buf; |
231 | 0 | s->bi_valid = bi_valid; |
232 | 0 | cmpr_bits_add(s, 7); |
233 | 0 | if (last) |
234 | 0 | zng_tr_emit_align(s); |
235 | 0 | } Unexecuted instantiation: deflate_quick.c:zng_tr_emit_end_block Unexecuted instantiation: trees.c:zng_tr_emit_end_block |
236 | | |
237 | | #endif |