package brotli
import "encoding/binary"
func (*hashLongestMatchQuickly ) HashTypeLength () uint {
return 8
}
func (*hashLongestMatchQuickly ) StoreLookahead () uint {
return 8
}
func (h *hashLongestMatchQuickly ) HashBytes (data []byte ) uint32 {
var hash uint64 = ((binary .LittleEndian .Uint64 (data ) << (64 - 8 *h .hashLen )) * kHashMul64 )
return uint32 (hash >> (64 - h .bucketBits ))
}
type hashLongestMatchQuickly struct {
hasherCommon
bucketBits uint
bucketSweep int
hashLen uint
useDictionary bool
buckets []uint32
}
func (h *hashLongestMatchQuickly ) Initialize (params *encoderParams ) {
h .buckets = make ([]uint32 , 1 <<h .bucketBits +h .bucketSweep )
}
func (h *hashLongestMatchQuickly ) Prepare (one_shot bool , input_size uint , data []byte ) {
var partial_prepare_threshold uint = (4 << h .bucketBits ) >> 7
if one_shot && input_size <= partial_prepare_threshold {
var i uint
for i = 0 ; i < input_size ; i ++ {
var key uint32 = h .HashBytes (data [i :])
for j := 0 ; j < h .bucketSweep ; j ++ {
h .buckets [key +uint32 (j )] = 0
}
}
} else {
for i := range h .buckets {
h .buckets [i ] = 0
}
}
}
func (h *hashLongestMatchQuickly ) Store (data []byte , mask uint , ix uint ) {
var key uint32 = h .HashBytes (data [ix &mask :])
var off uint32 = uint32 (ix >>3 ) % uint32 (h .bucketSweep )
h .buckets [key +off ] = uint32 (ix )
}
func (h *hashLongestMatchQuickly ) StoreRange (data []byte , mask uint , ix_start uint , ix_end uint ) {
var i uint
for i = ix_start ; i < ix_end ; i ++ {
h .Store (data , mask , i )
}
}
func (h *hashLongestMatchQuickly ) StitchToPreviousBlock (num_bytes uint , position uint , ringbuffer []byte , ringbuffer_mask uint ) {
if num_bytes >= h .HashTypeLength ()-1 && position >= 3 {
h .Store (ringbuffer , ringbuffer_mask , position -3 )
h .Store (ringbuffer , ringbuffer_mask , position -2 )
h .Store (ringbuffer , ringbuffer_mask , position -1 )
}
}
func (*hashLongestMatchQuickly ) PrepareDistanceCache (distance_cache []int ) {
}
func (h *hashLongestMatchQuickly ) 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 ) {
var best_len_in uint = out .len
var cur_ix_masked uint = cur_ix & ring_buffer_mask
var key uint32 = h .HashBytes (data [cur_ix_masked :])
var compare_char int = int (data [cur_ix_masked +best_len_in ])
var min_score uint = out .score
var best_score uint = out .score
var best_len uint = best_len_in
var cached_backward uint = uint (distance_cache [0 ])
var prev_ix uint = cur_ix - cached_backward
var bucket []uint32
out .len_code_delta = 0
if prev_ix < cur_ix {
prev_ix &= uint (uint32 (ring_buffer_mask ))
if compare_char == int (data [prev_ix +best_len ]) {
var len uint = findMatchLengthWithLimit (data [prev_ix :], data [cur_ix_masked :], max_length )
if len >= 4 {
var score uint = backwardReferenceScoreUsingLastDistance (uint (len ))
if best_score < score {
best_score = score
best_len = uint (len )
out .len = uint (len )
out .distance = cached_backward
out .score = best_score
compare_char = int (data [cur_ix_masked +best_len ])
if h .bucketSweep == 1 {
h .buckets [key ] = uint32 (cur_ix )
return
}
}
}
}
}
if h .bucketSweep == 1 {
var backward uint
var len uint
prev_ix = uint (h .buckets [key ])
h .buckets [key ] = uint32 (cur_ix )
backward = cur_ix - prev_ix
prev_ix &= uint (uint32 (ring_buffer_mask ))
if compare_char != int (data [prev_ix +best_len_in ]) {
return
}
if backward == 0 || backward > max_backward {
return
}
len = findMatchLengthWithLimit (data [prev_ix :], data [cur_ix_masked :], max_length )
if len >= 4 {
var score uint = backwardReferenceScore (uint (len ), backward )
if best_score < score {
out .len = uint (len )
out .distance = backward
out .score = score
return
}
}
} else {
bucket = h .buckets [key :]
var i int
prev_ix = uint (bucket [0 ])
bucket = bucket [1 :]
for i = 0 ; i < h .bucketSweep ; (func () { i ++; tmp3 := bucket ; bucket = bucket [1 :]; prev_ix = uint (tmp3 [0 ]) })() {
var backward uint = cur_ix - prev_ix
var len uint
prev_ix &= uint (uint32 (ring_buffer_mask ))
if compare_char != int (data [prev_ix +best_len ]) {
continue
}
if backward == 0 || backward > max_backward {
continue
}
len = findMatchLengthWithLimit (data [prev_ix :], data [cur_ix_masked :], max_length )
if len >= 4 {
var score uint = backwardReferenceScore (uint (len ), backward )
if best_score < score {
best_score = score
best_len = uint (len )
out .len = best_len
out .distance = backward
out .score = score
compare_char = int (data [cur_ix_masked +best_len ])
}
}
}
}
if h .useDictionary && min_score == out .score {
searchInStaticDictionary (dictionary , h , data [cur_ix_masked :], max_length , max_backward +gap , max_distance , out , true )
}
h .buckets [key +uint32 ((cur_ix >>3 )%uint (h .bucketSweep ))] = uint32 (cur_ix )
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .