Coverage Report

Created: 2025-10-13 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/h2o/deps/brotli/c/enc/static_dict.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
#include "./static_dict.h"
8
9
#include "../common/dictionary.h"
10
#include "./find_match_length.h"
11
#include "./port.h"
12
#include "./static_dict_lut.h"
13
14
#if defined(__cplusplus) || defined(c_plusplus)
15
extern "C" {
16
#endif
17
18
static const uint8_t kUppercaseFirst = 10;
19
static const uint8_t kOmitLastNTransforms[10] = {
20
  0, 12, 27, 23, 42, 63, 56, 48, 59, 64,
21
};
22
23
0
static BROTLI_INLINE uint32_t Hash(const uint8_t *data) {
24
0
  uint32_t h = BROTLI_UNALIGNED_LOAD32(data) * kDictHashMul32;
25
  /* The higher bits contain more mixture from the multiplication,
26
     so we take our results from there. */
27
0
  return h >> (32 - kDictNumBits);
28
0
}
29
30
static BROTLI_INLINE void AddMatch(size_t distance, size_t len, size_t len_code,
31
0
                                   uint32_t* matches) {
32
0
  uint32_t match = (uint32_t)((distance << 5) + len_code);
33
0
  matches[len] = BROTLI_MIN(uint32_t, matches[len], match);
34
0
}
35
36
static BROTLI_INLINE size_t DictMatchLength(const BrotliDictionary* dictionary,
37
                                            const uint8_t* data,
38
                                            size_t id,
39
                                            size_t len,
40
0
                                            size_t maxlen) {
41
0
  const size_t offset = dictionary->offsets_by_length[len] + len * id;
42
0
  return FindMatchLengthWithLimit(&dictionary->data[offset], data,
43
0
                                  BROTLI_MIN(size_t, len, maxlen));
44
0
}
45
46
static BROTLI_INLINE BROTLI_BOOL IsMatch(const BrotliDictionary* dictionary,
47
0
    DictWord w, const uint8_t* data, size_t max_length) {
48
0
  if (w.len > max_length) {
49
0
    return BROTLI_FALSE;
50
0
  } else {
51
0
    const size_t offset = dictionary->offsets_by_length[w.len] +
52
0
        (size_t)w.len * (size_t)w.idx;
53
0
    const uint8_t* dict = &dictionary->data[offset];
54
0
    if (w.transform == 0) {
55
      /* Match against base dictionary word. */
56
0
      return
57
0
          TO_BROTLI_BOOL(FindMatchLengthWithLimit(dict, data, w.len) == w.len);
58
0
    } else if (w.transform == 10) {
59
      /* Match against uppercase first transform.
60
         Note that there are only ASCII uppercase words in the lookup table. */
61
0
      return TO_BROTLI_BOOL(dict[0] >= 'a' && dict[0] <= 'z' &&
62
0
              (dict[0] ^ 32) == data[0] &&
63
0
              FindMatchLengthWithLimit(&dict[1], &data[1], w.len - 1u) ==
64
0
              w.len - 1u);
65
0
    } else {
66
      /* Match against uppercase all transform.
67
         Note that there are only ASCII uppercase words in the lookup table. */
68
0
      size_t i;
69
0
      for (i = 0; i < w.len; ++i) {
70
0
        if (dict[i] >= 'a' && dict[i] <= 'z') {
71
0
          if ((dict[i] ^ 32) != data[i]) return BROTLI_FALSE;
72
0
        } else {
73
0
          if (dict[i] != data[i]) return BROTLI_FALSE;
74
0
        }
75
0
      }
76
0
      return BROTLI_TRUE;
77
0
    }
78
0
  }
79
0
}
80
81
BROTLI_BOOL BrotliFindAllStaticDictionaryMatches(
82
    const BrotliDictionary* dictionary, const uint8_t* data, size_t min_length,
83
0
    size_t max_length, uint32_t* matches) {
84
0
  BROTLI_BOOL has_found_match = BROTLI_FALSE;
85
0
  {
86
0
    size_t offset = kStaticDictionaryBuckets[Hash(data)];
87
0
    BROTLI_BOOL end = !offset;
88
0
    while (!end) {
89
0
      DictWord w = kStaticDictionaryWords[offset++];
90
0
      const size_t l = w.len & 0x1F;
91
0
      const size_t n = (size_t)1 << dictionary->size_bits_by_length[l];
92
0
      const size_t id = w.idx;
93
0
      end = !!(w.len & 0x80);
94
0
      w.len = (uint8_t)l;
95
0
      if (w.transform == 0) {
96
0
        const size_t matchlen =
97
0
            DictMatchLength(dictionary, data, id, l, max_length);
98
0
        const uint8_t* s;
99
0
        size_t minlen;
100
0
        size_t maxlen;
101
0
        size_t len;
102
        /* Transform "" + kIdentity + "" */
103
0
        if (matchlen == l) {
104
0
          AddMatch(id, l, l, matches);
105
0
          has_found_match = BROTLI_TRUE;
106
0
        }
107
        /* Transforms "" + kOmitLast1 + "" and "" + kOmitLast1 + "ing " */
108
0
        if (matchlen >= l - 1) {
109
0
          AddMatch(id + 12 * n, l - 1, l, matches);
110
0
          if (l + 2 < max_length &&
111
0
              data[l - 1] == 'i' && data[l] == 'n' && data[l + 1] == 'g' &&
112
0
              data[l + 2] == ' ') {
113
0
            AddMatch(id + 49 * n, l + 3, l, matches);
114
0
          }
115
0
          has_found_match = BROTLI_TRUE;
116
0
        }
117
        /* Transform "" + kOmitLastN + "" (N = 2 .. 9) */
118
0
        minlen = min_length;
119
0
        if (l > 9) minlen = BROTLI_MAX(size_t, minlen, l - 9);
120
0
        maxlen = BROTLI_MIN(size_t, matchlen, l - 2);
121
0
        for (len = minlen; len <= maxlen; ++len) {
122
0
          AddMatch(id + kOmitLastNTransforms[l - len] * n, len, l, matches);
123
0
          has_found_match = BROTLI_TRUE;
124
0
        }
125
0
        if (matchlen < l || l + 6 >= max_length) {
126
0
          continue;
127
0
        }
128
0
        s = &data[l];
129
        /* Transforms "" + kIdentity + <suffix> */
130
0
        if (s[0] == ' ') {
131
0
          AddMatch(id + n, l + 1, l, matches);
132
0
          if (s[1] == 'a') {
133
0
            if (s[2] == ' ') {
134
0
              AddMatch(id + 28 * n, l + 3, l, matches);
135
0
            } else if (s[2] == 's') {
136
0
              if (s[3] == ' ') AddMatch(id + 46 * n, l + 4, l, matches);
137
0
            } else if (s[2] == 't') {
138
0
              if (s[3] == ' ') AddMatch(id + 60 * n, l + 4, l, matches);
139
0
            } else if (s[2] == 'n') {
140
0
              if (s[3] == 'd' && s[4] == ' ') {
141
0
                AddMatch(id + 10 * n, l + 5, l, matches);
142
0
              }
143
0
            }
144
0
          } else if (s[1] == 'b') {
145
0
            if (s[2] == 'y' && s[3] == ' ') {
146
0
              AddMatch(id + 38 * n, l + 4, l, matches);
147
0
            }
148
0
          } else if (s[1] == 'i') {
149
0
            if (s[2] == 'n') {
150
0
              if (s[3] == ' ') AddMatch(id + 16 * n, l + 4, l, matches);
151
0
            } else if (s[2] == 's') {
152
0
              if (s[3] == ' ') AddMatch(id + 47 * n, l + 4, l, matches);
153
0
            }
154
0
          } else if (s[1] == 'f') {
155
0
            if (s[2] == 'o') {
156
0
              if (s[3] == 'r' && s[4] == ' ') {
157
0
                AddMatch(id + 25 * n, l + 5, l, matches);
158
0
              }
159
0
            } else if (s[2] == 'r') {
160
0
              if (s[3] == 'o' && s[4] == 'm' && s[5] == ' ') {
161
0
                AddMatch(id + 37 * n, l + 6, l, matches);
162
0
              }
163
0
            }
164
0
          } else if (s[1] == 'o') {
165
0
            if (s[2] == 'f') {
166
0
              if (s[3] == ' ') AddMatch(id + 8 * n, l + 4, l, matches);
167
0
            } else if (s[2] == 'n') {
168
0
              if (s[3] == ' ') AddMatch(id + 45 * n, l + 4, l, matches);
169
0
            }
170
0
          } else if (s[1] == 'n') {
171
0
            if (s[2] == 'o' && s[3] == 't' && s[4] == ' ') {
172
0
              AddMatch(id + 80 * n, l + 5, l, matches);
173
0
            }
174
0
          } else if (s[1] == 't') {
175
0
            if (s[2] == 'h') {
176
0
              if (s[3] == 'e') {
177
0
                if (s[4] == ' ') AddMatch(id + 5 * n, l + 5, l, matches);
178
0
              } else if (s[3] == 'a') {
179
0
                if (s[4] == 't' && s[5] == ' ') {
180
0
                  AddMatch(id + 29 * n, l + 6, l, matches);
181
0
                }
182
0
              }
183
0
            } else if (s[2] == 'o') {
184
0
              if (s[3] == ' ') AddMatch(id + 17 * n, l + 4, l, matches);
185
0
            }
186
0
          } else if (s[1] == 'w') {
187
0
            if (s[2] == 'i' && s[3] == 't' && s[4] == 'h' && s[5] == ' ') {
188
0
              AddMatch(id + 35 * n, l + 6, l, matches);
189
0
            }
190
0
          }
191
0
        } else if (s[0] == '"') {
192
0
          AddMatch(id + 19 * n, l + 1, l, matches);
193
0
          if (s[1] == '>') {
194
0
            AddMatch(id + 21 * n, l + 2, l, matches);
195
0
          }
196
0
        } else if (s[0] == '.') {
197
0
          AddMatch(id + 20 * n, l + 1, l, matches);
198
0
          if (s[1] == ' ') {
199
0
            AddMatch(id + 31 * n, l + 2, l, matches);
200
0
            if (s[2] == 'T' && s[3] == 'h') {
201
0
              if (s[4] == 'e') {
202
0
                if (s[5] == ' ') AddMatch(id + 43 * n, l + 6, l, matches);
203
0
              } else if (s[4] == 'i') {
204
0
                if (s[5] == 's' && s[6] == ' ') {
205
0
                  AddMatch(id + 75 * n, l + 7, l, matches);
206
0
                }
207
0
              }
208
0
            }
209
0
          }
210
0
        } else if (s[0] == ',') {
211
0
          AddMatch(id + 76 * n, l + 1, l, matches);
212
0
          if (s[1] == ' ') {
213
0
            AddMatch(id + 14 * n, l + 2, l, matches);
214
0
          }
215
0
        } else if (s[0] == '\n') {
216
0
          AddMatch(id + 22 * n, l + 1, l, matches);
217
0
          if (s[1] == '\t') {
218
0
            AddMatch(id + 50 * n, l + 2, l, matches);
219
0
          }
220
0
        } else if (s[0] == ']') {
221
0
          AddMatch(id + 24 * n, l + 1, l, matches);
222
0
        } else if (s[0] == '\'') {
223
0
          AddMatch(id + 36 * n, l + 1, l, matches);
224
0
        } else if (s[0] == ':') {
225
0
          AddMatch(id + 51 * n, l + 1, l, matches);
226
0
        } else if (s[0] == '(') {
227
0
          AddMatch(id + 57 * n, l + 1, l, matches);
228
0
        } else if (s[0] == '=') {
229
0
          if (s[1] == '"') {
230
0
            AddMatch(id + 70 * n, l + 2, l, matches);
231
0
          } else if (s[1] == '\'') {
232
0
            AddMatch(id + 86 * n, l + 2, l, matches);
233
0
          }
234
0
        } else if (s[0] == 'a') {
235
0
          if (s[1] == 'l' && s[2] == ' ') {
236
0
            AddMatch(id + 84 * n, l + 3, l, matches);
237
0
          }
238
0
        } else if (s[0] == 'e') {
239
0
          if (s[1] == 'd') {
240
0
            if (s[2] == ' ') AddMatch(id + 53 * n, l + 3, l, matches);
241
0
          } else if (s[1] == 'r') {
242
0
            if (s[2] == ' ') AddMatch(id + 82 * n, l + 3, l, matches);
243
0
          } else if (s[1] == 's') {
244
0
            if (s[2] == 't' && s[3] == ' ') {
245
0
              AddMatch(id + 95 * n, l + 4, l, matches);
246
0
            }
247
0
          }
248
0
        } else if (s[0] == 'f') {
249
0
          if (s[1] == 'u' && s[2] == 'l' && s[3] == ' ') {
250
0
            AddMatch(id + 90 * n, l + 4, l, matches);
251
0
          }
252
0
        } else if (s[0] == 'i') {
253
0
          if (s[1] == 'v') {
254
0
            if (s[2] == 'e' && s[3] == ' ') {
255
0
              AddMatch(id + 92 * n, l + 4, l, matches);
256
0
            }
257
0
          } else if (s[1] == 'z') {
258
0
            if (s[2] == 'e' && s[3] == ' ') {
259
0
              AddMatch(id + 100 * n, l + 4, l, matches);
260
0
            }
261
0
          }
262
0
        } else if (s[0] == 'l') {
263
0
          if (s[1] == 'e') {
264
0
            if (s[2] == 's' && s[3] == 's' && s[4] == ' ') {
265
0
              AddMatch(id + 93 * n, l + 5, l, matches);
266
0
            }
267
0
          } else if (s[1] == 'y') {
268
0
            if (s[2] == ' ') AddMatch(id + 61 * n, l + 3, l, matches);
269
0
          }
270
0
        } else if (s[0] == 'o') {
271
0
          if (s[1] == 'u' && s[2] == 's' && s[3] == ' ') {
272
0
            AddMatch(id + 106 * n, l + 4, l, matches);
273
0
          }
274
0
        }
275
0
      } else {
276
        /* Set is_all_caps=0 for kUppercaseFirst and
277
               is_all_caps=1 otherwise (kUppercaseAll) transform. */
278
0
        const BROTLI_BOOL is_all_caps =
279
0
            TO_BROTLI_BOOL(w.transform != kUppercaseFirst);
280
0
        const uint8_t* s;
281
0
        if (!IsMatch(dictionary, w, data, max_length)) {
282
0
          continue;
283
0
        }
284
        /* Transform "" + kUppercase{First,All} + "" */
285
0
        AddMatch(id + (is_all_caps ? 44 : 9) * n, l, l, matches);
286
0
        has_found_match = BROTLI_TRUE;
287
0
        if (l + 1 >= max_length) {
288
0
          continue;
289
0
        }
290
        /* Transforms "" + kUppercase{First,All} + <suffix> */
291
0
        s = &data[l];
292
0
        if (s[0] == ' ') {
293
0
          AddMatch(id + (is_all_caps ? 68 : 4) * n, l + 1, l, matches);
294
0
        } else if (s[0] == '"') {
295
0
          AddMatch(id + (is_all_caps ? 87 : 66) * n, l + 1, l, matches);
296
0
          if (s[1] == '>') {
297
0
            AddMatch(id + (is_all_caps ? 97 : 69) * n, l + 2, l, matches);
298
0
          }
299
0
        } else if (s[0] == '.') {
300
0
          AddMatch(id + (is_all_caps ? 101 : 79) * n, l + 1, l, matches);
301
0
          if (s[1] == ' ') {
302
0
            AddMatch(id + (is_all_caps ? 114 : 88) * n, l + 2, l, matches);
303
0
          }
304
0
        } else if (s[0] == ',') {
305
0
          AddMatch(id + (is_all_caps ? 112 : 99) * n, l + 1, l, matches);
306
0
          if (s[1] == ' ') {
307
0
            AddMatch(id + (is_all_caps ? 107 : 58) * n, l + 2, l, matches);
308
0
          }
309
0
        } else if (s[0] == '\'') {
310
0
          AddMatch(id + (is_all_caps ? 94 : 74) * n, l + 1, l, matches);
311
0
        } else if (s[0] == '(') {
312
0
          AddMatch(id + (is_all_caps ? 113 : 78) * n, l + 1, l, matches);
313
0
        } else if (s[0] == '=') {
314
0
          if (s[1] == '"') {
315
0
            AddMatch(id + (is_all_caps ? 105 : 104) * n, l + 2, l, matches);
316
0
          } else if (s[1] == '\'') {
317
0
            AddMatch(id + (is_all_caps ? 116 : 108) * n, l + 2, l, matches);
318
0
          }
319
0
        }
320
0
      }
321
0
    }
322
0
  }
323
  /* Transforms with prefixes " " and "." */
324
0
  if (max_length >= 5 && (data[0] == ' ' || data[0] == '.')) {
325
0
    BROTLI_BOOL is_space = TO_BROTLI_BOOL(data[0] == ' ');
326
0
    size_t offset = kStaticDictionaryBuckets[Hash(&data[1])];
327
0
    BROTLI_BOOL end = !offset;
328
0
    while (!end) {
329
0
      DictWord w = kStaticDictionaryWords[offset++];
330
0
      const size_t l = w.len & 0x1F;
331
0
      const size_t n = (size_t)1 << dictionary->size_bits_by_length[l];
332
0
      const size_t id = w.idx;
333
0
      end = !!(w.len & 0x80);
334
0
      w.len = (uint8_t)l;
335
0
      if (w.transform == 0) {
336
0
        const uint8_t* s;
337
0
        if (!IsMatch(dictionary, w, &data[1], max_length - 1)) {
338
0
          continue;
339
0
        }
340
        /* Transforms " " + kIdentity + "" and "." + kIdentity + "" */
341
0
        AddMatch(id + (is_space ? 6 : 32) * n, l + 1, l, matches);
342
0
        has_found_match = BROTLI_TRUE;
343
0
        if (l + 2 >= max_length) {
344
0
          continue;
345
0
        }
346
        /* Transforms " " + kIdentity + <suffix> and "." + kIdentity + <suffix>
347
        */
348
0
        s = &data[l + 1];
349
0
        if (s[0] == ' ') {
350
0
          AddMatch(id + (is_space ? 2 : 77) * n, l + 2, l, matches);
351
0
        } else if (s[0] == '(') {
352
0
          AddMatch(id + (is_space ? 89 : 67) * n, l + 2, l, matches);
353
0
        } else if (is_space) {
354
0
          if (s[0] == ',') {
355
0
            AddMatch(id + 103 * n, l + 2, l, matches);
356
0
            if (s[1] == ' ') {
357
0
              AddMatch(id + 33 * n, l + 3, l, matches);
358
0
            }
359
0
          } else if (s[0] == '.') {
360
0
            AddMatch(id + 71 * n, l + 2, l, matches);
361
0
            if (s[1] == ' ') {
362
0
              AddMatch(id + 52 * n, l + 3, l, matches);
363
0
            }
364
0
          } else if (s[0] == '=') {
365
0
            if (s[1] == '"') {
366
0
              AddMatch(id + 81 * n, l + 3, l, matches);
367
0
            } else if (s[1] == '\'') {
368
0
              AddMatch(id + 98 * n, l + 3, l, matches);
369
0
            }
370
0
          }
371
0
        }
372
0
      } else if (is_space) {
373
        /* Set is_all_caps=0 for kUppercaseFirst and
374
               is_all_caps=1 otherwise (kUppercaseAll) transform. */
375
0
        const BROTLI_BOOL is_all_caps =
376
0
            TO_BROTLI_BOOL(w.transform != kUppercaseFirst);
377
0
        const uint8_t* s;
378
0
        if (!IsMatch(dictionary, w, &data[1], max_length - 1)) {
379
0
          continue;
380
0
        }
381
        /* Transforms " " + kUppercase{First,All} + "" */
382
0
        AddMatch(id + (is_all_caps ? 85 : 30) * n, l + 1, l, matches);
383
0
        has_found_match = BROTLI_TRUE;
384
0
        if (l + 2 >= max_length) {
385
0
          continue;
386
0
        }
387
        /* Transforms " " + kUppercase{First,All} + <suffix> */
388
0
        s = &data[l + 1];
389
0
        if (s[0] == ' ') {
390
0
          AddMatch(id + (is_all_caps ? 83 : 15) * n, l + 2, l, matches);
391
0
        } else if (s[0] == ',') {
392
0
          if (!is_all_caps) {
393
0
            AddMatch(id + 109 * n, l + 2, l, matches);
394
0
          }
395
0
          if (s[1] == ' ') {
396
0
            AddMatch(id + (is_all_caps ? 111 : 65) * n, l + 3, l, matches);
397
0
          }
398
0
        } else if (s[0] == '.') {
399
0
          AddMatch(id + (is_all_caps ? 115 : 96) * n, l + 2, l, matches);
400
0
          if (s[1] == ' ') {
401
0
            AddMatch(id + (is_all_caps ? 117 : 91) * n, l + 3, l, matches);
402
0
          }
403
0
        } else if (s[0] == '=') {
404
0
          if (s[1] == '"') {
405
0
            AddMatch(id + (is_all_caps ? 110 : 118) * n, l + 3, l, matches);
406
0
          } else if (s[1] == '\'') {
407
0
            AddMatch(id + (is_all_caps ? 119 : 120) * n, l + 3, l, matches);
408
0
          }
409
0
        }
410
0
      }
411
0
    }
412
0
  }
413
0
  if (max_length >= 6) {
414
    /* Transforms with prefixes "e ", "s ", ", " and "\xc2\xa0" */
415
0
    if ((data[1] == ' ' &&
416
0
         (data[0] == 'e' || data[0] == 's' || data[0] == ',')) ||
417
0
        (data[0] == 0xc2 && data[1] == 0xa0)) {
418
0
      size_t offset = kStaticDictionaryBuckets[Hash(&data[2])];
419
0
      BROTLI_BOOL end = !offset;
420
0
      while (!end) {
421
0
        DictWord w = kStaticDictionaryWords[offset++];
422
0
        const size_t l = w.len & 0x1F;
423
0
        const size_t n = (size_t)1 << dictionary->size_bits_by_length[l];
424
0
        const size_t id = w.idx;
425
0
        end = !!(w.len & 0x80);
426
0
        w.len = (uint8_t)l;
427
0
        if (w.transform == 0 &&
428
0
            IsMatch(dictionary, w, &data[2], max_length - 2)) {
429
0
          if (data[0] == 0xc2) {
430
0
            AddMatch(id + 102 * n, l + 2, l, matches);
431
0
            has_found_match = BROTLI_TRUE;
432
0
          } else if (l + 2 < max_length && data[l + 2] == ' ') {
433
0
            size_t t = data[0] == 'e' ? 18 : (data[0] == 's' ? 7 : 13);
434
0
            AddMatch(id + t * n, l + 3, l, matches);
435
0
            has_found_match = BROTLI_TRUE;
436
0
          }
437
0
        }
438
0
      }
439
0
    }
440
0
  }
441
0
  if (max_length >= 9) {
442
    /* Transforms with prefixes " the " and ".com/" */
443
0
    if ((data[0] == ' ' && data[1] == 't' && data[2] == 'h' &&
444
0
         data[3] == 'e' && data[4] == ' ') ||
445
0
        (data[0] == '.' && data[1] == 'c' && data[2] == 'o' &&
446
0
         data[3] == 'm' && data[4] == '/')) {
447
0
      size_t offset = kStaticDictionaryBuckets[Hash(&data[5])];
448
0
      BROTLI_BOOL end = !offset;
449
0
      while (!end) {
450
0
        DictWord w = kStaticDictionaryWords[offset++];
451
0
        const size_t l = w.len & 0x1F;
452
0
        const size_t n = (size_t)1 << dictionary->size_bits_by_length[l];
453
0
        const size_t id = w.idx;
454
0
        end = !!(w.len & 0x80);
455
0
        w.len = (uint8_t)l;
456
0
        if (w.transform == 0 &&
457
0
            IsMatch(dictionary, w, &data[5], max_length - 5)) {
458
0
          AddMatch(id + (data[0] == ' ' ? 41 : 72) * n, l + 5, l, matches);
459
0
          has_found_match = BROTLI_TRUE;
460
0
          if (l + 5 < max_length) {
461
0
            const uint8_t* s = &data[l + 5];
462
0
            if (data[0] == ' ') {
463
0
              if (l + 8 < max_length &&
464
0
                  s[0] == ' ' && s[1] == 'o' && s[2] == 'f' && s[3] == ' ') {
465
0
                AddMatch(id + 62 * n, l + 9, l, matches);
466
0
                if (l + 12 < max_length &&
467
0
                    s[4] == 't' && s[5] == 'h' && s[6] == 'e' && s[7] == ' ') {
468
0
                  AddMatch(id + 73 * n, l + 13, l, matches);
469
0
                }
470
0
              }
471
0
            }
472
0
          }
473
0
        }
474
0
      }
475
0
    }
476
0
  }
477
0
  return has_found_match;
478
0
}
479
480
#if defined(__cplusplus) || defined(c_plusplus)
481
}  /* extern "C" */
482
#endif