/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 const unsigned char Z_INTERNAL zng_dist_code[DIST_CODE_LEN]; |
18 | | extern const unsigned char Z_INTERNAL zng_length_code[STD_MAX_MATCH-STD_MIN_MATCH+1]; |
19 | | |
20 | | /* Combined base + extra_bits tables for single-lookup optimization */ |
21 | | extern Z_INTERNAL const uint16_t lbase_extra[LENGTH_CODES]; |
22 | | extern Z_INTERNAL const uint32_t dbase_extra[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 | | * NOTE: Static analyzers can't evaluate value of total_bits, so we |
44 | | * also need to make sure bi_valid is within acceptable range, |
45 | | * otherwise the shifts will overflow. |
46 | | */ |
47 | 12.1M | #define send_bits(s, t_val, t_len, bi_buf, bi_valid) {\ |
48 | 12.1M | uint64_t val = (uint64_t)t_val;\ |
49 | 12.1M | uint32_t len = (uint32_t)t_len;\ |
50 | 12.1M | uint32_t total_bits = bi_valid + len;\ |
51 | 12.1M | send_bits_trace(s, val, len);\ |
52 | 12.1M | sent_bits_add(s, len);\ |
53 | 12.1M | if (total_bits < BIT_BUF_SIZE && bi_valid < BIT_BUF_SIZE) {\ |
54 | 11.2M | bi_buf |= val << bi_valid;\ |
55 | 11.2M | bi_valid = total_bits;\ |
56 | 11.2M | } else if (bi_valid >= BIT_BUF_SIZE) {\ |
57 | 0 | put_uint64(s, bi_buf);\ |
58 | 0 | bi_buf = val;\ |
59 | 0 | bi_valid = len;\ |
60 | 954k | } else {\ |
61 | 954k | bi_buf |= val << bi_valid;\ |
62 | 954k | put_uint64(s, bi_buf);\ |
63 | 954k | bi_buf = val >> (BIT_BUF_SIZE - bi_valid);\ |
64 | 954k | bi_valid = total_bits - BIT_BUF_SIZE;\ |
65 | 954k | }\ |
66 | 12.1M | } |
67 | | |
68 | | /* Send a code of the given tree. c and tree must not have side effects */ |
69 | | #ifdef ZLIB_DEBUG |
70 | | # define send_code(s, c, tree, bi_buf, bi_valid) { \ |
71 | | send_code_trace(s, c); \ |
72 | | send_bits(s, tree[c].Code, tree[c].Len, bi_buf, bi_valid); \ |
73 | | } |
74 | | #else |
75 | | # define send_code(s, c, tree, bi_buf, bi_valid) \ |
76 | 10.7M | send_bits(s, tree[c].Code, tree[c].Len, bi_buf, bi_valid) |
77 | | #endif |
78 | | |
79 | | /* =========================================================================== |
80 | | * Flush the bit buffer and align the output on a byte boundary |
81 | | */ |
82 | 17.7k | static inline void bi_windup(deflate_state *s) { |
83 | 17.7k | if (s->bi_valid > 56) { |
84 | 931 | put_uint64(s, s->bi_buf); |
85 | 16.8k | } else { |
86 | 16.8k | if (s->bi_valid > 24) { |
87 | 6.27k | put_uint32(s, (uint32_t)s->bi_buf); |
88 | 6.27k | s->bi_buf >>= 32; |
89 | 6.27k | s->bi_valid -= 32; |
90 | 6.27k | } |
91 | 16.8k | if (s->bi_valid > 8) { |
92 | 5.07k | put_short(s, (uint16_t)s->bi_buf); |
93 | 5.07k | s->bi_buf >>= 16; |
94 | 5.07k | s->bi_valid -= 16; |
95 | 5.07k | } |
96 | 16.8k | if (s->bi_valid > 0) { |
97 | 12.0k | put_byte(s, s->bi_buf); |
98 | 12.0k | } |
99 | 16.8k | } |
100 | 17.7k | s->bi_buf = 0; |
101 | 17.7k | s->bi_valid = 0; |
102 | 17.7k | } Unexecuted instantiation: deflate_quick.c:bi_windup Line | Count | Source | 82 | 17.7k | static inline void bi_windup(deflate_state *s) { | 83 | 17.7k | if (s->bi_valid > 56) { | 84 | 931 | put_uint64(s, s->bi_buf); | 85 | 16.8k | } else { | 86 | 16.8k | if (s->bi_valid > 24) { | 87 | 6.27k | put_uint32(s, (uint32_t)s->bi_buf); | 88 | 6.27k | s->bi_buf >>= 32; | 89 | 6.27k | s->bi_valid -= 32; | 90 | 6.27k | } | 91 | 16.8k | if (s->bi_valid > 8) { | 92 | 5.07k | put_short(s, (uint16_t)s->bi_buf); | 93 | 5.07k | s->bi_buf >>= 16; | 94 | 5.07k | s->bi_valid -= 16; | 95 | 5.07k | } | 96 | 16.8k | if (s->bi_valid > 0) { | 97 | 12.0k | put_byte(s, s->bi_buf); | 98 | 12.0k | } | 99 | 16.8k | } | 100 | 17.7k | s->bi_buf = 0; | 101 | 17.7k | s->bi_valid = 0; | 102 | 17.7k | } |
|
103 | | |
104 | | /* =========================================================================== |
105 | | * Emit literal code |
106 | | */ |
107 | | static inline void zng_emit_lit(deflate_state *s, const ct_data *ltree, unsigned c, |
108 | 9.42M | uint64_t *bi_buf, uint32_t *bi_valid) { |
109 | 9.42M | send_code(s, c, ltree, *bi_buf, *bi_valid); |
110 | 9.42M | Tracecv(isgraph(c & 0xff), (stderr, " '%c' ", c)); |
111 | 9.42M | } Unexecuted instantiation: deflate_quick.c:zng_emit_lit Line | Count | Source | 108 | 9.42M | uint64_t *bi_buf, uint32_t *bi_valid) { | 109 | 9.42M | send_code(s, c, ltree, *bi_buf, *bi_valid); | 110 | 9.42M | Tracecv(isgraph(c & 0xff), (stderr, " '%c' ", c)); | 111 | 9.42M | } |
|
112 | | |
113 | | /* =========================================================================== |
114 | | * Emit match distance/length code |
115 | | */ |
116 | | static inline uint32_t zng_emit_dist(deflate_state *s, const ct_data *ltree, const ct_data *dtree, |
117 | 575k | uint32_t lc, uint32_t dist, uint64_t *bi_buf, uint32_t *bi_valid) { |
118 | 575k | uint32_t c, extra, lext; |
119 | 575k | uint8_t code; |
120 | 575k | uint64_t match_bits; |
121 | 575k | uint32_t match_bits_len; |
122 | | |
123 | | /* Send the length code, len is the match length - STD_MIN_MATCH */ |
124 | 575k | code = zng_length_code[lc]; |
125 | 575k | c = code+LITERALS+1; |
126 | 575k | Assert(c < L_CODES, "bad l_code"); |
127 | 575k | send_code_trace(s, c); |
128 | | |
129 | 575k | match_bits = ltree[c].Code; |
130 | 575k | match_bits_len = ltree[c].Len; |
131 | | /* Get extra bits count and subtract base length from match length */ |
132 | 575k | lext = lbase_extra[code]; |
133 | 575k | extra = lext >> 8; |
134 | 575k | lc -= lext & 0xff; |
135 | 575k | match_bits |= ((uint64_t)(lc & ((1U << extra) - 1)) << match_bits_len); |
136 | 575k | match_bits_len += extra; |
137 | | |
138 | 575k | dist--; /* dist is now the match distance - 1 */ |
139 | 575k | code = d_code(dist); |
140 | 575k | Assert(code < D_CODES, "bad d_code"); |
141 | 575k | send_code_trace(s, code); |
142 | | |
143 | | /* Send the distance code */ |
144 | 575k | match_bits |= ((uint64_t)dtree[code].Code << match_bits_len); |
145 | 575k | match_bits_len += dtree[code].Len; |
146 | | /* Get extra bits count and subtract base distance */ |
147 | 575k | lext = dbase_extra[code]; |
148 | 575k | extra = lext >> 16; |
149 | 575k | dist -= lext & 0xffff; |
150 | 575k | match_bits |= ((uint64_t)(dist & ((1U << extra) - 1)) << match_bits_len); |
151 | 575k | match_bits_len += extra; |
152 | | |
153 | 575k | send_bits(s, match_bits, match_bits_len, *bi_buf, *bi_valid); |
154 | | |
155 | 575k | return match_bits_len; |
156 | 575k | } Unexecuted instantiation: deflate_quick.c:zng_emit_dist Line | Count | Source | 117 | 575k | uint32_t lc, uint32_t dist, uint64_t *bi_buf, uint32_t *bi_valid) { | 118 | 575k | uint32_t c, extra, lext; | 119 | 575k | uint8_t code; | 120 | 575k | uint64_t match_bits; | 121 | 575k | uint32_t match_bits_len; | 122 | | | 123 | | /* Send the length code, len is the match length - STD_MIN_MATCH */ | 124 | 575k | code = zng_length_code[lc]; | 125 | 575k | c = code+LITERALS+1; | 126 | 575k | Assert(c < L_CODES, "bad l_code"); | 127 | 575k | send_code_trace(s, c); | 128 | | | 129 | 575k | match_bits = ltree[c].Code; | 130 | 575k | match_bits_len = ltree[c].Len; | 131 | | /* Get extra bits count and subtract base length from match length */ | 132 | 575k | lext = lbase_extra[code]; | 133 | 575k | extra = lext >> 8; | 134 | 575k | lc -= lext & 0xff; | 135 | 575k | match_bits |= ((uint64_t)(lc & ((1U << extra) - 1)) << match_bits_len); | 136 | 575k | match_bits_len += extra; | 137 | | | 138 | 575k | dist--; /* dist is now the match distance - 1 */ | 139 | 575k | code = d_code(dist); | 140 | 575k | Assert(code < D_CODES, "bad d_code"); | 141 | 575k | send_code_trace(s, code); | 142 | | | 143 | | /* Send the distance code */ | 144 | 575k | match_bits |= ((uint64_t)dtree[code].Code << match_bits_len); | 145 | 575k | match_bits_len += dtree[code].Len; | 146 | | /* Get extra bits count and subtract base distance */ | 147 | 575k | lext = dbase_extra[code]; | 148 | 575k | extra = lext >> 16; | 149 | 575k | dist -= lext & 0xffff; | 150 | 575k | match_bits |= ((uint64_t)(dist & ((1U << extra) - 1)) << match_bits_len); | 151 | 575k | match_bits_len += extra; | 152 | | | 153 | 575k | send_bits(s, match_bits, match_bits_len, *bi_buf, *bi_valid); | 154 | | | 155 | 575k | return match_bits_len; | 156 | 575k | } |
|
157 | | |
158 | | /* =========================================================================== |
159 | | * Emit end block |
160 | | */ |
161 | | static inline void zng_emit_end_block(deflate_state *s, const ct_data *ltree, const int last, |
162 | 39.9k | uint64_t *bi_buf, uint32_t *bi_valid) { |
163 | 39.9k | send_code(s, END_BLOCK, ltree, *bi_buf, *bi_valid); |
164 | 39.9k | Tracev((stderr, "\n+++ Emit End Block: Last: %u Pending: %u Total Out: %" PRIu64 "\n", |
165 | 39.9k | last, s->pending, (uint64_t)s->strm->total_out)); |
166 | 39.9k | Z_UNUSED(last); |
167 | 39.9k | } Unexecuted instantiation: deflate_quick.c:zng_emit_end_block trees.c:zng_emit_end_block Line | Count | Source | 162 | 39.9k | uint64_t *bi_buf, uint32_t *bi_valid) { | 163 | 39.9k | send_code(s, END_BLOCK, ltree, *bi_buf, *bi_valid); | 164 | 39.9k | Tracev((stderr, "\n+++ Emit End Block: Last: %u Pending: %u Total Out: %" PRIu64 "\n", | 165 | 39.9k | last, s->pending, (uint64_t)s->strm->total_out)); | 166 | 39.9k | Z_UNUSED(last); | 167 | 39.9k | } |
|
168 | | |
169 | | /* =========================================================================== |
170 | | * Emit literal and count bits |
171 | | */ |
172 | 0 | static inline void zng_tr_emit_lit(deflate_state *s, const ct_data *ltree, unsigned c) { |
173 | 0 | uint64_t bi_buf = s->bi_buf; |
174 | 0 | uint32_t bi_valid = s->bi_valid; |
175 | 0 | zng_emit_lit(s, ltree, c, &bi_buf, &bi_valid); |
176 | 0 | s->bi_buf = bi_buf; |
177 | 0 | s->bi_valid = bi_valid; |
178 | 0 | cmpr_bits_add(s, ltree[c].Len); |
179 | 0 | } Unexecuted instantiation: deflate_quick.c:zng_tr_emit_lit Unexecuted instantiation: trees.c:zng_tr_emit_lit |
180 | | |
181 | | /* =========================================================================== |
182 | | * Emit match and count bits |
183 | | */ |
184 | | static inline void zng_tr_emit_dist(deflate_state *s, const ct_data *ltree, const ct_data *dtree, |
185 | 0 | uint32_t lc, uint32_t dist) { |
186 | 0 | uint64_t bi_buf = s->bi_buf; |
187 | 0 | uint32_t bi_valid = s->bi_valid; |
188 | 0 | uint32_t bits = zng_emit_dist(s, ltree, dtree, lc, dist, &bi_buf, &bi_valid); |
189 | 0 | s->bi_buf = bi_buf; |
190 | 0 | s->bi_valid = bi_valid; |
191 | 0 | cmpr_bits_add(s, bits); |
192 | 0 | } Unexecuted instantiation: deflate_quick.c:zng_tr_emit_dist Unexecuted instantiation: trees.c:zng_tr_emit_dist |
193 | | |
194 | | /* =========================================================================== |
195 | | * Emit start of block |
196 | | */ |
197 | 47.4k | static inline void zng_tr_emit_tree(deflate_state *s, int type, const int last) { |
198 | 47.4k | uint32_t bi_valid = s->bi_valid; |
199 | 47.4k | uint64_t bi_buf = s->bi_buf; |
200 | 47.4k | uint32_t header_bits = (type << 1) + last; |
201 | 47.4k | send_bits(s, header_bits, 3, bi_buf, bi_valid); |
202 | 47.4k | cmpr_bits_add(s, 3); |
203 | 47.4k | s->bi_valid = bi_valid; |
204 | 47.4k | s->bi_buf = bi_buf; |
205 | 47.4k | Tracev((stderr, "\n--- Emit Tree: Last: %u\n", last)); |
206 | 47.4k | } Unexecuted instantiation: deflate_quick.c:zng_tr_emit_tree Line | Count | Source | 197 | 47.4k | static inline void zng_tr_emit_tree(deflate_state *s, int type, const int last) { | 198 | 47.4k | uint32_t bi_valid = s->bi_valid; | 199 | 47.4k | uint64_t bi_buf = s->bi_buf; | 200 | 47.4k | uint32_t header_bits = (type << 1) + last; | 201 | 47.4k | send_bits(s, header_bits, 3, bi_buf, bi_valid); | 202 | 47.4k | cmpr_bits_add(s, 3); | 203 | 47.4k | s->bi_valid = bi_valid; | 204 | 47.4k | s->bi_buf = bi_buf; | 205 | 47.4k | Tracev((stderr, "\n--- Emit Tree: Last: %u\n", last)); | 206 | 47.4k | } |
|
207 | | |
208 | | /* =========================================================================== |
209 | | * Align bit buffer on a byte boundary and count bits |
210 | | */ |
211 | 17.7k | static inline void zng_tr_emit_align(deflate_state *s) { |
212 | 17.7k | bi_windup(s); /* align on byte boundary */ |
213 | 17.7k | sent_bits_align(s); |
214 | 17.7k | } Unexecuted instantiation: deflate_quick.c:zng_tr_emit_align trees.c:zng_tr_emit_align Line | Count | Source | 211 | 17.7k | static inline void zng_tr_emit_align(deflate_state *s) { | 212 | 17.7k | bi_windup(s); /* align on byte boundary */ | 213 | 17.7k | sent_bits_align(s); | 214 | 17.7k | } |
|
215 | | |
216 | | /* =========================================================================== |
217 | | * Emit an end block and align bit buffer if last block |
218 | | */ |
219 | 0 | static inline void zng_tr_emit_end_block(deflate_state *s, const ct_data *ltree, const int last) { |
220 | 0 | uint64_t bi_buf = s->bi_buf; |
221 | 0 | uint32_t bi_valid = s->bi_valid; |
222 | 0 | zng_emit_end_block(s, ltree, last, &bi_buf, &bi_valid); |
223 | 0 | s->bi_buf = bi_buf; |
224 | 0 | s->bi_valid = bi_valid; |
225 | 0 | cmpr_bits_add(s, 7); |
226 | 0 | if (last) |
227 | 0 | zng_tr_emit_align(s); |
228 | 0 | } Unexecuted instantiation: deflate_quick.c:zng_tr_emit_end_block Unexecuted instantiation: trees.c:zng_tr_emit_end_block |
229 | | |
230 | | #endif |