github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/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 }