gen.go 4.3 KB

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