source: code/trunk/vendor/github.com/andybalholm/brotli/hash_rolling.go@ 145

Last change on this file since 145 was 145, checked in by Izuru Yakumo, 22 months ago

Updated the Makefile and vendored depedencies

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 4.8 KB
Line 
1package brotli
2
3/* Copyright 2018 Google Inc. All Rights Reserved.
4
5 Distributed under MIT license.
6 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
7*/
8
9/* NOTE: this hasher does not search in the dictionary. It is used as
10 backup-hasher, the main hasher already searches in it. */
11
12const kRollingHashMul32 uint32 = 69069
13
14const kInvalidPosHashRolling uint32 = 0xffffffff
15
16/* This hasher uses a longer forward length, but returning a higher value here
17 will hurt compression by the main hasher when combined with a composite
18 hasher. The hasher tests for forward itself instead. */
19func (*hashRolling) HashTypeLength() uint {
20 return 4
21}
22
23func (*hashRolling) StoreLookahead() uint {
24 return 4
25}
26
27/* Computes a code from a single byte. A lookup table of 256 values could be
28 used, but simply adding 1 works about as good. */
29func (*hashRolling) HashByte(b byte) uint32 {
30 return uint32(b) + 1
31}
32
33func (h *hashRolling) HashRollingFunctionInitial(state uint32, add byte, factor uint32) uint32 {
34 return uint32(factor*state + h.HashByte(add))
35}
36
37func (h *hashRolling) HashRollingFunction(state uint32, add byte, rem byte, factor uint32, factor_remove uint32) uint32 {
38 return uint32(factor*state + h.HashByte(add) - factor_remove*h.HashByte(rem))
39}
40
41/* Rolling hash for long distance long string matches. Stores one position
42 per bucket, bucket key is computed over a long region. */
43type hashRolling struct {
44 hasherCommon
45
46 jump int
47
48 state uint32
49 table []uint32
50 next_ix uint
51 factor uint32
52 factor_remove uint32
53}
54
55func (h *hashRolling) Initialize(params *encoderParams) {
56 h.state = 0
57 h.next_ix = 0
58
59 h.factor = kRollingHashMul32
60
61 /* Compute the factor of the oldest byte to remove: factor**steps modulo
62 0xffffffff (the multiplications rely on 32-bit overflow) */
63 h.factor_remove = 1
64
65 for i := 0; i < 32; i += h.jump {
66 h.factor_remove *= h.factor
67 }
68
69 h.table = make([]uint32, 16777216)
70 for i := 0; i < 16777216; i++ {
71 h.table[i] = kInvalidPosHashRolling
72 }
73}
74
75func (h *hashRolling) Prepare(one_shot bool, input_size uint, data []byte) {
76 /* Too small size, cannot use this hasher. */
77 if input_size < 32 {
78 return
79 }
80 h.state = 0
81 for i := 0; i < 32; i += h.jump {
82 h.state = h.HashRollingFunctionInitial(h.state, data[i], h.factor)
83 }
84}
85
86func (*hashRolling) Store(data []byte, mask uint, ix uint) {
87}
88
89func (*hashRolling) StoreRange(data []byte, mask uint, ix_start uint, ix_end uint) {
90}
91
92func (h *hashRolling) StitchToPreviousBlock(num_bytes uint, position uint, ringbuffer []byte, ring_buffer_mask uint) {
93 var position_masked uint
94 /* In this case we must re-initialize the hasher from scratch from the
95 current position. */
96
97 var available uint = num_bytes
98 if position&uint(h.jump-1) != 0 {
99 var diff uint = uint(h.jump) - (position & uint(h.jump-1))
100 if diff > available {
101 available = 0
102 } else {
103 available = available - diff
104 }
105 position += diff
106 }
107
108 position_masked = position & ring_buffer_mask
109
110 /* wrapping around ringbuffer not handled. */
111 if available > ring_buffer_mask-position_masked {
112 available = ring_buffer_mask - position_masked
113 }
114
115 h.Prepare(false, available, ringbuffer[position&ring_buffer_mask:])
116 h.next_ix = position
117}
118
119func (*hashRolling) PrepareDistanceCache(distance_cache []int) {
120}
121
122func (h *hashRolling) FindLongestMatch(dictionary *encoderDictionary, data []byte, ring_buffer_mask uint, distance_cache []int, cur_ix uint, max_length uint, max_backward uint, gap uint, max_distance uint, out *hasherSearchResult) {
123 var cur_ix_masked uint = cur_ix & ring_buffer_mask
124 var pos uint = h.next_ix
125
126 if cur_ix&uint(h.jump-1) != 0 {
127 return
128 }
129
130 /* Not enough lookahead */
131 if max_length < 32 {
132 return
133 }
134
135 for pos = h.next_ix; pos <= cur_ix; pos += uint(h.jump) {
136 var code uint32 = h.state & ((16777216 * 64) - 1)
137 var rem byte = data[pos&ring_buffer_mask]
138 var add byte = data[(pos+32)&ring_buffer_mask]
139 var found_ix uint = uint(kInvalidPosHashRolling)
140
141 h.state = h.HashRollingFunction(h.state, add, rem, h.factor, h.factor_remove)
142
143 if code < 16777216 {
144 found_ix = uint(h.table[code])
145 h.table[code] = uint32(pos)
146 if pos == cur_ix && uint32(found_ix) != kInvalidPosHashRolling {
147 /* The cast to 32-bit makes backward distances up to 4GB work even
148 if cur_ix is above 4GB, despite using 32-bit values in the table. */
149 var backward uint = uint(uint32(cur_ix - found_ix))
150 if backward <= max_backward {
151 var found_ix_masked uint = found_ix & ring_buffer_mask
152 var len uint = findMatchLengthWithLimit(data[found_ix_masked:], data[cur_ix_masked:], max_length)
153 if len >= 4 && len > out.len {
154 var score uint = backwardReferenceScore(uint(len), backward)
155 if score > out.score {
156 out.len = uint(len)
157 out.distance = backward
158 out.score = score
159 out.len_code_delta = 0
160 }
161 }
162 }
163 }
164 }
165 }
166
167 h.next_ix = cur_ix + uint(h.jump)
168}
Note: See TracBrowser for help on using the repository browser.