654 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			654 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Go
		
	
	
	
| package brotli
 | |
| 
 | |
| /* Copyright 2013 Google Inc. All Rights Reserved.
 | |
| 
 | |
|    Distributed under MIT license.
 | |
|    See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
 | |
| */
 | |
| 
 | |
| /* Utilities for building Huffman decoding tables. */
 | |
| 
 | |
| const huffmanMaxCodeLength = 15
 | |
| 
 | |
| /* Maximum possible Huffman table size for an alphabet size of (index * 32),
 | |
|    max code length 15 and root table bits 8. */
 | |
| var kMaxHuffmanTableSize = []uint16{
 | |
| 	256,
 | |
| 	402,
 | |
| 	436,
 | |
| 	468,
 | |
| 	500,
 | |
| 	534,
 | |
| 	566,
 | |
| 	598,
 | |
| 	630,
 | |
| 	662,
 | |
| 	694,
 | |
| 	726,
 | |
| 	758,
 | |
| 	790,
 | |
| 	822,
 | |
| 	854,
 | |
| 	886,
 | |
| 	920,
 | |
| 	952,
 | |
| 	984,
 | |
| 	1016,
 | |
| 	1048,
 | |
| 	1080,
 | |
| 	1112,
 | |
| 	1144,
 | |
| 	1176,
 | |
| 	1208,
 | |
| 	1240,
 | |
| 	1272,
 | |
| 	1304,
 | |
| 	1336,
 | |
| 	1368,
 | |
| 	1400,
 | |
| 	1432,
 | |
| 	1464,
 | |
| 	1496,
 | |
| 	1528,
 | |
| }
 | |
| 
 | |
| /* BROTLI_NUM_BLOCK_LEN_SYMBOLS == 26 */
 | |
| const huffmanMaxSize26 = 396
 | |
| 
 | |
| /* BROTLI_MAX_BLOCK_TYPE_SYMBOLS == 258 */
 | |
| const huffmanMaxSize258 = 632
 | |
| 
 | |
| /* BROTLI_MAX_CONTEXT_MAP_SYMBOLS == 272 */
 | |
| const huffmanMaxSize272 = 646
 | |
| 
 | |
| const huffmanMaxCodeLengthCodeLength = 5
 | |
| 
 | |
| /* Do not create this struct directly - use the ConstructHuffmanCode
 | |
|  * constructor below! */
 | |
| type huffmanCode struct {
 | |
| 	bits  byte
 | |
| 	value uint16
 | |
| }
 | |
| 
 | |
| func constructHuffmanCode(bits byte, value uint16) huffmanCode {
 | |
| 	var h huffmanCode
 | |
| 	h.bits = bits
 | |
| 	h.value = value
 | |
| 	return h
 | |
| }
 | |
| 
 | |
| /* Builds Huffman lookup table assuming code lengths are in symbol order. */
 | |
| 
 | |
| /* Builds Huffman lookup table assuming code lengths are in symbol order.
 | |
|    Returns size of resulting table. */
 | |
| 
 | |
| /* Builds a simple Huffman table. The |num_symbols| parameter is to be
 | |
|    interpreted as follows: 0 means 1 symbol, 1 means 2 symbols,
 | |
|    2 means 3 symbols, 3 means 4 symbols with lengths [2, 2, 2, 2],
 | |
|    4 means 4 symbols with lengths [1, 2, 3, 3]. */
 | |
| 
 | |
| /* Contains a collection of Huffman trees with the same alphabet size. */
 | |
| /* max_symbol is needed due to simple codes since log2(alphabet_size) could be
 | |
|    greater than log2(max_symbol). */
 | |
| type huffmanTreeGroup struct {
 | |
| 	htrees        [][]huffmanCode
 | |
| 	codes         []huffmanCode
 | |
| 	alphabet_size uint16
 | |
| 	max_symbol    uint16
 | |
| 	num_htrees    uint16
 | |
| }
 | |
| 
 | |
| const reverseBitsMax = 8
 | |
| 
 | |
| const reverseBitsBase = 0
 | |
| 
 | |
