| 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 | */ |
| 78 | static 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 | */ |
| 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 & 0xff), (stderr, " '%c' " , c)); |
| 113 | |
| 114 | return ltree[c].Len; |
| 115 | } |
| 116 | |
| 117 | /* =========================================================================== |
| 118 | * Emit match distance/length code |
| 119 | */ |
| 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, ; |
| 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 | */ |
| 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 | Z_UNUSED(last); |
| 179 | } |
| 180 | |
| 181 | /* =========================================================================== |
| 182 | * Emit literal and count bits |
| 183 | */ |
| 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 | */ |
| 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 | */ |
| 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 = (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 | */ |
| 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 | */ |
| 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 | |