isomorfeus-ferret 0.12.4 → 0.12.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (216) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +612 -612
  3. data/README.md +77 -48
  4. data/ext/isomorfeus_ferret_ext/bm_hash.c +9 -6
  5. data/ext/isomorfeus_ferret_ext/bm_micro_string.c +4 -2
  6. data/ext/isomorfeus_ferret_ext/brotli_common_constants.c +15 -0
  7. data/ext/isomorfeus_ferret_ext/brotli_common_constants.h +200 -0
  8. data/ext/isomorfeus_ferret_ext/brotli_common_context.c +156 -0
  9. data/ext/isomorfeus_ferret_ext/brotli_common_context.h +113 -0
  10. data/ext/isomorfeus_ferret_ext/brotli_common_dictionary.c +5914 -0
  11. data/ext/isomorfeus_ferret_ext/brotli_common_dictionary.h +64 -0
  12. data/ext/isomorfeus_ferret_ext/brotli_common_platform.c +22 -0
  13. data/ext/isomorfeus_ferret_ext/brotli_common_platform.h +594 -0
  14. data/ext/isomorfeus_ferret_ext/brotli_common_transform.c +291 -0
  15. data/ext/isomorfeus_ferret_ext/brotli_common_transform.h +85 -0
  16. data/ext/isomorfeus_ferret_ext/brotli_common_version.h +26 -0
  17. data/ext/isomorfeus_ferret_ext/brotli_dec_bit_reader.c +76 -0
  18. data/ext/isomorfeus_ferret_ext/brotli_dec_bit_reader.h +351 -0
  19. data/ext/isomorfeus_ferret_ext/brotli_dec_decode.c +2608 -0
  20. data/ext/isomorfeus_ferret_ext/brotli_dec_huffman.c +339 -0
  21. data/ext/isomorfeus_ferret_ext/brotli_dec_huffman.h +121 -0
  22. data/ext/isomorfeus_ferret_ext/brotli_dec_prefix.h +732 -0
  23. data/ext/isomorfeus_ferret_ext/brotli_dec_state.c +159 -0
  24. data/ext/isomorfeus_ferret_ext/brotli_dec_state.h +365 -0
  25. data/ext/isomorfeus_ferret_ext/brotli_decode.h +344 -0
  26. data/ext/isomorfeus_ferret_ext/brotli_enc_backward_references.c +145 -0
  27. data/ext/isomorfeus_ferret_ext/brotli_enc_backward_references.h +39 -0
  28. data/ext/isomorfeus_ferret_ext/brotli_enc_backward_references_hq.c +843 -0
  29. data/ext/isomorfeus_ferret_ext/brotli_enc_backward_references_hq.h +95 -0
  30. data/ext/isomorfeus_ferret_ext/brotli_enc_backward_references_inc.h +163 -0
  31. data/ext/isomorfeus_ferret_ext/brotli_enc_bit_cost.c +35 -0
  32. data/ext/isomorfeus_ferret_ext/brotli_enc_bit_cost.h +63 -0
  33. data/ext/isomorfeus_ferret_ext/brotli_enc_bit_cost_inc.h +127 -0
  34. data/ext/isomorfeus_ferret_ext/brotli_enc_block_encoder_inc.h +34 -0
  35. data/ext/isomorfeus_ferret_ext/brotli_enc_block_splitter.c +194 -0
  36. data/ext/isomorfeus_ferret_ext/brotli_enc_block_splitter.h +51 -0
  37. data/ext/isomorfeus_ferret_ext/brotli_enc_block_splitter_inc.h +440 -0
  38. data/ext/isomorfeus_ferret_ext/brotli_enc_brotli_bit_stream.c +1314 -0
  39. data/ext/isomorfeus_ferret_ext/brotli_enc_brotli_bit_stream.h +84 -0
  40. data/ext/isomorfeus_ferret_ext/brotli_enc_cluster.c +56 -0
  41. data/ext/isomorfeus_ferret_ext/brotli_enc_cluster.h +48 -0
  42. data/ext/isomorfeus_ferret_ext/brotli_enc_cluster_inc.h +320 -0
  43. data/ext/isomorfeus_ferret_ext/brotli_enc_command.c +28 -0
  44. data/ext/isomorfeus_ferret_ext/brotli_enc_command.h +190 -0
  45. data/ext/isomorfeus_ferret_ext/brotli_enc_compress_fragment.c +790 -0
  46. data/ext/isomorfeus_ferret_ext/brotli_enc_compress_fragment.h +61 -0
  47. data/ext/isomorfeus_ferret_ext/brotli_enc_compress_fragment_two_pass.c +645 -0
  48. data/ext/isomorfeus_ferret_ext/brotli_enc_compress_fragment_two_pass.h +54 -0
  49. data/ext/isomorfeus_ferret_ext/brotli_enc_dictionary_hash.c +1846 -0
  50. data/ext/isomorfeus_ferret_ext/brotli_enc_dictionary_hash.h +25 -0
  51. data/ext/isomorfeus_ferret_ext/brotli_enc_encode.c +1927 -0
  52. data/ext/isomorfeus_ferret_ext/brotli_enc_encoder_dict.c +33 -0
  53. data/ext/isomorfeus_ferret_ext/brotli_enc_encoder_dict.h +43 -0
  54. data/ext/isomorfeus_ferret_ext/brotli_enc_entropy_encode.c +503 -0
  55. data/ext/isomorfeus_ferret_ext/brotli_enc_entropy_encode.h +122 -0
  56. data/ext/isomorfeus_ferret_ext/brotli_enc_entropy_encode_static.h +539 -0
  57. data/ext/isomorfeus_ferret_ext/brotli_enc_fast_log.c +105 -0
  58. data/ext/isomorfeus_ferret_ext/brotli_enc_fast_log.h +66 -0
  59. data/ext/isomorfeus_ferret_ext/brotli_enc_find_match_length.h +79 -0
  60. data/ext/isomorfeus_ferret_ext/brotli_enc_hash.h +488 -0
  61. data/ext/isomorfeus_ferret_ext/brotli_enc_hash_composite_inc.h +125 -0
  62. data/ext/isomorfeus_ferret_ext/brotli_enc_hash_forgetful_chain_inc.h +293 -0
  63. data/ext/isomorfeus_ferret_ext/brotli_enc_hash_longest_match64_inc.h +267 -0
  64. data/ext/isomorfeus_ferret_ext/brotli_enc_hash_longest_match_inc.h +262 -0
  65. data/ext/isomorfeus_ferret_ext/brotli_enc_hash_longest_match_quickly_inc.h +266 -0
  66. data/ext/isomorfeus_ferret_ext/brotli_enc_hash_rolling_inc.h +212 -0
  67. data/ext/isomorfeus_ferret_ext/brotli_enc_hash_to_binary_tree_inc.h +329 -0
  68. data/ext/isomorfeus_ferret_ext/brotli_enc_histogram.c +100 -0
  69. data/ext/isomorfeus_ferret_ext/brotli_enc_histogram.h +63 -0
  70. data/ext/isomorfeus_ferret_ext/brotli_enc_histogram_inc.h +51 -0
  71. data/ext/isomorfeus_ferret_ext/brotli_enc_literal_cost.c +175 -0
  72. data/ext/isomorfeus_ferret_ext/brotli_enc_literal_cost.h +30 -0
  73. data/ext/isomorfeus_ferret_ext/brotli_enc_memory.c +170 -0
  74. data/ext/isomorfeus_ferret_ext/brotli_enc_memory.h +114 -0
  75. data/ext/isomorfeus_ferret_ext/brotli_enc_metablock.c +663 -0
  76. data/ext/isomorfeus_ferret_ext/brotli_enc_metablock.h +105 -0
  77. data/ext/isomorfeus_ferret_ext/brotli_enc_metablock_inc.h +183 -0
  78. data/ext/isomorfeus_ferret_ext/brotli_enc_params.h +46 -0
  79. data/ext/isomorfeus_ferret_ext/brotli_enc_prefix.h +53 -0
  80. data/ext/isomorfeus_ferret_ext/brotli_enc_quality.h +165 -0
  81. data/ext/isomorfeus_ferret_ext/brotli_enc_ringbuffer.h +167 -0
  82. data/ext/isomorfeus_ferret_ext/brotli_enc_static_dict.c +486 -0
  83. data/ext/isomorfeus_ferret_ext/brotli_enc_static_dict.h +40 -0
  84. data/ext/isomorfeus_ferret_ext/brotli_enc_static_dict_lut.h +5864 -0
  85. data/ext/isomorfeus_ferret_ext/brotli_enc_utf8_util.c +85 -0
  86. data/ext/isomorfeus_ferret_ext/brotli_enc_utf8_util.h +32 -0
  87. data/ext/isomorfeus_ferret_ext/brotli_enc_write_bits.h +87 -0
  88. data/ext/isomorfeus_ferret_ext/brotli_encode.h +448 -0
  89. data/ext/isomorfeus_ferret_ext/brotli_port.h +288 -0
  90. data/ext/isomorfeus_ferret_ext/brotli_types.h +83 -0
  91. data/ext/isomorfeus_ferret_ext/frb_index.c +35 -4
  92. data/ext/isomorfeus_ferret_ext/frb_store.c +34 -5
  93. data/ext/isomorfeus_ferret_ext/frt_document.h +1 -0
  94. data/ext/isomorfeus_ferret_ext/frt_fs_store.c +1 -0
  95. data/ext/isomorfeus_ferret_ext/frt_index.c +174 -25
  96. data/ext/isomorfeus_ferret_ext/frt_index.h +6 -3
  97. data/ext/isomorfeus_ferret_ext/frt_posh.h +11 -19
  98. data/ext/isomorfeus_ferret_ext/frt_q_parser.c +1844 -1911
  99. data/ext/isomorfeus_ferret_ext/frt_q_phrase.c +12 -15
  100. data/ext/isomorfeus_ferret_ext/frt_ram_store.c +1 -0
  101. data/ext/isomorfeus_ferret_ext/frt_scanner.c +1 -0
  102. data/ext/isomorfeus_ferret_ext/frt_scanner_mb.c +1 -0
  103. data/ext/isomorfeus_ferret_ext/frt_scanner_utf8.c +1 -0
  104. data/ext/isomorfeus_ferret_ext/frt_search.h +1 -1
  105. data/ext/isomorfeus_ferret_ext/libstemmer.c +14 -11
  106. data/ext/isomorfeus_ferret_ext/libstemmer.h +4 -9
  107. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_basque.c +1167 -0
  108. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_basque.h +6 -0
  109. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_catalan.c +1433 -0
  110. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_catalan.h +6 -0
  111. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_danish.c +120 -143
  112. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_danish.h +1 -2
  113. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_dutch.c +217 -237
  114. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_dutch.h +1 -1
  115. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_english.c +377 -432
  116. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_english.h +1 -1
  117. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_finnish.c +298 -342
  118. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_finnish.h +1 -2
  119. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_french.c +530 -524
  120. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_french.h +1 -1
  121. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_german.c +201 -214
  122. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_german.h +1 -1
  123. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_hungarian.c +1 -1
  124. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_indonesian.c +394 -0
  125. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_indonesian.h +6 -0
  126. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_irish.c +457 -0
  127. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_irish.h +6 -0
  128. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_italian.c +396 -439
  129. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_italian.h +1 -1
  130. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_norwegian.c +104 -128
  131. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_norwegian.h +1 -1
  132. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_porter.c +242 -273
  133. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_porter.h +1 -1
  134. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_portuguese.c +406 -461
  135. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_portuguese.h +1 -2
  136. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_spanish.c +405 -456
  137. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_spanish.h +1 -1
  138. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_swedish.c +108 -126
  139. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_1_swedish.h +1 -1
  140. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_2_hungarian.c +849 -0
  141. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_2_hungarian.h +6 -0
  142. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_2_romanian.c +373 -405
  143. data/ext/isomorfeus_ferret_ext/stem_ISO_8859_2_romanian.h +1 -1
  144. data/ext/isomorfeus_ferret_ext/stem_KOI8_R_russian.c +288 -305
  145. data/ext/isomorfeus_ferret_ext/stem_KOI8_R_russian.h +1 -1
  146. data/ext/isomorfeus_ferret_ext/stem_UTF_8_arabic.c +1651 -0
  147. data/ext/isomorfeus_ferret_ext/stem_UTF_8_arabic.h +6 -0
  148. data/ext/isomorfeus_ferret_ext/stem_UTF_8_armenian.c +546 -0
  149. data/ext/isomorfeus_ferret_ext/stem_UTF_8_armenian.h +6 -0
  150. data/ext/isomorfeus_ferret_ext/stem_UTF_8_basque.c +1171 -0
  151. data/ext/isomorfeus_ferret_ext/stem_UTF_8_basque.h +6 -0
  152. data/ext/isomorfeus_ferret_ext/stem_UTF_8_catalan.c +1436 -0
  153. data/ext/isomorfeus_ferret_ext/stem_UTF_8_catalan.h +6 -0
  154. data/ext/isomorfeus_ferret_ext/stem_UTF_8_danish.c +121 -141
  155. data/ext/isomorfeus_ferret_ext/stem_UTF_8_danish.h +1 -1
  156. data/ext/isomorfeus_ferret_ext/stem_UTF_8_dutch.c +221 -241
  157. data/ext/isomorfeus_ferret_ext/stem_UTF_8_dutch.h +1 -1
  158. data/ext/isomorfeus_ferret_ext/stem_UTF_8_english.c +381 -431
  159. data/ext/isomorfeus_ferret_ext/stem_UTF_8_english.h +1 -1
  160. data/ext/isomorfeus_ferret_ext/stem_UTF_8_finnish.c +300 -345
  161. data/ext/isomorfeus_ferret_ext/stem_UTF_8_finnish.h +1 -1
  162. data/ext/isomorfeus_ferret_ext/stem_UTF_8_french.c +518 -511
  163. data/ext/isomorfeus_ferret_ext/stem_UTF_8_french.h +1 -1
  164. data/ext/isomorfeus_ferret_ext/stem_UTF_8_german.c +201 -209
  165. data/ext/isomorfeus_ferret_ext/stem_UTF_8_german.h +1 -1
  166. data/ext/isomorfeus_ferret_ext/stem_UTF_8_greek.c +3660 -0
  167. data/ext/isomorfeus_ferret_ext/stem_UTF_8_greek.h +6 -0
  168. data/ext/isomorfeus_ferret_ext/stem_UTF_8_hindi.c +309 -0
  169. data/ext/isomorfeus_ferret_ext/stem_UTF_8_hindi.h +6 -0
  170. data/ext/isomorfeus_ferret_ext/stem_UTF_8_hungarian.c +306 -671
  171. data/ext/isomorfeus_ferret_ext/stem_UTF_8_hungarian.h +1 -1
  172. data/ext/isomorfeus_ferret_ext/stem_UTF_8_indonesian.c +394 -0
  173. data/ext/isomorfeus_ferret_ext/stem_UTF_8_indonesian.h +6 -0
  174. data/ext/isomorfeus_ferret_ext/stem_UTF_8_irish.c +457 -0
  175. data/ext/isomorfeus_ferret_ext/stem_UTF_8_irish.h +6 -0
  176. data/ext/isomorfeus_ferret_ext/stem_UTF_8_italian.c +400 -442
  177. data/ext/isomorfeus_ferret_ext/stem_UTF_8_italian.h +1 -1
  178. data/ext/isomorfeus_ferret_ext/stem_UTF_8_lithuanian.c +824 -0
  179. data/ext/isomorfeus_ferret_ext/stem_UTF_8_lithuanian.h +6 -0
  180. data/ext/isomorfeus_ferret_ext/stem_UTF_8_nepali.c +408 -0
  181. data/ext/isomorfeus_ferret_ext/stem_UTF_8_nepali.h +6 -0
  182. data/ext/isomorfeus_ferret_ext/stem_UTF_8_norwegian.c +105 -127
  183. data/ext/isomorfeus_ferret_ext/stem_UTF_8_norwegian.h +1 -1
  184. data/ext/isomorfeus_ferret_ext/stem_UTF_8_porter.c +245 -276
  185. data/ext/isomorfeus_ferret_ext/stem_UTF_8_porter.h +1 -1
  186. data/ext/isomorfeus_ferret_ext/stem_UTF_8_portuguese.c +409 -464
  187. data/ext/isomorfeus_ferret_ext/stem_UTF_8_portuguese.h +1 -1
  188. data/ext/isomorfeus_ferret_ext/stem_UTF_8_romanian.c +376 -408
  189. data/ext/isomorfeus_ferret_ext/stem_UTF_8_romanian.h +1 -1
  190. data/ext/isomorfeus_ferret_ext/stem_UTF_8_russian.c +272 -287
  191. data/ext/isomorfeus_ferret_ext/stem_UTF_8_russian.h +1 -1
  192. data/ext/isomorfeus_ferret_ext/stem_UTF_8_serbian.c +6530 -0
  193. data/ext/isomorfeus_ferret_ext/stem_UTF_8_serbian.h +6 -0
  194. data/ext/isomorfeus_ferret_ext/stem_UTF_8_spanish.c +407 -458
  195. data/ext/isomorfeus_ferret_ext/stem_UTF_8_spanish.h +1 -1
  196. data/ext/isomorfeus_ferret_ext/stem_UTF_8_swedish.c +110 -125
  197. data/ext/isomorfeus_ferret_ext/stem_UTF_8_swedish.h +1 -1
  198. data/ext/isomorfeus_ferret_ext/stem_UTF_8_tamil.c +1865 -0
  199. data/ext/isomorfeus_ferret_ext/stem_UTF_8_tamil.h +6 -0
  200. data/ext/isomorfeus_ferret_ext/stem_UTF_8_turkish.c +698 -806
  201. data/ext/isomorfeus_ferret_ext/stem_UTF_8_turkish.h +1 -1
  202. data/ext/isomorfeus_ferret_ext/stem_UTF_8_yiddish.c +1220 -0
  203. data/ext/isomorfeus_ferret_ext/stem_UTF_8_yiddish.h +6 -0
  204. data/ext/isomorfeus_ferret_ext/stem_api.c +1 -9
  205. data/ext/isomorfeus_ferret_ext/stem_api.h +1 -3
  206. data/ext/isomorfeus_ferret_ext/stem_header.h +30 -26
  207. data/ext/isomorfeus_ferret_ext/stem_modules.h +113 -26
  208. data/ext/isomorfeus_ferret_ext/stem_modules.txt +18 -5
  209. data/ext/isomorfeus_ferret_ext/stem_utilities.c +167 -132
  210. data/ext/isomorfeus_ferret_ext/test.c +7 -1
  211. data/ext/isomorfeus_ferret_ext/test_fields.c +57 -45
  212. data/ext/isomorfeus_ferret_ext/test_index.c +4 -1
  213. data/ext/isomorfeus_ferret_ext/test_search.c +0 -1
  214. data/lib/isomorfeus/ferret/version.rb +1 -1
  215. metadata +125 -5
  216. data/ext/isomorfeus_ferret_ext/q_parser.y +0 -1366