| var kReverseBits = [1 << reverseBitsMax]byte{
 | |
| 	0x00,
 | |
| 	0x80,
 | |
| 	0x40,
 | |
| 	0xC0,
 | |
| 	0x20,
 | |
| 	0xA0,
 | |
| 	0x60,
 | |
| 	0xE0,
 | |
| 	0x10,
 | |
| 	0x90,
 | |
| 	0x50,
 | |
| 	0xD0,
 | |
| 	0x30,
 | |
| 	0xB0,
 | |
| 	0x70,
 | |
| 	0xF0,
 | |
| 	0x08,
 | |
| 	0x88,
 | |
| 	0x48,
 | |
| 	0xC8,
 | |
| 	0x28,
 | |
| 	0xA8,
 | |
| 	0x68,
 | |
| 	0xE8,
 | |
| 	0x18,
 | |
| 	0x98,
 | |
| 	0x58,
 | |
| 	0xD8,
 | |
| 	0x38,
 | |
| 	0xB8,
 | |
| 	0x78,
 | |
| 	0xF8,
 | |
| 	0x04,
 | |
| 	0x84,
 | |
| 	0x44,
 | |
| 	0xC4,
 | |
| 	0x24,
 | |
| 	0xA4,
 | |
| 	0x64,
 | |
| 	0xE4,
 | |
| 	0x14,
 | |
| 	0x94,
 | |
| 	0x54,
 | |
| 	0xD4,
 | |
| 	0x34,
 | |
| 	0xB4,
 | |
| 	0x74,
 | |
| 	0xF4,
 | |
| 	0x0C,
 | |
| 	0x8C,
 | |
| 	0x4C,
 | |
| 	0xCC,
 | |
| 	0x2C,
 | |
| 	0xAC,
 | |
| 	0x6C,
 | |
| 	0xEC,
 | |
| 	0x1C,
 | |
| 	0x9C,
 | |
| 	0x5C,
 | |
| 	0xDC,
 | |
| 	0x3C,
 | |
| 	0xBC,
 | |
| 	0x7C,
 | |
| 	0xFC,
 | |
| 	0x02,
 | |
| 	0x82,
 | |
| 	0x42,
 | |
| 	0xC2,
 | |
| 	0x22,
 | |
| 	0xA2,
 | |
| 	0x62,
 | |
| 	0xE2,
 | |
| 	0x12,
 | |
| 	0x92,
 | |
| 	0x52,
 | |
| 	0xD2,
 | |
| 	0x32,
 | |
| 	0xB2,
 | |
| 	0x72,
 | |
| 	0xF2,
 | |
| 	0x0A,
 | |
| 	0x8A,
 | |
| 	0x4A,
 | |
| 	0xCA,
 | |
| 	0x2A,
 | |
| 	0xAA,
 | |
| 	0x6A,
 | |
| 	0xEA,
 | |
| 	0x1A,
 | |
| 	0x9A,
 | |
| 	0x5A,
 | |
| 	0xDA,
 | |
| 	0x3A,
 | |
| 	0xBA,
 | |
| 	0x7A,
 | |
| 	0xFA,
 | |
| 	0x06,
 | |
| 	0x86,
 | |
| 	0x46,
 | |
| 	0xC6,
 | |
| 	0x26,
 | |
| 	0xA6,
 | |
| 	0x66,
 | |
| 	0xE6,
 | |
| 	0x16,
 | |
| 	0x96,
 | |
| 	0x56,
 | |
| 	0xD6,
 | |
| 	0x36,
 | |
| 	0xB6,
 | |
| 	0x76,
 | |
| 	0xF6,
 | |
| 	0x0E,
 | |
| 	0x8E,
 | |
| 	0x4E,
 | |
| 	0xCE,
 | |
| 	0x2E,
 | |
| 	0xAE,
 | |
| 	0x6E,
 | |
| 	0xEE,
 | |
| 	0x1E,
 | |
| 	0x9E,
 | |
| 	0x5E,
 | |
| 	0xDE,
 | |
| 	0x3E,
 | |
| 	0xBE,
 | |
| 	0x7E,
 | |
| 	0xFE,
 | |
| 	0x01,
 | |
| 	0x81,
 | |
| 	0x41,
 | |
| 	0xC1,
 | |
| 	0x21,
 | |
| 	0xA1,
 | |
| 	0x61,
 | |
| 	0xE1,
 | |
| 	0x11,
 | |
| 	0x91,
 | |
| 	0x51,
 | |
| 	0xD1,
 | |
| 	0x31,
 | |
| 	0xB1,
 | |
| 	0x71,
 | |
| 	0xF1,
 | |
| 	0x09,
 | |
| 	0x89,
 | |
| 	0x49,
 | |
| 	0xC9,
 | |
| 	0x29,
 | |
| 	0xA9,
 | |
| 	0x69,
 | |
| 	0xE9,
 | |
| 	0x19,
 | |
| 	0x99,
 | |
| 	0x59,
 | |
| 	0xD9,
 | |
| 	0x39,
 | |
| 	0xB9,
 | |
| 	0x79,
 | |
| 	0xF9,
 | |
| 	0x05,
 | |
| 	0x85,
 | |
| 	0x45,
 | |
| 	0xC5,
 | |
| 	0x25,
 | |
| 	0xA5,
 | |
| 	0x65,
 | |
| 	0xE5,
 | |
| 	0x15,
 | |
| 	0x95,
 | |
| 	0x55,
 | |
| 	0xD5,
 | |
| 	0x35,
 | |
| 	0xB5,
 | |
| 	0x75,
 | |
| 	0xF5,
 | |
| 	0x0D,
 | |
| 	0x8D,
 | |
| 	0x4D,
 | |
| 	0xCD,
 | |
| 	0x2D,
 | |
| 	0xAD,
 | |
| 	0x6D,
 | |
| 	0xED,
 | |
| 	0x1D,
 | |
| 	0x9D,
 | |
| 	0x5D,
 | |
| 	0xDD,
 | |
| 	0x3D,
 | |
| 	0xBD,
 | |
| 	0x7D,
 | |
| 	0xFD,
 | |
| 	0x03,
 | |
| 	0x83,
 | |
| 	0x43,
 | |
| 	0xC3,
 | |
| 	0x23,
 | |
| 	0xA3,
 | |
| 	0x63,
 | |
| 	0xE3,
 | |
| 	0x13,
 | |
| 	0x93,
 | |
| 	0x53,
 | |
| 	0xD3,
 | |
| 	0x33,
 | |
| 	0xB3,
 | |
| 	0x73,
 | |
| 	0xF3,
 | |
| 	0x0B,
 | |
| 	0x8B,
 | |
| 	0x4B,
 | |
| 	0xCB,
 | |
| 	0x2B,
 | |
| 	0xAB,
 | |
| 	0x6B,
 | |
| 	0xEB,
 | |
| 	0x1B,
 | |
| 	0x9B,
 | |
| 	0x5B,
 | |
| 	0xDB,
 | |
| 	0x3B,
 | |
| 	0xBB,
 | |
| 	0x7B,
 | |
| 	0xFB,
 | |
| 	0x07,
 | |
| 	0x87,
 | |
| 	0x47,
 | |
| 	0xC7,
 | |
| 	0x27,
 | |
| 	0xA7,
 | |
| 	0x67,
 | |
| 	0xE7,
 | |
| 	0x17,
 | |
| 	0x97,
 | |
| 	0x57,
 | |
| 	0xD7,
 | |
| 	0x37,
 | |
| 	0xB7,
 | |
| 	0x77,
 | |
| 	0xF7,
 | |
| 	0x0F,
 | |
| 	0x8F,
 | |
| 	0x4F,
 | |
| 	0xCF,
 | |
| 	0x2F,
 | |
| 	0xAF,
 | |
| 	0x6F,
 | |
| 	0xEF,
 | |
| 	0x1F,
 | |
| 	0x9F,
 | |
| 	0x5F,
 | |
| 	0xDF,
 | |
| 	0x3F,
 | |
| 	0xBF,
 | |
| 	0x7F,
 | |
| 	0xFF,
 | |
| }
 | |
