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