@@ -0,0 +1,125 @@
1
+ /* NOLINT(build/header_guard) */
2
+ /* Copyright 2018 Google Inc. All Rights Reserved.
3
+
4
+ Distributed under MIT license.
5
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
6
+ */
7
+
8
+ /* template parameters: FN, HASHER_A, HASHER_B */
9
+
10
+ /* Composite hasher: This hasher allows to combine two other hashers, HASHER_A
11
+ and HASHER_B. */
12
+
13
+ #define HashComposite HASHER()
14
+
15
+ #define FN_A(X) EXPAND_CAT(X, HASHER_A)
16
+ #define FN_B(X) EXPAND_CAT(X, HASHER_B)
17
+
18
+ static BROTLI_INLINE size_t FN(HashTypeLength)(void) {
19
+ size_t a = FN_A(HashTypeLength)();
20
+ size_t b = FN_B(HashTypeLength)();
21
+ return a > b ? a : b;
22
+ }
23
+
24
+ static BROTLI_INLINE size_t FN(StoreLookahead)(void) {
25
+ size_t a = FN_A(StoreLookahead)();
26
+ size_t b = FN_B(StoreLookahead)();
27
+ return a > b ? a : b;
28
+ }
29
+
30
+ typedef struct HashComposite {
31
+ HASHER_A ha;
32
+ HASHER_B hb;
33
+ HasherCommon hb_common;
34
+
35
+ /* Shortcuts. */
36
+ void* extra;
37
+ HasherCommon* common;
38
+
39
+ BROTLI_BOOL fresh;
40
+ const BrotliEncoderParams* params;
41
+ } HashComposite;
42
+
43
+ static void FN(Initialize)(HasherCommon* common,
44
+ HashComposite* BROTLI_RESTRICT self, const BrotliEncoderParams* params) {
45
+ self->common = common;
46
+ self->extra = common->extra;
47
+
48
+ self->hb_common = *self->common;
49
+ self->fresh = BROTLI_TRUE;
50
+ self->params = params;
51
+ /* TODO: Initialize of the hashers is defered to Prepare (and params
52
+ remembered here) because we don't get the one_shot and input_size params
53
+ here that are needed to know the memory size of them. Instead provide
54
+ those params to all hashers FN(Initialize) */
55
+ }
56
+
57
+ static void FN(Prepare)(
58
+ HashComposite* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,
59
+ size_t input_size, const uint8_t* BROTLI_RESTRICT data) {
60
+ if (self->fresh) {
61
+ self->fresh = BROTLI_FALSE;
62
+ self->hb_common.extra = (uint8_t*)self->extra +
63
+ FN_A(HashMemAllocInBytes)(self->params, one_shot, input_size);
64
+
65
+ FN_A(Initialize)(self->common, &self->ha, self->params);
66
+ FN_B(Initialize)(&self->hb_common, &self->hb, self->params);
67
+ }
68
+ FN_A(Prepare)(&self->ha, one_shot, input_size, data);
69
+ FN_B(Prepare)(&self->hb, one_shot, input_size, data);
70
+ }
71
+
72
+ static BROTLI_INLINE size_t FN(HashMemAllocInBytes)(
73
+ const BrotliEncoderParams* params, BROTLI_BOOL one_shot,
74
+ size_t input_size) {
75
+ return FN_A(HashMemAllocInBytes)(params, one_shot, input_size) +
76
+ FN_B(HashMemAllocInBytes)(params, one_shot, input_size);
77
+ }
78
+
79
+ static BROTLI_INLINE void FN(Store)(HashComposite* BROTLI_RESTRICT self,
80
+ const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) {
81
+ FN_A(Store)(&self->ha, data, mask, ix);
82
+ FN_B(Store)(&self->hb, data, mask, ix);
83
+ }
84
+
85
+ static BROTLI_INLINE void FN(StoreRange)(
86
+ HashComposite* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,
87
+ const size_t mask, const size_t ix_start,
88
+ const size_t ix_end) {
89
+ FN_A(StoreRange)(&self->ha, data, mask, ix_start, ix_end);
90
+ FN_B(StoreRange)(&self->hb, data, mask, ix_start, ix_end);
91
+ }
92
+
93
+ static BROTLI_INLINE void FN(StitchToPreviousBlock)(
94
+ HashComposite* BROTLI_RESTRICT self,
95
+ size_t num_bytes, size_t position, const uint8_t* ringbuffer,
96
+ size_t ring_buffer_mask) {
97
+ FN_A(StitchToPreviousBlock)(&self->ha, num_bytes, position,
98
+ ringbuffer, ring_buffer_mask);
99
+ FN_B(StitchToPreviousBlock)(&self->hb, num_bytes, position,
100
+ ringbuffer, ring_buffer_mask);
101
+ }
102
+
103
+ static BROTLI_INLINE void FN(PrepareDistanceCache)(
104
+ HashComposite* BROTLI_RESTRICT self, int* BROTLI_RESTRICT distance_cache) {
105
+ FN_A(PrepareDistanceCache)(&self->ha, distance_cache);
106
+ FN_B(PrepareDistanceCache)(&self->hb, distance_cache);
107
+ }
108
+
109
+ static BROTLI_INLINE void FN(FindLongestMatch)(
110
+ HashComposite* BROTLI_RESTRICT self,
111
+ const BrotliEncoderDictionary* dictionary,
112
+ const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,
113
+ const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,
114
+ const size_t max_length, const size_t max_backward,
115
+ const size_t dictionary_distance, const size_t max_distance,
116
+ HasherSearchResult* BROTLI_RESTRICT out) {
117
+ FN_A(FindLongestMatch)(&self->ha, dictionary, data, ring_buffer_mask,
118
+ distance_cache, cur_ix, max_length, max_backward, dictionary_distance,
119
+ max_distance, out);
120
+ FN_B(FindLongestMatch)(&self->hb, dictionary, data, ring_buffer_mask,
121
+ distance_cache, cur_ix, max_length, max_backward, dictionary_distance,
122
+ max_distance, out);
123
+ }
124
+
125
+ #undef HashComposite
@@ -0,0 +1,293 @@
1
+ /* NOLINT(build/header_guard) */
2
+ /* Copyright 2016 Google Inc. All Rights Reserved.
3
+
4
+ Distributed under MIT license.
5
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
6
+ */
7
+
8
+ /* template parameters: FN, BUCKET_BITS, NUM_BANKS, BANK_BITS,
9
+ NUM_LAST_DISTANCES_TO_CHECK */
10
+
11
+ /* A (forgetful) hash table to the data seen by the compressor, to
12
+ help create backward references to previous data.
13
+
14
+ Hashes are stored in chains which are bucketed to groups. Group of chains
15
+ share a storage "bank". When more than "bank size" chain nodes are added,
16
+ oldest nodes are replaced; this way several chains may share a tail. */
17
+
18
+ #define HashForgetfulChain HASHER()
19
+
20
+ #define BANK_SIZE (1 << BANK_BITS)
21
+
22
+ /* Number of hash buckets. */
23
+ #define BUCKET_SIZE (1 << BUCKET_BITS)
24
+
25
+ #define CAPPED_CHAINS 0
26
+
27
+ static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; }
28
+ static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; }
29
+
30
+ /* HashBytes is the function that chooses the bucket to place the address in.*/
31
+ static BROTLI_INLINE size_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data) {
32
+ const uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;
33
+ /* The higher bits contain more mixture from the multiplication,
34
+ so we take our results from there. */
35
+ return h >> (32 - BUCKET_BITS);
36
+ }
37
+
38
+ typedef struct FN(Slot) {
39
+ uint16_t delta;
40
+ uint16_t next;
41
+ } FN(Slot);
42
+
43
+ typedef struct FN(Bank) {
44
+ FN(Slot) slots[BANK_SIZE];
45
+ } FN(Bank);
46
+
47
+ typedef struct HashForgetfulChain {
48
+ uint16_t free_slot_idx[NUM_BANKS]; /* Up to 1KiB. Move to dynamic? */
49
+ size_t max_hops;
50
+
51
+ /* Shortcuts. */
52
+ void* extra;
53
+ HasherCommon* common;
54
+
55
+ /* --- Dynamic size members --- */
56
+
57
+ /* uint32_t addr[BUCKET_SIZE]; */
58
+
59
+ /* uint16_t head[BUCKET_SIZE]; */
60
+
61
+ /* Truncated hash used for quick rejection of "distance cache" candidates. */
62
+ /* uint8_t tiny_hash[65536];*/
63
+
64
+ /* FN(Bank) banks[NUM_BANKS]; */
65
+ } HashForgetfulChain;
66
+
67
+ static uint32_t* FN(Addr)(void* extra) {
68
+ return (uint32_t*)extra;
69
+ }
70
+
71
+ static uint16_t* FN(Head)(void* extra) {
72
+ return (uint16_t*)(&FN(Addr)(extra)[BUCKET_SIZE]);
73
+ }
74
+
75
+ static uint8_t* FN(TinyHash)(void* extra) {
76
+ return (uint8_t*)(&FN(Head)(extra)[BUCKET_SIZE]);
77
+ }
78
+
79
+ static FN(Bank)* FN(Banks)(void* extra) {
80
+ return (FN(Bank)*)(&FN(TinyHash)(extra)[65536]);
81
+ }
82
+
83
+ static void FN(Initialize)(
84
+ HasherCommon* common, HashForgetfulChain* BROTLI_RESTRICT self,
85
+ const BrotliEncoderParams* params) {
86
+ self->common = common;
87
+ self->extra = common->extra;
88
+
89
+ self->max_hops = (params->quality > 6 ? 7u : 8u) << (params->quality - 4);
90
+ }
91
+
92
+ static void FN(Prepare)(
93
+ HashForgetfulChain* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,
94
+ size_t input_size, const uint8_t* BROTLI_RESTRICT data) {
95
+ uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra);
96
+ uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra);
97
+ uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra);
98
+ /* Partial preparation is 100 times slower (per socket). */
99
+ size_t partial_prepare_threshold = BUCKET_SIZE >> 6;
100
+ if (one_shot && input_size <= partial_prepare_threshold) {
101
+ size_t i;
102
+ for (i = 0; i < input_size; ++i) {
103
+ size_t bucket = FN(HashBytes)(&data[i]);
104
+ /* See InitEmpty comment. */
105
+ addr[bucket] = 0xCCCCCCCC;
106
+ head[bucket] = 0xCCCC;
107
+ }
108
+ } else {
109
+ /* Fill |addr| array with 0xCCCCCCCC value. Because of wrapping, position
110
+ processed by hasher never reaches 3GB + 64M; this makes all new chains
111
+ to be terminated after the first node. */
112
+ memset(addr, 0xCC, sizeof(uint32_t) * BUCKET_SIZE);
113
+ memset(head, 0, sizeof(uint16_t) * BUCKET_SIZE);
114
+ }
115
+ memset(tiny_hash, 0, sizeof(uint8_t) * 65536);
116
+ memset(self->free_slot_idx, 0, sizeof(self->free_slot_idx));
117
+ }
118
+
119
+ static BROTLI_INLINE size_t FN(HashMemAllocInBytes)(
120
+ const BrotliEncoderParams* params, BROTLI_BOOL one_shot,
121
+ size_t input_size) {
122
+ BROTLI_UNUSED(params);
123
+ BROTLI_UNUSED(one_shot);
124
+ BROTLI_UNUSED(input_size);
125
+ return sizeof(uint32_t) * BUCKET_SIZE + sizeof(uint16_t) * BUCKET_SIZE +
126
+ sizeof(uint8_t) * 65536 + sizeof(FN(Bank)) * NUM_BANKS;
127
+ }
128
+
129
+ /* Look at 4 bytes at &data[ix & mask]. Compute a hash from these, and prepend
130
+ node to corresponding chain; also update tiny_hash for current position. */
131
+ static BROTLI_INLINE void FN(Store)(HashForgetfulChain* BROTLI_RESTRICT self,
132
+ const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) {
133
+ uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra);
134
+ uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra);
135
+ uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra);
136
+ FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra);
137
+ const size_t key = FN(HashBytes)(&data[ix & mask]);
138
+ const size_t bank = key & (NUM_BANKS - 1);
139
+ const size_t idx = self->free_slot_idx[bank]++ & (BANK_SIZE - 1);
140
+ size_t delta = ix - addr[key];
141
+ tiny_hash[(uint16_t)ix] = (uint8_t)key;
142
+ if (delta > 0xFFFF) delta = CAPPED_CHAINS ? 0 : 0xFFFF;
143
+ banks[bank].slots[idx].delta = (uint16_t)delta;
144
+ banks[bank].slots[idx].next = head[key];
145
+ addr[key] = (uint32_t)ix;
146
+ head[key] = (uint16_t)idx;
147
+ }
148
+
149
+ static BROTLI_INLINE void FN(StoreRange)(
150
+ HashForgetfulChain* BROTLI_RESTRICT self,
151
+ const uint8_t* BROTLI_RESTRICT data, const size_t mask,
152
+ const size_t ix_start, const size_t ix_end) {
153
+ size_t i;
154
+ for (i = ix_start; i < ix_end; ++i) {
155
+ FN(Store)(self, data, mask, i);
156
+ }
157
+ }
158
+
159
+ static BROTLI_INLINE void FN(StitchToPreviousBlock)(
160
+ HashForgetfulChain* BROTLI_RESTRICT self,
161
+ size_t num_bytes, size_t position, const uint8_t* ringbuffer,
162
+ size_t ring_buffer_mask) {
163
+ if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {
164
+ /* Prepare the hashes for three last bytes of the last write.
165
+ These could not be calculated before, since they require knowledge
166
+ of both the previous and the current block. */
167
+ FN(Store)(self, ringbuffer, ring_buffer_mask, position - 3);
168
+ FN(Store)(self, ringbuffer, ring_buffer_mask, position - 2);
169
+ FN(Store)(self, ringbuffer, ring_buffer_mask, position - 1);
170
+ }
171
+ }
172
+
173
+ static BROTLI_INLINE void FN(PrepareDistanceCache)(
174
+ HashForgetfulChain* BROTLI_RESTRICT self,
175
+ int* BROTLI_RESTRICT distance_cache) {
176
+ BROTLI_UNUSED(self);
177
+ PrepareDistanceCache(distance_cache, NUM_LAST_DISTANCES_TO_CHECK);
178
+ }
179
+
180
+ /* Find a longest backward match of &data[cur_ix] up to the length of
181
+ max_length and stores the position cur_ix in the hash table.
182
+
183
+ REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache
184
+ values; if this method is invoked repeatedly with the same distance
185
+ cache values, it is enough to invoke FN(PrepareDistanceCache) once.
186
+
187
+ Does not look for matches longer than max_length.
188
+ Does not look for matches further away than max_backward.
189
+ Writes the best match into |out|.
190
+ |out|->score is updated only if a better match is found. */
191
+ static BROTLI_INLINE void FN(FindLongestMatch)(
192
+ HashForgetfulChain* BROTLI_RESTRICT self,
193
+ const BrotliEncoderDictionary* dictionary,
194
+ const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,
195
+ const int* BROTLI_RESTRICT distance_cache,
196
+ const size_t cur_ix, const size_t max_length, const size_t max_backward,
197
+ const size_t dictionary_distance, const size_t max_distance,
198
+ HasherSearchResult* BROTLI_RESTRICT out) {
199
+ uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra);
200
+ uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra);
201
+ uint8_t* BROTLI_RESTRICT tiny_hashes = FN(TinyHash)(self->extra);
202
+ FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra);
203
+ const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
204
+ /* Don't accept a short copy from far away. */
205
+ score_t min_score = out->score;
206
+ score_t best_score = out->score;
207
+ size_t best_len = out->len;
208
+ size_t i;
209
+ const size_t key = FN(HashBytes)(&data[cur_ix_masked]);
210
+ const uint8_t tiny_hash = (uint8_t)(key);
211
+ out->len = 0;
212
+ out->len_code_delta = 0;
213
+ /* Try last distance first. */
214
+ for (i = 0; i < NUM_LAST_DISTANCES_TO_CHECK; ++i) {
215
+ const size_t backward = (size_t)distance_cache[i];
216
+ size_t prev_ix = (cur_ix - backward);
217
+ /* For distance code 0 we want to consider 2-byte matches. */
218
+ if (i > 0 && tiny_hashes[(uint16_t)prev_ix] != tiny_hash) continue;
219
+ if (prev_ix >= cur_ix || backward > max_backward) {
220
+ continue;
221
+ }
222
+ prev_ix &= ring_buffer_mask;
223
+ {
224
+ const size_t len = FindMatchLengthWithLimit(&data[prev_ix],
225
+ &data[cur_ix_masked],
226
+ max_length);
227
+ if (len >= 2) {
228
+ score_t score = BackwardReferenceScoreUsingLastDistance(len);
229
+ if (best_score < score) {
230
+ if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i);
231
+ if (best_score < score) {
232
+ best_score = score;
233
+ best_len = len;
234
+ out->len = best_len;
235
+ out->distance = backward;
236
+ out->score = best_score;
237
+ }
238
+ }
239
+ }
240
+ }
241
+ }
242
+ {
243
+ const size_t bank = key & (NUM_BANKS - 1);
244
+ size_t backward = 0;
245
+ size_t hops = self->max_hops;
246
+ size_t delta = cur_ix - addr[key];
247
+ size_t slot = head[key];
248
+ while (hops--) {
249
+ size_t prev_ix;
250
+ size_t last = slot;
251
+ backward += delta;
252
+ if (backward > max_backward || (CAPPED_CHAINS && !delta)) break;
253
+ prev_ix = (cur_ix - backward) & ring_buffer_mask;
254
+ slot = banks[bank].slots[last].next;
255
+ delta = banks[bank].slots[last].delta;
256
+ if (cur_ix_masked + best_len > ring_buffer_mask ||
257
+ prev_ix + best_len > ring_buffer_mask ||
258
+ data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {
259
+ continue;
260
+ }
261
+ {
262
+ const size_t len = FindMatchLengthWithLimit(&data[prev_ix],
263
+ &data[cur_ix_masked],
264
+ max_length);
265
+ if (len >= 4) {
266
+ /* Comparing for >= 3 does not change the semantics, but just saves
267
+ for a few unnecessary binary logarithms in backward reference
268
+ score, since we are not interested in such short matches. */
269
+ score_t score = BackwardReferenceScore(len, backward);
270
+ if (best_score < score) {
271
+ best_score = score;
272
+ best_len = len;
273
+ out->len = best_len;
274
+ out->distance = backward;
275
+ out->score = best_score;
276
+ }
277
+ }
278
+ }
279
+ }
280
+ FN(Store)(self, data, ring_buffer_mask, cur_ix);
281
+ }
282
+ if (out->score == min_score) {
283
+ SearchInStaticDictionary(dictionary,
284
+ self->common, &data[cur_ix_masked], max_length, dictionary_distance,
285
+ max_distance, out, BROTLI_FALSE);
286
+ }
287
+ }
288
+
289
+ #undef BANK_SIZE
290
+ #undef BUCKET_SIZE
291
+ #undef CAPPED_CHAINS
292
+
293
+ #undef HashForgetfulChain
@@ -0,0 +1,267 @@
1
+ /* NOLINT(build/header_guard) */
2
+ /* Copyright 2010 Google Inc. All Rights Reserved.
3
+
4
+ Distributed under MIT license.
5
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
6
+ */
7
+
8
+ /* template parameters: FN */
9
+
10
+ /* A (forgetful) hash table to the data seen by the compressor, to
11
+ help create backward references to previous data.
12
+
13
+ This is a hash map of fixed size (bucket_size_) to a ring buffer of
14
+ fixed size (block_size_). The ring buffer contains the last block_size_
15
+ index positions of the given hash key in the compressed data. */
16
+
17
+ #define HashLongestMatch HASHER()
18
+
19
+ static BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 8; }
20
+ static BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 8; }
21
+
22
+ /* HashBytes is the function that chooses the bucket to place the address in. */
23
+ static BROTLI_INLINE uint32_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data,
24
+ const uint64_t mask,
25
+ const int shift) {
26
+ const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(data) & mask) * kHashMul64Long;
27
+ /* The higher bits contain more mixture from the multiplication,
28
+ so we take our results from there. */
29
+ return (uint32_t)(h >> shift);
30
+ }
31
+
32
+ typedef struct HashLongestMatch {
33
+ /* Number of hash buckets. */
34
+ size_t bucket_size_;
35
+ /* Only block_size_ newest backward references are kept,
36
+ and the older are forgotten. */
37
+ size_t block_size_;
38
+ /* Left-shift for computing hash bucket index from hash value. */
39
+ int hash_shift_;
40
+ /* Mask for selecting the next 4-8 bytes of input */
41
+ uint64_t hash_mask_;
42
+ /* Mask for accessing entries in a block (in a ring-buffer manner). */
43
+ uint32_t block_mask_;
44
+
45
+ int block_bits_;
46
+ int num_last_distances_to_check_;
47
+
48
+ /* Shortcuts. */
49
+ HasherCommon* common_;
50
+
51
+ /* --- Dynamic size members --- */
52
+
53
+ /* Number of entries in a particular bucket. */
54
+ uint16_t* num_; /* uint16_t[bucket_size]; */
55
+
56
+ /* Buckets containing block_size_ of backward references. */
57
+ uint32_t* buckets_; /* uint32_t[bucket_size * block_size]; */
58
+ } HashLongestMatch;
59
+
60
+ static void FN(Initialize)(
61
+ HasherCommon* common, HashLongestMatch* BROTLI_RESTRICT self,
62
+ const BrotliEncoderParams* params) {
63
+ self->common_ = common;
64
+
65
+ BROTLI_UNUSED(params);
66
+ self->hash_shift_ = 64 - common->params.bucket_bits;
67
+ self->hash_mask_ = (~((uint64_t)0U)) >> (64 - 8 * common->params.hash_len);
68
+ self->bucket_size_ = (size_t)1 << common->params.bucket_bits;
69
+ self->block_bits_ = common->params.block_bits;
70
+ self->block_size_ = (size_t)1 << common->params.block_bits;
71
+ self->block_mask_ = (uint32_t)(self->block_size_ - 1);
72
+ self->num_last_distances_to_check_ =
73
+ common->params.num_last_distances_to_check;
74
+ self->num_ = (uint16_t*)common->extra;
75
+ self->buckets_ = (uint32_t*)&self->num_[self->bucket_size_];
76
+ }
77
+
78
+ static void FN(Prepare)(
79
+ HashLongestMatch* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,
80
+ size_t input_size, const uint8_t* BROTLI_RESTRICT data) {
81
+ uint16_t* BROTLI_RESTRICT num = self->num_;
82
+ /* Partial preparation is 100 times slower (per socket). */
83
+ size_t partial_prepare_threshold = self->bucket_size_ >> 6;
84
+ if (one_shot && input_size <= partial_prepare_threshold) {
85
+ size_t i;
86
+ for (i = 0; i < input_size; ++i) {
87
+ const uint32_t key = FN(HashBytes)(&data[i], self->hash_mask_,
88
+ self->hash_shift_);
89
+ num[key] = 0;
90
+ }
91
+ } else {
92
+ memset(num, 0, self->bucket_size_ * sizeof(num[0]));
93
+ }
94
+ }
95
+
96
+ static BROTLI_INLINE size_t FN(HashMemAllocInBytes)(
97
+ const BrotliEncoderParams* params, BROTLI_BOOL one_shot,
98
+ size_t input_size) {
99
+ size_t bucket_size = (size_t)1 << params->hasher.bucket_bits;
100
+ size_t block_size = (size_t)1 << params->hasher.block_bits;
101
+ BROTLI_UNUSED(one_shot);
102
+ BROTLI_UNUSED(input_size);
103
+ return sizeof(uint16_t) * bucket_size +
104
+ sizeof(uint32_t) * bucket_size * block_size;
105
+ }
106
+
107
+ /* Look at 4 bytes at &data[ix & mask].
108
+ Compute a hash from these, and store the value of ix at that position. */
109
+ static BROTLI_INLINE void FN(Store)(
110
+ HashLongestMatch* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,
111
+ const size_t mask, const size_t ix) {
112
+ uint16_t* BROTLI_RESTRICT num = self->num_;
113
+ uint32_t* BROTLI_RESTRICT buckets = self->buckets_;
114
+ const uint32_t key = FN(HashBytes)(&data[ix & mask], self->hash_mask_,
115
+ self->hash_shift_);
116
+ const size_t minor_ix = num[key] & self->block_mask_;
117
+ const size_t offset = minor_ix + (key << self->block_bits_);
118
+ ++num[key];
119
+ buckets[offset] = (uint32_t)ix;
120
+ }
121
+
122
+ static BROTLI_INLINE void FN(StoreRange)(HashLongestMatch* BROTLI_RESTRICT self,
123
+ const uint8_t* BROTLI_RESTRICT data, const size_t mask,
124
+ const size_t ix_start, const size_t ix_end) {
125
+ size_t i;
126
+ for (i = ix_start; i < ix_end; ++i) {
127
+ FN(Store)(self, data, mask, i);
128
+ }
129
+ }
130
+
131
+ static BROTLI_INLINE void FN(StitchToPreviousBlock)(
132
+ HashLongestMatch* BROTLI_RESTRICT self,
133
+ size_t num_bytes, size_t position, const uint8_t* ringbuffer,
134
+ size_t ringbuffer_mask) {
135
+ if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {
136
+ /* Prepare the hashes for three last bytes of the last write.
137
+ These could not be calculated before, since they require knowledge
138
+ of both the previous and the current block. */
139
+ FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3);
140
+ FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2);
141
+ FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1);
142
+ }
143
+ }
144
+
145
+ static BROTLI_INLINE void FN(PrepareDistanceCache)(
146
+ HashLongestMatch* BROTLI_RESTRICT self,
147
+ int* BROTLI_RESTRICT distance_cache) {
148
+ PrepareDistanceCache(distance_cache, self->num_last_distances_to_check_);
149
+ }
150
+
151
+ /* Find a longest backward match of &data[cur_ix] up to the length of
152
+ max_length and stores the position cur_ix in the hash table.
153
+
154
+ REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache
155
+ values; if this method is invoked repeatedly with the same distance
156
+ cache values, it is enough to invoke FN(PrepareDistanceCache) once.
157
+
158
+ Does not look for matches longer than max_length.
159
+ Does not look for matches further away than max_backward.
160
+ Writes the best match into |out|.
161
+ |out|->score is updated only if a better match is found. */
162
+ static BROTLI_INLINE void FN(FindLongestMatch)(
163
+ HashLongestMatch* BROTLI_RESTRICT self,
164
+ const BrotliEncoderDictionary* dictionary,
165
+ const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,
166
+ const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,
167
+ const size_t max_length, const size_t max_backward,
168
+ const size_t dictionary_distance, const size_t max_distance,
169
+ HasherSearchResult* BROTLI_RESTRICT out) {
170
+ uint16_t* BROTLI_RESTRICT num = self->num_;
171
+ uint32_t* BROTLI_RESTRICT buckets = self->buckets_;
172
+ const size_t cur_ix_masked = cur_ix & ring_buffer_mask;
173
+ /* Don't accept a short copy from far away. */
174
+ score_t min_score = out->score;
175
+ score_t best_score = out->score;
176
+ size_t best_len = out->len;
177
+ size_t i;
178
+ out->len = 0;
179
+ out->len_code_delta = 0;
180
+ /* Try last distance first. */
181
+ for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) {
182
+ const size_t backward = (size_t)distance_cache[i];
183
+ size_t prev_ix = (size_t)(cur_ix - backward);
184
+ if (prev_ix >= cur_ix) {
185
+ continue;
186
+ }
187
+ if (BROTLI_PREDICT_FALSE(backward > max_backward)) {
188
+ continue;
189
+ }
190
+ prev_ix &= ring_buffer_mask;
191
+
192
+ if (cur_ix_masked + best_len > ring_buffer_mask ||
193
+ prev_ix + best_len > ring_buffer_mask ||
194
+ data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {
195
+ continue;
196
+ }
197
+ {
198
+ const size_t len = FindMatchLengthWithLimit(&data[prev_ix],
199
+ &data[cur_ix_masked],
200
+ max_length);
201
+ if (len >= 3 || (len == 2 && i < 2)) {
202
+ /* Comparing for >= 2 does not change the semantics, but just saves for
203
+ a few unnecessary binary logarithms in backward reference score,
204
+ since we are not interested in such short matches. */
205
+ score_t score = BackwardReferenceScoreUsingLastDistance(len);
206
+ if (best_score < score) {
207
+ if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i);
208
+ if (best_score < score) {
209
+ best_score = score;
210
+ best_len = len;
211
+ out->len = best_len;
212
+ out->distance = backward;
213
+ out->score = best_score;
214
+ }
215
+ }
216
+ }
217
+ }
218
+ }
219
+ {
220
+ const uint32_t key = FN(HashBytes)(
221
+ &data[cur_ix_masked], self->hash_mask_, self->hash_shift_);
222
+ uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_];
223
+ const size_t down =
224
+ (num[key] > self->block_size_) ?
225
+ (num[key] - self->block_size_) : 0u;
226
+ for (i = num[key]; i > down;) {
227
+ size_t prev_ix = bucket[--i & self->block_mask_];
228
+ const size_t backward = cur_ix - prev_ix;
229
+ if (BROTLI_PREDICT_FALSE(backward > max_backward)) {
230
+ break;
231
+ }
232
+ prev_ix &= ring_buffer_mask;
233
+ if (cur_ix_masked + best_len > ring_buffer_mask ||
234
+ prev_ix + best_len > ring_buffer_mask ||
235
+ data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {
236
+ continue;
237
+ }
238
+ {
239
+ const size_t len = FindMatchLengthWithLimit(&data[prev_ix],
240
+ &data[cur_ix_masked],
241
+ max_length);
242
+ if (len >= 4) {
243
+ /* Comparing for >= 3 does not change the semantics, but just saves
244
+ for a few unnecessary binary logarithms in backward reference
245
+ score, since we are not interested in such short matches. */
246
+ score_t score = BackwardReferenceScore(len, backward);
247
+ if (best_score < score) {
248
+ best_score = score;
249
+ best_len = len;
250
+ out->len = best_len;
251
+ out->distance = backward;
252
+ out->score = best_score;
253
+ }
254
+ }
255
+ }
256
+ }
257
+ bucket[num[key] & self->block_mask_] = (uint32_t)cur_ix;
258
+ ++num[key];
259
+ }
260
+ if (min_score == out->score) {
261
+ SearchInStaticDictionary(dictionary,
262
+ self->common_, &data[cur_ix_masked], max_length, dictionary_distance,
263
+ max_distance, out, BROTLI_FALSE);
264
+ }
265
+ }
266
+
267
+ #undef HashLongestMatch