package brotli

/* Copyright 2018 Google Inc. All Rights Reserved.

   Distributed under MIT license.
   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/

/* NOTE: this hasher does not search in the dictionary. It is used as
   backup-hasher, the main hasher already searches in it. */

const kRollingHashMul32 uint32 = 69069

const kInvalidPosHashRolling uint32 = 0xffffffff

/* This hasher uses a longer forward length, but returning a higher value here
   will hurt compression by the main hasher when combined with a composite
   hasher. The hasher tests for forward itself instead. */
func (*hashRolling) () uint {
	return 4
}

func (*hashRolling) () uint {
	return 4
}

/* Computes a code from a single byte. A lookup table of 256 values could be
   used, but simply adding 1 works about as good. */
func (*hashRolling) ( byte) uint32 {
	return uint32() + 1
}

func ( *hashRolling) ( uint32,  byte,  uint32) uint32 {
	return uint32(* + .HashByte())
}

func ( *hashRolling) ( uint32,  byte,  byte,  uint32,  uint32) uint32 {
	return uint32(* + .HashByte() - *.HashByte())
}

/* Rolling hash for long distance long string matches. Stores one position
   per bucket, bucket key is computed over a long region. */
type hashRolling struct {
	hasherCommon

	jump int

	state         uint32
	table         []uint32
	next_ix       uint
	factor        uint32
	factor_remove uint32
}

func ( *hashRolling) ( *encoderParams) {
	.state = 0
	.next_ix = 0

	.factor = kRollingHashMul32

	/* Compute the factor of the oldest byte to remove: factor**steps modulo
	   0xffffffff (the multiplications rely on 32-bit overflow) */
	.factor_remove = 1

	for  := 0;  < 32;  += .jump {
		.factor_remove *= .factor
	}

	.table = make([]uint32, 16777216)
	for  := 0;  < 16777216; ++ {
		.table[] = kInvalidPosHashRolling
	}
}

func ( *hashRolling) ( bool,  uint,  []byte) {
	/* Too small size, cannot use this hasher. */
	if  < 32 {
		return
	}
	.state = 0
	for  := 0;  < 32;  += .jump {
		.state = .HashRollingFunctionInitial(.state, [], .factor)
	}
}

func (*hashRolling) ( []byte,  uint,  uint) {
}

func (*hashRolling) ( []byte,  uint,  uint,  uint) {
}

func ( *hashRolling) ( uint,  uint,  []byte,  uint) {
	var  uint
	/* In this case we must re-initialize the hasher from scratch from the
	   current position. */

	var  uint = 
	if &uint(.jump-1) != 0 {
		var  uint = uint(.jump) - ( & uint(.jump-1))
		if  >  {
			 = 0
		} else {
			 =  - 
		}
		 += 
	}

	 =  & 

	/* wrapping around ringbuffer not handled. */
	if  > - {
		 =  - 
	}

	.Prepare(false, , [&:])
	.next_ix = 
}

func (*hashRolling) ( []int) {
}

func ( *hashRolling) ( *encoderDictionary,  []byte,  uint,  []int,  uint,  uint,  uint,  uint,  uint,  *hasherSearchResult) {
	var  uint =  & 
	var  uint = .next_ix

	if &uint(.jump-1) != 0 {
		return
	}

	/* Not enough lookahead */
	if  < 32 {
		return
	}

	for  = .next_ix;  <= ;  += uint(.jump) {
		var  uint32 = .state & ((16777216 * 64) - 1)
		var  byte = [&]
		var  byte = [(+32)&]
		var  uint = uint(kInvalidPosHashRolling)

		.state = .HashRollingFunction(.state, , , .factor, .factor_remove)

		if  < 16777216 {
			 = uint(.table[])
			.table[] = uint32()
			if  ==  && uint32() != kInvalidPosHashRolling {
				/* The cast to 32-bit makes backward distances up to 4GB work even
				   if cur_ix is above 4GB, despite using 32-bit values in the table. */
				var  uint = uint(uint32( - ))
				if  <=  {
					var  uint =  & 
					var  uint = findMatchLengthWithLimit([:], [:], )
					if  >= 4 &&  > .len {
						var  uint = backwardReferenceScore(uint(), )
						if  > .score {
							.len = uint()
							.distance = 
							.score = 
							.len_code_delta = 0
						}
					}
				}
			}
		}
	}

	.next_ix =  + uint(.jump)
}