package brotli

import 

/* Copyright 2013 Google Inc. All Rights Reserved.

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

/* Class to model the static dictionary. */

const maxStaticDictionaryMatchLen = 37

const kInvalidMatch uint32 = 0xFFFFFFF

/* Copyright 2013 Google Inc. All Rights Reserved.

   Distributed under MIT license.
   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
*/
func hash( []byte) uint32 {
	var  uint32 = binary.LittleEndian.Uint32() * kDictHashMul32

	/* The higher bits contain more mixture from the multiplication,
	   so we take our results from there. */
	return  >> uint(32-kDictNumBits)
}

func addMatch( uint,  uint,  uint,  []uint32) {
	var  uint32 = uint32(( << 5) + )
	[] = brotli_min_uint32_t([], )
}

func dictMatchLength( *dictionary,  []byte,  uint,  uint,  uint) uint {
	var  uint = uint(.offsets_by_length[]) + *
	return findMatchLengthWithLimit(.data[:], , brotli_min_size_t(uint(), ))
}

func isMatch( *dictionary,  dictWord,  []byte,  uint) bool {
	if uint(.len) >  {
		return false
	} else {
		var  uint = uint(.offsets_by_length[.len]) + uint(.len)*uint(.idx)
		var  []byte = .data[:]
		if .transform == 0 {
			/* Match against base dictionary word. */
			return findMatchLengthWithLimit(, , uint(.len)) == uint(.len)
		} else if .transform == 10 {
			/* Match against uppercase first transform.
			   Note that there are only ASCII uppercase words in the lookup table. */
			return [0] >= 'a' && [0] <= 'z' && ([0]^32) == [0] && findMatchLengthWithLimit([1:], [1:], uint(.len)-1) == uint(.len-1)
		} else {
			/* Match against uppercase all transform.
			   Note that there are only ASCII uppercase words in the lookup table. */
			var  uint
			for  = 0;  < uint(.len); ++ {
				if [] >= 'a' && [] <= 'z' {
					if ([] ^ 32) != [] {
						return false
					}
				} else {
					if [] != [] {
						return false
					}
				}
			}

			return true
		}
	}
}

