github.com/andybalholm/brotli@v1.0.6/compress_fragment_two_pass.go (about)

     1  package brotli
     2  
     3  import "encoding/binary"
     4  
     5  /* Copyright 2015 Google Inc. All Rights Reserved.
     6  
     7     Distributed under MIT license.
     8     See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
     9  */
    10  
    11  /* Function for fast encoding of an input fragment, independently from the input
    12     history. This function uses two-pass processing: in the first pass we save
    13     the found backward matches and literal bytes into a buffer, and in the
    14     second pass we emit them into the bit stream using prefix codes built based
    15     on the actual command and literal byte histograms. */
    16  
    17  const kCompressFragmentTwoPassBlockSize uint = 1 << 17
    18  
    19  func hash1(p []byte, shift uint, length uint) uint32 {
    20  	var h uint64 = (binary.LittleEndian.Uint64(p) << ((8 - length) * 8)) * uint64(kHashMul32)
    21  	return uint32(h >> shift)
    22  }
    23  
    24  func hashBytesAtOffset(v uint64, offset uint, shift uint, length uint) uint32 {
    25  	assert(offset <= 8-length)
    26  	{
    27  		var h uint64 = ((v >> (8 * offset)) << ((8 - length) * 8)) * uint64(kHashMul32)
    28  		return uint32(h >> shift)
    29  	}
    30  }
    31  
    32  func isMatch1(p1 []byte, p2 []byte, length uint) bool {
    33  	if binary.LittleEndian.Uint32(p1) != binary.LittleEndian.Uint32(p2) {
    34  		return false
    35  	}
    36  	if length == 4 {
    37  		return true
    38  	}
    39  	return p1[4] == p2[4] && p1[5] == p2[5]
    40  }
    41  
    42  /* Builds a command and distance prefix code (each 64 symbols) into "depth" and
    43     "bits" based on "histogram" and stores it into the bit stream. */
    44  func buildAndStoreCommandPrefixCode(histogram []uint32, depth []byte, bits []uint16, storage_ix *uint, storage []byte) {
    45  	var tree [129]huffmanTree
    46  	var cmd_depth = [numCommandSymbols]byte{0}
    47  	/* Tree size for building a tree over 64 symbols is 2 * 64 + 1. */
    48  
    49  	var cmd_bits [64]uint16
    50  	createHuffmanTree(histogram, 64, 15, tree[:], depth)
    51  	createHuffmanTree(histogram[64:], 64, 14, tree[:], depth[64:])
    52  
    53  	/* We have to jump through a few hoops here in order to compute
    54  	   the command bits because the symbols are in a different order than in
    55  	   the full alphabet. This looks complicated, but having the symbols
    56  	   in this order in the command bits saves a few branches in the Emit*
    57  	   functions. */
    58  	copy(cmd_depth[:], depth[24:][:24])
    59  
    60  	copy(cmd_depth[24:][:], depth[:8])
    61  	copy(cmd_depth[32:][:], depth[48:][:8])
    62  	copy(cmd_depth[40:][:], depth[8:][:8])
    63  	copy(cmd_depth[48:][:], depth[56:][:8])
    64  	copy(cmd_depth[56:][:], depth[16:][:8])
    65  	convertBitDepthsToSymbols(cmd_depth[:], 64, cmd_bits[:])
    66  	copy(bits, cmd_bits[24:][:8])
    67  	copy(bits[8:], cmd_bits[40:][:8])
    68  	copy(bits[16:], cmd_bits[56:][:8])
    69  	copy(bits[24:], cmd_bits[:24])
    70  	copy(bits[48:], cmd_bits[32:][:8])
    71  	copy(bits[56:], cmd_bits[48:][:8])
    72  	convertBitDepthsToSymbols(depth[64:], 64, bits[64:])
    73  	{
    74  		/* Create the bit length array for the full command alphabet. */
    75  		var i uint
    76  		for i := 0; i < int(64); i++ {
    77  			cmd_depth[i] = 0
    78  		} /* only 64 first values were used */
    79  		copy(cmd_depth[:], depth[24:][:8])
    80  		copy(cmd_depth[64:][:], depth[32:][:8])
    81  		copy(cmd_depth[128:][:], depth[40:][:8])
    82  		copy(cmd_depth[192:][:], depth[48:][:8])
    83  		copy(cmd_depth[384:][:], depth[56:][:8])
    84  		for i = 0; i < 8; i++ {
    85  			cmd_depth[128+8*i] = depth[i]
    86  			cmd_depth[256+8*i] = depth[8+i]
    87  			cmd_depth[448+8*i] = depth[16+i]
    88  		}
    89  
    90  		storeHuffmanTree(cmd_depth[:], numCommandSymbols, tree[:], storage_ix, storage)
    91  	}
    92  
    93  	storeHuffmanTree(depth[64:], 64, tree[:], storage_ix, storage)
    94  }
    95  
    96  func emitInsertLen(insertlen uint32, commands *[]uint32) {
    97  	if insertlen < 6 {
    98  		(*commands)[0] = insertlen
    99  	} else if insertlen < 130 {
   100  		var tail uint32 = insertlen - 2
   101  		var nbits uint32 = log2FloorNonZero(uint(tail)) - 1
   102  		var prefix uint32 = tail >> nbits
   103  		var inscode uint32 = (nbits << 1) + prefix + 2
   104  		var extra uint32 = tail - (prefix << nbits)
   105  		(*commands)[0] = inscode | extra<<8
   106  	} else if insertlen < 2114 {
   107  		var tail uint32 = insertlen - 66
   108  		var nbits uint32 = log2FloorNonZero(uint(tail))
   109  		var code uint32 = nbits + 10
   110  		var extra uint32 = tail - (1 << nbits)
   111  		(*commands)[0] = code | extra<<8
   112  	} else if insertlen < 6210 {
   113  		var extra uint32 = insertlen - 2114
   114  		(*commands)[0] = 21 | extra<<8
   115  	} else if insertlen < 22594 {
   116  		var extra uint32 = insertlen - 6210
   117  		(*commands)[0] = 22 | extra<<8
   118  	} else {
   119  		var extra uint32 = insertlen - 22594
   120  		(*commands)[0] = 23 | extra<<8
   121  	}
   122  
   123  	*commands = (*commands)[1:]
   124  }
   125  
   126  func emitCopyLen(copylen uint, commands *[]uint32) {
   127  	if copylen < 10 {
   128  		(*commands)[0] = uint32(copylen + 38)
   129  	} else if copylen < 134 {
   130  		var tail uint = copylen - 6
   131  		var nbits uint = uint(log2FloorNonZero(tail) - 1)
   132  		var prefix uint = tail >> nbits
   133  		var code uint = (nbits << 1) + prefix + 44
   134  		var extra uint = tail - (prefix << nbits)
   135  		(*commands)[0] = uint32(code | extra<<8)
   136  	} else if copylen < 2118 {
   137  		var tail uint = copylen - 70
   138  		var nbits uint = uint(log2FloorNonZero(tail))
   139  		var code uint = nbits + 52
   140  		var extra uint = tail - (uint(1) << nbits)
   141  		(*commands)[0] = uint32(code | extra<<8)
   142  	} else {
   143  		var extra uint = copylen - 2118
   144  		(*commands)[0] = uint32(63 | extra<<8)
   145  	}
   146  
   147  	*commands = (*commands)[1:]
   148  }
   149  
   150  func emitCopyLenLastDistance(copylen uint, commands *[]uint32) {
   151  	if copylen < 12 {
   152  		(*commands)[0] = uint32(copylen + 20)
   153  		*commands = (*commands)[1:]
   154  	} else if copylen < 72 {
   155  		var tail uint = copylen - 8
   156  		var nbits uint = uint(log2FloorNonZero(tail) - 1)
   157  		var prefix uint = tail >> nbits
   158  		var code uint = (nbits << 1) + prefix + 28
   159  		var extra uint = tail - (prefix << nbits)
   160  		(*commands)[0] = uint32(code | extra<<8)
   161  		*commands = (*commands)[1:]
   162  	} else if copylen < 136 {
   163  		var tail uint = copylen - 8
   164  		var code uint = (tail >> 5) + 54
   165  		var extra uint = tail & 31
   166  		(*commands)[0] = uint32(code | extra<<8)
   167  		*commands = (*commands)[1:]
   168  		(*commands)[0] = 64
   169  		*commands = (*commands)[1:]
   170  	} else if copylen < 2120 {
   171  		var tail uint = copylen - 72
   172  		var nbits uint = uint(log2FloorNonZero(tail))
   173  		var code uint = nbits + 52
   174  		var extra uint = tail - (uint(1) << nbits)
   175  		(*commands)[0] = uint32(code | extra<<8)
   176  		*commands = (*commands)[1:]
   177  		(*commands)[0] = 64
   178  		*commands = (*commands)[1:]
   179  	} else {
   180  		var extra uint = copylen - 2120
   181  		(*commands)[0] = uint32(63 | extra<<8)
   182  		*commands = (*commands)[1:]
   183  		(*commands)[0] = 64
   184  		*commands = (*commands)[1:]
   185  	}
   186  }
   187  
   188  func emitDistance(distance uint32, commands *[]uint32) {
   189  	var d uint32 = distance + 3
   190  	var nbits uint32 = log2FloorNonZero(uint(d)) - 1
   191  	var prefix uint32 = (d >> nbits) & 1
   192  	var offset uint32 = (2 + prefix) << nbits
   193  	var distcode uint32 = 2*(nbits-1) + prefix + 80
   194  	var extra uint32 = d - offset
   195  	(*commands)[0] = distcode | extra<<8
   196  	*commands = (*commands)[1:]
   197  }
   198  
   199  /* REQUIRES: len <= 1 << 24. */
   200  func storeMetaBlockHeader(len uint, is_uncompressed bool, storage_ix *uint, storage []byte) {
   201  	var nibbles uint = 6
   202  
   203  	/* ISLAST */
   204  	writeBits(1, 0, storage_ix, storage)
   205  
   206  	if len <= 1<<16 {
   207  		nibbles = 4
   208  	} else if len <= 1<<20 {
   209  		nibbles = 5
   210  	}
   211  
   212  	writeBits(2, uint64(nibbles)-4, storage_ix, storage)
   213  	writeBits(nibbles*4, uint64(len)-1, storage_ix, storage)
   214  
   215  	/* ISUNCOMPRESSED */
   216  	writeSingleBit(is_uncompressed, storage_ix, storage)
   217  }
   218  
   219  func createCommands(input []byte, block_size uint, input_size uint, base_ip_ptr []byte, table []int, table_bits uint, min_match uint, literals *[]byte, commands *[]uint32) {
   220  	var ip int = 0
   221  	var shift uint = 64 - table_bits
   222  	var ip_end int = int(block_size)
   223  	var base_ip int = -cap(base_ip_ptr) + cap(input)
   224  	var next_emit int = 0
   225  	var last_distance int = -1
   226  	/* "ip" is the input pointer. */
   227  
   228  	const kInputMarginBytes uint = windowGap
   229  
   230  	/* "next_emit" is a pointer to the first byte that is not covered by a
   231  	   previous copy. Bytes between "next_emit" and the start of the next copy or
   232  	   the end of the input will be emitted as literal bytes. */
   233  	if block_size >= kInputMarginBytes {
   234  		var len_limit uint = brotli_min_size_t(block_size-min_match, input_size-kInputMarginBytes)
   235  		var ip_limit int = int(len_limit)
   236  		/* For the last block, we need to keep a 16 bytes margin so that we can be
   237  		   sure that all distances are at most window size - 16.
   238  		   For all other blocks, we only need to keep a margin of 5 bytes so that
   239  		   we don't go over the block size with a copy. */
   240  
   241  		var next_hash uint32
   242  		ip++
   243  		for next_hash = hash1(input[ip:], shift, min_match); ; {
   244  			var skip uint32 = 32
   245  			var next_ip int = ip
   246  			/* Step 1: Scan forward in the input looking for a 6-byte-long match.
   247  			   If we get close to exhausting the input then goto emit_remainder.
   248  
   249  			   Heuristic match skipping: If 32 bytes are scanned with no matches
   250  			   found, start looking only at every other byte. If 32 more bytes are
   251  			   scanned, look at every third byte, etc.. When a match is found,
   252  			   immediately go back to looking at every byte. This is a small loss
   253  			   (~5% performance, ~0.1% density) for compressible data due to more
   254  			   bookkeeping, but for non-compressible data (such as JPEG) it's a huge
   255  			   win since the compressor quickly "realizes" the data is incompressible
   256  			   and doesn't bother looking for matches everywhere.
   257  
   258  			   The "skip" variable keeps track of how many bytes there are since the
   259  			   last match; dividing it by 32 (ie. right-shifting by five) gives the
   260  			   number of bytes to move ahead for each iteration. */
   261  
   262  			var candidate int
   263  
   264  			assert(next_emit < ip)
   265  
   266  		trawl:
   267  			for {
   268  				var hash uint32 = next_hash
   269  				var bytes_between_hash_lookups uint32 = skip >> 5
   270  				skip++
   271  				ip = next_ip
   272  				assert(hash == hash1(input[ip:], shift, min_match))
   273  				next_ip = int(uint32(ip) + bytes_between_hash_lookups)
   274  				if next_ip > ip_limit {
   275  					goto emit_remainder
   276  				}
   277  
   278  				next_hash = hash1(input[next_ip:], shift, min_match)
   279  				candidate = ip - last_distance
   280  				if isMatch1(input[ip:], base_ip_ptr[candidate-base_ip:], min_match) {
   281  					if candidate < ip {
   282  						table[hash] = int(ip - base_ip)
   283  						break
   284  					}
   285  				}
   286  
   287  				candidate = base_ip + table[hash]
   288  				assert(candidate >= base_ip)
   289  				assert(candidate < ip)
   290  
   291  				table[hash] = int(ip - base_ip)
   292  				if isMatch1(input[ip:], base_ip_ptr[candidate-base_ip:], min_match) {
   293  					break
   294  				}
   295  			}
   296  
   297  			/* Check copy distance. If candidate is not feasible, continue search.
   298  			   Checking is done outside of hot loop to reduce overhead. */
   299  			if ip-candidate > maxDistance_compress_fragment {
   300  				goto trawl
   301  			}
   302  
   303  			/* Step 2: Emit the found match together with the literal bytes from
   304  			   "next_emit", and then see if we can find a next match immediately
   305  			   afterwards. Repeat until we find no match for the input
   306  			   without emitting some literal bytes. */
   307  			{
   308  				var base int = ip
   309  				/* > 0 */
   310  				var matched uint = min_match + findMatchLengthWithLimit(base_ip_ptr[uint(candidate-base_ip)+min_match:], input[uint(ip)+min_match:], uint(ip_end-ip)-min_match)
   311  				var distance int = int(base - candidate)
   312  				/* We have a 6-byte match at ip, and we need to emit bytes in
   313  				   [next_emit, ip). */
   314  
   315  				var insert int = int(base - next_emit)
   316  				ip += int(matched)
   317  				emitInsertLen(uint32(insert), commands)
   318  				copy(*literals, input[next_emit:][:uint(insert)])
   319  				*literals = (*literals)[insert:]
   320  				if distance == last_distance {
   321  					(*commands)[0] = 64
   322  					*commands = (*commands)[1:]
   323  				} else {
   324  					emitDistance(uint32(distance), commands)
   325  					last_distance = distance
   326  				}
   327  
   328  				emitCopyLenLastDistance(matched, commands)
   329  
   330  				next_emit = ip
   331  				if ip >= ip_limit {
   332  					goto emit_remainder
   333  				}
   334  				{
   335  					var input_bytes uint64
   336  					var cur_hash uint32
   337  					/* We could immediately start working at ip now, but to improve
   338  					   compression we first update "table" with the hashes of some
   339  					   positions within the last copy. */
   340  
   341  					var prev_hash uint32
   342  					if min_match == 4 {
   343  						input_bytes = binary.LittleEndian.Uint64(input[ip-3:])
   344  						cur_hash = hashBytesAtOffset(input_bytes, 3, shift, min_match)
   345  						prev_hash = hashBytesAtOffset(input_bytes, 0, shift, min_match)
   346  						table[prev_hash] = int(ip - base_ip - 3)
   347  						prev_hash = hashBytesAtOffset(input_bytes, 1, shift, min_match)
   348  						table[prev_hash] = int(ip - base_ip - 2)
   349  						prev_hash = hashBytesAtOffset(input_bytes, 0, shift, min_match)
   350  						table[prev_hash] = int(ip - base_ip - 1)
   351  					} else {
   352  						input_bytes = binary.LittleEndian.Uint64(input[ip-5:])
   353  						prev_hash = hashBytesAtOffset(input_bytes, 0, shift, min_match)
   354  						table[prev_hash] = int(ip - base_ip - 5)
   355  						prev_hash = hashBytesAtOffset(input_bytes, 1, shift, min_match)
   356  						table[prev_hash] = int(ip - base_ip - 4)
   357  						prev_hash = hashBytesAtOffset(input_bytes, 2, shift, min_match)
   358  						table[prev_hash] = int(ip - base_ip - 3)
   359  						input_bytes = binary.LittleEndian.Uint64(input[ip-2:])
   360  						cur_hash = hashBytesAtOffset(input_bytes, 2, shift, min_match)
   361  						prev_hash = hashBytesAtOffset(input_bytes, 0, shift, min_match)
   362  						table[prev_hash] = int(ip - base_ip - 2)
   363  						prev_hash = hashBytesAtOffset(input_bytes, 1, shift, min_match)
   364  						table[prev_hash] = int(ip - base_ip - 1)
   365  					}
   366  
   367  					candidate = base_ip + table[cur_hash]
   368  					table[cur_hash] = int(ip - base_ip)
   369  				}
   370  			}
   371  
   372  			for ip-candidate <= maxDistance_compress_fragment && isMatch1(input[ip:], base_ip_ptr[candidate-base_ip:], min_match) {
   373  				var base int = ip
   374  				/* We have a 6-byte match at ip, and no need to emit any
   375  				   literal bytes prior to ip. */
   376  
   377  				var matched uint = min_match + findMatchLengthWithLimit(base_ip_ptr[uint(candidate-base_ip)+min_match:], input[uint(ip)+min_match:], uint(ip_end-ip)-min_match)
   378  				ip += int(matched)
   379  				last_distance = int(base - candidate) /* > 0 */
   380  				emitCopyLen(matched, commands)
   381  				emitDistance(uint32(last_distance), commands)
   382  
   383  				next_emit = ip
   384  				if ip >= ip_limit {
   385  					goto emit_remainder
   386  				}
   387  				{
   388  					var input_bytes uint64
   389  					var cur_hash uint32
   390  					/* We could immediately start working at ip now, but to improve
   391  					   compression we first update "table" with the hashes of some
   392  					   positions within the last copy. */
   393  
   394  					var prev_hash uint32
   395  					if min_match == 4 {
   396  						input_bytes = binary.LittleEndian.Uint64(input[ip-3:])
   397  						cur_hash = hashBytesAtOffset(input_bytes, 3, shift, min_match)
   398  						prev_hash = hashBytesAtOffset(input_bytes, 0, shift, min_match)
   399  						table[prev_hash] = int(ip - base_ip - 3)
   400  						prev_hash = hashBytesAtOffset(input_bytes, 1, shift, min_match)
   401  						table[prev_hash] = int(ip - base_ip - 2)
   402  						prev_hash = hashBytesAtOffset(input_bytes, 2, shift, min_match)
   403  						table[prev_hash] = int(ip - base_ip - 1)
   404  					} else {
   405  						input_bytes = binary.LittleEndian.Uint64(input[ip-5:])
   406  						prev_hash = hashBytesAtOffset(input_bytes, 0, shift, min_match)
   407  						table[prev_hash] = int(ip - base_ip - 5)
   408  						prev_hash = hashBytesAtOffset(input_bytes, 1, shift, min_match)
   409  						table[prev_hash] = int(ip - base_ip - 4)
   410  						prev_hash = hashBytesAtOffset(input_bytes, 2, shift, min_match)
   411  						table[prev_hash] = int(ip - base_ip - 3)
   412  						input_bytes = binary.LittleEndian.Uint64(input[ip-2:])
   413  						cur_hash = hashBytesAtOffset(input_bytes, 2, shift, min_match)
   414  						prev_hash = hashBytesAtOffset(input_bytes, 0, shift, min_match)
   415  						table[prev_hash] = int(ip - base_ip - 2)
   416  						prev_hash = hashBytesAtOffset(input_bytes, 1, shift, min_match)
   417  						table[prev_hash] = int(ip - base_ip - 1)
   418  					}
   419  
   420  					candidate = base_ip + table[cur_hash]
   421  					table[cur_hash] = int(ip - base_ip)
   422  				}
   423  			}
   424  
   425  			ip++
   426  			next_hash = hash1(input[ip:], shift, min_match)
   427  		}
   428  	}
   429  
   430  emit_remainder:
   431  	assert(next_emit <= ip_end)
   432  
   433  	/* Emit the remaining bytes as literals. */
   434  	if next_emit < ip_end {
   435  		var insert uint32 = uint32(ip_end - next_emit)
   436  		emitInsertLen(insert, commands)
   437  		copy(*literals, input[next_emit:][:insert])
   438  		*literals = (*literals)[insert:]
   439  	}
   440  }
   441  
   442  var storeCommands_kNumExtraBits = [128]uint32{
   443  	0,
   444  	0,
   445  	0,
   446  	0,
   447  	0,
   448  	0,
   449  	1,
   450  	1,
   451  	2,
   452  	2,
   453  	3,
   454  	3,
   455  	4,
   456  	4,
   457  	5,
   458  	5,
   459  	6,
   460  	7,
   461  	8,
   462  	9,
   463  	10,
   464  	12,
   465  	14,
   466  	24,
   467  	0,
   468  	0,
   469  	0,
   470  	0,
   471  	0,
   472  	0,
   473  	0,
   474  	0,
   475  	1,
   476  	1,
   477  	2,
   478  	2,
   479  	3,
   480  	3,
   481  	4,
   482  	4,
   483  	0,
   484  	0,
   485  	0,
   486  	0,
   487  	0,
   488  	0,
   489  	0,
   490  	0,
   491  	1,
   492  	1,
   493  	2,
   494  	2,
   495  	3,
   496  	3,
   497  	4,
   498  	4,
   499  	5,
   500  	5,
   501  	6,
   502  	7,
   503  	8,
   504  	9,
   505  	10,
   506  	24,
   507  	0,
   508  	0,
   509  	0,
   510  	0,
   511  	0,
   512  	0,
   513  	0,
   514  	0,
   515  	0,
   516  	0,
   517  	0,
   518  	0,
   519  	0,
   520  	0,
   521  	0,
   522  	0,
   523  	1,
   524  	1,
   525  	2,
   526  	2,
   527  	3,
   528  	3,
   529  	4,
   530  	4,
   531  	5,
   532  	5,
   533  	6,
   534  	6,
   535  	7,
   536  	7,
   537  	8,
   538  	8,
   539  	9,
   540  	9,
   541  	10,
   542  	10,
   543  	11,
   544  	11,
   545  	12,
   546  	12,
   547  	13,
   548  	13,
   549  	14,
   550  	14,
   551  	15,
   552  	15,
   553  	16,
   554  	16,
   555  	17,
   556  	17,
   557  	18,
   558  	18,
   559  	19,
   560  	19,
   561  	20,
   562  	20,
   563  	21,
   564  	21,
   565  	22,
   566  	22,
   567  	23,
   568  	23,
   569  	24,
   570  	24,
   571  }
   572  var storeCommands_kInsertOffset = [24]uint32{
   573  	0,
   574  	1,
   575  	2,
   576  	3,
   577  	4,
   578  	5,
   579  	6,
   580  	8,
   581  	10,
   582  	14,
   583  	18,
   584  	26,
   585  	34,
   586  	50,
   587  	66,
   588  	98,
   589  	130,
   590  	194,
   591  	322,
   592  	578,
   593  	1090,
   594  	2114,
   595  	6210,
   596  	22594,
   597  }
   598  
   599  func storeCommands(literals []byte, num_literals uint, commands []uint32, num_commands uint, storage_ix *uint, storage []byte) {
   600  	var lit_depths [256]byte
   601  	var lit_bits [256]uint16
   602  	var lit_histo = [256]uint32{0}
   603  	var cmd_depths = [128]byte{0}
   604  	var cmd_bits = [128]uint16{0}
   605  	var cmd_histo = [128]uint32{0}
   606  	var i uint
   607  	for i = 0; i < num_literals; i++ {
   608  		lit_histo[literals[i]]++
   609  	}
   610  
   611  	buildAndStoreHuffmanTreeFast(lit_histo[:], num_literals, /* max_bits = */
   612  		8, lit_depths[:], lit_bits[:], storage_ix, storage)
   613  
   614  	for i = 0; i < num_commands; i++ {
   615  		var code uint32 = commands[i] & 0xFF
   616  		assert(code < 128)
   617  		cmd_histo[code]++
   618  	}
   619  
   620  	cmd_histo[1] += 1
   621  	cmd_histo[2] += 1
   622  	cmd_histo[64] += 1
   623  	cmd_histo[84] += 1
   624  	buildAndStoreCommandPrefixCode(cmd_histo[:], cmd_depths[:], cmd_bits[:], storage_ix, storage)
   625  
   626  	for i = 0; i < num_commands; i++ {
   627  		var cmd uint32 = commands[i]
   628  		var code uint32 = cmd & 0xFF
   629  		var extra uint32 = cmd >> 8
   630  		assert(code < 128)
   631  		writeBits(uint(cmd_depths[code]), uint64(cmd_bits[code]), storage_ix, storage)
   632  		writeBits(uint(storeCommands_kNumExtraBits[code]), uint64(extra), storage_ix, storage)
   633  		if code < 24 {
   634  			var insert uint32 = storeCommands_kInsertOffset[code] + extra
   635  			var j uint32
   636  			for j = 0; j < insert; j++ {
   637  				var lit byte = literals[0]
   638  				writeBits(uint(lit_depths[lit]), uint64(lit_bits[lit]), storage_ix, storage)
   639  				literals = literals[1:]
   640  			}
   641  		}
   642  	}
   643  }
   644  
   645  /* Acceptable loss for uncompressible speedup is 2% */
   646  const minRatio = 0.98
   647  
   648  const sampleRate = 43
   649  
   650  func shouldCompress(input []byte, input_size uint, num_literals uint) bool {
   651  	var corpus_size float64 = float64(input_size)
   652  	if float64(num_literals) < minRatio*corpus_size {
   653  		return true
   654  	} else {
   655  		var literal_histo = [256]uint32{0}
   656  		var max_total_bit_cost float64 = corpus_size * 8 * minRatio / sampleRate
   657  		var i uint
   658  		for i = 0; i < input_size; i += sampleRate {
   659  			literal_histo[input[i]]++
   660  		}
   661  
   662  		return bitsEntropy(literal_histo[:], 256) < max_total_bit_cost
   663  	}
   664  }
   665  
   666  func rewindBitPosition(new_storage_ix uint, storage_ix *uint, storage []byte) {
   667  	var bitpos uint = new_storage_ix & 7
   668  	var mask uint = (1 << bitpos) - 1
   669  	storage[new_storage_ix>>3] &= byte(mask)
   670  	*storage_ix = new_storage_ix
   671  }
   672  
   673  func emitUncompressedMetaBlock(input []byte, input_size uint, storage_ix *uint, storage []byte) {
   674  	storeMetaBlockHeader(input_size, true, storage_ix, storage)
   675  	*storage_ix = (*storage_ix + 7) &^ 7
   676  	copy(storage[*storage_ix>>3:], input[:input_size])
   677  	*storage_ix += input_size << 3
   678  	storage[*storage_ix>>3] = 0
   679  }
   680  
   681  func compressFragmentTwoPassImpl(input []byte, input_size uint, is_last bool, command_buf []uint32, literal_buf []byte, table []int, table_bits uint, min_match uint, storage_ix *uint, storage []byte) {
   682  	/* Save the start of the first block for position and distance computations.
   683  	 */
   684  	var base_ip []byte = input
   685  
   686  	for input_size > 0 {
   687  		var block_size uint = brotli_min_size_t(input_size, kCompressFragmentTwoPassBlockSize)
   688  		var commands []uint32 = command_buf
   689  		var literals []byte = literal_buf
   690  		var num_literals uint
   691  		createCommands(input, block_size, input_size, base_ip, table, table_bits, min_match, &literals, &commands)
   692  		num_literals = uint(-cap(literals) + cap(literal_buf))
   693  		if shouldCompress(input, block_size, num_literals) {
   694  			var num_commands uint = uint(-cap(commands) + cap(command_buf))
   695  			storeMetaBlockHeader(block_size, false, storage_ix, storage)
   696  
   697  			/* No block splits, no contexts. */
   698  			writeBits(13, 0, storage_ix, storage)
   699  
   700  			storeCommands(literal_buf, num_literals, command_buf, num_commands, storage_ix, storage)
   701  		} else {
   702  			/* Since we did not find many backward references and the entropy of
   703  			   the data is close to 8 bits, we can simply emit an uncompressed block.
   704  			   This makes compression speed of uncompressible data about 3x faster. */
   705  			emitUncompressedMetaBlock(input, block_size, storage_ix, storage)
   706  		}
   707  
   708  		input = input[block_size:]
   709  		input_size -= block_size
   710  	}
   711  }
   712  
   713  /* Compresses "input" string to the "*storage" buffer as one or more complete
   714     meta-blocks, and updates the "*storage_ix" bit position.
   715  
   716     If "is_last" is 1, emits an additional empty last meta-block.
   717  
   718     REQUIRES: "input_size" is greater than zero, or "is_last" is 1.
   719     REQUIRES: "input_size" is less or equal to maximal metablock size (1 << 24).
   720     REQUIRES: "command_buf" and "literal_buf" point to at least
   721                kCompressFragmentTwoPassBlockSize long arrays.
   722     REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero.
   723     REQUIRES: "table_size" is a power of two
   724     OUTPUT: maximal copy distance <= |input_size|
   725     OUTPUT: maximal copy distance <= BROTLI_MAX_BACKWARD_LIMIT(18) */
   726  func compressFragmentTwoPass(input []byte, input_size uint, is_last bool, command_buf []uint32, literal_buf []byte, table []int, table_size uint, storage_ix *uint, storage []byte) {
   727  	var initial_storage_ix uint = *storage_ix
   728  	var table_bits uint = uint(log2FloorNonZero(table_size))
   729  	var min_match uint
   730  	if table_bits <= 15 {
   731  		min_match = 4
   732  	} else {
   733  		min_match = 6
   734  	}
   735  	compressFragmentTwoPassImpl(input, input_size, is_last, command_buf, literal_buf, table, table_bits, min_match, storage_ix, storage)
   736  
   737  	/* If output is larger than single uncompressed block, rewrite it. */
   738  	if *storage_ix-initial_storage_ix > 31+(input_size<<3) {
   739  		rewindBitPosition(initial_storage_ix, storage_ix, storage)
   740  		emitUncompressedMetaBlock(input, input_size, storage_ix, storage)
   741  	}
   742  
   743  	if is_last {
   744  		writeBits(1, 1, storage_ix, storage) /* islast */
   745  		writeBits(1, 1, storage_ix, storage) /* isempty */
   746  		*storage_ix = (*storage_ix + 7) &^ 7
   747  	}
   748  }