/src/fluent-bit/lib/miniz/miniz_tdef.c
Line | Count | Source |
1 | | /************************************************************************** |
2 | | * |
3 | | * Copyright 2013-2014 RAD Game Tools and Valve Software |
4 | | * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC |
5 | | * All Rights Reserved. |
6 | | * |
7 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
8 | | * of this software and associated documentation files (the "Software"), to deal |
9 | | * in the Software without restriction, including without limitation the rights |
10 | | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
11 | | * copies of the Software, and to permit persons to whom the Software is |
12 | | * furnished to do so, subject to the following conditions: |
13 | | * |
14 | | * The above copyright notice and this permission notice shall be included in |
15 | | * all copies or substantial portions of the Software. |
16 | | * |
17 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
18 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
19 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
20 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
21 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
22 | | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
23 | | * THE SOFTWARE. |
24 | | * |
25 | | **************************************************************************/ |
26 | | |
27 | | #include "miniz.h" |
28 | | |
29 | | #ifndef MINIZ_NO_DEFLATE_APIS |
30 | | |
31 | | #ifdef __cplusplus |
32 | | extern "C" { |
33 | | #endif |
34 | | |
35 | | /* ------------------- Low-level Compression (independent from all decompression API's) */ |
36 | | |
37 | | /* Purposely making these tables static for faster init and thread safety. */ |
38 | | static const mz_uint16 s_tdefl_len_sym[256] = |
39 | | { |
40 | | 257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272, |
41 | | 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276, 276, 276, 276, 276, |
42 | | 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, |
43 | | 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, |
44 | | 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, |
45 | | 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, |
46 | | 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, |
47 | | 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 285 |
48 | | }; |
49 | | |
50 | | static const mz_uint8 s_tdefl_len_extra[256] = |
51 | | { |
52 | | 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
53 | | 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, |
54 | | 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, |
55 | | 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0 |
56 | | }; |
57 | | |
58 | | static const mz_uint8 s_tdefl_small_dist_sym[512] = |
59 | | { |
60 | | 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, |
61 | | 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, |
62 | | 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, |
63 | | 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, |
64 | | 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, |
65 | | 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, |
66 | | 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, |
67 | | 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, |
68 | | 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, |
69 | | 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, |
70 | | 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, |
71 | | 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17 |
72 | | }; |
73 | | |
74 | | static const mz_uint8 s_tdefl_small_dist_extra[512] = |
75 | | { |
76 | | 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, |
77 | | 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, |
78 | | 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, |
79 | | 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
80 | | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
81 | | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
82 | | 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, |
83 | | 7, 7, 7, 7, 7, 7, 7, 7 |
84 | | }; |
85 | | |
86 | | static const mz_uint8 s_tdefl_large_dist_sym[128] = |
87 | | { |
88 | | 0, 0, 18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, |
89 | | 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, |
90 | | 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 |
91 | | }; |
92 | | |
93 | | static const mz_uint8 s_tdefl_large_dist_extra[128] = |
94 | | { |
95 | | 0, 0, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, |
96 | | 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, |
97 | | 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13 |
98 | | }; |
99 | | |
100 | | /* Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. */ |
101 | | typedef struct |
102 | | { |
103 | | mz_uint16 m_key, m_sym_index; |
104 | | } tdefl_sym_freq; |
105 | | static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq *pSyms0, tdefl_sym_freq *pSyms1) |
106 | 5.63k | { |
107 | 5.63k | mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; |
108 | 5.63k | tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1; |
109 | 5.63k | MZ_CLEAR_ARR(hist); |
110 | 309k | for (i = 0; i < num_syms; i++) |
111 | 303k | { |
112 | 303k | mz_uint freq = pSyms0[i].m_key; |
113 | 303k | hist[freq & 0xFF]++; |
114 | 303k | hist[256 + ((freq >> 8) & 0xFF)]++; |
115 | 303k | } |
116 | 11.1k | while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) |
117 | 5.47k | total_passes--; |
118 | 11.4k | for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) |
119 | 5.79k | { |
120 | 5.79k | const mz_uint32 *pHist = &hist[pass << 8]; |
121 | 5.79k | mz_uint offsets[256], cur_ofs = 0; |
122 | 1.48M | for (i = 0; i < 256; i++) |
123 | 1.48M | { |
124 | 1.48M | offsets[i] = cur_ofs; |
125 | 1.48M | cur_ofs += pHist[i]; |
126 | 1.48M | } |
127 | 343k | for (i = 0; i < num_syms; i++) |
128 | 337k | pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i]; |
129 | 5.79k | { |
130 | 5.79k | tdefl_sym_freq *t = pCur_syms; |
131 | 5.79k | pCur_syms = pNew_syms; |
132 | 5.79k | pNew_syms = t; |
133 | 5.79k | } |
134 | 5.79k | } |
135 | 5.63k | return pCur_syms; |
136 | 5.63k | } |
137 | | |
138 | | /* tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. */ |
139 | | static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) |
140 | 5.63k | { |
141 | 5.63k | int root, leaf, next, avbl, used, dpth; |
142 | 5.63k | if (n == 0) |
143 | 25 | return; |
144 | 5.61k | else if (n == 1) |
145 | 44 | { |
146 | 44 | A[0].m_key = 1; |
147 | 44 | return; |
148 | 44 | } |
149 | 5.56k | A[0].m_key += A[1].m_key; |
150 | 5.56k | root = 0; |
151 | 5.56k | leaf = 2; |
152 | 298k | for (next = 1; next < n - 1; next++) |
153 | 292k | { |
154 | 292k | if (leaf >= n || A[root].m_key < A[leaf].m_key) |
155 | 144k | { |
156 | 144k | A[next].m_key = A[root].m_key; |
157 | 144k | A[root++].m_key = (mz_uint16)next; |
158 | 144k | } |
159 | 147k | else |
160 | 147k | A[next].m_key = A[leaf++].m_key; |
161 | 292k | if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key)) |
162 | 147k | { |
163 | 147k | A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key); |
164 | 147k | A[root++].m_key = (mz_uint16)next; |
165 | 147k | } |
166 | 144k | else |
167 | 144k | A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key); |
168 | 292k | } |
169 | 5.56k | A[n - 2].m_key = 0; |
170 | 298k | for (next = n - 3; next >= 0; next--) |
171 | 292k | A[next].m_key = A[A[next].m_key].m_key + 1; |
172 | 5.56k | avbl = 1; |
173 | 5.56k | used = dpth = 0; |
174 | 5.56k | root = n - 2; |
175 | 5.56k | next = n - 1; |
176 | 48.7k | while (avbl > 0) |
177 | 43.1k | { |
178 | 341k | while (root >= 0 && (int)A[root].m_key == dpth) |
179 | 298k | { |
180 | 298k | used++; |
181 | 298k | root--; |
182 | 298k | } |
183 | 346k | while (avbl > used) |
184 | 303k | { |
185 | 303k | A[next--].m_key = (mz_uint16)(dpth); |
186 | 303k | avbl--; |
187 | 303k | } |
188 | 43.1k | avbl = 2 * used; |
189 | 43.1k | dpth++; |
190 | 43.1k | used = 0; |
191 | 43.1k | } |
192 | 5.56k | } |
193 | | |
194 | | /* Limits canonical Huffman code table's max code size. */ |
195 | | enum |
196 | | { |
197 | | TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 |
198 | | }; |
199 | | static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size) |
200 | 5.63k | { |
201 | 5.63k | int i; |
202 | 5.63k | mz_uint32 total = 0; |
203 | 5.63k | if (code_list_len <= 1) |
204 | 69 | return; |
205 | 115k | for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) |
206 | 109k | pNum_codes[max_code_size] += pNum_codes[i]; |
207 | 74.0k | for (i = max_code_size; i > 0; i--) |
208 | 68.4k | total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i)); |
209 | 6.05k | while (total != (1UL << max_code_size)) |
210 | 488 | { |
211 | 488 | pNum_codes[max_code_size]--; |
212 | 683 | for (i = max_code_size - 1; i > 0; i--) |
213 | 683 | if (pNum_codes[i]) |
214 | 488 | { |
215 | 488 | pNum_codes[i]--; |
216 | 488 | pNum_codes[i + 1] += 2; |
217 | 488 | break; |
218 | 488 | } |
219 | 488 | total--; |
220 | 488 | } |
221 | 5.56k | } |
222 | | |
223 | | static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table) |
224 | 5.66k | { |
225 | 5.66k | int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; |
226 | 5.66k | mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; |
227 | 5.66k | MZ_CLEAR_ARR(num_codes); |
228 | 5.66k | if (static_table) |
229 | 26 | { |
230 | 4.18k | for (i = 0; i < table_len; i++) |
231 | 4.16k | num_codes[d->m_huff_code_sizes[table_num][i]]++; |
232 | 26 | } |
233 | 5.63k | else |
234 | 5.63k | { |
235 | 5.63k | tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms; |
236 | 5.63k | int num_used_syms = 0; |
237 | 5.63k | const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0]; |
238 | 642k | for (i = 0; i < table_len; i++) |
239 | 636k | if (pSym_count[i]) |
240 | 303k | { |
241 | 303k | syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; |
242 | 303k | syms0[num_used_syms++].m_sym_index = (mz_uint16)i; |
243 | 303k | } |
244 | | |
245 | 5.63k | pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); |
246 | 5.63k | tdefl_calculate_minimum_redundancy(pSyms, num_used_syms); |
247 | | |
248 | 309k | for (i = 0; i < num_used_syms; i++) |
249 | 303k | num_codes[pSyms[i].m_key]++; |
250 | | |
251 | 5.63k | tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit); |
252 | | |
253 | 5.63k | MZ_CLEAR_ARR(d->m_huff_code_sizes[table_num]); |
254 | 5.63k | MZ_CLEAR_ARR(d->m_huff_codes[table_num]); |
255 | 75.1k | for (i = 1, j = num_used_syms; i <= code_size_limit; i++) |
256 | 373k | for (l = num_codes[i]; l > 0; l--) |
257 | 303k | d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i); |
258 | 5.63k | } |
259 | | |
260 | 5.66k | next_code[1] = 0; |
261 | 69.9k | for (j = 0, i = 2; i <= code_size_limit; i++) |
262 | 64.2k | next_code[i] = j = ((j + num_codes[i - 1]) << 1); |
263 | | |
264 | 646k | for (i = 0; i < table_len; i++) |
265 | 641k | { |
266 | 641k | mz_uint rev_code = 0, code, code_size; |
267 | 641k | if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) |
268 | 333k | continue; |
269 | 307k | code = next_code[code_size]++; |
270 | 2.57M | for (l = code_size; l > 0; l--, code >>= 1) |
271 | 2.26M | rev_code = (rev_code << 1) | (code & 1); |
272 | 307k | d->m_huff_codes[table_num][i] = (mz_uint16)rev_code; |
273 | 307k | } |
274 | 5.66k | } |
275 | | |
276 | | #define TDEFL_PUT_BITS(b, l) \ |
277 | 4.62M | do \ |
278 | 4.62M | { \ |
279 | 4.62M | mz_uint bits = b; \ |
280 | 4.62M | mz_uint len = l; \ |
281 | 4.62M | MZ_ASSERT(bits <= ((1U << len) - 1U)); \ |
282 | 4.62M | d->m_bit_buffer |= (bits << d->m_bits_in); \ |
283 | 4.62M | d->m_bits_in += len; \ |
284 | 8.39M | while (d->m_bits_in >= 8) \ |
285 | 4.62M | { \ |
286 | 3.77M | if (d->m_pOutput_buf < d->m_pOutput_buf_end) \ |
287 | 3.77M | *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \ |
288 | 3.77M | d->m_bit_buffer >>= 8; \ |
289 | 3.77M | d->m_bits_in -= 8; \ |
290 | 3.77M | } \ |
291 | 4.62M | } \ |
292 | 4.62M | MZ_MACRO_END |
293 | | |
294 | | #define TDEFL_RLE_PREV_CODE_SIZE() \ |
295 | 468k | { \ |
296 | 468k | if (rle_repeat_count) \ |
297 | 468k | { \ |
298 | 50.1k | if (rle_repeat_count < 3) \ |
299 | 50.1k | { \ |
300 | 39.5k | d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \ |
301 | 89.2k | while (rle_repeat_count--) \ |
302 | 49.6k | packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \ |
303 | 39.5k | } \ |
304 | 50.1k | else \ |
305 | 50.1k | { \ |
306 | 10.5k | d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); \ |
307 | 10.5k | packed_code_sizes[num_packed_code_sizes++] = 16; \ |
308 | 10.5k | packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \ |
309 | 10.5k | } \ |
310 | 50.1k | rle_repeat_count = 0; \ |
311 | 50.1k | } \ |
312 | 468k | } |
313 | | |
314 | | #define TDEFL_RLE_ZERO_CODE_SIZE() \ |
315 | 285k | { \ |
316 | 285k | if (rle_z_count) \ |
317 | 285k | { \ |
318 | 79.1k | if (rle_z_count < 3) \ |
319 | 79.1k | { \ |
320 | 53.3k | d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); \ |
321 | 120k | while (rle_z_count--) \ |
322 | 67.2k | packed_code_sizes[num_packed_code_sizes++] = 0; \ |
323 | 53.3k | } \ |
324 | 79.1k | else if (rle_z_count <= 10) \ |
325 | 25.7k | { \ |
326 | 21.5k | d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); \ |
327 | 21.5k | packed_code_sizes[num_packed_code_sizes++] = 17; \ |
328 | 21.5k | packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \ |
329 | 21.5k | } \ |
330 | 25.7k | else \ |
331 | 25.7k | { \ |
332 | 4.16k | d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); \ |
333 | 4.16k | packed_code_sizes[num_packed_code_sizes++] = 18; \ |
334 | 4.16k | packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \ |
335 | 4.16k | } \ |
336 | 79.1k | rle_z_count = 0; \ |
337 | 79.1k | } \ |
338 | 285k | } |
339 | | |
340 | | static const mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; |
341 | | |
342 | | static void tdefl_start_dynamic_block(tdefl_compressor *d) |
343 | 1.87k | { |
344 | 1.87k | int num_lit_codes, num_dist_codes, num_bit_lengths; |
345 | 1.87k | mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index; |
346 | 1.87k | mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF; |
347 | | |
348 | 1.87k | d->m_huff_count[0][256] = 1; |
349 | | |
350 | 1.87k | tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE); |
351 | 1.87k | tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE); |
352 | | |
353 | 15.6k | for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) |
354 | 15.6k | if (d->m_huff_code_sizes[0][num_lit_codes - 1]) |
355 | 1.85k | break; |
356 | 21.4k | for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) |
357 | 21.4k | if (d->m_huff_code_sizes[1][num_dist_codes - 1]) |
358 | 1.81k | break; |
359 | | |
360 | 1.87k | memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes); |
361 | 1.87k | memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes); |
362 | 1.87k | total_code_sizes_to_pack = num_lit_codes + num_dist_codes; |
363 | 1.87k | num_packed_code_sizes = 0; |
364 | 1.87k | rle_z_count = 0; |
365 | 1.87k | rle_repeat_count = 0; |
366 | | |
367 | 1.87k | memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2); |
368 | 562k | for (i = 0; i < total_code_sizes_to_pack; i++) |
369 | 560k | { |
370 | 560k | mz_uint8 code_size = code_sizes_to_pack[i]; |
371 | 560k | if (!code_size) |
372 | 275k | { |
373 | 275k | TDEFL_RLE_PREV_CODE_SIZE(); |
374 | 275k | if (++rle_z_count == 138) |
375 | 67 | { |
376 | 67 | TDEFL_RLE_ZERO_CODE_SIZE(); |
377 | 67 | } |
378 | 275k | } |
379 | 284k | else |
380 | 284k | { |
381 | 284k | TDEFL_RLE_ZERO_CODE_SIZE(); |
382 | 284k | if (code_size != prev_code_size) |
383 | 187k | { |
384 | 187k | TDEFL_RLE_PREV_CODE_SIZE(); |
385 | 187k | d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); |
386 | 187k | packed_code_sizes[num_packed_code_sizes++] = code_size; |
387 | 187k | } |
388 | 96.5k | else if (++rle_repeat_count == 6) |
389 | 3.88k | { |
390 | 3.88k | TDEFL_RLE_PREV_CODE_SIZE(); |
391 | 3.88k | } |
392 | 284k | } |
393 | 560k | prev_code_size = code_size; |
394 | 560k | } |
395 | 1.87k | if (rle_repeat_count) |
396 | 472 | { |
397 | 472 | TDEFL_RLE_PREV_CODE_SIZE(); |
398 | 472 | } |
399 | 1.40k | else |
400 | 1.40k | { |
401 | 1.40k | TDEFL_RLE_ZERO_CODE_SIZE(); |
402 | 1.40k | } |
403 | | |
404 | 1.87k | tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE); |
405 | | |
406 | 1.87k | TDEFL_PUT_BITS(2, 2); |
407 | | |
408 | 1.87k | TDEFL_PUT_BITS(num_lit_codes - 257, 5); |
409 | 1.87k | TDEFL_PUT_BITS(num_dist_codes - 1, 5); |
410 | | |
411 | 7.13k | for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) |
412 | 7.13k | if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) |
413 | 1.87k | break; |
414 | 1.87k | num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); |
415 | 1.87k | TDEFL_PUT_BITS(num_bit_lengths - 4, 4); |
416 | 32.3k | for (i = 0; (int)i < num_bit_lengths; i++) |
417 | 30.4k | TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3); |
418 | | |
419 | 343k | for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;) |
420 | 341k | { |
421 | 341k | mz_uint code = packed_code_sizes[packed_code_sizes_index++]; |
422 | 341k | MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2); |
423 | 341k | TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]); |
424 | 341k | if (code >= 16) |
425 | 36.3k | TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]); |
426 | 341k | } |
427 | 1.87k | } |
428 | | |
429 | | static void tdefl_start_static_block(tdefl_compressor *d) |
430 | 13 | { |
431 | 13 | mz_uint i; |
432 | 13 | mz_uint8 *p = &d->m_huff_code_sizes[0][0]; |
433 | | |
434 | 1.88k | for (i = 0; i <= 143; ++i) |
435 | 1.87k | *p++ = 8; |
436 | 1.46k | for (; i <= 255; ++i) |
437 | 1.45k | *p++ = 9; |
438 | 325 | for (; i <= 279; ++i) |
439 | 312 | *p++ = 7; |
440 | 117 | for (; i <= 287; ++i) |
441 | 104 | *p++ = 8; |
442 | | |
443 | 13 | memset(d->m_huff_code_sizes[1], 5, 32); |
444 | | |
445 | 13 | tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE); |
446 | 13 | tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE); |
447 | | |
448 | 13 | TDEFL_PUT_BITS(1, 2); |
449 | 13 | } |
450 | | |
451 | | static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; |
452 | | |
453 | | #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS |
454 | | static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) |
455 | | { |
456 | | mz_uint flags; |
457 | | mz_uint8 *pLZ_codes; |
458 | | mz_uint8 *pOutput_buf = d->m_pOutput_buf; |
459 | | mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf; |
460 | | mz_uint64 bit_buffer = d->m_bit_buffer; |
461 | | mz_uint bits_in = d->m_bits_in; |
462 | | |
463 | | #define TDEFL_PUT_BITS_FAST(b, l) \ |
464 | | { \ |
465 | | bit_buffer |= (((mz_uint64)(b)) << bits_in); \ |
466 | | bits_in += (l); \ |
467 | | } |
468 | | |
469 | | flags = 1; |
470 | | for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1) |
471 | | { |
472 | | if (flags == 1) |
473 | | flags = *pLZ_codes++ | 0x100; |
474 | | |
475 | | if (flags & 1) |
476 | | { |
477 | | mz_uint s0, s1, n0, n1, sym, num_extra_bits; |
478 | | mz_uint match_len = pLZ_codes[0]; |
479 | | match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); |
480 | | pLZ_codes += 3; |
481 | | |
482 | | MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); |
483 | | TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); |
484 | | TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); |
485 | | |
486 | | /* This sequence coaxes MSVC into using cmov's vs. jmp's. */ |
487 | | s0 = s_tdefl_small_dist_sym[match_dist & 511]; |
488 | | n0 = s_tdefl_small_dist_extra[match_dist & 511]; |
489 | | s1 = s_tdefl_large_dist_sym[match_dist >> 8]; |
490 | | n1 = s_tdefl_large_dist_extra[match_dist >> 8]; |
491 | | sym = (match_dist < 512) ? s0 : s1; |
492 | | num_extra_bits = (match_dist < 512) ? n0 : n1; |
493 | | |
494 | | MZ_ASSERT(d->m_huff_code_sizes[1][sym]); |
495 | | TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); |
496 | | TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); |
497 | | } |
498 | | else |
499 | | { |
500 | | mz_uint lit = *pLZ_codes++; |
501 | | MZ_ASSERT(d->m_huff_code_sizes[0][lit]); |
502 | | TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); |
503 | | |
504 | | if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) |
505 | | { |
506 | | flags >>= 1; |
507 | | lit = *pLZ_codes++; |
508 | | MZ_ASSERT(d->m_huff_code_sizes[0][lit]); |
509 | | TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); |
510 | | |
511 | | if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) |
512 | | { |
513 | | flags >>= 1; |
514 | | lit = *pLZ_codes++; |
515 | | MZ_ASSERT(d->m_huff_code_sizes[0][lit]); |
516 | | TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); |
517 | | } |
518 | | } |
519 | | } |
520 | | |
521 | | if (pOutput_buf >= d->m_pOutput_buf_end) |
522 | | return MZ_FALSE; |
523 | | |
524 | | memcpy(pOutput_buf, &bit_buffer, sizeof(mz_uint64)); |
525 | | pOutput_buf += (bits_in >> 3); |
526 | | bit_buffer >>= (bits_in & ~7); |
527 | | bits_in &= 7; |
528 | | } |
529 | | |
530 | | #undef TDEFL_PUT_BITS_FAST |
531 | | |
532 | | d->m_pOutput_buf = pOutput_buf; |
533 | | d->m_bits_in = 0; |
534 | | d->m_bit_buffer = 0; |
535 | | |
536 | | while (bits_in) |
537 | | { |
538 | | mz_uint32 n = MZ_MIN(bits_in, 16); |
539 | | TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n); |
540 | | bit_buffer >>= n; |
541 | | bits_in -= n; |
542 | | } |
543 | | |
544 | | TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); |
545 | | |
546 | | return (d->m_pOutput_buf < d->m_pOutput_buf_end); |
547 | | } |
548 | | #else |
549 | | static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) |
550 | 1.89k | { |
551 | 1.89k | mz_uint flags; |
552 | 1.89k | mz_uint8 *pLZ_codes; |
553 | | |
554 | 1.89k | flags = 1; |
555 | 3.28M | for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1) |
556 | 3.28M | { |
557 | 3.28M | if (flags == 1) |
558 | 411k | flags = *pLZ_codes++ | 0x100; |
559 | 3.28M | if (flags & 1) |
560 | 184k | { |
561 | 184k | mz_uint sym, num_extra_bits; |
562 | 184k | mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); |
563 | 184k | pLZ_codes += 3; |
564 | | |
565 | 184k | MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); |
566 | 184k | TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); |
567 | 184k | TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); |
568 | | |
569 | 184k | if (match_dist < 512) |
570 | 124k | { |
571 | 124k | sym = s_tdefl_small_dist_sym[match_dist]; |
572 | 124k | num_extra_bits = s_tdefl_small_dist_extra[match_dist]; |
573 | 124k | } |
574 | 59.4k | else |
575 | 59.4k | { |
576 | 59.4k | sym = s_tdefl_large_dist_sym[match_dist >> 8]; |
577 | 59.4k | num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8]; |
578 | 59.4k | } |
579 | 184k | MZ_ASSERT(d->m_huff_code_sizes[1][sym]); |
580 | 184k | TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); |
581 | 184k | TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); |
582 | 184k | } |
583 | 3.10M | else |
584 | 3.10M | { |
585 | 3.10M | mz_uint lit = *pLZ_codes++; |
586 | 3.10M | MZ_ASSERT(d->m_huff_code_sizes[0][lit]); |
587 | 3.10M | TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); |
588 | 3.10M | } |
589 | 3.28M | } |
590 | | |
591 | 1.89k | TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); |
592 | | |
593 | 1.89k | return (d->m_pOutput_buf < d->m_pOutput_buf_end); |
594 | 1.89k | } |
595 | | #endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS */ |
596 | | |
597 | | static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) |
598 | 1.89k | { |
599 | 1.89k | if (static_block) |
600 | 13 | tdefl_start_static_block(d); |
601 | 1.87k | else |
602 | 1.87k | tdefl_start_dynamic_block(d); |
603 | 1.89k | return tdefl_compress_lz_codes(d); |
604 | 1.89k | } |
605 | | |
606 | | static const mz_uint s_tdefl_num_probes[11]; |
607 | | |
608 | | static int tdefl_flush_block(tdefl_compressor *d, int flush) |
609 | 1.89k | { |
610 | 1.89k | mz_uint saved_bit_buf, saved_bits_in; |
611 | 1.89k | mz_uint8 *pSaved_output_buf; |
612 | 1.89k | mz_bool comp_block_succeeded = MZ_FALSE; |
613 | 1.89k | int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size; |
614 | 1.89k | mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf; |
615 | | |
616 | 1.89k | d->m_pOutput_buf = pOutput_buf_start; |
617 | 1.89k | d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16; |
618 | | |
619 | 1.89k | MZ_ASSERT(!d->m_output_flush_remaining); |
620 | 1.89k | d->m_output_flush_ofs = 0; |
621 | 1.89k | d->m_output_flush_remaining = 0; |
622 | | |
623 | 1.89k | *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left); |
624 | 1.89k | d->m_pLZ_code_buf -= (d->m_num_flags_left == 8); |
625 | | |
626 | 1.89k | if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) |
627 | 0 | { |
628 | 0 | const mz_uint8 cmf = 0x78; |
629 | 0 | mz_uint8 flg, flevel = 3; |
630 | 0 | mz_uint header, i, mz_un = sizeof(s_tdefl_num_probes) / sizeof(mz_uint); |
631 | | |
632 | | /* Determine compression level by reversing the process in tdefl_create_comp_flags_from_zip_params() */ |
633 | 0 | for (i = 0; i < mz_un; i++) |
634 | 0 | if (s_tdefl_num_probes[i] == (d->m_flags & 0xFFF)) break; |
635 | |
|
636 | 0 | if (i < 2) |
637 | 0 | flevel = 0; |
638 | 0 | else if (i < 6) |
639 | 0 | flevel = 1; |
640 | 0 | else if (i == 6) |
641 | 0 | flevel = 2; |
642 | |
|
643 | 0 | header = cmf << 8 | (flevel << 6); |
644 | 0 | header += 31 - (header % 31); |
645 | 0 | flg = header & 0xFF; |
646 | |
|
647 | 0 | TDEFL_PUT_BITS(cmf, 8); |
648 | 0 | TDEFL_PUT_BITS(flg, 8); |
649 | 0 | } |
650 | | |
651 | 1.89k | TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1); |
652 | | |
653 | 1.89k | pSaved_output_buf = d->m_pOutput_buf; |
654 | 1.89k | saved_bit_buf = d->m_bit_buffer; |
655 | 1.89k | saved_bits_in = d->m_bits_in; |
656 | | |
657 | 1.89k | if (!use_raw_block) |
658 | 1.89k | comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48)); |
659 | | |
660 | | /* If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. */ |
661 | 1.89k | if (((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) && |
662 | 100 | ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size)) |
663 | 100 | { |
664 | 100 | mz_uint i; |
665 | 100 | d->m_pOutput_buf = pSaved_output_buf; |
666 | 100 | d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; |
667 | 100 | TDEFL_PUT_BITS(0, 2); |
668 | 100 | if (d->m_bits_in) |
669 | 97 | { |
670 | 97 | TDEFL_PUT_BITS(0, 8 - d->m_bits_in); |
671 | 97 | } |
672 | 300 | for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) |
673 | 200 | { |
674 | 200 | TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16); |
675 | 200 | } |
676 | 363k | for (i = 0; i < d->m_total_lz_bytes; ++i) |
677 | 362k | { |
678 | 362k | TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8); |
679 | 362k | } |
680 | 100 | } |
681 | | /* Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. */ |
682 | 1.79k | else if (!comp_block_succeeded) |
683 | 0 | { |
684 | 0 | d->m_pOutput_buf = pSaved_output_buf; |
685 | 0 | d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; |
686 | 0 | tdefl_compress_block(d, MZ_TRUE); |
687 | 0 | } |
688 | | |
689 | 1.89k | if (flush) |
690 | 1.85k | { |
691 | 1.85k | if (flush == TDEFL_FINISH) |
692 | 1.85k | { |
693 | 1.85k | if (d->m_bits_in) |
694 | 1.51k | { |
695 | 1.51k | TDEFL_PUT_BITS(0, 8 - d->m_bits_in); |
696 | 1.51k | } |
697 | 1.85k | if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) |
698 | 0 | { |
699 | 0 | mz_uint i, a = d->m_adler32; |
700 | 0 | for (i = 0; i < 4; i++) |
701 | 0 | { |
702 | 0 | TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); |
703 | 0 | a <<= 8; |
704 | 0 | } |
705 | 0 | } |
706 | 1.85k | } |
707 | 0 | else |
708 | 0 | { |
709 | 0 | mz_uint i, z = 0; |
710 | 0 | TDEFL_PUT_BITS(0, 3); |
711 | 0 | if (d->m_bits_in) |
712 | 0 | { |
713 | 0 | TDEFL_PUT_BITS(0, 8 - d->m_bits_in); |
714 | 0 | } |
715 | 0 | for (i = 2; i; --i, z ^= 0xFFFF) |
716 | 0 | { |
717 | 0 | TDEFL_PUT_BITS(z & 0xFFFF, 16); |
718 | 0 | } |
719 | 0 | } |
720 | 1.85k | } |
721 | | |
722 | 1.89k | MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end); |
723 | | |
724 | 1.89k | memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); |
725 | 1.89k | memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); |
726 | | |
727 | 1.89k | d->m_pLZ_code_buf = d->m_lz_code_buf + 1; |
728 | 1.89k | d->m_pLZ_flags = d->m_lz_code_buf; |
729 | 1.89k | d->m_num_flags_left = 8; |
730 | 1.89k | d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; |
731 | 1.89k | d->m_total_lz_bytes = 0; |
732 | 1.89k | d->m_block_index++; |
733 | | |
734 | 1.89k | if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) |
735 | 1.89k | { |
736 | 1.89k | if (d->m_pPut_buf_func) |
737 | 0 | { |
738 | 0 | *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; |
739 | 0 | if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user)) |
740 | 0 | return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED); |
741 | 0 | } |
742 | 1.89k | else if (pOutput_buf_start == d->m_output_buf) |
743 | 1.89k | { |
744 | 1.89k | int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs)); |
745 | 1.89k | memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy); |
746 | 1.89k | d->m_out_buf_ofs += bytes_to_copy; |
747 | 1.89k | if ((n -= bytes_to_copy) != 0) |
748 | 0 | { |
749 | 0 | d->m_output_flush_ofs = bytes_to_copy; |
750 | 0 | d->m_output_flush_remaining = n; |
751 | 0 | } |
752 | 1.89k | } |
753 | 0 | else |
754 | 0 | { |
755 | 0 | d->m_out_buf_ofs += n; |
756 | 0 | } |
757 | 1.89k | } |
758 | | |
759 | 1.89k | return d->m_output_flush_remaining; |
760 | 1.89k | } |
761 | | |
762 | | #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES |
763 | | #ifdef MINIZ_UNALIGNED_USE_MEMCPY |
764 | | static mz_uint16 TDEFL_READ_UNALIGNED_WORD(const mz_uint8* p) |
765 | | { |
766 | | mz_uint16 ret; |
767 | | memcpy(&ret, p, sizeof(mz_uint16)); |
768 | | return ret; |
769 | | } |
770 | | static mz_uint16 TDEFL_READ_UNALIGNED_WORD2(const mz_uint16* p) |
771 | | { |
772 | | mz_uint16 ret; |
773 | | memcpy(&ret, p, sizeof(mz_uint16)); |
774 | | return ret; |
775 | | } |
776 | | #else |
777 | | #define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16 *)(p) |
778 | | #define TDEFL_READ_UNALIGNED_WORD2(p) *(const mz_uint16 *)(p) |
779 | | #endif |
780 | | static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) |
781 | | { |
782 | | mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; |
783 | | mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; |
784 | | const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q; |
785 | | mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD2(s); |
786 | | MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); |
787 | | if (max_match_len <= match_len) |
788 | | return; |
789 | | for (;;) |
790 | | { |
791 | | for (;;) |
792 | | { |
793 | | if (--num_probes_left == 0) |
794 | | return; |
795 | | #define TDEFL_PROBE \ |
796 | | next_probe_pos = d->m_next[probe_pos]; \ |
797 | | if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \ |
798 | | return; \ |
799 | | probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ |
800 | | if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) \ |
801 | | break; |
802 | | TDEFL_PROBE; |
803 | | TDEFL_PROBE; |
804 | | TDEFL_PROBE; |
805 | | } |
806 | | if (!dist) |
807 | | break; |
808 | | q = (const mz_uint16 *)(d->m_dict + probe_pos); |
809 | | if (TDEFL_READ_UNALIGNED_WORD2(q) != s01) |
810 | | continue; |
811 | | p = s; |
812 | | probe_len = 32; |
813 | | do |
814 | | { |
815 | | } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && |
816 | | (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0)); |
817 | | if (!probe_len) |
818 | | { |
819 | | *pMatch_dist = dist; |
820 | | *pMatch_len = MZ_MIN(max_match_len, (mz_uint)TDEFL_MAX_MATCH_LEN); |
821 | | break; |
822 | | } |
823 | | else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q)) > match_len) |
824 | | { |
825 | | *pMatch_dist = dist; |
826 | | if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) |
827 | | break; |
828 | | c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]); |
829 | | } |
830 | | } |
831 | | } |
832 | | #else |
833 | | static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) |
834 | 3.28M | { |
835 | 3.28M | mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; |
836 | 3.28M | mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; |
837 | 3.28M | const mz_uint8 *s = d->m_dict + pos, *p, *q; |
838 | 3.28M | mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1]; |
839 | 3.28M | MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); |
840 | 3.28M | if (max_match_len <= match_len) |
841 | 2.29k | return; |
842 | 3.28M | for (;;) |
843 | 4.66M | { |
844 | 4.66M | for (;;) |
845 | 6.45M | { |
846 | 6.45M | if (--num_probes_left == 0) |
847 | 38.4k | return; |
848 | 6.41M | #define TDEFL_PROBE \ |
849 | 11.1M | next_probe_pos = d->m_next[probe_pos]; \ |
850 | 11.1M | if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \ |
851 | 11.1M | return; \ |
852 | 11.1M | probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ |
853 | 7.95M | if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) \ |
854 | 7.95M | break; |
855 | 13.1M | TDEFL_PROBE; |
856 | 13.1M | TDEFL_PROBE; |
857 | 4.17M | TDEFL_PROBE; |
858 | 3.61M | } |
859 | 1.39M | if (!dist) |
860 | 0 | break; |
861 | 1.39M | p = s; |
862 | 1.39M | q = d->m_dict + probe_pos; |
863 | 15.9M | for (probe_len = 0; probe_len < max_match_len; probe_len++) |
864 | 15.9M | if (*p++ != *q++) |
865 | 1.38M | break; |
866 | 1.39M | if (probe_len > match_len) |
867 | 634k | { |
868 | 634k | *pMatch_dist = dist; |
869 | 634k | if ((*pMatch_len = match_len = probe_len) == max_match_len) |
870 | 8.90k | return; |
871 | 625k | c0 = d->m_dict[pos + match_len]; |
872 | 625k | c1 = d->m_dict[pos + match_len - 1]; |
873 | 625k | } |
874 | 1.39M | } |
875 | 3.28M | } |
876 | | #endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES */ |
877 | | |
878 | | #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN |
879 | | #ifdef MINIZ_UNALIGNED_USE_MEMCPY |
880 | | static mz_uint32 TDEFL_READ_UNALIGNED_WORD32(const mz_uint8* p) |
881 | | { |
882 | | mz_uint32 ret; |
883 | | memcpy(&ret, p, sizeof(mz_uint32)); |
884 | | return ret; |
885 | | } |
886 | | #else |
887 | | #define TDEFL_READ_UNALIGNED_WORD32(p) *(const mz_uint32 *)(p) |
888 | | #endif |
889 | | static mz_bool tdefl_compress_fast(tdefl_compressor *d) |
890 | | { |
891 | | /* Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. */ |
892 | | mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left; |
893 | | mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags; |
894 | | mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; |
895 | | |
896 | | while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) |
897 | | { |
898 | | const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096; |
899 | | mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; |
900 | | mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size); |
901 | | d->m_src_buf_left -= num_bytes_to_process; |
902 | | lookahead_size += num_bytes_to_process; |
903 | | |
904 | | while (num_bytes_to_process) |
905 | | { |
906 | | mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process); |
907 | | memcpy(d->m_dict + dst_pos, d->m_pSrc, n); |
908 | | if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) |
909 | | memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos)); |
910 | | d->m_pSrc += n; |
911 | | dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK; |
912 | | num_bytes_to_process -= n; |
913 | | } |
914 | | |
915 | | dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size); |
916 | | if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) |
917 | | break; |
918 | | |
919 | | while (lookahead_size >= 4) |
920 | | { |
921 | | mz_uint cur_match_dist, cur_match_len = 1; |
922 | | mz_uint8 *pCur_dict = d->m_dict + cur_pos; |
923 | | mz_uint first_trigram = TDEFL_READ_UNALIGNED_WORD32(pCur_dict) & 0xFFFFFF; |
924 | | mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK; |
925 | | mz_uint probe_pos = d->m_hash[hash]; |
926 | | d->m_hash[hash] = (mz_uint16)lookahead_pos; |
927 | | |
928 | | if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((TDEFL_READ_UNALIGNED_WORD32(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) |
929 | | { |
930 | | const mz_uint16 *p = (const mz_uint16 *)pCur_dict; |
931 | | const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos); |
932 | | mz_uint32 probe_len = 32; |
933 | | do |
934 | | { |
935 | | } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && |
936 | | (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0)); |
937 | | cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q); |
938 | | if (!probe_len) |
939 | | cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0; |
940 | | |
941 | | if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U))) |
942 | | { |
943 | | cur_match_len = 1; |
944 | | *pLZ_code_buf++ = (mz_uint8)first_trigram; |
945 | | *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); |
946 | | d->m_huff_count[0][(mz_uint8)first_trigram]++; |
947 | | } |
948 | | else |
949 | | { |
950 | | mz_uint32 s0, s1; |
951 | | cur_match_len = MZ_MIN(cur_match_len, lookahead_size); |
952 | | |
953 | | MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE)); |
954 | | |
955 | | cur_match_dist--; |
956 | | |
957 | | pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN); |
958 | | #ifdef MINIZ_UNALIGNED_USE_MEMCPY |
959 | | memcpy(&pLZ_code_buf[1], &cur_match_dist, sizeof(cur_match_dist)); |
960 | | #else |
961 | | *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist; |
962 | | #endif |
963 | | pLZ_code_buf += 3; |
964 | | *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80); |
965 | | |
966 | | s0 = s_tdefl_small_dist_sym[cur_match_dist & 511]; |
967 | | s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8]; |
968 | | d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++; |
969 | | |
970 | | d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++; |
971 | | } |
972 | | } |
973 | | else |
974 | | { |
975 | | *pLZ_code_buf++ = (mz_uint8)first_trigram; |
976 | | *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); |
977 | | d->m_huff_count[0][(mz_uint8)first_trigram]++; |
978 | | } |
979 | | |
980 | | if (--num_flags_left == 0) |
981 | | { |
982 | | num_flags_left = 8; |
983 | | pLZ_flags = pLZ_code_buf++; |
984 | | } |
985 | | |
986 | | total_lz_bytes += cur_match_len; |
987 | | lookahead_pos += cur_match_len; |
988 | | dict_size = MZ_MIN(dict_size + cur_match_len, (mz_uint)TDEFL_LZ_DICT_SIZE); |
989 | | cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK; |
990 | | MZ_ASSERT(lookahead_size >= cur_match_len); |
991 | | lookahead_size -= cur_match_len; |
992 | | |
993 | | if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) |
994 | | { |
995 | | int n; |
996 | | d->m_lookahead_pos = lookahead_pos; |
997 | | d->m_lookahead_size = lookahead_size; |
998 | | d->m_dict_size = dict_size; |
999 | | d->m_total_lz_bytes = total_lz_bytes; |
1000 | | d->m_pLZ_code_buf = pLZ_code_buf; |
1001 | | d->m_pLZ_flags = pLZ_flags; |
1002 | | d->m_num_flags_left = num_flags_left; |
1003 | | if ((n = tdefl_flush_block(d, 0)) != 0) |
1004 | | return (n < 0) ? MZ_FALSE : MZ_TRUE; |
1005 | | total_lz_bytes = d->m_total_lz_bytes; |
1006 | | pLZ_code_buf = d->m_pLZ_code_buf; |
1007 | | pLZ_flags = d->m_pLZ_flags; |
1008 | | num_flags_left = d->m_num_flags_left; |
1009 | | } |
1010 | | } |
1011 | | |
1012 | | while (lookahead_size) |
1013 | | { |
1014 | | mz_uint8 lit = d->m_dict[cur_pos]; |
1015 | | |
1016 | | total_lz_bytes++; |
1017 | | *pLZ_code_buf++ = lit; |
1018 | | *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); |
1019 | | if (--num_flags_left == 0) |
1020 | | { |
1021 | | num_flags_left = 8; |
1022 | | pLZ_flags = pLZ_code_buf++; |
1023 | | } |
1024 | | |
1025 | | d->m_huff_count[0][lit]++; |
1026 | | |
1027 | | lookahead_pos++; |
1028 | | dict_size = MZ_MIN(dict_size + 1, (mz_uint)TDEFL_LZ_DICT_SIZE); |
1029 | | cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; |
1030 | | lookahead_size--; |
1031 | | |
1032 | | if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) |
1033 | | { |
1034 | | int n; |
1035 | | d->m_lookahead_pos = lookahead_pos; |
1036 | | d->m_lookahead_size = lookahead_size; |
1037 | | d->m_dict_size = dict_size; |
1038 | | d->m_total_lz_bytes = total_lz_bytes; |
1039 | | d->m_pLZ_code_buf = pLZ_code_buf; |
1040 | | d->m_pLZ_flags = pLZ_flags; |
1041 | | d->m_num_flags_left = num_flags_left; |
1042 | | if ((n = tdefl_flush_block(d, 0)) != 0) |
1043 | | return (n < 0) ? MZ_FALSE : MZ_TRUE; |
1044 | | total_lz_bytes = d->m_total_lz_bytes; |
1045 | | pLZ_code_buf = d->m_pLZ_code_buf; |
1046 | | pLZ_flags = d->m_pLZ_flags; |
1047 | | num_flags_left = d->m_num_flags_left; |
1048 | | } |
1049 | | } |
1050 | | } |
1051 | | |
1052 | | d->m_lookahead_pos = lookahead_pos; |
1053 | | d->m_lookahead_size = lookahead_size; |
1054 | | d->m_dict_size = dict_size; |
1055 | | d->m_total_lz_bytes = total_lz_bytes; |
1056 | | d->m_pLZ_code_buf = pLZ_code_buf; |
1057 | | d->m_pLZ_flags = pLZ_flags; |
1058 | | d->m_num_flags_left = num_flags_left; |
1059 | | return MZ_TRUE; |
1060 | | } |
1061 | | #endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */ |
1062 | | |
1063 | | static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit) |
1064 | 3.10M | { |
1065 | 3.10M | d->m_total_lz_bytes++; |
1066 | 3.10M | *d->m_pLZ_code_buf++ = lit; |
1067 | 3.10M | *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); |
1068 | 3.10M | if (--d->m_num_flags_left == 0) |
1069 | 386k | { |
1070 | 386k | d->m_num_flags_left = 8; |
1071 | 386k | d->m_pLZ_flags = d->m_pLZ_code_buf++; |
1072 | 386k | } |
1073 | 3.10M | d->m_huff_count[0][lit]++; |
1074 | 3.10M | } |
1075 | | |
1076 | | static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist) |
1077 | 184k | { |
1078 | 184k | mz_uint32 s0, s1; |
1079 | | |
1080 | 184k | MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE)); |
1081 | | |
1082 | 184k | d->m_total_lz_bytes += match_len; |
1083 | | |
1084 | 184k | d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN); |
1085 | | |
1086 | 184k | match_dist -= 1; |
1087 | 184k | d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF); |
1088 | 184k | d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); |
1089 | 184k | d->m_pLZ_code_buf += 3; |
1090 | | |
1091 | 184k | *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); |
1092 | 184k | if (--d->m_num_flags_left == 0) |
1093 | 23.1k | { |
1094 | 23.1k | d->m_num_flags_left = 8; |
1095 | 23.1k | d->m_pLZ_flags = d->m_pLZ_code_buf++; |
1096 | 23.1k | } |
1097 | | |
1098 | 184k | s0 = s_tdefl_small_dist_sym[match_dist & 511]; |
1099 | 184k | s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127]; |
1100 | 184k | d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++; |
1101 | 184k | d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++; |
1102 | 184k | } |
1103 | | |
1104 | | static mz_bool tdefl_compress_normal(tdefl_compressor *d) |
1105 | 3.71k | { |
1106 | 3.71k | const mz_uint8 *pSrc = d->m_pSrc; |
1107 | 3.71k | size_t src_buf_left = d->m_src_buf_left; |
1108 | 3.71k | tdefl_flush flush = d->m_flush; |
1109 | | |
1110 | 3.28M | while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) |
1111 | 3.28M | { |
1112 | 3.28M | mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos; |
1113 | | /* Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. */ |
1114 | 3.28M | if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) |
1115 | 3.28M | { |
1116 | 3.28M | mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2; |
1117 | 3.28M | mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]; |
1118 | 3.28M | mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size); |
1119 | 3.28M | const mz_uint8 *pSrc_end = pSrc ? pSrc + num_bytes_to_process : NULL; |
1120 | 3.28M | src_buf_left -= num_bytes_to_process; |
1121 | 3.28M | d->m_lookahead_size += num_bytes_to_process; |
1122 | 11.2M | while (pSrc != pSrc_end) |
1123 | 8.00M | { |
1124 | 8.00M | mz_uint8 c = *pSrc++; |
1125 | 8.00M | d->m_dict[dst_pos] = c; |
1126 | 8.00M | if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) |
1127 | 0 | d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; |
1128 | 8.00M | hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); |
1129 | 8.00M | d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; |
1130 | 8.00M | d->m_hash[hash] = (mz_uint16)(ins_pos); |
1131 | 8.00M | dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; |
1132 | 8.00M | ins_pos++; |
1133 | 8.00M | } |
1134 | 3.28M | } |
1135 | 1.85k | else |
1136 | 1.85k | { |
1137 | 480k | while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) |
1138 | 478k | { |
1139 | 478k | mz_uint8 c = *pSrc++; |
1140 | 478k | mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; |
1141 | 478k | src_buf_left--; |
1142 | 478k | d->m_dict[dst_pos] = c; |
1143 | 478k | if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) |
1144 | 476k | d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; |
1145 | 478k | if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) |
1146 | 474k | { |
1147 | 474k | mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2; |
1148 | 474k | mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); |
1149 | 474k | d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; |
1150 | 474k | d->m_hash[hash] = (mz_uint16)(ins_pos); |
1151 | 474k | } |
1152 | 478k | } |
1153 | 1.85k | } |
1154 | 3.28M | d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size); |
1155 | 3.28M | if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) |
1156 | 1.27k | break; |
1157 | | |
1158 | | /* Simple lazy/greedy parsing state machine. */ |
1159 | 3.28M | len_to_move = 1; |
1160 | 3.28M | cur_match_dist = 0; |
1161 | 3.28M | cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); |
1162 | 3.28M | cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; |
1163 | 3.28M | if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) |
1164 | 0 | { |
1165 | 0 | if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) |
1166 | 0 | { |
1167 | 0 | mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK]; |
1168 | 0 | cur_match_len = 0; |
1169 | 0 | while (cur_match_len < d->m_lookahead_size) |
1170 | 0 | { |
1171 | 0 | if (d->m_dict[cur_pos + cur_match_len] != c) |
1172 | 0 | break; |
1173 | 0 | cur_match_len++; |
1174 | 0 | } |
1175 | 0 | if (cur_match_len < TDEFL_MIN_MATCH_LEN) |
1176 | 0 | cur_match_len = 0; |
1177 | 0 | else |
1178 | 0 | cur_match_dist = 1; |
1179 | 0 | } |
1180 | 0 | } |
1181 | 3.28M | else |
1182 | 3.28M | { |
1183 | 3.28M | tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len); |
1184 | 3.28M | } |
1185 | 3.28M | if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) |
1186 | 5.73k | { |
1187 | 5.73k | cur_match_dist = cur_match_len = 0; |
1188 | 5.73k | } |
1189 | 3.28M | if (d->m_saved_match_len) |
1190 | 0 | { |
1191 | 0 | if (cur_match_len > d->m_saved_match_len) |
1192 | 0 | { |
1193 | 0 | tdefl_record_literal(d, (mz_uint8)d->m_saved_lit); |
1194 | 0 | if (cur_match_len >= 128) |
1195 | 0 | { |
1196 | 0 | tdefl_record_match(d, cur_match_len, cur_match_dist); |
1197 | 0 | d->m_saved_match_len = 0; |
1198 | 0 | len_to_move = cur_match_len; |
1199 | 0 | } |
1200 | 0 | else |
1201 | 0 | { |
1202 | 0 | d->m_saved_lit = d->m_dict[cur_pos]; |
1203 | 0 | d->m_saved_match_dist = cur_match_dist; |
1204 | 0 | d->m_saved_match_len = cur_match_len; |
1205 | 0 | } |
1206 | 0 | } |
1207 | 0 | else |
1208 | 0 | { |
1209 | 0 | tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist); |
1210 | 0 | len_to_move = d->m_saved_match_len - 1; |
1211 | 0 | d->m_saved_match_len = 0; |
1212 | 0 | } |
1213 | 0 | } |
1214 | 3.28M | else if (!cur_match_dist) |
1215 | 3.10M | tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]); |
1216 | 184k | else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128)) |
1217 | 184k | { |
1218 | 184k | tdefl_record_match(d, cur_match_len, cur_match_dist); |
1219 | 184k | len_to_move = cur_match_len; |
1220 | 184k | } |
1221 | 0 | else |
1222 | 0 | { |
1223 | 0 | d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; |
1224 | 0 | d->m_saved_match_dist = cur_match_dist; |
1225 | 0 | d->m_saved_match_len = cur_match_len; |
1226 | 0 | } |
1227 | | /* Move the lookahead forward by len_to_move bytes. */ |
1228 | 3.28M | d->m_lookahead_pos += len_to_move; |
1229 | 3.28M | MZ_ASSERT(d->m_lookahead_size >= len_to_move); |
1230 | 3.28M | d->m_lookahead_size -= len_to_move; |
1231 | 3.28M | d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, (mz_uint)TDEFL_LZ_DICT_SIZE); |
1232 | | /* Check if it's time to flush the current LZ codes to the internal output buffer. */ |
1233 | 3.28M | if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) || |
1234 | 3.28M | ((d->m_total_lz_bytes > 31 * 1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))) |
1235 | 37 | { |
1236 | 37 | int n; |
1237 | 37 | d->m_pSrc = pSrc; |
1238 | 37 | d->m_src_buf_left = src_buf_left; |
1239 | 37 | if ((n = tdefl_flush_block(d, 0)) != 0) |
1240 | 0 | return (n < 0) ? MZ_FALSE : MZ_TRUE; |
1241 | 37 | } |
1242 | 3.28M | } |
1243 | | |
1244 | 3.71k | d->m_pSrc = pSrc; |
1245 | 3.71k | d->m_src_buf_left = src_buf_left; |
1246 | 3.71k | return MZ_TRUE; |
1247 | 3.71k | } |
1248 | | |
1249 | | static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) |
1250 | 3.71k | { |
1251 | 3.71k | if (d->m_pIn_buf_size) |
1252 | 3.71k | { |
1253 | 3.71k | *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; |
1254 | 3.71k | } |
1255 | | |
1256 | 3.71k | if (d->m_pOut_buf_size) |
1257 | 3.71k | { |
1258 | 3.71k | size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining); |
1259 | 3.71k | memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n); |
1260 | 3.71k | d->m_output_flush_ofs += (mz_uint)n; |
1261 | 3.71k | d->m_output_flush_remaining -= (mz_uint)n; |
1262 | 3.71k | d->m_out_buf_ofs += n; |
1263 | | |
1264 | 3.71k | *d->m_pOut_buf_size = d->m_out_buf_ofs; |
1265 | 3.71k | } |
1266 | | |
1267 | 3.71k | return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY; |
1268 | 3.71k | } |
1269 | | |
1270 | | tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush) |
1271 | 3.71k | { |
1272 | 3.71k | if (!d) |
1273 | 0 | { |
1274 | 0 | if (pIn_buf_size) |
1275 | 0 | *pIn_buf_size = 0; |
1276 | 0 | if (pOut_buf_size) |
1277 | 0 | *pOut_buf_size = 0; |
1278 | 0 | return TDEFL_STATUS_BAD_PARAM; |
1279 | 0 | } |
1280 | | |
1281 | 3.71k | d->m_pIn_buf = pIn_buf; |
1282 | 3.71k | d->m_pIn_buf_size = pIn_buf_size; |
1283 | 3.71k | d->m_pOut_buf = pOut_buf; |
1284 | 3.71k | d->m_pOut_buf_size = pOut_buf_size; |
1285 | 3.71k | d->m_pSrc = (const mz_uint8 *)(pIn_buf); |
1286 | 3.71k | d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0; |
1287 | 3.71k | d->m_out_buf_ofs = 0; |
1288 | 3.71k | d->m_flush = flush; |
1289 | | |
1290 | 3.71k | if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) || |
1291 | 3.71k | (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf)) |
1292 | 0 | { |
1293 | 0 | if (pIn_buf_size) |
1294 | 0 | *pIn_buf_size = 0; |
1295 | 0 | if (pOut_buf_size) |
1296 | 0 | *pOut_buf_size = 0; |
1297 | 0 | return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM); |
1298 | 0 | } |
1299 | 3.71k | d->m_wants_to_finish |= (flush == TDEFL_FINISH); |
1300 | | |
1301 | 3.71k | if ((d->m_output_flush_remaining) || (d->m_finished)) |
1302 | 0 | return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); |
1303 | | |
1304 | | #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN |
1305 | | if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) && |
1306 | | ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) && |
1307 | | ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0)) |
1308 | | { |
1309 | | if (!tdefl_compress_fast(d)) |
1310 | | return d->m_prev_return_status; |
1311 | | } |
1312 | | else |
1313 | | #endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */ |
1314 | 3.71k | { |
1315 | 3.71k | if (!tdefl_compress_normal(d)) |
1316 | 0 | return d->m_prev_return_status; |
1317 | 3.71k | } |
1318 | | |
1319 | 3.71k | if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf)) |
1320 | 3.71k | d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf); |
1321 | | |
1322 | 3.71k | if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining)) |
1323 | 1.85k | { |
1324 | 1.85k | if (tdefl_flush_block(d, flush) < 0) |
1325 | 0 | return d->m_prev_return_status; |
1326 | 1.85k | d->m_finished = (flush == TDEFL_FINISH); |
1327 | 1.85k | if (flush == TDEFL_FULL_FLUSH) |
1328 | 0 | { |
1329 | 0 | MZ_CLEAR_ARR(d->m_hash); |
1330 | 0 | MZ_CLEAR_ARR(d->m_next); |
1331 | 0 | d->m_dict_size = 0; |
1332 | 0 | } |
1333 | 1.85k | } |
1334 | | |
1335 | 3.71k | return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); |
1336 | 3.71k | } |
1337 | | |
1338 | | tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush) |
1339 | 0 | { |
1340 | 0 | MZ_ASSERT(d->m_pPut_buf_func); |
1341 | 0 | return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush); |
1342 | 0 | } |
1343 | | |
1344 | | tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) |
1345 | 1.85k | { |
1346 | 1.85k | d->m_pPut_buf_func = pPut_buf_func; |
1347 | 1.85k | d->m_pPut_buf_user = pPut_buf_user; |
1348 | 1.85k | d->m_flags = (mz_uint)(flags); |
1349 | 1.85k | d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; |
1350 | 1.85k | d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0; |
1351 | 1.85k | d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3; |
1352 | 1.85k | if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) |
1353 | 1.85k | MZ_CLEAR_ARR(d->m_hash); |
1354 | 1.85k | d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0; |
1355 | 1.85k | d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0; |
1356 | 1.85k | d->m_pLZ_code_buf = d->m_lz_code_buf + 1; |
1357 | 1.85k | d->m_pLZ_flags = d->m_lz_code_buf; |
1358 | 1.85k | *d->m_pLZ_flags = 0; |
1359 | 1.85k | d->m_num_flags_left = 8; |
1360 | 1.85k | d->m_pOutput_buf = d->m_output_buf; |
1361 | 1.85k | d->m_pOutput_buf_end = d->m_output_buf; |
1362 | 1.85k | d->m_prev_return_status = TDEFL_STATUS_OKAY; |
1363 | 1.85k | d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; |
1364 | 1.85k | d->m_adler32 = 1; |
1365 | 1.85k | d->m_pIn_buf = NULL; |
1366 | 1.85k | d->m_pOut_buf = NULL; |
1367 | 1.85k | d->m_pIn_buf_size = NULL; |
1368 | 1.85k | d->m_pOut_buf_size = NULL; |
1369 | 1.85k | d->m_flush = TDEFL_NO_FLUSH; |
1370 | 1.85k | d->m_pSrc = NULL; |
1371 | 1.85k | d->m_src_buf_left = 0; |
1372 | 1.85k | d->m_out_buf_ofs = 0; |
1373 | 1.85k | if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) |
1374 | 1.85k | MZ_CLEAR_ARR(d->m_dict); |
1375 | 1.85k | memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); |
1376 | 1.85k | memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); |
1377 | 1.85k | return TDEFL_STATUS_OKAY; |
1378 | 1.85k | } |
1379 | | |
1380 | | tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) |
1381 | 0 | { |
1382 | 0 | return d->m_prev_return_status; |
1383 | 0 | } |
1384 | | |
1385 | | mz_uint32 tdefl_get_adler32(tdefl_compressor *d) |
1386 | 3.71k | { |
1387 | 3.71k | return d->m_adler32; |
1388 | 3.71k | } |
1389 | | |
1390 | | mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) |
1391 | 0 | { |
1392 | 0 | tdefl_compressor *pComp; |
1393 | 0 | mz_bool succeeded; |
1394 | 0 | if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) |
1395 | 0 | return MZ_FALSE; |
1396 | 0 | pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); |
1397 | 0 | if (!pComp) |
1398 | 0 | return MZ_FALSE; |
1399 | 0 | succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY); |
1400 | 0 | succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE); |
1401 | 0 | MZ_FREE(pComp); |
1402 | 0 | return succeeded; |
1403 | 0 | } |
1404 | | |
1405 | | typedef struct |
1406 | | { |
1407 | | size_t m_size, m_capacity; |
1408 | | mz_uint8 *m_pBuf; |
1409 | | mz_bool m_expandable; |
1410 | | } tdefl_output_buffer; |
1411 | | |
1412 | | static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser) |
1413 | 0 | { |
1414 | 0 | tdefl_output_buffer *p = (tdefl_output_buffer *)pUser; |
1415 | 0 | size_t new_size = p->m_size + len; |
1416 | 0 | if (new_size > p->m_capacity) |
1417 | 0 | { |
1418 | 0 | size_t new_capacity = p->m_capacity; |
1419 | 0 | mz_uint8 *pNew_buf; |
1420 | 0 | if (!p->m_expandable) |
1421 | 0 | return MZ_FALSE; |
1422 | 0 | do |
1423 | 0 | { |
1424 | 0 | new_capacity = MZ_MAX(128U, new_capacity << 1U); |
1425 | 0 | } while (new_size > new_capacity); |
1426 | 0 | pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity); |
1427 | 0 | if (!pNew_buf) |
1428 | 0 | return MZ_FALSE; |
1429 | 0 | p->m_pBuf = pNew_buf; |
1430 | 0 | p->m_capacity = new_capacity; |
1431 | 0 | } |
1432 | 0 | memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len); |
1433 | 0 | p->m_size = new_size; |
1434 | 0 | return MZ_TRUE; |
1435 | 0 | } |
1436 | | |
1437 | | void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) |
1438 | 0 | { |
1439 | 0 | tdefl_output_buffer out_buf; |
1440 | 0 | MZ_CLEAR_OBJ(out_buf); |
1441 | 0 | if (!pOut_len) |
1442 | 0 | return MZ_FALSE; |
1443 | 0 | else |
1444 | 0 | *pOut_len = 0; |
1445 | 0 | out_buf.m_expandable = MZ_TRUE; |
1446 | 0 | if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) |
1447 | 0 | return NULL; |
1448 | 0 | *pOut_len = out_buf.m_size; |
1449 | 0 | return out_buf.m_pBuf; |
1450 | 0 | } |
1451 | | |
1452 | | size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) |
1453 | 0 | { |
1454 | 0 | tdefl_output_buffer out_buf; |
1455 | 0 | MZ_CLEAR_OBJ(out_buf); |
1456 | 0 | if (!pOut_buf) |
1457 | 0 | return 0; |
1458 | 0 | out_buf.m_pBuf = (mz_uint8 *)pOut_buf; |
1459 | 0 | out_buf.m_capacity = out_buf_len; |
1460 | 0 | if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) |
1461 | 0 | return 0; |
1462 | 0 | return out_buf.m_size; |
1463 | 0 | } |
1464 | | |
1465 | | static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; |
1466 | | |
1467 | | /* level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). */ |
1468 | | mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy) |
1469 | 1.85k | { |
1470 | 1.85k | mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); |
1471 | 1.85k | if (window_bits > 0) |
1472 | 0 | comp_flags |= TDEFL_WRITE_ZLIB_HEADER; |
1473 | | |
1474 | 1.85k | if (!level) |
1475 | 0 | comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; |
1476 | 1.85k | else if (strategy == MZ_FILTERED) |
1477 | 0 | comp_flags |= TDEFL_FILTER_MATCHES; |
1478 | 1.85k | else if (strategy == MZ_HUFFMAN_ONLY) |
1479 | 0 | comp_flags &= ~TDEFL_MAX_PROBES_MASK; |
1480 | 1.85k | else if (strategy == MZ_FIXED) |
1481 | 0 | comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; |
1482 | 1.85k | else if (strategy == MZ_RLE) |
1483 | 0 | comp_flags |= TDEFL_RLE_MATCHES; |
1484 | | |
1485 | 1.85k | return comp_flags; |
1486 | 1.85k | } |
1487 | | |
1488 | | #ifdef _MSC_VER |
1489 | | #pragma warning(push) |
1490 | | #pragma warning(disable : 4204) /* nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) */ |
1491 | | #endif |
1492 | | |
1493 | | /* Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at |
1494 | | http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/. |
1495 | | This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck. */ |
1496 | | void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip) |
1497 | 0 | { |
1498 | | /* Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. */ |
1499 | 0 | static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; |
1500 | 0 | tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); |
1501 | 0 | tdefl_output_buffer out_buf; |
1502 | 0 | int i, bpl = w * num_chans, y, z; |
1503 | 0 | mz_uint32 c; |
1504 | 0 | *pLen_out = 0; |
1505 | 0 | if (!pComp) |
1506 | 0 | return NULL; |
1507 | 0 | MZ_CLEAR_OBJ(out_buf); |
1508 | 0 | out_buf.m_expandable = MZ_TRUE; |
1509 | 0 | out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h); |
1510 | 0 | if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity))) |
1511 | 0 | { |
1512 | 0 | MZ_FREE(pComp); |
1513 | 0 | return NULL; |
1514 | 0 | } |
1515 | | /* write dummy header */ |
1516 | 0 | for (z = 41; z; --z) |
1517 | 0 | tdefl_output_buffer_putter(&z, 1, &out_buf); |
1518 | | /* compress image data */ |
1519 | 0 | tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER); |
1520 | 0 | for (y = 0; y < h; ++y) |
1521 | 0 | { |
1522 | 0 | tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); |
1523 | 0 | tdefl_compress_buffer(pComp, (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); |
1524 | 0 | } |
1525 | 0 | if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) |
1526 | 0 | { |
1527 | 0 | MZ_FREE(pComp); |
1528 | 0 | MZ_FREE(out_buf.m_pBuf); |
1529 | 0 | return NULL; |
1530 | 0 | } |
1531 | | /* write real header */ |
1532 | 0 | *pLen_out = out_buf.m_size - 41; |
1533 | 0 | { |
1534 | 0 | static const mz_uint8 chans[] = { 0x00, 0x00, 0x04, 0x02, 0x06 }; |
1535 | 0 | mz_uint8 pnghdr[41] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, |
1536 | 0 | 0x0a, 0x1a, 0x0a, 0x00, 0x00, |
1537 | 0 | 0x00, 0x0d, 0x49, 0x48, 0x44, |
1538 | 0 | 0x52, 0x00, 0x00, 0x00, 0x00, |
1539 | 0 | 0x00, 0x00, 0x00, 0x00, 0x08, |
1540 | 0 | 0x00, 0x00, 0x00, 0x00, 0x00, |
1541 | 0 | 0x00, 0x00, 0x00, 0x00, 0x00, |
1542 | 0 | 0x00, 0x00, 0x49, 0x44, 0x41, |
1543 | 0 | 0x54 }; |
1544 | 0 | pnghdr[18] = (mz_uint8)(w >> 8); |
1545 | 0 | pnghdr[19] = (mz_uint8)w; |
1546 | 0 | pnghdr[22] = (mz_uint8)(h >> 8); |
1547 | 0 | pnghdr[23] = (mz_uint8)h; |
1548 | 0 | pnghdr[25] = chans[num_chans]; |
1549 | 0 | pnghdr[33] = (mz_uint8)(*pLen_out >> 24); |
1550 | 0 | pnghdr[34] = (mz_uint8)(*pLen_out >> 16); |
1551 | 0 | pnghdr[35] = (mz_uint8)(*pLen_out >> 8); |
1552 | 0 | pnghdr[36] = (mz_uint8)*pLen_out; |
1553 | 0 | c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17); |
1554 | 0 | for (i = 0; i < 4; ++i, c <<= 8) |
1555 | 0 | ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24); |
1556 | 0 | memcpy(out_buf.m_pBuf, pnghdr, 41); |
1557 | 0 | } |
1558 | | /* write footer (IDAT CRC-32, followed by IEND chunk) */ |
1559 | 0 | if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) |
1560 | 0 | { |
1561 | 0 | *pLen_out = 0; |
1562 | 0 | MZ_FREE(pComp); |
1563 | 0 | MZ_FREE(out_buf.m_pBuf); |
1564 | 0 | return NULL; |
1565 | 0 | } |
1566 | 0 | c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4); |
1567 | 0 | for (i = 0; i < 4; ++i, c <<= 8) |
1568 | 0 | (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24); |
1569 | | /* compute final size of file, grab compressed data buffer and return */ |
1570 | 0 | *pLen_out += 57; |
1571 | 0 | MZ_FREE(pComp); |
1572 | 0 | return out_buf.m_pBuf; |
1573 | 0 | } |
1574 | | void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out) |
1575 | 0 | { |
1576 | | /* Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out) */ |
1577 | 0 | return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE); |
1578 | 0 | } |
1579 | | |
1580 | | #ifndef MINIZ_NO_MALLOC |
1581 | | /* Allocate the tdefl_compressor and tinfl_decompressor structures in C so that */ |
1582 | | /* non-C language bindings to tdefL_ and tinfl_ API don't need to worry about */ |
1583 | | /* structure size and allocation mechanism. */ |
1584 | | tdefl_compressor *tdefl_compressor_alloc(void) |
1585 | 0 | { |
1586 | 0 | return (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); |
1587 | 0 | } |
1588 | | |
1589 | | void tdefl_compressor_free(tdefl_compressor *pComp) |
1590 | 0 | { |
1591 | 0 | MZ_FREE(pComp); |
1592 | 0 | } |
1593 | | #endif |
1594 | | |
1595 | | #ifdef _MSC_VER |
1596 | | #pragma warning(pop) |
1597 | | #endif |
1598 | | |
1599 | | #ifdef __cplusplus |
1600 | | } |
1601 | | #endif |
1602 | | |
1603 | | #endif /*#ifndef MINIZ_NO_DEFLATE_APIS*/ |