// Copyright 2012 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build ignore // This program generates fixedhuff.go // Invoke as // // go run gen.go -output fixedhuff.go package main import ( "bytes" "flag" "fmt" "go/format" "io/ioutil" "log" ) var filename = flag.String("output", "fixedhuff.go", "output file name") const maxCodeLen = 16 // Note: the definition of the huffmanDecoder struct is copied from // inflate.go, as it is private to the implementation. // chunk & 15 is number of bits // chunk >> 4 is value, including table link const ( huffmanChunkBits = 9 huffmanNumChunks = 1 << huffmanChunkBits huffmanCountMask = 15 huffmanValueShift = 4 ) type huffmanDecoder struct { min int // the minimum code length chunks [huffmanNumChunks]uint32 // chunks as described above links [][]uint32 // overflow links linkMask uint32 // mask the width of the link table } // Initialize Huffman decoding tables from array of code lengths. func (h *huffmanDecoder) init(bits []int) bool { // Count number of codes of each length, // compute min and max length. var count [maxCodeLen]int var min, max int for _, n := range bits { if n == 0 { continue } if min == 0 || n < min { min = n } if n > max { max = n } count[n]++ } if max == 0 { return false } h.min = min var linkBits uint var numLinks int if max > huffmanChunkBits { linkBits = uint(max) - huffmanChunkBits numLinks = 1 << linkBits h.linkMask = uint32(numLinks - 1) } code := 0 var nextcode [maxCodeLen]int for i := min; i <= max; i++ { if i == huffmanChunkBits+1 { // create link tables link := code >> 1 h.links = make([][]uint32, huffmanNumChunks-link) for j := uint(link); j < huffmanNumChunks; j++ { reverse := int(reverseByte[j>>8]) | int(reverseByte[j&0xff])<<8 reverse >>= uint(16 - huffmanChunkBits) off := j - uint(link) h.chunks[reverse] = uint32(off<>8]) | int(reverseByte[code&0xff])<<8 reverse >>= uint(16 - n) if n <= huffmanChunkBits { for off := reverse; off < huffmanNumChunks; off += 1 << uint(n) { h.chunks[off] = chunk } } else { linktab := h.links[h.chunks[reverse&(huffmanNumChunks-1)]>>huffmanValueShift] reverse >>= huffmanChunkBits for off := reverse; off < numLinks; off += 1 << uint(n-huffmanChunkBits) { linktab[off] = chunk } } } return true } func main() { flag.Parse() var h huffmanDecoder var bits [288]int initReverseByte() for i := 0; i < 144; i++ { bits[i] = 8 } for i := 144; i < 256; i++ { bits[i] = 9 } for i := 256; i < 280; i++ { bits[i] = 7 } for i := 280; i < 288; i++ { bits[i] = 8 } h.init(bits[:]) var buf bytes.Buffer fmt.Fprintf(&buf, `// Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file.`+"\n\n") fmt.Fprintln(&buf, "package flate") fmt.Fprintln(&buf) fmt.Fprintln(&buf, "// autogenerated by go run gen.go -output fixedhuff.go, DO NOT EDIT") fmt.Fprintln(&buf) fmt.Fprintln(&buf, "var fixedHuffmanDecoder = huffmanDecoder{") fmt.Fprintf(&buf, "\t%d,\n", h.min) fmt.Fprintln(&buf, "\t[huffmanNumChunks]uint32{") for i := 0; i < huffmanNumChunks; i++ { if i&7 == 0 { fmt.Fprintf(&buf, "\t\t") } else { fmt.Fprintf(&buf, " ") } fmt.Fprintf(&buf, "0x%04x,", h.chunks[i]) if i&7 == 7 { fmt.Fprintln(&buf) } } fmt.Fprintln(&buf, "\t},") fmt.Fprintln(&buf, "\tnil, 0,") fmt.Fprintln(&buf, "}") data, err := format.Source(buf.Bytes()) if err != nil { log.Fatal(err) } err = ioutil.WriteFile(*filename, data, 0644) if err != nil { log.Fatal(err) } } var reverseByte [256]byte func initReverseByte() { for x := 0; x < 256; x++ { var result byte for i := uint(0); i < 8; i++ { result |= byte(((x >> i) & 1) << (7 - i)) } reverseByte[x] = result } }