func findAllStaticDictionaryMatches( *encoderDictionary,  []byte,  uint,  uint,  []uint32) bool {
	var  bool = false
	{
		var  uint = uint(.buckets[hash()])
		var  bool =  == 0
		for ! {
			 := .dict_words[]
			++
			var  uint = uint(.len) & 0x1F
			var  uint = uint(1) << .words.size_bits_by_length[]
			var  uint = uint(.idx)
			 = !(.len&0x80 == 0)
			.len = byte()
			if .transform == 0 {
				var  uint = dictMatchLength(.words, , , , )
				var  []byte
				var  uint
				var  uint
				var  uint

				/* Transform "" + BROTLI_TRANSFORM_IDENTITY + "" */
				if  ==  {
					addMatch(, , , )
					 = true
				}

				/* Transforms "" + BROTLI_TRANSFORM_OMIT_LAST_1 + "" and
				   "" + BROTLI_TRANSFORM_OMIT_LAST_1 + "ing " */
				if  >= -1 {
					addMatch(+12*, -1, , )
					if +2 <  && [-1] == 'i' && [] == 'n' && [+1] == 'g' && [+2] == ' ' {
						addMatch(+49*, +3, , )
					}

					 = true
				}

				/* Transform "" + BROTLI_TRANSFORM_OMIT_LAST_# + "" (# = 2 .. 9) */
				 = 

				if  > 9 {
					 = brotli_max_size_t(, -9)
				}
				 = brotli_min_size_t(, -2)
				for  = ;  <= ; ++ {
					var  uint =  - 
					var  uint = ( << 2) + uint((.cutoffTransforms>>(*6))&0x3F)
					addMatch(+*, uint(), , )
					 = true
				}

				if  <  || +6 >=  {
					continue
				}

				 = [:]

				/* Transforms "" + BROTLI_TRANSFORM_IDENTITY + <suffix> */
				if [0] == ' ' {
					addMatch(+, +1, , )
					if [1] == 'a' {
						if [2] == ' ' {
							addMatch(+28*, +3, , )
						} else if [2] == 's' {
							if [3] == ' ' {
								addMatch(+46*, +4, , )
							}
						} else if [2] == 't' {
							if [3] == ' ' {
								addMatch(+60*, +4, , )
							}
						} else if [2] == 'n' {
							if [3] == 'd' && [4] == ' ' {
								addMatch(+10*, +5, , )
							}
						}
					} else if [1] == 'b' {
						if [2] == 'y' && [3] == ' ' {
							addMatch(+38*, +4, , )
						}
					} else if [1] == 'i' {
						if [2] == 'n' {
							if [3] == ' ' {
								addMatch(+16*, +4, , )
							}
						} else if [2] == 's' {
							if [3] == ' ' {
								addMatch(+47*, +4, , )
							}
						}
					} else if [1] == 'f' {
						if [2] == 'o' {
							if [3] == 'r' && [4] == ' ' {
								addMatch(+25*, +5, , )
							}
						} else if [2] == 'r' {
							if [3] == 'o' && [4] == 'm' && [5] == ' ' {
								addMatch(+37*, +6, , )
							}
						}
					} else if [1] == 'o' {
						if [2] == 'f' {
							if [3] == ' ' {
								addMatch(+8*, +4, , )
							}
						} else if [2] == 'n' {
							if [3] == ' ' {
								addMatch(+45*, +4, , )
							}
						}
					} else if [1] == 'n' {
						if [2] == 'o' && [3] == 't' && [4] == ' ' {
							addMatch(+80*, +5, , )
						}
					} else if [1] == 't' {
						if [2] == 'h' {
							if [3] == 'e' {
								if [4] == ' ' {
									addMatch(+5*, +5, , )
								}
							} else if [3] == 'a' {
								if [4] == 't' && [5] == ' ' {
									addMatch(+29*, +6, , )
								}
							}
						} else if [2] == 'o' {
							if [3] == ' ' {
								addMatch(+17*, +4, , )
							}
						}
					} else if [1] == 'w' {
						if [2] == 'i' && [3] == 't' && [4] == 'h' && [5] == ' ' {
							addMatch(+35*, +6, , )
						}
					}
				} else if [0] == '"' {
					addMatch(+19*, +1, , )
					if [1] == '>' {
						addMatch(+21*, +2, , )
					}
				} else if [0] == '.' {
					addMatch(+20*, +1, , )
					if [1] == ' ' {
						addMatch(+31*, +2, , )
						if [2] == 'T' && [3] == 'h' {
							if [4] == 'e' {
								if [5] == ' ' {
									addMatch(+43*, +6, , )
								}
							} else if [4] == 'i' {
								if [5] == 's' && [6] == ' ' {
									addMatch(+75*, +7, , )
								}
							}
						}
					}
				} else if [0] == ',' {
					addMatch(+76*, +1, , )
					if [1] == ' ' {
						addMatch(+14*, +2, , )
					}
				} else if [0] == '\n' {
					addMatch(+22*, +1, , )
					if [1] == '\t' {
						addMatch(+50*, +2, , )
					}
				} else if [0] == ']' {
					addMatch(+24*, +1, , )
				} else if [0] == '\'' {
					addMatch(+36*, +1, , )
				} else if [0] == ':' {
					addMatch(+51*, +1, , )
				} else if [0] == '(' {
					addMatch(+57*, +1, , )
				} else if [0] == '=' {
					if [1] == '"' {
						addMatch(+70*, +2, , )
					} else if [1] == '\'' {
						addMatch(+86*, +2, , )
					}
				} else if [0] == 'a' {
					if [1] == 'l' && [2] == ' ' {
						addMatch(+84*, +3, , )
					}
				} else if [0] == 'e' {
					if [1] == 'd' {
						if [2] == ' ' {
							addMatch(+53*, +3, , )
						}
					} else if [1] == 'r' {
						if [2] == ' ' {
							addMatch(+82*, +3, , )
						}
					} else if [1] == 's' {
						if [2] == 't' && [3] == ' ' {
							addMatch(+95*, +4, , )
						}
					}
				} else if [0] == 'f' {
					if [1] == 'u' && [2] == 'l' && [3] == ' ' {
						addMatch(+90*, +4, , )
					}
				} else if [0] == 'i' {
					if [1] == 'v' {
						if [2] == 'e' && [3] == ' ' {
							addMatch(+92*, +4, , )
						}
					} else if [1] == 'z' {
						if [2] == 'e' && [3] == ' ' {
							addMatch(+100*, +4, , )
						}
					}
				} else if [0] == 'l' {
					if [1] == 'e' {
						if [2] == 's' && [3] == 's' && [4] == ' ' {
							addMatch(+93*, +5, , )
						}
					} else if [1] == 'y' {
						if [2] == ' ' {
							addMatch(+61*, +3, , )
						}
					}
				} else if [0] == 'o' {
					if [1] == 'u' && [2] == 's' && [3] == ' ' {
						addMatch(+106*, +4, , )
					}
				}
			} else {
				var  bool = (.transform != transformUppercaseFirst)
				/* Set is_all_caps=0 for BROTLI_TRANSFORM_UPPERCASE_FIRST and
				    is_all_caps=1 otherwise (BROTLI_TRANSFORM_UPPERCASE_ALL)
				transform. */

				var  []byte
				if !isMatch(.words, , , ) {
					continue
				}

				/* Transform "" + kUppercase{First,All} + "" */
				var  int
				if  {
					 = 44
				} else {
					 = 9
				}
				addMatch(+uint()*, , , )

				 = true
				if +1 >=  {
					continue
				}

				/* Transforms "" + kUppercase{First,All} + <suffix> */
				 = [:]

				if [0] == ' ' {
					var  int
					if  {
						 = 68
					} else {
						 = 4
					}
					addMatch(+uint()*, +1, , )
				} else if [0] == '"' {
					var  int
					if  {
						 = 87
					} else {
						 = 66
					}
					addMatch(+uint()*, +1, , )
					if [1] == '>' {
						var  int
						if  {
							 = 97
						} else {
							 = 69
						}
						addMatch(+uint()*, +2, , )
					}
				} else if [0] == '.' {
					var  int
					if  {
						 = 101
					} else {
						 = 79
					}
					addMatch(+uint()*, +1, , )
					if [1] == ' ' {
						var  int
						if  {
							 = 114
						} else {
							 = 88
						}
						addMatch(+uint()*, +2, , )
					}
				} else if [0] == ',' {
					var  int
					if  {
						 = 112
					} else {
						 = 99
					}
					addMatch(+uint()*, +1, , )
					if [1] == ' ' {
						var  int
						if  {
							 = 107
						} else {
							 = 58
						}
						addMatch(+uint()*, +2, , )
					}
				} else if [0] == '\'' {
					var  int
					if  {
						 = 94
					} else {
						 = 74
					}
					addMatch(+uint()*, +1, , )
				} else if [0] == '(' {
					var  int
					if  {
						 = 113
					} else {
						 = 78
					}
					addMatch(+uint()*, +1, , )
				} else if [0] == '=' {
					if [1] == '"' {
						var  int
						if  {
							 = 105
						} else {
							 = 104
						}
						addMatch(+uint()*, +2, , )
					} else if [1] == '\'' {
						var  int
						if  {
							 = 116
						} else {
							 = 108
						}
						addMatch(+uint()*, +2, , )
					}
				}
			}
		}
	}

	/* Transforms with prefixes " " and "." */
	if  >= 5 && ([0] == ' ' || [0] == '.') {
		var  bool = ([0] == ' ')
		var  uint = uint(.buckets[hash([1:])])
		var  bool =  == 0
		for ! {
			 := .dict_words[]
			++
			var  uint = uint(.len) & 0x1F
			var  uint = uint(1) << .words.size_bits_by_length[]
			var  uint = uint(.idx)
			 = !(.len&0x80 == 0)
			.len = byte()
			if .transform == 0 {
				var  []byte
				if !isMatch(.words, , [1:], -1) {
					continue
				}

				/* Transforms " " + BROTLI_TRANSFORM_IDENTITY + "" and
				   "." + BROTLI_TRANSFORM_IDENTITY + "" */
				var  int
				if  {
					 = 6
				} else {
					 = 32
				}
				addMatch(+uint()*, +1, , )

				 = true
				if +2 >=  {
					continue
				}

				/* Transforms " " + BROTLI_TRANSFORM_IDENTITY + <suffix> and
				   "." + BROTLI_TRANSFORM_IDENTITY + <suffix>
				*/
				 = [+1:]

				if [0] == ' ' {
					var  int
					if  {
						 = 2
					} else {
						 = 77
					}
					addMatch(+uint()*, +2, , )
				} else if [0] == '(' {
					var  int
					if  {
						 = 89
					} else {
						 = 67
					}
					addMatch(+uint()*, +2, , )
				} else if  {
					if [0] == ',' {
						addMatch(+103*, +2, , )
						if [1] == ' ' {
							addMatch(+33*, +3, , )
						}
					} else if [0] == '.' {
						addMatch(+71*, +2, , )
						if [1] == ' ' {
							addMatch(+52*, +3, , )
						}
					} else if [0] == '=' {
						if [1] == '"' {
							addMatch(+81*, +3, , )
						} else if [1] == '\'' {
							addMatch(+98*, +3, , )
						}
					}
				}
			} else if  {
				var  bool = (.transform != transformUppercaseFirst)
				/* Set is_all_caps=0 for BROTLI_TRANSFORM_UPPERCASE_FIRST and
				    is_all_caps=1 otherwise (BROTLI_TRANSFORM_UPPERCASE_ALL)
				transform. */

				var  []byte
				if !isMatch(.words, , [1:], -1) {
					continue
				}

				/* Transforms " " + kUppercase{First,All} + "" */
				var  int
				if  {
					 = 85
				} else {
					 = 30
				}
				addMatch(+uint()*, +1, , )

				 = true
				if +2 >=  {
					continue
				}

				/* Transforms " " + kUppercase{First,All} + <suffix> */
				 = [+1:]

				if [0] == ' ' {
					var  int
					if  {
						 = 83
					} else {
						 = 15
					}
					addMatch(+uint()*, +2, , )
				} else if [0] == ',' {
					if ! {
						addMatch(+109*, +2, , )
					}

					if [1] == ' ' {
						var  int
						if  {
							 = 111
						} else {
							 = 65
						}
						addMatch(+uint()*, +3, , )
					}
				} else if [0] == '.' {
					var  int
					if  {
						 = 115
					} else {
						 = 96
					}
					addMatch(+uint()*, +2, , )
					if [1] == ' ' {
						var  int
						if  {
							 = 117
						} else {
							 = 91
						}
						addMatch(+uint()*, +3, , )
					}
				} else if [0] == '=' {
					if [1] == '"' {
						var  int
						if  {
							 = 110
						} else {
							 = 118
						}
						addMatch(+uint()*, +3, , )
					} else if [1] == '\'' {
						var  int
						if  {
							 = 119
						} else {
							 = 120
						}
						addMatch(+uint()*, +3, , )
					}
				}
			}
		}
	}

	if  >= 6 {
		/* Transforms with prefixes "e ", "s ", ", " and "\xC2\xA0" */
		if ([1] == ' ' && ([0] == 'e' || [0] == 's' || [0] == ',')) || ([0] == 0xC2 && [1] == 0xA0) {
			var  uint = uint(.buckets[hash([2:])])
			var  bool =  == 0
			for ! {
				 := .dict_words[]
				++
				var  uint = uint(.len) & 0x1F
				var  uint = uint(1) << .words.size_bits_by_length[]
				var  uint = uint(.idx)
				 = !(.len&0x80 == 0)
				.len = byte()
				if .transform == 0 && isMatch(.words, , [2:], -2) {
					if [0] == 0xC2 {
						addMatch(+102*, +2, , )
						 = true
					} else if +2 <  && [+2] == ' ' {
						var  uint = 13
						if [0] == 'e' {
							 = 18
						} else if [0] == 's' {
							 = 7
						}
						addMatch(+*, +3, , )
						 = true
					}
				}
			}
		}
	}

	if  >= 9 {
		/* Transforms with prefixes " the " and ".com/" */
		if ([0] == ' ' && [1] == 't' && [2] == 'h' && [3] == 'e' && [4] == ' ') || ([0] == '.' && [1] == 'c' && [2] == 'o' && [3] == 'm' && [4] == '/') {
			var  uint = uint(.buckets[hash([5:])])
			var  bool =  == 0
			for ! {
				 := .dict_words[]
				++
				var  uint = uint(.len) & 0x1F
				var  uint = uint(1) << .words.size_bits_by_length[]
				var  uint = uint(.idx)
				 = !(.len&0x80 == 0)
				.len = byte()
				if .transform == 0 && isMatch(.words, , [5:], -5) {
					var  int
					if [0] == ' ' {
						 = 41
					} else {
						 = 72
					}
					addMatch(+uint()*, +5, , )
					 = true
					if +5 <  {
						var  []byte = [+5:]
						if [0] == ' ' {
							if +8 <  && [0] == ' ' && [1] == 'o' && [2] == 'f' && [3] == ' ' {
								addMatch(+62*, +9, , )
								if +12 <  && [4] == 't' && [5] == 'h' && [6] == 'e' && [7] == ' ' {
									addMatch(+73*, +13, , )
								}
							}
						}
					}
				}
			}
		}
	}

	return 
}