| 
 | |
| const reverseBitsLowest = (uint64(1) << (reverseBitsMax - 1 + reverseBitsBase))
 | |
| 
 | |
| /* Returns reverse(num >> BROTLI_REVERSE_BITS_BASE, BROTLI_REVERSE_BITS_MAX),
 | |
|    where reverse(value, len) is the bit-wise reversal of the len least
 | |
|    significant bits of value. */
 | |
| func reverseBits8(num uint64) uint64 {
 | |
| 	return uint64(kReverseBits[num])
 | |
| }
 | |
| 
 | |
| /* Stores code in table[0], table[step], table[2*step], ..., table[end] */
 | |
| /* Assumes that end is an integer multiple of step */
 | |
| func replicateValue(table []huffmanCode, step int, end int, code huffmanCode) {
 | |
| 	for {
 | |
| 		end -= step
 | |
| 		table[end] = code
 | |
| 		if end <= 0 {
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* Returns the table width of the next 2nd level table. |count| is the histogram
 | |
|    of bit lengths for the remaining symbols, |len| is the code length of the
 | |
|    next processed symbol. */
 | |
| func nextTableBitSize(count []uint16, len int, root_bits int) int {
 | |
| 	var left int = 1 << uint(len-root_bits)
 | |
| 	for len < huffmanMaxCodeLength {
 | |
| 		left -= int(count[len])
 | |
| 		if left <= 0 {
 | |
| 			break
 | |
| 		}
 | |
| 		len++
 | |
| 		left <<= 1
 | |
| 	}
 | |
| 
 | |
| 	return len - root_bits
 | |
| }
 | |
| 
 | |
| func buildCodeLengthsHuffmanTable(table []huffmanCode, code_lengths []byte, count []uint16) {
 | |
| 	var code huffmanCode /* current table entry */ /* symbol index in original or sorted table */ /* prefix code */ /* prefix code addend */ /* step size to replicate values in current table */ /* size of current table */ /* symbols sorted by code length */
 | |
| 	var symbol int
 | |
| 	var key uint64
 | |
| 	var key_step uint64
 | |
| 	var step int
 | |
| 	var table_size int
 | |
| 	var sorted [codeLengthCodes]int
 | |
| 	var offset [huffmanMaxCodeLengthCodeLength + 1]int
 | |
| 	var bits int
 | |
| 	var bits_count int
 | |
| 	/* offsets in sorted table for each length */
 | |
| 	assert(huffmanMaxCodeLengthCodeLength <= reverseBitsMax)
 | |
| 
 | |
| 	/* Generate offsets into sorted symbol table by code length. */
 | |
| 	symbol = -1
 | |
| 
 | |
| 	bits = 1
 | |
| 	var i int
 | |
| 	for i = 0; i < huffmanMaxCodeLengthCodeLength; i++ {
 | |
| 		symbol += int(count[bits])
 | |
| 		offset[bits] = symbol
 | |
| 		bits++
 | |
| 	}
 | |
| 
 | |
| 	/* Symbols with code length 0 are placed after all other symbols. */
 | |
| 	offset[0] = codeLengthCodes - 1
 | |
| 
 | |
| 	/* Sort symbols by length, by symbol order within each length. */
 | |
| 	symbol = codeLengthCodes
 | |
| 
 | |
| 	for {
 | |
| 		var i int
 | |
| 		for i = 0; i < 6; i++ {
 | |
| 			symbol--
 | |
| 			sorted[offset[code_lengths[symbol]]] = symbol
 | |
| 			offset[code_lengths[symbol]]--
 | |
| 		}
 | |
| 		if symbol == 0 {
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	table_size = 1 << huffmanMaxCodeLengthCodeLength
 | |
| 
 | |
| 	/* Special case: all symbols but one have 0 code length. */
 | |
| 	if offset[0] == 0 {
 | |
| 		code = constructHuffmanCode(0, uint16(sorted[0]))
 | |
| 		for key = 0; key < uint64(table_size); key++ {
 | |
| 			table[key] = code
 | |
| 		}
 | |
| 
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	/* Fill in table. */
 | |
| 	key = 0
 | |
| 
 | |
| 	key_step = reverseBitsLowest
 | |
| 	symbol = 0
 | |
| 	bits = 1
 | |
| 	step = 2
 | |
| 	for {
 | |
| 		for bits_count = int(count[bits]); bits_count != 0; bits_count-- {
 | |
| 			code = constructHuffmanCode(byte(bits), uint16(sorted[symbol]))
 | |
| 			symbol++
 | |
| 			replicateValue(table[reverseBits8(key):], step, table_size, code)
 | |
| 			key += key_step
 | |
| 		}
 | |
| 
 | |
| 		step <<= 1
 | |
| 		key_step >>= 1
 | |
| 		bits++
 | |
| 		if bits > huffmanMaxCodeLengthCodeLength {
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func buildHuffmanTable(root_table []huffmanCode, root_bits int, symbol_lists symbolList, count []uint16) uint32 {
 | |
| 	var code huffmanCode /* current table entry */ /* next available space in table */ /* current code length */ /* symbol index in original or sorted table */ /* prefix code */ /* prefix code addend */ /* 2nd level table prefix code */ /* 2nd level table prefix code addend */ /* step size to replicate values in current table */ /* key length of current table */ /* size of current table */ /* sum of root table size and 2nd level table sizes */
 | |
| 	var table []huffmanCode
 | |
| 	var len int
 | |
| 	var symbol int
 | |
| 	var key uint64
 | |
| 	var key_step uint64
 | |
| 	var sub_key uint64
 | |
| 	var sub_key_step uint64
 | |
| 	var step int
 | |
| 	var table_bits int
 | |
| 	var table_size int
 | |
| 	var total_size int
 | |
| 	var max_length int = -1
 | |
| 	var bits int
 | |
| 	var bits_count int
 | |
| 
 | |
| 	assert(root_bits <= reverseBitsMax)
 | |
| 	assert(huffmanMaxCodeLength-root_bits <= reverseBitsMax)
 | |
| 
 | |
| 	for symbolListGet(symbol_lists, max_length) == 0xFFFF {
 | |
| 		max_length--
 | |
| 	}
 | |
| 	max_length += huffmanMaxCodeLength + 1
 | |
| 
 | |
| 	table = root_table
 | |
| 	table_bits = root_bits
 | |
| 	table_size = 1 << uint(table_bits)
 | |
| 	total_size = table_size
 | |
| 
 | |
| 	/* Fill in the root table. Reduce the table size to if possible,
 | |
| 	   and create the repetitions by memcpy. */
 | |
| 	if table_bits > max_length {
 | |
| 		table_bits = max_length
 | |
| 		table_size = 1 << uint(table_bits)
 | |
| 	}
 | |
| 
 | |
| 	key = 0
 | |
| 	key_step = reverseBitsLowest
 | |
| 	bits = 1
 | |
| 	step = 2
 | |
| 	for {
 | |
| 		symbol = bits - (huffmanMaxCodeLength + 1)
 | |
| 		for bits_count = int(count[bits]); bits_count != 0; bits_count-- {
 | |
| 			symbol = int(symbolListGet(symbol_lists, symbol))
 | |
| 			code = constructHuffmanCode(byte(bits), uint16(symbol))
 | |
| 			replicateValue(table[reverseBits8(key):], step, table_size, code)
 | |
| 			key += key_step
 | |
| 		}
 | |
| 
 | |
| 		step <<= 1
 | |
| 		key_step >>= 1
 | |
| 		bits++
 | |
| 		if bits > table_bits {
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* If root_bits != table_bits then replicate to fill the remaining slots. */
 | |
| 	for total_size != table_size {
 | |
| 		copy(table[table_size:], table[:uint(table_size)])
 | |
| 		table_size <<= 1
 | |
| 	}
 | |
| 
 | |
| 	/* Fill in 2nd level tables and add pointers to root table. */
 | |
| 	key_step = reverseBitsLowest >> uint(root_bits-1)
 | |
| 
 | |
| 	sub_key = reverseBitsLowest << 1
 | |
| 	sub_key_step = reverseBitsLowest
 | |
| 	len = root_bits + 1
 | |
| 	step = 2
 | |
| 	for ; len <= max_length; len++ {
 | |
| 		symbol = len - (huffmanMaxCodeLength + 1)
 | |
| 		for ; count[len] != 0; count[len]-- {
 | |
| 			if sub_key == reverseBitsLowest<<1 {
 | |
| 				table = table[table_size:]
 | |
| 				table_bits = nextTableBitSize(count, int(len), root_bits)
 | |
| 				table_size = 1 << uint(table_bits)
 | |
| 				total_size += table_size
 | |
| 				sub_key = reverseBits8(key)
 | |
| 				key += key_step
 | |
| 				root_table[sub_key] = constructHuffmanCode(byte(table_bits+root_bits), uint16(uint64(uint(-cap(table)+cap(root_table)))-sub_key))
 | |
| 				sub_key = 0
 | |
| 			}
 | |
| 
 | |
| 			symbol = int(symbolListGet(symbol_lists, symbol))
 | |
| 			code = constructHuffmanCode(byte(len-root_bits), uint16(symbol))
 | |
| 			replicateValue(table[reverseBits8(sub_key):], step, table_size, code)
 | |
| 			sub_key += sub_key_step
 | |
| 		}
 | |
| 
 | |
| 		step <<= 1
 | |
| 		sub_key_step >>= 1
 | |
| 	}
 | |
| 
 | |
| 	return uint32(total_size)
 | |
| }
 | |
| 
 | |
| func buildSimpleHuffmanTable(table []huffmanCode, root_bits int, val []uint16, num_symbols uint32) uint32 {
 | |
| 	var table_size uint32 = 1
 | |
| 	var goal_size uint32 = 1 << uint(root_bits)
 | |
| 	switch num_symbols {
 | |
| 	case 0:
 | |
| 		table[0] = constructHuffmanCode(0, val[0])
 | |
| 
 | |
| 	case 1:
 | |
| 		if val[1] > val[0] {
 | |
| 			table[0] = constructHuffmanCode(1, val[0])
 | |
| 			table[1] = constructHuffmanCode(1, val[1])
 | |
| 		} else {
 | |
| 			table[0] = constructHuffmanCode(1, val[1])
 | |
| 			table[1] = constructHuffmanCode(1, val[0])
 | |
| 		}
 | |
| 
 | |
| 		table_size = 2
 | |
| 
 | |
| 	case 2:
 | |
| 		table[0] = constructHuffmanCode(1, val[0])
 | |
| 		table[2] = constructHuffmanCode(1, val[0])
 | |
| 		if val[2] > val[1] {
 | |
| 			table[1] = constructHuffmanCode(2, val[1])
 | |
| 			table[3] = constructHuffmanCode(2, val[2])
 | |
| 		} else {
 | |
| 			table[1] = constructHuffmanCode(2, val[2])
 | |
| 			table[3] = constructHuffmanCode(2, val[1])
 | |
| 		}
 | |
| 
 | |
| 		table_size = 4
 | |
| 
 | |
| 	case 3:
 | |
| 		var i int
 | |
| 		var k int
 | |
| 		for i = 0; i < 3; i++ {
 | |
| 			for k = i + 1; k < 4; k++ {
 | |
| 				if val[k] < val[i] {
 | |
| 					var t uint16 = val[k]
 | |
| 					val[k] = val[i]
 | |
| 					val[i] = t
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		table[0] = constructHuffmanCode(2, val[0])
 | |
| 		table[2] = constructHuffmanCode(2, val[1])
 | |
| 		table[1] = constructHuffmanCode(2, val[2])
 | |
| 		table[3] = constructHuffmanCode(2, val[3])
 | |
| 		table_size = 4
 | |
| 
 | |
| 	case 4:
 | |
| 		if val[3] < val[2] {
 | |
| 			var t uint16 = val[3]
 | |
| 			val[3] = val[2]
 | |
| 			val[2] = t
 | |
| 		}
 | |
| 
 | |
| 		table[0] = constructHuffmanCode(1, val[0])
 | |
| 		table[1] = constructHuffmanCode(2, val[1])
 | |
| 		table[2] = constructHuffmanCode(1, val[0])
 | |
| 		table[3] = constructHuffmanCode(3, val[2])
 | |
| 		table[4] = constructHuffmanCode(1, val[0])
 | |
| 		table[5] = constructHuffmanCode(2, val[1])
 | |
| 		table[6] = constructHuffmanCode(1, val[0])
 | |
| 		table[7] = constructHuffmanCode(3, val[3])
 | |
| 		table_size = 8
 | |
| 	}
 | |
| 
 | |
| 	for table_size != goal_size {
 | |
| 		copy(table[table_size:], table[:uint(table_size)])
 | |
| 		table_size <<= 1
 | |
| 	}
 | |
| 
 | |
| 	return goal_size
 | |
| }
 |