github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/compress/flate/gen.go (about)

     1  // Copyright 2012 The Go Authors.  All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build ignore
     6  
     7  // This program generates fixedhuff.go
     8  // Invoke as
     9  //
    10  //      go run gen.go |gofmt >fixedhuff.go
    11  
    12  package main
    13  
    14  import (
    15  	"fmt"
    16  )
    17  
    18  const maxCodeLen = 16
    19  
    20  // Note: the definition of the huffmanDecoder struct is copied from
    21  // inflate.go, as it is private to the implementation.
    22  
    23  // chunk & 15 is number of bits
    24  // chunk >> 4 is value, including table link
    25  
    26  const (
    27  	huffmanChunkBits  = 9
    28  	huffmanNumChunks  = 1 << huffmanChunkBits
    29  	huffmanCountMask  = 15
    30  	huffmanValueShift = 4
    31  )
    32  
    33  type huffmanDecoder struct {
    34  	min      int                      // the minimum code length
    35  	chunks   [huffmanNumChunks]uint32 // chunks as described above
    36  	links    [][]uint32               // overflow links
    37  	linkMask uint32                   // mask the width of the link table
    38  }
    39  
    40  // Initialize Huffman decoding tables from array of code lengths.
    41  func (h *huffmanDecoder) init(bits []int) bool {
    42  	// Count number of codes of each length,
    43  	// compute min and max length.
    44  	var count [maxCodeLen]int
    45  	var min, max int
    46  	for _, n := range bits {
    47  		if n == 0 {
    48  			continue
    49  		}
    50  		if min == 0 || n < min {
    51  			min = n
    52  		}
    53  		if n > max {
    54  			max = n
    55  		}
    56  		count[n]++
    57  	}
    58  	if max == 0 {
    59  		return false
    60  	}
    61  
    62  	h.min = min
    63  	var linkBits uint
    64  	var numLinks int
    65  	if max > huffmanChunkBits {
    66  		linkBits = uint(max) - huffmanChunkBits
    67  		numLinks = 1 << linkBits
    68  		h.linkMask = uint32(numLinks - 1)
    69  	}
    70  	code := 0
    71  	var nextcode [maxCodeLen]int
    72  	for i := min; i <= max; i++ {
    73  		if i == huffmanChunkBits+1 {
    74  			// create link tables
    75  			link := code >> 1
    76  			h.links = make([][]uint32, huffmanNumChunks-link)
    77  			for j := uint(link); j < huffmanNumChunks; j++ {
    78  				reverse := int(reverseByte[j>>8]) | int(reverseByte[j&0xff])<<8
    79  				reverse >>= uint(16 - huffmanChunkBits)
    80  				off := j - uint(link)
    81  				h.chunks[reverse] = uint32(off<<huffmanValueShift + uint(i))
    82  				h.links[off] = make([]uint32, 1<<linkBits)
    83  			}
    84  		}
    85  		n := count[i]
    86  		nextcode[i] = code
    87  		code += n
    88  		code <<= 1
    89  	}
    90  
    91  	for i, n := range bits {
    92  		if n == 0 {
    93  			continue
    94  		}
    95  		code := nextcode[n]
    96  		nextcode[n]++
    97  		chunk := uint32(i<<huffmanValueShift | n)
    98  		reverse := int(reverseByte[code>>8]) | int(reverseByte[code&0xff])<<8
    99  		reverse >>= uint(16 - n)
   100  		if n <= huffmanChunkBits {
   101  			for off := reverse; off < huffmanNumChunks; off += 1 << uint(n) {
   102  				h.chunks[off] = chunk
   103  			}
   104  		} else {
   105  			linktab := h.links[h.chunks[reverse&(huffmanNumChunks-1)]>>huffmanValueShift]
   106  			reverse >>= huffmanChunkBits
   107  			for off := reverse; off < numLinks; off += 1 << uint(n-huffmanChunkBits) {
   108  				linktab[off] = chunk
   109  			}
   110  		}
   111  	}
   112  	return true
   113  }
   114  
   115  func main() {
   116  	var h huffmanDecoder
   117  	var bits [288]int
   118  	initReverseByte()
   119  	for i := 0; i < 144; i++ {
   120  		bits[i] = 8
   121  	}
   122  	for i := 144; i < 256; i++ {
   123  		bits[i] = 9
   124  	}
   125  	for i := 256; i < 280; i++ {
   126  		bits[i] = 7
   127  	}
   128  	for i := 280; i < 288; i++ {
   129  		bits[i] = 8
   130  	}
   131  	h.init(bits[:])
   132  	fmt.Println("package flate")
   133  	fmt.Println()
   134  	fmt.Println("// autogenerated by gen.go, DO NOT EDIT")
   135  	fmt.Println()
   136  	fmt.Println("var fixedHuffmanDecoder = huffmanDecoder{")
   137  	fmt.Printf("\t%d,\n", h.min)
   138  	fmt.Println("\t[huffmanNumChunks]uint32{")
   139  	for i := 0; i < huffmanNumChunks; i++ {
   140  		if i&7 == 0 {
   141  			fmt.Printf("\t\t")
   142  		} else {
   143  			fmt.Printf(" ")
   144  		}
   145  		fmt.Printf("0x%04x,", h.chunks[i])
   146  		if i&7 == 7 {
   147  			fmt.Println()
   148  		}
   149  	}
   150  	fmt.Println("\t},")
   151  	fmt.Println("\tnil, 0,")
   152  	fmt.Println("}")
   153  }
   154  
   155  var reverseByte [256]byte
   156  
   157  func initReverseByte() {
   158  	for x := 0; x < 256; x++ {
   159  		var result byte
   160  		for i := uint(0); i < 8; i++ {
   161  			result |= byte(((x >> i) & 1) << (7 - i))
   162  		}
   163  		reverseByte[x] = result
   164  	}
   165  }