brotli/enc/
static_dict.rs

1use core::cmp::{max, min};
2pub const kNumDistanceCacheEntries: usize = 4;
3
4use super::super::dictionary::{
5    kBrotliDictionary, kBrotliDictionaryOffsetsByLength, kBrotliDictionarySizeBitsByLength,
6};
7use super::static_dict_lut::{
8    kDictHashMul32, kDictNumBits, kStaticDictionaryBuckets, kStaticDictionaryWords, DictWord,
9};
10#[allow(unused)]
11static kUppercaseFirst: u8 = 10u8;
12
13#[allow(unused)]
14static kOmitLastNTransforms: [u8; 10] = [0, 12, 27, 23, 42, 63, 56, 48, 59, 64];
15
16pub struct BrotliDictionary {
17    pub size_bits_by_length: &'static [u8; 25],
18    pub offsets_by_length: &'static [u32; 25],
19    pub data: &'static [u8; 122784],
20}
21
22pub static kBrotliEncDictionary: BrotliDictionary = BrotliDictionary {
23    size_bits_by_length: &kBrotliDictionarySizeBitsByLength,
24    offsets_by_length: &kBrotliDictionaryOffsetsByLength,
25    data: &kBrotliDictionary,
26};
27
28#[inline(always)]
29pub fn BrotliGetDictionary() -> &'static BrotliDictionary {
30    &kBrotliEncDictionary
31}
32#[inline(always)]
33pub fn BROTLI_UNALIGNED_LOAD32(sl: &[u8]) -> u32 {
34    let mut p = [0u8; 4];
35    p[..].clone_from_slice(sl.split_at(4).0);
36    (p[0] as u32) | ((p[1] as u32) << 8) | ((p[2] as u32) << 16) | ((p[3] as u32) << 24)
37}
38#[inline(always)]
39pub fn Hash(data: &[u8]) -> u32 {
40    let h: u32 = BROTLI_UNALIGNED_LOAD32(data).wrapping_mul(kDictHashMul32);
41    h >> (32i32 - kDictNumBits)
42}
43#[inline(always)]
44pub fn BROTLI_UNALIGNED_LOAD64(sl: &[u8]) -> u64 {
45    let mut p = [0u8; 8];
46    p[..].clone_from_slice(sl.split_at(8).0);
47    (p[0] as u64)
48        | ((p[1] as u64) << 8)
49        | ((p[2] as u64) << 16)
50        | ((p[3] as u64) << 24)
51        | ((p[4] as u64) << 32)
52        | ((p[5] as u64) << 40)
53        | ((p[6] as u64) << 48)
54        | ((p[7] as u64) << 56)
55}
56#[inline(always)]
57pub fn BROTLI_UNALIGNED_STORE64(outp: &mut [u8], v: u64) {
58    let p = [
59        (v & 0xff) as u8,
60        ((v >> 8) & 0xff) as u8,
61        ((v >> 16) & 0xff) as u8,
62        ((v >> 24) & 0xff) as u8,
63        ((v >> 32) & 0xff) as u8,
64        ((v >> 40) & 0xff) as u8,
65        ((v >> 48) & 0xff) as u8,
66        ((v >> 56) & 0xff) as u8,
67    ];
68    outp.split_at_mut(8).0.clone_from_slice(&p[..]);
69}
70
71macro_rules! sub_match {
72    ($s1 : expr, $s2 : expr, $limit : expr, $matched : expr, $split_pair1 : expr, $split_pair2 : expr, $s1_lo : expr, $s2_lo : expr, $s1_as_64 : expr, $s2_as_64 : expr, $vec_len: expr) => {
73        $split_pair1 = $s1.split_at($vec_len);
74        $s1_lo[..$vec_len].clone_from_slice($split_pair1.0);
75        $s1 = $split_pair1.1;
76        $split_pair2 = $s2.split_at($vec_len);
77        $s2_lo[..$vec_len].clone_from_slice($split_pair2.0);
78        $s2 = $split_pair2.1;
79        $limit -= $vec_len;
80        for index in 0..($vec_len >> 3) {
81            $s1_as_64 = BROTLI_UNALIGNED_LOAD64(&$s1_lo[(index << 3)..((index + 1) << 3)]);
82            $s2_as_64 = BROTLI_UNALIGNED_LOAD64(&$s2_lo[(index << 3)..((index + 1) << 3)]);
83            if $s2_as_64 == $s1_as_64 {
84                $matched = $matched.wrapping_add(8) as u32 as usize;
85            } else {
86                $matched = $matched
87                    .wrapping_add((($s2_as_64 ^ $s1_as_64).trailing_zeros() >> 3) as usize)
88                    as u32 as usize;
89                return $matched;
90            }
91        }
92    };
93}
94
95macro_rules! sub_match8 {
96    ($s1 : expr, $s2 : expr, $limit : expr, $matched : expr, $s1_as_64 : expr, $s2_as_64 : expr) => {
97        $limit -= 8;
98        $s1_as_64 = BROTLI_UNALIGNED_LOAD64($s1);
99        $s1 = $s1.split_at(8).1;
100        $s2_as_64 = BROTLI_UNALIGNED_LOAD64($s2);
101        $s2 = $s2.split_at(8).1;
102        if $s2_as_64 == $s1_as_64 {
103            $matched = $matched.wrapping_add(8) as u32 as usize;
104        } else {
105            $matched = $matched
106                .wrapping_add((($s2_as_64 ^ $s1_as_64).trailing_zeros() >> 3) as usize)
107                as u32 as usize;
108            return $matched;
109        }
110    };
111}
112
113// factor of 10 slower (example takes 158s, not 30, and for the 30 second run it took 15 of them)
114#[allow(unused)]
115pub fn SlowerFindMatchLengthWithLimit(s1: &[u8], s2: &[u8], limit: usize) -> usize {
116    for index in 0..limit {
117        if s1[index] != s2[index] {
118            return index;
119        }
120    }
121    limit
122}
123// factor of 5 slower (example takes 90 seconds)
124#[allow(unused)]
125pub fn FindMatchLengthWithLimit(s1: &[u8], s2: &[u8], limit: usize) -> usize {
126    for (index, pair) in s1[..limit].iter().zip(s2[..limit].iter()).enumerate() {
127        if *pair.0 != *pair.1 {
128            return index;
129        }
130    }
131    limit
132}
133#[allow(unused)]
134pub fn FindMatchLengthWithLimitMin4(s1: &[u8], s2: &[u8], limit: usize) -> usize {
135    let (s1_start, s1_rest) = s1.split_at(5);
136    let (s2_start, s2_rest) = s2.split_at(5);
137    let v0 = BROTLI_UNALIGNED_LOAD32(s1_start);
138    let v1 = BROTLI_UNALIGNED_LOAD32(s2_start);
139    let beyond_ok = s1_start[4] != s2_start[4];
140    if v0 != v1 {
141        return 0;
142    }
143    if limit <= 4 || beyond_ok {
144        return min(limit, 4);
145    }
146    ComplexFindMatchLengthWithLimit(s1_rest, s2_rest, limit - 5) + 5
147}
148#[inline]
149pub fn ComplexFindMatchLengthWithLimit(mut s1: &[u8], mut s2: &[u8], mut limit: usize) -> usize {
150    let mut matched: usize = 0usize;
151    let mut s1_as_64: u64;
152    let mut s2_as_64: u64;
153    if limit >= 8 {
154        sub_match8!(s1, s2, limit, matched, s1_as_64, s2_as_64);
155        if limit >= 16 {
156            let mut split_pair1: (&[u8], &[u8]);
157            let mut split_pair2: (&[u8], &[u8]);
158            {
159                let mut s1_lo = [0u8; 16];
160                let mut s1_hi = [0u8; 16];
161                sub_match!(
162                    s1,
163                    s2,
164                    limit,
165                    matched,
166                    split_pair1,
167                    split_pair2,
168                    s1_lo,
169                    s1_hi,
170                    s1_as_64,
171                    s2_as_64,
172                    16
173                );
174            }
175            if limit >= 32 {
176                let mut s1_lo_a = [0u8; 128];
177                let mut s1_hi_a = [0u8; 128];
178                sub_match!(
179                    s1,
180                    s2,
181                    limit,
182                    matched,
183                    split_pair1,
184                    split_pair2,
185                    s1_lo_a,
186                    s1_hi_a,
187                    s1_as_64,
188                    s2_as_64,
189                    32
190                );
191                if limit >= 64 {
192                    sub_match!(
193                        s1,
194                        s2,
195                        limit,
196                        matched,
197                        split_pair1,
198                        split_pair2,
199                        s1_lo_a,
200                        s1_hi_a,
201                        s1_as_64,
202                        s2_as_64,
203                        64
204                    );
205                    while limit >= 128 {
206                        sub_match!(
207                            s1,
208                            s2,
209                            limit,
210                            matched,
211                            split_pair1,
212                            split_pair2,
213                            s1_lo_a,
214                            s1_hi_a,
215                            s1_as_64,
216                            s2_as_64,
217                            128
218                        );
219                    }
220                }
221            }
222        }
223        while limit >= 8 {
224            sub_match8!(s1, s2, limit, matched, s1_as_64, s2_as_64);
225        }
226    }
227    assert!(s1.len() >= (limit & 7usize));
228    assert!(s2.len() >= (limit & 7usize));
229    for index in 0..(limit & 7usize) {
230        if s1[index] != s2[index] {
231            return matched + index;
232        }
233    }
234    matched + (limit & 7usize) // made it through the loop
235}
236
237#[allow(unused)]
238pub fn slowFindMatchLengthWithLimit(s1: &[u8], s2: &[u8], limit: usize) -> usize {
239    for (index, it) in s1[..limit].iter().zip(s2[..limit].iter()).enumerate() {
240        if it.0 != it.1 {
241            return index;
242        }
243    }
244    limit
245}
246
247pub fn IsMatch(dictionary: &BrotliDictionary, w: DictWord, data: &[u8], max_length: usize) -> i32 {
248    if w.l as usize > max_length {
249        0
250    } else {
251        let offset: usize = (dictionary.offsets_by_length[w.l as usize] as usize)
252            .wrapping_add((w.len() as usize).wrapping_mul(w.idx() as usize));
253        let dict = &dictionary.data.split_at(offset).1;
254        if w.transform() as i32 == 0i32 {
255            if FindMatchLengthWithLimit(dict, data, w.l as usize) == w.l as usize {
256                1
257            } else {
258                0
259            }
260        } else if w.transform() as i32 == 10i32 {
261            if dict[0] as i32 >= b'a' as i32
262                && (dict[0] as i32 <= b'z' as i32)
263                && (dict[0] as i32 ^ 32i32 == data[0] as i32)
264                && (FindMatchLengthWithLimit(
265                    dict.split_at(1).1,
266                    data.split_at(1).1,
267                    (w.len() as u32).wrapping_sub(1) as usize,
268                ) == (w.len() as u32).wrapping_sub(1) as usize)
269            {
270                1
271            } else {
272                0
273            }
274        } else {
275            for i in 0usize..w.len() as usize {
276                if dict[i] as i32 >= b'a' as i32 && (dict[i] as i32 <= b'z' as i32) {
277                    if dict[i] as i32 ^ 32i32 != data[i] as i32 {
278                        return 0;
279                    }
280                } else if dict[i] as i32 != data[i] as i32 {
281                    return 0;
282                }
283            }
284            1
285        }
286    }
287}
288
289#[allow(unused)]
290fn AddMatch(distance: usize, len: usize, len_code: usize, mut matches: &mut [u32]) {
291    let match_: u32 = (distance << 5).wrapping_add(len_code) as u32;
292    matches[len] = min(matches[len], match_);
293}
294
295#[allow(unused)]
296fn DictMatchLength(
297    dictionary: &BrotliDictionary,
298    data: &[u8],
299    id: usize,
300    len: usize,
301    maxlen: usize,
302) -> usize {
303    let offset: usize =
304        (dictionary.offsets_by_length[len] as usize).wrapping_add(len.wrapping_mul(id));
305    FindMatchLengthWithLimit(dictionary.data.split_at(offset).1, data, min(len, maxlen))
306}
307
308#[allow(unused)]
309pub fn BrotliFindAllStaticDictionaryMatches(
310    dictionary: &BrotliDictionary,
311    data: &[u8],
312    min_length: usize,
313    max_length: usize,
314    mut matches: &mut [u32],
315) -> i32 {
316    let mut has_found_match: i32 = 0i32;
317    {
318        let mut offset: usize = kStaticDictionaryBuckets[Hash(data) as usize] as usize;
319        let mut end: i32 = (offset == 0) as i32;
320        while end == 0 {
321            let mut w: DictWord = kStaticDictionaryWords[offset];
322            offset = offset.wrapping_add(1);
323            let l: usize = (w.len() as i32 & 0x1fi32) as usize;
324            let n: usize = 1usize << dictionary.size_bits_by_length[l] as i32;
325            let id: usize = w.idx() as usize;
326            end = !(w.len() as i32 & 0x80i32 == 0) as i32;
327            w.l = l as u8;
328            if w.transform() as i32 == 0i32 {
329                let matchlen: usize = DictMatchLength(dictionary, data, id, l, max_length);
330
331                let mut minlen: usize;
332
333                let mut len: usize;
334                if matchlen == l {
335                    //eprint!("Adding match {} {} {}\n", w.len(), w.transform(), w.idx());
336                    AddMatch(id, l, l, matches);
337                    has_found_match = 1i32;
338                }
339                if matchlen >= l.wrapping_sub(1) {
340                    //eprint!("Bdding match {} {} {}\n", w.len(), w.transform(), w.idx());
341                    AddMatch(
342                        id.wrapping_add((12usize).wrapping_mul(n)),
343                        l.wrapping_sub(1),
344                        l,
345                        matches,
346                    );
347                    if l.wrapping_add(2) < max_length
348                        && (data[(l.wrapping_sub(1) as usize)] as i32 == b'i' as i32)
349                        && (data[(l as usize)] as i32 == b'n' as i32)
350                        && (data[(l.wrapping_add(1) as usize)] as i32 == b'g' as i32)
351                        && (data[(l.wrapping_add(2) as usize)] as i32 == b' ' as i32)
352                    {
353                        //eprint!("Cdding match {} {} {}\n", w.len(), w.transform(), w.idx());
354                        AddMatch(
355                            id.wrapping_add((49usize).wrapping_mul(n)),
356                            l.wrapping_add(3),
357                            l,
358                            matches,
359                        );
360                    }
361                    has_found_match = 1i32;
362                }
363                minlen = min_length;
364                if l > 9usize {
365                    minlen = max(minlen, l.wrapping_sub(9));
366                }
367                let maxlen: usize = min(matchlen, l.wrapping_sub(2));
368                for len in minlen..=maxlen {
369                    //eprint!("Ddding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
370                    AddMatch(
371                        id.wrapping_add(
372                            (kOmitLastNTransforms[l.wrapping_sub(len)] as usize).wrapping_mul(n),
373                        ),
374                        len,
375                        l,
376                        matches,
377                    );
378                    has_found_match = 1i32;
379                }
380
381                if matchlen < l || l.wrapping_add(6) >= max_length {
382                    continue;
383                }
384                let s: &[u8] = data.split_at(l as usize).1;
385                if s[0] as i32 == b' ' as i32 {
386                    //eprint!("Edding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
387                    AddMatch(id.wrapping_add(n), l.wrapping_add(1), l, matches);
388                    if s[1] as i32 == b'a' as i32 {
389                        if s[2] as i32 == b' ' as i32 {
390                            //eprint!("Fdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
391                            AddMatch(
392                                id.wrapping_add((28usize).wrapping_mul(n)),
393                                l.wrapping_add(3),
394                                l,
395                                matches,
396                            );
397                        } else if s[2] as i32 == b's' as i32 {
398                            if s[3] as i32 == b' ' as i32 {
399                                //eprint!("Gdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
400                                AddMatch(
401                                    id.wrapping_add((46usize).wrapping_mul(n)),
402                                    l.wrapping_add(4),
403                                    l,
404                                    matches,
405                                );
406                            }
407                        } else if s[2] as i32 == b't' as i32 {
408                            if s[3] as i32 == b' ' as i32 {
409                                //eprint!("Hdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
410                                AddMatch(
411                                    id.wrapping_add((60usize).wrapping_mul(n)),
412                                    l.wrapping_add(4),
413                                    l,
414                                    matches,
415                                );
416                            }
417                        } else if s[2] as i32 == b'n' as i32
418                            && s[3] as i32 == b'd' as i32
419                            && (s[4] as i32 == b' ' as i32)
420                        {
421                            //eprint!("Idding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
422                            AddMatch(
423                                id.wrapping_add((10usize).wrapping_mul(n)),
424                                l.wrapping_add(5),
425                                l,
426                                matches,
427                            );
428                        }
429                    } else if s[1] as i32 == b'b' as i32 {
430                        if s[2] as i32 == b'y' as i32 && (s[3] as i32 == b' ' as i32) {
431                            //eprint!("Jdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
432                            AddMatch(
433                                id.wrapping_add((38usize).wrapping_mul(n)),
434                                l.wrapping_add(4),
435                                l,
436                                matches,
437                            );
438                        }
439                    } else if s[1] as i32 == b'i' as i32 {
440                        if s[2] as i32 == b'n' as i32 {
441                            if s[3] as i32 == b' ' as i32 {
442                                //eprint!("Kdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
443                                AddMatch(
444                                    id.wrapping_add((16usize).wrapping_mul(n)),
445                                    l.wrapping_add(4),
446                                    l,
447                                    matches,
448                                );
449                            }
450                        } else if s[2] as i32 == b's' as i32 && s[3] as i32 == b' ' as i32 {
451                            //eprint!("Ldding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
452                            AddMatch(
453                                id.wrapping_add((47usize).wrapping_mul(n)),
454                                l.wrapping_add(4),
455                                l,
456                                matches,
457                            );
458                        }
459                    } else if s[1] as i32 == b'f' as i32 {
460                        if s[2] as i32 == b'o' as i32 {
461                            if s[3] as i32 == b'r' as i32 && (s[4] as i32 == b' ' as i32) {
462                                //eprint!("Mdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
463                                AddMatch(
464                                    id.wrapping_add((25usize).wrapping_mul(n)),
465                                    l.wrapping_add(5),
466                                    l,
467                                    matches,
468                                );
469                            }
470                        } else if s[2] as i32 == b'r' as i32
471                            && s[3] as i32 == b'o' as i32
472                            && (s[4] as i32 == b'm' as i32)
473                            && (s[5] as i32 == b' ' as i32)
474                        {
475                            //eprint!("Ndding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
476                            AddMatch(
477                                id.wrapping_add((37usize).wrapping_mul(n)),
478                                l.wrapping_add(6),
479                                l,
480                                matches,
481                            );
482                        }
483                    } else if s[1] as i32 == b'o' as i32 {
484                        if s[2] as i32 == b'f' as i32 {
485                            if s[3] as i32 == b' ' as i32 {
486                                //eprint!("Odding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
487                                AddMatch(
488                                    id.wrapping_add((8usize).wrapping_mul(n)),
489                                    l.wrapping_add(4),
490                                    l,
491                                    matches,
492                                );
493                            }
494                        } else if s[2] as i32 == b'n' as i32 && s[3] as i32 == b' ' as i32 {
495                            //eprint!("Pdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
496                            AddMatch(
497                                id.wrapping_add((45usize).wrapping_mul(n)),
498                                l.wrapping_add(4),
499                                l,
500                                matches,
501                            );
502                        }
503                    } else if s[1] as i32 == b'n' as i32 {
504                        if s[2] as i32 == b'o' as i32
505                            && (s[3] as i32 == b't' as i32)
506                            && (s[4] as i32 == b' ' as i32)
507                        {
508                            //eprint!("Qdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
509                            AddMatch(
510                                id.wrapping_add((80usize).wrapping_mul(n)),
511                                l.wrapping_add(5),
512                                l,
513                                matches,
514                            );
515                        }
516                    } else if s[1] as i32 == b't' as i32 {
517                        if s[2] as i32 == b'h' as i32 {
518                            if s[3] as i32 == b'e' as i32 {
519                                if s[4] as i32 == b' ' as i32 {
520                                    //eprint!("Rdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
521                                    AddMatch(
522                                        id.wrapping_add((5usize).wrapping_mul(n)),
523                                        l.wrapping_add(5),
524                                        l,
525                                        matches,
526                                    );
527                                }
528                            } else if s[3] as i32 == b'a' as i32
529                                && s[4] as i32 == b't' as i32
530                                && (s[5] as i32 == b' ' as i32)
531                            {
532                                //eprint!("Sdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
533                                AddMatch(
534                                    id.wrapping_add((29usize).wrapping_mul(n)),
535                                    l.wrapping_add(6),
536                                    l,
537                                    matches,
538                                );
539                            }
540                        } else if s[2] as i32 == b'o' as i32 && s[3] as i32 == b' ' as i32 {
541                            //eprint!("Tdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
542                            AddMatch(
543                                id.wrapping_add((17usize).wrapping_mul(n)),
544                                l.wrapping_add(4),
545                                l,
546                                matches,
547                            );
548                        }
549                    } else if s[1] as i32 == b'w' as i32
550                        && s[2] as i32 == b'i' as i32
551                        && (s[3] as i32 == b't' as i32)
552                        && (s[4] as i32 == b'h' as i32)
553                        && (s[5] as i32 == b' ' as i32)
554                    {
555                        //eprint!("Udding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
556                        AddMatch(
557                            id.wrapping_add((35usize).wrapping_mul(n)),
558                            l.wrapping_add(6),
559                            l,
560                            matches,
561                        );
562                    }
563                } else if s[0] as i32 == b'\"' as i32 {
564                    //eprint!("Vdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
565                    AddMatch(
566                        id.wrapping_add((19usize).wrapping_mul(n)),
567                        l.wrapping_add(1),
568                        l,
569                        matches,
570                    );
571                    if s[1] as i32 == b'>' as i32 {
572                        //eprint!("Wdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
573                        AddMatch(
574                            id.wrapping_add((21usize).wrapping_mul(n)),
575                            l.wrapping_add(2),
576                            l,
577                            matches,
578                        );
579                    }
580                } else if s[0] as i32 == b'.' as i32 {
581                    //eprint!("Xdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
582                    AddMatch(
583                        id.wrapping_add((20usize).wrapping_mul(n)),
584                        l.wrapping_add(1),
585                        l,
586                        matches,
587                    );
588                    if s[1] as i32 == b' ' as i32 {
589                        //eprint!("Ydding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
590                        AddMatch(
591                            id.wrapping_add((31usize).wrapping_mul(n)),
592                            l.wrapping_add(2),
593                            l,
594                            matches,
595                        );
596                        if s[2] as i32 == b'T' as i32 && (s[3] as i32 == b'h' as i32) {
597                            if s[4] as i32 == b'e' as i32 {
598                                if s[5] as i32 == b' ' as i32 {
599                                    //eprint!("Zdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
600                                    AddMatch(
601                                        id.wrapping_add((43usize).wrapping_mul(n)),
602                                        l.wrapping_add(6),
603                                        l,
604                                        matches,
605                                    );
606                                }
607                            } else if s[4] as i32 == b'i' as i32
608                                && s[5] as i32 == b's' as i32
609                                && (s[6] as i32 == b' ' as i32)
610                            {
611                                //eprint!("AAdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
612                                AddMatch(
613                                    id.wrapping_add((75usize).wrapping_mul(n)),
614                                    l.wrapping_add(7),
615                                    l,
616                                    matches,
617                                );
618                            }
619                        }
620                    }
621                } else if s[0] as i32 == b',' as i32 {
622                    //eprint!("ABdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
623                    AddMatch(
624                        id.wrapping_add((76usize).wrapping_mul(n)),
625                        l.wrapping_add(1),
626                        l,
627                        matches,
628                    );
629                    if s[1] as i32 == b' ' as i32 {
630                        //eprint!("ACdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
631                        AddMatch(
632                            id.wrapping_add((14usize).wrapping_mul(n)),
633                            l.wrapping_add(2),
634                            l,
635                            matches,
636                        );
637                    }
638                } else if s[0] as i32 == b'\n' as i32 {
639                    //eprint!("ADdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
640                    AddMatch(
641                        id.wrapping_add((22usize).wrapping_mul(n)),
642                        l.wrapping_add(1),
643                        l,
644                        matches,
645                    );
646                    if s[1] as i32 == b'\t' as i32 {
647                        //eprint!("AEdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
648                        AddMatch(
649                            id.wrapping_add((50usize).wrapping_mul(n)),
650                            l.wrapping_add(2),
651                            l,
652                            matches,
653                        );
654                    }
655                } else if s[0] as i32 == b']' as i32 {
656                    //eprint!("AFdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
657                    AddMatch(
658                        id.wrapping_add((24usize).wrapping_mul(n)),
659                        l.wrapping_add(1),
660                        l,
661                        matches,
662                    );
663                } else if s[0] as i32 == b'\'' as i32 {
664                    //eprint!("AGdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
665                    AddMatch(
666                        id.wrapping_add((36usize).wrapping_mul(n)),
667                        l.wrapping_add(1),
668                        l,
669                        matches,
670                    );
671                } else if s[0] as i32 == b':' as i32 {
672                    //eprint!("AHdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
673                    AddMatch(
674                        id.wrapping_add((51usize).wrapping_mul(n)),
675                        l.wrapping_add(1),
676                        l,
677                        matches,
678                    );
679                } else if s[0] as i32 == b'(' as i32 {
680                    //eprint!("AIdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
681                    AddMatch(
682                        id.wrapping_add((57usize).wrapping_mul(n)),
683                        l.wrapping_add(1),
684                        l,
685                        matches,
686                    );
687                } else if s[0] as i32 == b'=' as i32 {
688                    if s[1] as i32 == b'\"' as i32 {
689                        //eprint!("AJdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
690                        AddMatch(
691                            id.wrapping_add((70usize).wrapping_mul(n)),
692                            l.wrapping_add(2),
693                            l,
694                            matches,
695                        );
696                    } else if s[1] as i32 == b'\'' as i32 {
697                        //eprint!("AKdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
698                        AddMatch(
699                            id.wrapping_add((86usize).wrapping_mul(n)),
700                            l.wrapping_add(2),
701                            l,
702                            matches,
703                        );
704                    }
705                } else if s[0] as i32 == b'a' as i32 {
706                    if s[1] as i32 == b'l' as i32 && (s[2] as i32 == b' ' as i32) {
707                        //eprint!("ALdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
708                        AddMatch(
709                            id.wrapping_add((84usize).wrapping_mul(n)),
710                            l.wrapping_add(3),
711                            l,
712                            matches,
713                        );
714                    }
715                } else if s[0] as i32 == b'e' as i32 {
716                    if s[1] as i32 == b'd' as i32 {
717                        if s[2] as i32 == b' ' as i32 {
718                            //eprint!("AMdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
719                            AddMatch(
720                                id.wrapping_add((53usize).wrapping_mul(n)),
721                                l.wrapping_add(3),
722                                l,
723                                matches,
724                            );
725                        }
726                    } else if s[1] as i32 == b'r' as i32 {
727                        if s[2] as i32 == b' ' as i32 {
728                            //eprint!("ANdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
729                            AddMatch(
730                                id.wrapping_add((82usize).wrapping_mul(n)),
731                                l.wrapping_add(3),
732                                l,
733                                matches,
734                            );
735                        }
736                    } else if s[1] as i32 == b's' as i32
737                        && s[2] as i32 == b't' as i32
738                        && (s[3] as i32 == b' ' as i32)
739                    {
740                        //eprint!("AOdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
741                        AddMatch(
742                            id.wrapping_add((95usize).wrapping_mul(n)),
743                            l.wrapping_add(4),
744                            l,
745                            matches,
746                        );
747                    }
748                } else if s[0] as i32 == b'f' as i32 {
749                    if s[1] as i32 == b'u' as i32
750                        && (s[2] as i32 == b'l' as i32)
751                        && (s[3] as i32 == b' ' as i32)
752                    {
753                        //eprint!("APdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
754                        AddMatch(
755                            id.wrapping_add((90usize).wrapping_mul(n)),
756                            l.wrapping_add(4),
757                            l,
758                            matches,
759                        );
760                    }
761                } else if s[0] as i32 == b'i' as i32 {
762                    if s[1] as i32 == b'v' as i32 {
763                        if s[2] as i32 == b'e' as i32 && (s[3] as i32 == b' ' as i32) {
764                            //eprint!("AQdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
765                            AddMatch(
766                                id.wrapping_add((92usize).wrapping_mul(n)),
767                                l.wrapping_add(4),
768                                l,
769                                matches,
770                            );
771                        }
772                    } else if s[1] as i32 == b'z' as i32
773                        && s[2] as i32 == b'e' as i32
774                        && (s[3] as i32 == b' ' as i32)
775                    {
776                        //eprint!("ARdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
777                        AddMatch(
778                            id.wrapping_add((100usize).wrapping_mul(n)),
779                            l.wrapping_add(4),
780                            l,
781                            matches,
782                        );
783                    }
784                } else if s[0] as i32 == b'l' as i32 {
785                    if s[1] as i32 == b'e' as i32 {
786                        if s[2] as i32 == b's' as i32
787                            && (s[3] as i32 == b's' as i32)
788                            && (s[4] as i32 == b' ' as i32)
789                        {
790                            //eprint!("ASdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
791                            AddMatch(
792                                id.wrapping_add((93usize).wrapping_mul(n)),
793                                l.wrapping_add(5),
794                                l,
795                                matches,
796                            );
797                        }
798                    } else if s[1] as i32 == b'y' as i32 && s[2] as i32 == b' ' as i32 {
799                        //eprint!("ATdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
800                        AddMatch(
801                            id.wrapping_add((61usize).wrapping_mul(n)),
802                            l.wrapping_add(3),
803                            l,
804                            matches,
805                        );
806                    }
807                } else if s[0] as i32 == b'o' as i32
808                    && s[1] as i32 == b'u' as i32
809                    && (s[2] as i32 == b's' as i32)
810                    && (s[3] as i32 == b' ' as i32)
811                {
812                    //eprint!("AUdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), len);
813                    AddMatch(
814                        id.wrapping_add((106usize).wrapping_mul(n)),
815                        l.wrapping_add(4),
816                        l,
817                        matches,
818                    );
819                }
820            } else {
821                let is_all_caps = w.transform() != kUppercaseFirst;
822
823                if IsMatch(dictionary, w, data, max_length) == 0 {
824                    continue;
825                }
826                //eprint!("AVdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
827                AddMatch(
828                    id.wrapping_add((if is_all_caps { 44usize } else { 9usize }).wrapping_mul(n)),
829                    l,
830                    l,
831                    matches,
832                );
833                has_found_match = 1i32;
834                if l.wrapping_add(1) >= max_length {
835                    continue;
836                }
837                let s: &[u8] = data.split_at(l as usize).1;
838                if s[0] as i32 == b' ' as i32 {
839                    //eprint!("AWdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
840                    AddMatch(
841                        id.wrapping_add(
842                            (if is_all_caps { 68usize } else { 4usize }).wrapping_mul(n),
843                        ),
844                        l.wrapping_add(1),
845                        l,
846                        matches,
847                    );
848                } else if s[0] as i32 == b'\"' as i32 {
849                    //eprint!("AXdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
850                    AddMatch(
851                        id.wrapping_add(
852                            (if is_all_caps { 87usize } else { 66usize }).wrapping_mul(n),
853                        ),
854                        l.wrapping_add(1),
855                        l,
856                        matches,
857                    );
858                    if s[1] as i32 == b'>' as i32 {
859                        //eprint!("AYdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
860                        AddMatch(
861                            id.wrapping_add(
862                                (if is_all_caps { 97usize } else { 69usize }).wrapping_mul(n),
863                            ),
864                            l.wrapping_add(2),
865                            l,
866                            matches,
867                        );
868                    }
869                } else if s[0] as i32 == b'.' as i32 {
870                    //eprint!("AZdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
871                    AddMatch(
872                        id.wrapping_add(
873                            (if is_all_caps { 101usize } else { 79usize }).wrapping_mul(n),
874                        ),
875                        l.wrapping_add(1),
876                        l,
877                        matches,
878                    );
879                    if s[1] as i32 == b' ' as i32 {
880                        //eprint!("BAdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
881                        AddMatch(
882                            id.wrapping_add(
883                                (if is_all_caps { 114usize } else { 88usize }).wrapping_mul(n),
884                            ),
885                            l.wrapping_add(2),
886                            l,
887                            matches,
888                        );
889                    }
890                } else if s[0] as i32 == b',' as i32 {
891                    //eprint!("BBdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
892                    AddMatch(
893                        id.wrapping_add(
894                            (if is_all_caps { 112usize } else { 99usize }).wrapping_mul(n),
895                        ),
896                        l.wrapping_add(1),
897                        l,
898                        matches,
899                    );
900                    if s[1] as i32 == b' ' as i32 {
901                        //eprint!("BCdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
902                        AddMatch(
903                            id.wrapping_add(
904                                (if is_all_caps { 107usize } else { 58usize }).wrapping_mul(n),
905                            ),
906                            l.wrapping_add(2),
907                            l,
908                            matches,
909                        );
910                    }
911                } else if s[0] as i32 == b'\'' as i32 {
912                    //eprint!("BDdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
913                    AddMatch(
914                        id.wrapping_add(
915                            (if is_all_caps { 94usize } else { 74usize }).wrapping_mul(n),
916                        ),
917                        l.wrapping_add(1),
918                        l,
919                        matches,
920                    );
921                } else if s[0] as i32 == b'(' as i32 {
922                    //eprint!("BEdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
923                    AddMatch(
924                        id.wrapping_add(
925                            (if is_all_caps { 113usize } else { 78usize }).wrapping_mul(n),
926                        ),
927                        l.wrapping_add(1),
928                        l,
929                        matches,
930                    );
931                } else if s[0] as i32 == b'=' as i32 {
932                    if s[1] as i32 == b'\"' as i32 {
933                        //eprint!("BFdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
934                        AddMatch(
935                            id.wrapping_add(
936                                (if is_all_caps { 105usize } else { 104usize }).wrapping_mul(n),
937                            ),
938                            l.wrapping_add(2),
939                            l,
940                            matches,
941                        );
942                    } else if s[1] as i32 == b'\'' as i32 {
943                        //eprint!("BGdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
944                        AddMatch(
945                            id.wrapping_add(
946                                (if is_all_caps { 116usize } else { 108usize }).wrapping_mul(n),
947                            ),
948                            l.wrapping_add(2),
949                            l,
950                            matches,
951                        );
952                    }
953                }
954            }
955        }
956    }
957    if max_length >= 5usize && (data[0] as i32 == b' ' as i32 || data[0] as i32 == b'.' as i32) {
958        let is_space = data[0] == b' ';
959        let mut offset: usize =
960            kStaticDictionaryBuckets[Hash(data.split_at(1).1) as usize] as usize;
961        let mut end: i32 = (offset == 0) as i32;
962        while end == 0 {
963            let mut w: DictWord = kStaticDictionaryWords[offset];
964            offset = offset.wrapping_add(1);
965            let l: usize = (w.len() as i32 & 0x1fi32) as usize;
966            let n: usize = 1usize << dictionary.size_bits_by_length[l] as i32;
967            let id: usize = w.idx() as usize;
968            end = !(w.len() as i32 & 0x80i32 == 0) as i32;
969            w.l = l as u8;
970            if w.transform() as i32 == 0i32 {
971                if IsMatch(
972                    dictionary,
973                    w,
974                    data.split_at(1).1,
975                    max_length.wrapping_sub(1),
976                ) == 0
977                {
978                    continue;
979                }
980                //eprint!("BHdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
981                AddMatch(
982                    id.wrapping_add((if is_space { 6usize } else { 32usize }).wrapping_mul(n)),
983                    l.wrapping_add(1),
984                    l,
985                    matches,
986                );
987                has_found_match = 1i32;
988                if l.wrapping_add(2) >= max_length {
989                    continue;
990                }
991                let s: &[u8] = data.split_at(l.wrapping_add(1) as usize).1;
992                if s[0] as i32 == b' ' as i32 {
993                    //eprint!("BIdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
994                    AddMatch(
995                        id.wrapping_add((if is_space { 2usize } else { 77usize }).wrapping_mul(n)),
996                        l.wrapping_add(2),
997                        l,
998                        matches,
999                    );
1000                } else if s[0] as i32 == b'(' as i32 {
1001                    //eprint!("BJdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1002                    AddMatch(
1003                        id.wrapping_add((if is_space { 89usize } else { 67usize }).wrapping_mul(n)),
1004                        l.wrapping_add(2),
1005                        l,
1006                        matches,
1007                    );
1008                } else if is_space {
1009                    if s[0] as i32 == b',' as i32 {
1010                        //eprint!("BKdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1011                        AddMatch(
1012                            id.wrapping_add((103usize).wrapping_mul(n)),
1013                            l.wrapping_add(2),
1014                            l,
1015                            matches,
1016                        );
1017                        if s[1] as i32 == b' ' as i32 {
1018                            //eprint!("BLdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1019                            AddMatch(
1020                                id.wrapping_add((33usize).wrapping_mul(n)),
1021                                l.wrapping_add(3),
1022                                l,
1023                                matches,
1024                            );
1025                        }
1026                    } else if s[0] as i32 == b'.' as i32 {
1027                        //eprint!("BMdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1028                        AddMatch(
1029                            id.wrapping_add((71usize).wrapping_mul(n)),
1030                            l.wrapping_add(2),
1031                            l,
1032                            matches,
1033                        );
1034                        if s[1] as i32 == b' ' as i32 {
1035                            //eprint!("BNdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1036                            AddMatch(
1037                                id.wrapping_add((52usize).wrapping_mul(n)),
1038                                l.wrapping_add(3),
1039                                l,
1040                                matches,
1041                            );
1042                        }
1043                    } else if s[0] as i32 == b'=' as i32 {
1044                        if s[1] as i32 == b'\"' as i32 {
1045                            //eprint!("BOdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1046                            AddMatch(
1047                                id.wrapping_add((81usize).wrapping_mul(n)),
1048                                l.wrapping_add(3),
1049                                l,
1050                                matches,
1051                            );
1052                        } else if s[1] as i32 == b'\'' as i32 {
1053                            //eprint!("BPdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1054                            AddMatch(
1055                                id.wrapping_add((98usize).wrapping_mul(n)),
1056                                l.wrapping_add(3),
1057                                l,
1058                                matches,
1059                            );
1060                        }
1061                    }
1062                }
1063            } else if is_space {
1064                let is_all_caps = w.transform() != kUppercaseFirst;
1065
1066                if IsMatch(
1067                    dictionary,
1068                    w,
1069                    data.split_at(1).1,
1070                    max_length.wrapping_sub(1),
1071                ) == 0
1072                {
1073                    continue;
1074                }
1075                //eprint!("CAdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1076                AddMatch(
1077                    id.wrapping_add((if is_all_caps { 85usize } else { 30usize }).wrapping_mul(n)),
1078                    l.wrapping_add(1),
1079                    l,
1080                    matches,
1081                );
1082                has_found_match = 1i32;
1083                if l.wrapping_add(2) >= max_length {
1084                    continue;
1085                }
1086                let s: &[u8] = data.split_at(l.wrapping_add(1)).1;
1087                if s[0] as i32 == b' ' as i32 {
1088                    //eprint!("CBdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1089                    AddMatch(
1090                        id.wrapping_add(
1091                            (if is_all_caps { 83usize } else { 15usize }).wrapping_mul(n),
1092                        ),
1093                        l.wrapping_add(2),
1094                        l,
1095                        matches,
1096                    );
1097                } else if s[0] as i32 == b',' as i32 {
1098                    if !is_all_caps {
1099                        //eprint!("CCdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1100                        AddMatch(
1101                            id.wrapping_add((109usize).wrapping_mul(n)),
1102                            l.wrapping_add(2),
1103                            l,
1104                            matches,
1105                        );
1106                    }
1107                    if s[1] as i32 == b' ' as i32 {
1108                        //eprint!("CDdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1109                        AddMatch(
1110                            id.wrapping_add(
1111                                (if is_all_caps { 111usize } else { 65usize }).wrapping_mul(n),
1112                            ),
1113                            l.wrapping_add(3),
1114                            l,
1115                            matches,
1116                        );
1117                    }
1118                } else if s[0] as i32 == b'.' as i32 {
1119                    //eprint!("CEdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1120                    AddMatch(
1121                        id.wrapping_add(
1122                            (if is_all_caps { 115usize } else { 96usize }).wrapping_mul(n),
1123                        ),
1124                        l.wrapping_add(2),
1125                        l,
1126                        matches,
1127                    );
1128                    if s[1] as i32 == b' ' as i32 {
1129                        //eprint!("CFdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1130                        AddMatch(
1131                            id.wrapping_add(
1132                                (if is_all_caps { 117usize } else { 91usize }).wrapping_mul(n),
1133                            ),
1134                            l.wrapping_add(3),
1135                            l,
1136                            matches,
1137                        );
1138                    }
1139                } else if s[0] as i32 == b'=' as i32 {
1140                    if s[1] as i32 == b'\"' as i32 {
1141                        //eprint!("CGdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1142                        AddMatch(
1143                            id.wrapping_add(
1144                                (if is_all_caps { 110usize } else { 118usize }).wrapping_mul(n),
1145                            ),
1146                            l.wrapping_add(3),
1147                            l,
1148                            matches,
1149                        );
1150                    } else if s[1] as i32 == b'\'' as i32 {
1151                        //eprint!("CHdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1152                        AddMatch(
1153                            id.wrapping_add(
1154                                (if is_all_caps { 119usize } else { 120usize }).wrapping_mul(n),
1155                            ),
1156                            l.wrapping_add(3),
1157                            l,
1158                            matches,
1159                        );
1160                    }
1161                }
1162            }
1163        }
1164    }
1165    if max_length >= 6usize
1166        && (data[1] as i32 == b' ' as i32
1167            && (data[0] as i32 == b'e' as i32
1168                || data[0] as i32 == b's' as i32
1169                || data[0] as i32 == b',' as i32)
1170            || data[0] as i32 == 0xc2i32 && (data[1] as i32 == 0xa0i32))
1171    {
1172        let mut offset: usize =
1173            kStaticDictionaryBuckets[Hash(data.split_at(2).1) as usize] as usize;
1174        let mut end: i32 = (offset == 0) as i32;
1175        while end == 0 {
1176            let mut w: DictWord = kStaticDictionaryWords[offset];
1177            offset = offset.wrapping_add(1);
1178            let l: usize = (w.len() as i32 & 0x1fi32) as usize;
1179            let n: usize = 1usize << dictionary.size_bits_by_length[l] as i32;
1180            let id: usize = w.idx() as usize;
1181            end = !(w.len() as i32 & 0x80i32 == 0) as i32;
1182            w.l = l as u8;
1183            if w.transform() as i32 == 0i32
1184                && (IsMatch(
1185                    dictionary,
1186                    w,
1187                    data.split_at(2).1,
1188                    max_length.wrapping_sub(2),
1189                ) != 0)
1190            {
1191                if data[0] as i32 == 0xc2i32 {
1192                    //eprint!("CIdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1193                    AddMatch(
1194                        id.wrapping_add((102usize).wrapping_mul(n)),
1195                        l.wrapping_add(2),
1196                        l,
1197                        matches,
1198                    );
1199                    has_found_match = 1i32;
1200                } else if l.wrapping_add(2) < max_length
1201                    && (data[(l.wrapping_add(2) as usize)] as i32 == b' ' as i32)
1202                {
1203                    let t: usize = (if data[0] as i32 == b'e' as i32 {
1204                        18i32
1205                    } else if data[0] as i32 == b's' as i32 {
1206                        7i32
1207                    } else {
1208                        13i32
1209                    }) as usize;
1210                    //eprint!("CJdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1211                    AddMatch(
1212                        id.wrapping_add(t.wrapping_mul(n)),
1213                        l.wrapping_add(3),
1214                        l,
1215                        matches,
1216                    );
1217                    has_found_match = 1i32;
1218                }
1219            }
1220        }
1221    }
1222    if max_length >= 9usize
1223        && (data[0] as i32 == b' ' as i32
1224            && (data[1] as i32 == b't' as i32)
1225            && (data[2] as i32 == b'h' as i32)
1226            && (data[3] as i32 == b'e' as i32)
1227            && (data[4] as i32 == b' ' as i32)
1228            || data[0] as i32 == b'.' as i32
1229                && (data[1] as i32 == b'c' as i32)
1230                && (data[2] as i32 == b'o' as i32)
1231                && (data[3] as i32 == b'm' as i32)
1232                && (data[4] as i32 == b'/' as i32))
1233    {
1234        let mut offset: usize =
1235            kStaticDictionaryBuckets[Hash(data.split_at(5).1) as usize] as usize;
1236        let mut end: i32 = (offset == 0) as i32;
1237        while end == 0 {
1238            let mut w: DictWord = kStaticDictionaryWords[offset];
1239            offset = offset.wrapping_add(1);
1240            let l: usize = (w.len() as i32 & 0x1fi32) as usize;
1241            let n: usize = 1usize << dictionary.size_bits_by_length[l] as i32;
1242            let id: usize = w.idx() as usize;
1243            end = !(w.len() as i32 & 0x80i32 == 0) as i32;
1244            w.l = l as u8;
1245            if w.transform() as i32 == 0i32
1246                && (IsMatch(
1247                    dictionary,
1248                    w,
1249                    data.split_at(5).1,
1250                    max_length.wrapping_sub(5),
1251                ) != 0)
1252            {
1253                //eprint!("CKdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1254                AddMatch(
1255                    id.wrapping_add(
1256                        (if data[0] as i32 == b' ' as i32 {
1257                            41i32
1258                        } else {
1259                            72i32
1260                        } as usize)
1261                            .wrapping_mul(n),
1262                    ),
1263                    l.wrapping_add(5),
1264                    l,
1265                    matches,
1266                );
1267                has_found_match = 1i32;
1268                if l.wrapping_add(5) < max_length {
1269                    let s: &[u8] = data.split_at(l.wrapping_add(5) as usize).1;
1270                    if data[0] as i32 == b' ' as i32
1271                        && l.wrapping_add(8) < max_length
1272                        && (s[0] as i32 == b' ' as i32)
1273                        && (s[1] as i32 == b'o' as i32)
1274                        && (s[2] as i32 == b'f' as i32)
1275                        && (s[3] as i32 == b' ' as i32)
1276                    {
1277                        //eprint!("CLdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1278                        AddMatch(
1279                            id.wrapping_add((62usize).wrapping_mul(n)),
1280                            l.wrapping_add(9),
1281                            l,
1282                            matches,
1283                        );
1284                        if l.wrapping_add(12) < max_length
1285                            && (s[4] as i32 == b't' as i32)
1286                            && (s[5] as i32 == b'h' as i32)
1287                            && (s[6] as i32 == b'e' as i32)
1288                            && (s[7] as i32 == b' ' as i32)
1289                        {
1290                            //eprint!("BQdding match {} {} {} {}\n", w.len(), w.transform(), w.idx(), 666);
1291                            AddMatch(
1292                                id.wrapping_add((73usize).wrapping_mul(n)),
1293                                l.wrapping_add(13),
1294                                l,
1295                                matches,
1296                            );
1297                        }
1298                    }
1299                }
1300            }
1301        }
1302    }
1303    has_found_match
1304}
1305
1306#[cfg(test)]
1307mod test {
1308    #[allow(unused)]
1309    fn construct_situation(seed: &[u8], mut output: &mut [u8], limit: usize, matchfor: usize) {
1310        output[..].clone_from_slice(seed);
1311        if matchfor >= limit {
1312            return;
1313        }
1314        output[matchfor] = output[matchfor].wrapping_add((matchfor as u8 % 253u8).wrapping_add(1));
1315    }
1316    #[test]
1317    fn test_find_match_length() {
1318        let mut a = [91u8; 600000];
1319        let mut b = [0u8; 600000];
1320        for i in 1..a.len() {
1321            a[i] = (a[i - 1] % 19u8).wrapping_add(17);
1322        }
1323        construct_situation(&a[..], &mut b[..], a.len(), 0);
1324        assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 0);
1325        construct_situation(&a[..], &mut b[..], a.len(), 1);
1326        assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 1);
1327        construct_situation(&a[..], &mut b[..], a.len(), 10);
1328        assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 10);
1329        construct_situation(&a[..], &mut b[..], a.len(), 9);
1330        assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 9);
1331        construct_situation(&a[..], &mut b[..], a.len(), 7);
1332        assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 7);
1333        construct_situation(&a[..], &mut b[..], a.len(), 8);
1334        assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 8);
1335        construct_situation(&a[..], &mut b[..], a.len(), 48);
1336        assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 48);
1337        construct_situation(&a[..], &mut b[..], a.len(), 49);
1338        assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 49);
1339        construct_situation(&a[..], &mut b[..], a.len(), 63);
1340        assert_eq!(super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()), 63);
1341        construct_situation(&a[..], &mut b[..], a.len(), 222);
1342        assert_eq!(
1343            super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1344            222
1345        );
1346        construct_situation(&a[..], &mut b[..], a.len(), 1590);
1347        assert_eq!(
1348            super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1349            1590
1350        );
1351        construct_situation(&a[..], &mut b[..], a.len(), 12590);
1352        assert_eq!(
1353            super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1354            12590
1355        );
1356        construct_situation(&a[..], &mut b[..], a.len(), 52592);
1357        assert_eq!(
1358            super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1359            52592
1360        );
1361        construct_situation(&a[..], &mut b[..], a.len(), 152592);
1362        assert_eq!(
1363            super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1364            152592
1365        );
1366        construct_situation(&a[..], &mut b[..], a.len(), 252591);
1367        assert_eq!(
1368            super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1369            252591
1370        );
1371        construct_situation(&a[..], &mut b[..], a.len(), 131072);
1372        assert_eq!(
1373            super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1374            131072
1375        );
1376        construct_situation(&a[..], &mut b[..], a.len(), 131073);
1377        assert_eq!(
1378            super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1379            131073
1380        );
1381        construct_situation(&a[..], &mut b[..], a.len(), 131072 + 64 + 32 + 16 + 8);
1382        assert_eq!(
1383            super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1384            131072 + 64 + 32 + 16 + 8
1385        );
1386        construct_situation(&a[..], &mut b[..], a.len(), 272144 + 64 + 32 + 16 + 8 + 1);
1387        assert_eq!(
1388            super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1389            272144 + 64 + 32 + 16 + 8 + 1
1390        );
1391        construct_situation(&a[..], &mut b[..], a.len(), 2 * 272144 + 64 + 32 + 16 + 8);
1392        assert_eq!(
1393            super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1394            2 * 272144 + 64 + 32 + 16 + 8
1395        );
1396        construct_situation(&a[..], &mut b[..], a.len(), a.len());
1397        assert_eq!(
1398            super::FindMatchLengthWithLimit(&a[..], &b[..], a.len()),
1399            a.len()
1400        );
1401    }
1402}