mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			166 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			166 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
// 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 |gofmt >fixedhuff.go
 | 
						|
 | 
						|
package main
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
)
 | 
						|
 | 
						|
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<<huffmanValueShift + uint(i))
 | 
						|
				h.links[off] = make([]uint32, 1<<linkBits)
 | 
						|
			}
 | 
						|
		}
 | 
						|
		n := count[i]
 | 
						|
		nextcode[i] = code
 | 
						|
		code += n
 | 
						|
		code <<= 1
 | 
						|
	}
 | 
						|
 | 
						|
	for i, n := range bits {
 | 
						|
		if n == 0 {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		code := nextcode[n]
 | 
						|
		nextcode[n]++
 | 
						|
		chunk := uint32(i<<huffmanValueShift | n)
 | 
						|
		reverse := int(reverseByte[code>>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() {
 | 
						|
	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[:])
 | 
						|
	fmt.Println("package flate")
 | 
						|
	fmt.Println()
 | 
						|
	fmt.Println("// autogenerated by gen.go, DO NOT EDIT")
 | 
						|
	fmt.Println()
 | 
						|
	fmt.Println("var fixedHuffmanDecoder = huffmanDecoder{")
 | 
						|
	fmt.Printf("\t%d,\n", h.min)
 | 
						|
	fmt.Println("\t[huffmanNumChunks]uint32{")
 | 
						|
	for i := 0; i < huffmanNumChunks; i++ {
 | 
						|
		if i&7 == 0 {
 | 
						|
			fmt.Printf("\t\t")
 | 
						|
		} else {
 | 
						|
			fmt.Printf(" ")
 | 
						|
		}
 | 
						|
		fmt.Printf("0x%04x,", h.chunks[i])
 | 
						|
		if i&7 == 7 {
 | 
						|
			fmt.Println()
 | 
						|
		}
 | 
						|
	}
 | 
						|
	fmt.Println("\t},")
 | 
						|
	fmt.Println("\tnil, 0,")
 | 
						|
	fmt.Println("}")
 | 
						|
}
 | 
						|
 | 
						|
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
 | 
						|
	}
 | 
						|
}
 |