Coverage Report

Created: 2026-10-28 08:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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