/src/ghostpdl/brotli/c/enc/backward_references.c
Line | Count | Source |
1 | | /* Copyright 2013 Google Inc. All Rights Reserved. |
2 | | |
3 | | Distributed under MIT license. |
4 | | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT |
5 | | */ |
6 | | |
7 | | /* Function to find backward reference copies. */ |
8 | | |
9 | | #include "backward_references.h" |
10 | | |
11 | | #include "../common/constants.h" |
12 | | #include "../common/context.h" |
13 | | #include "../common/platform.h" |
14 | | #include "command.h" |
15 | | #include "compound_dictionary.h" |
16 | | #include "encoder_dict.h" |
17 | | #include "hash.h" |
18 | | #include "params.h" |
19 | | #include "quality.h" /* IWYU pragma: keep for inc */ |
20 | | |
21 | | BROTLI_INTERNAL const BROTLI_MODEL("small") |
22 | | uint8_t kIsBase64[256] = { |
23 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
24 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, |
25 | | 0, 0, 0, 1, /* 43 '+', 47 '/' (45 '-' is 0) */ |
26 | | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 48-57 '0'-'9' (61 '=' |
27 | | is 0) */ |
28 | | 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 65-79 'A'-'O' */ |
29 | | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 80-90 'P'-'Z' */ |
30 | | 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 97-111 'a'-'o' */ |
31 | | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 112-122 'p'-'z' */ |
32 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
33 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
34 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
35 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
36 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
37 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
38 | | |
39 | | static const size_t kBase64TriggerLen = 8; |
40 | | |
41 | 0 | static BROTLI_INLINE BROTLI_BOOL IsBase64Char(uint8_t c) { |
42 | 0 | return TO_BROTLI_BOOL(kIsBase64[c]); |
43 | 0 | } |
44 | | |
45 | | static BROTLI_INLINE BROTLI_BOOL MatchTrigger(const uint8_t* ringbuffer, |
46 | 0 | size_t mask, size_t pos) { |
47 | 0 | const char* trigger = ";base64,"; |
48 | 0 | size_t i; |
49 | 0 | for (i = 0; i < kBase64TriggerLen; ++i) { |
50 | 0 | if (ringbuffer[(pos + i) & mask] != trigger[i]) return BROTLI_FALSE; |
51 | 0 | } |
52 | 0 | return BROTLI_TRUE; |
53 | 0 | } |
54 | | |
55 | | static const uint64_t kBase64Trigger64 = |
56 | | BROTLI_MAKE_UINT64_T(0x2C343665u, 0x7361623Bu); |
57 | | |
58 | | static size_t FindNextBase64Trigger(const uint8_t* ringbuffer, size_t mask, |
59 | 0 | size_t pos, size_t end) { |
60 | 0 | while (pos + kBase64TriggerLen <= end) { |
61 | 0 | size_t ringbuffer_size = mask + 1; |
62 | 0 | size_t pos_index = pos & mask; |
63 | 0 | size_t contiguous_len = ringbuffer_size - pos_index; |
64 | 0 | size_t max_scan_len = end - pos; |
65 | 0 | size_t scan_len = BROTLI_MIN(size_t, contiguous_len, max_scan_len); |
66 | |
|
67 | 0 | const uint8_t* p = |
68 | 0 | (const uint8_t*)memchr(&ringbuffer[pos_index], ';', scan_len); |
69 | 0 | if (p != NULL) { |
70 | 0 | size_t offset = (size_t)(p - &ringbuffer[pos_index]); |
71 | 0 | if (offset + kBase64TriggerLen <= scan_len) { |
72 | 0 | if (BROTLI_UNALIGNED_LOAD64LE(p) == kBase64Trigger64) { |
73 | 0 | return pos + offset; |
74 | 0 | } |
75 | 0 | } else if (pos + offset + kBase64TriggerLen <= end) { |
76 | 0 | if (MatchTrigger(ringbuffer, mask, pos + offset)) { |
77 | 0 | return pos + offset; |
78 | 0 | } |
79 | 0 | } else { |
80 | 0 | return end; |
81 | 0 | } |
82 | 0 | pos += offset + 1; |
83 | 0 | } else { |
84 | 0 | pos += scan_len; |
85 | 0 | } |
86 | 0 | } |
87 | 0 | return end; |
88 | 0 | } |
89 | | |
90 | | static BROTLI_INLINE BROTLI_BOOL CompareRingbuffer( |
91 | | const uint8_t* ringbuffer, size_t mask, |
92 | 0 | size_t pos1, size_t pos2, size_t len) { |
93 | 0 | size_t idx1 = pos1 & mask; |
94 | 0 | size_t idx2 = pos2 & mask; |
95 | 0 | if (idx1 + len <= mask + 1 && idx2 + len <= mask + 1) { |
96 | 0 | return TO_BROTLI_BOOL( |
97 | 0 | memcmp(&ringbuffer[idx1], &ringbuffer[idx2], len) == 0); |
98 | 0 | } |
99 | 0 | while (len > 0) { |
100 | 0 | size_t chunk1 = mask + 1 - (pos1 & mask); |
101 | 0 | size_t chunk2 = mask + 1 - (pos2 & mask); |
102 | 0 | size_t chunk = BROTLI_MIN(size_t, len, BROTLI_MIN(size_t, chunk1, chunk2)); |
103 | 0 | if (memcmp(&ringbuffer[pos1 & mask], &ringbuffer[pos2 & mask], chunk) != 0) { |
104 | 0 | return BROTLI_FALSE; |
105 | 0 | } |
106 | 0 | pos1 += chunk; |
107 | 0 | pos2 += chunk; |
108 | 0 | len -= chunk; |
109 | 0 | } |
110 | 0 | return BROTLI_TRUE; |
111 | 0 | } |
112 | | |
113 | | #if defined(__cplusplus) || defined(c_plusplus) |
114 | | extern "C" { |
115 | | #endif |
116 | | |
117 | | static BROTLI_INLINE size_t ComputeDistanceCode(size_t distance, |
118 | | size_t max_distance, |
119 | 0 | const int* dist_cache) { |
120 | 0 | if (distance <= max_distance) { |
121 | 0 | size_t distance_plus_3 = distance + 3; |
122 | 0 | size_t offset0 = distance_plus_3 - (size_t)dist_cache[0]; |
123 | 0 | size_t offset1 = distance_plus_3 - (size_t)dist_cache[1]; |
124 | 0 | if (distance == (size_t)dist_cache[0]) { |
125 | 0 | return 0; |
126 | 0 | } else if (distance == (size_t)dist_cache[1]) { |
127 | 0 | return 1; |
128 | 0 | } else if (offset0 < 7) { |
129 | 0 | return (0x9750468 >> (4 * offset0)) & 0xF; |
130 | 0 | } else if (offset1 < 7) { |
131 | 0 | return (0xFDB1ACE >> (4 * offset1)) & 0xF; |
132 | 0 | } else if (distance == (size_t)dist_cache[2]) { |
133 | 0 | return 2; |
134 | 0 | } else if (distance == (size_t)dist_cache[3]) { |
135 | 0 | return 3; |
136 | 0 | } |
137 | 0 | } |
138 | 0 | return distance + BROTLI_NUM_DISTANCE_SHORT_CODES - 1; |
139 | 0 | } |
140 | | |
141 | 0 | #define EXPAND_CAT(a, b) CAT(a, b) |
142 | 0 | #define CAT(a, b) a ## b |
143 | 0 | #define FN(X) EXPAND_CAT(X, HASHER()) |
144 | | #define EXPORT_FN(X) EXPAND_CAT(X, EXPAND_CAT(PREFIX(), HASHER())) |
145 | | |
146 | | #define PREFIX() N |
147 | 0 | #define ENABLE_COMPOUND_DICTIONARY 0 |
148 | | |
149 | 0 | #define HASHER() H2 |
150 | | /* NOLINTNEXTLINE(build/include) */ |
151 | | #include "backward_references_inc.h" |
152 | | #undef HASHER |
153 | | |
154 | 0 | #define HASHER() H3 |
155 | | /* NOLINTNEXTLINE(build/include) */ |
156 | | #include "backward_references_inc.h" |
157 | | #undef HASHER |
158 | | |
159 | 0 | #define HASHER() H4 |
160 | | /* NOLINTNEXTLINE(build/include) */ |
161 | | #include "backward_references_inc.h" |
162 | | #undef HASHER |
163 | | |
164 | 0 | #define HASHER() H5 |
165 | | /* NOLINTNEXTLINE(build/include) */ |
166 | | #include "backward_references_inc.h" |
167 | | #undef HASHER |
168 | | |
169 | 0 | #define HASHER() H6 |
170 | | /* NOLINTNEXTLINE(build/include) */ |
171 | | #include "backward_references_inc.h" |
172 | | #undef HASHER |
173 | | |
174 | 0 | #define HASHER() H40 |
175 | | /* NOLINTNEXTLINE(build/include) */ |
176 | | #include "backward_references_inc.h" |
177 | | #undef HASHER |
178 | | |
179 | 0 | #define HASHER() H41 |
180 | | /* NOLINTNEXTLINE(build/include) */ |
181 | | #include "backward_references_inc.h" |
182 | | #undef HASHER |
183 | | |
184 | 0 | #define HASHER() H42 |
185 | | /* NOLINTNEXTLINE(build/include) */ |
186 | | #include "backward_references_inc.h" |
187 | | #undef HASHER |
188 | | |
189 | 0 | #define HASHER() H54 |
190 | | /* NOLINTNEXTLINE(build/include) */ |
191 | | #include "backward_references_inc.h" |
192 | | #undef HASHER |
193 | | |
194 | 0 | #define HASHER() H35 |
195 | | /* NOLINTNEXTLINE(build/include) */ |
196 | | #include "backward_references_inc.h" |
197 | | #undef HASHER |
198 | | |
199 | 0 | #define HASHER() H55 |
200 | | /* NOLINTNEXTLINE(build/include) */ |
201 | | #include "backward_references_inc.h" |
202 | | #undef HASHER |
203 | | |
204 | 0 | #define HASHER() H65 |
205 | | /* NOLINTNEXTLINE(build/include) */ |
206 | | #include "backward_references_inc.h" |
207 | | #undef HASHER |
208 | | |
209 | | #if defined(BROTLI_MAX_SIMD_QUALITY) |
210 | 0 | #define HASHER() H58 |
211 | | /* NOLINTNEXTLINE(build/include) */ |
212 | | #include "backward_references_inc.h" |
213 | | #undef HASHER |
214 | | |
215 | 0 | #define HASHER() H59 |
216 | | /* NOLINTNEXTLINE(build/include) */ |
217 | | #include "backward_references_opt_inc.h" |
218 | | #undef HASHER |
219 | | |
220 | 0 | #define HASHER() H68 |
221 | | /* NOLINTNEXTLINE(build/include) */ |
222 | | #include "backward_references_inc.h" |
223 | | #undef HASHER |
224 | | #endif |
225 | | |
226 | | #undef ENABLE_COMPOUND_DICTIONARY |
227 | | #undef PREFIX |
228 | | #define PREFIX() D |
229 | 0 | #define ENABLE_COMPOUND_DICTIONARY 1 |
230 | | |
231 | 0 | #define HASHER() H3 |
232 | | /* NOLINTNEXTLINE(build/include) */ |
233 | | #include "backward_references_inc.h" |
234 | | #undef HASHER |
235 | 0 | #define HASHER() H4 |
236 | | /* NOLINTNEXTLINE(build/include) */ |
237 | | #include "backward_references_inc.h" |
238 | | #undef HASHER |
239 | 0 | #define HASHER() H5 |
240 | | /* NOLINTNEXTLINE(build/include) */ |
241 | | #include "backward_references_inc.h" |
242 | | #undef HASHER |
243 | 0 | #define HASHER() H6 |
244 | | /* NOLINTNEXTLINE(build/include) */ |
245 | | #include "backward_references_inc.h" |
246 | | #undef HASHER |
247 | 0 | #define HASHER() H40 |
248 | | /* NOLINTNEXTLINE(build/include) */ |
249 | | #include "backward_references_inc.h" |
250 | | #undef HASHER |
251 | 0 | #define HASHER() H41 |
252 | | /* NOLINTNEXTLINE(build/include) */ |
253 | | #include "backward_references_inc.h" |
254 | | #undef HASHER |
255 | 0 | #define HASHER() H42 |
256 | | /* NOLINTNEXTLINE(build/include) */ |
257 | | #include "backward_references_inc.h" |
258 | | #undef HASHER |
259 | 0 | #define HASHER() H55 |
260 | | /* NOLINTNEXTLINE(build/include) */ |
261 | | #include "backward_references_inc.h" |
262 | | #undef HASHER |
263 | 0 | #define HASHER() H65 |
264 | | /* NOLINTNEXTLINE(build/include) */ |
265 | | #include "backward_references_inc.h" |
266 | | #undef HASHER |
267 | | #if defined(BROTLI_MAX_SIMD_QUALITY) |
268 | 0 | #define HASHER() H58 |
269 | | /* NOLINTNEXTLINE(build/include) */ |
270 | | #include "backward_references_inc.h" |
271 | | #undef HASHER |
272 | 0 | #define HASHER() H59 |
273 | | /* NOLINTNEXTLINE(build/include) */ |
274 | | #include "backward_references_opt_inc.h" |
275 | | #undef HASHER |
276 | 0 | #define HASHER() H68 |
277 | | /* NOLINTNEXTLINE(build/include) */ |
278 | | #include "backward_references_inc.h" |
279 | | #undef HASHER |
280 | | #endif |
281 | | |
282 | | #undef ENABLE_COMPOUND_DICTIONARY |
283 | | #undef PREFIX |
284 | | |
285 | | #undef EXPORT_FN |
286 | | #undef FN |
287 | | #undef CAT |
288 | | #undef EXPAND_CAT |
289 | | |
290 | | void BrotliCreateBackwardReferences(size_t num_bytes, |
291 | | size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, |
292 | | ContextLut literal_context_lut, const BrotliEncoderParams* params, |
293 | | Hasher* hasher, int* dist_cache, size_t* last_insert_len, |
294 | 0 | Command* commands, size_t* num_commands, size_t* num_literals) { |
295 | 0 | if (params->dictionary.compound.num_chunks != 0) { |
296 | 0 | switch (params->hasher.type) { |
297 | 0 | #define CASE_(N) \ |
298 | 0 | case N: \ |
299 | 0 | CreateBackwardReferencesDH ## N(num_bytes, \ |
300 | 0 | position, ringbuffer, ringbuffer_mask, \ |
301 | 0 | literal_context_lut, params, hasher, dist_cache, \ |
302 | 0 | last_insert_len, commands, num_commands, num_literals); \ |
303 | 0 | return; |
304 | 0 | CASE_(3) |
305 | 0 | CASE_(4) |
306 | 0 | CASE_(5) |
307 | 0 | CASE_(6) |
308 | 0 | #if defined(BROTLI_MAX_SIMD_QUALITY) |
309 | 0 | CASE_(58) |
310 | 0 | CASE_(59) |
311 | 0 | CASE_(68) |
312 | 0 | #endif |
313 | 0 | CASE_(40) |
314 | 0 | CASE_(41) |
315 | 0 | CASE_(42) |
316 | 0 | CASE_(55) |
317 | 0 | CASE_(65) |
318 | 0 | #undef CASE_ |
319 | 0 | default: |
320 | 0 | BROTLI_DCHECK(BROTLI_FALSE); |
321 | 0 | break; |
322 | 0 | } |
323 | 0 | } |
324 | | |
325 | 0 | switch (params->hasher.type) { |
326 | 0 | #define CASE_(N) \ |
327 | 0 | case N: \ |
328 | 0 | CreateBackwardReferencesNH ## N(num_bytes, \ |
329 | 0 | position, ringbuffer, ringbuffer_mask, \ |
330 | 0 | literal_context_lut, params, hasher, dist_cache, \ |
331 | 0 | last_insert_len, commands, num_commands, num_literals); \ |
332 | 0 | return; |
333 | 0 | FOR_GENERIC_HASHERS(CASE_) |
334 | 0 | #undef CASE_ |
335 | 0 | default: |
336 | 0 | BROTLI_DCHECK(BROTLI_FALSE); |
337 | 0 | break; |
338 | 0 | } |
339 | 0 | } |
340 | | |
341 | | #if defined(__cplusplus) || defined(c_plusplus) |
342 | | } /* extern "C" */ |
343 | | #endif |