* Dump: Use mholt/archive/v3 to support tar including many compressions Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Dump: Allow dump output to stdout Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Dump: Fixed bug present since #6677 where SessionConfig.Provider is never "file" Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Dump: never pack RepoRootPath, LFS.ContentPath and LogRootPath when they are below AppDataPath Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Dump: also dump LFS (fixes #10058) Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Dump: never dump CustomPath if CustomPath is a subdir of or equal to AppDataPath (fixes #10365) Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * Use log.Info instead of fmt.Fprintf Signed-off-by: Philipp Homann <homann.philipp@googlemail.com> * import ordering * make fmt Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io> Co-authored-by: Matti R <matti@mdranta.net>
		
			
				
	
	
		
			1097 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			1097 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
| package rardecode
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"io"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	rangeBottom = 1 << 15
 | |
| 	rangeTop    = 1 << 24
 | |
| 
 | |
| 	maxFreq = 124
 | |
| 
 | |
| 	intBits    = 7
 | |
| 	periodBits = 7
 | |
| 	binScale   = 1 << (intBits + periodBits)
 | |
| 
 | |
| 	n0       = 1
 | |
| 	n1       = 4
 | |
| 	n2       = 4
 | |
| 	n3       = 4
 | |
| 	n4       = (128 + 3 - 1*n1 - 2*n2 - 3*n3) / 4
 | |
| 	nIndexes = n0 + n1 + n2 + n3 + n4
 | |
| 
 | |
| 	// memory is allocated in units. A unit contains unitSize number of bytes.
 | |
| 	// A unit can store one context or two states.
 | |
| 	unitSize = 12
 | |
| 
 | |
| 	maxUint16 = 1<<16 - 1
 | |
| 	freeMark  = -1
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	errCorruptPPM = errors.New("rardecode: corrupt ppm data")
 | |
| 
 | |
| 	expEscape  = []byte{25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2}
 | |
| 	initBinEsc = []uint16{0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051}
 | |
| 
 | |
| 	ns2Index   [256]byte
 | |
| 	ns2BSIndex [256]byte
 | |
| 
 | |
| 	// units2Index maps the number of units in a block to a freelist index
 | |
| 	units2Index [128 + 1]byte
 | |
| 	// index2Units maps a freelist index to the size of the block in units
 | |
| 	index2Units [nIndexes]int32
 | |
| )
 | |
| 
 | |
| func init() {
 | |
| 	ns2BSIndex[0] = 2 * 0
 | |
| 	ns2BSIndex[1] = 2 * 1
 | |
| 	for i := 2; i < 11; i++ {
 | |
| 		ns2BSIndex[i] = 2 * 2
 | |
| 	}
 | |
| 	for i := 11; i < 256; i++ {
 | |
| 		ns2BSIndex[i] = 2 * 3
 | |
| 	}
 | |
| 
 | |
| 	var j, n byte
 | |
| 	for i := range ns2Index {
 | |
| 		ns2Index[i] = n
 | |
| 		if j <= 3 {
 | |
| 			n++
 | |
| 			j = n
 | |
| 		} else {
 | |
| 			j--
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	var ii byte
 | |
| 	var iu, units int32
 | |
| 	for i, n := range []int{n0, n1, n2, n3, n4} {
 | |
| 		for j := 0; j < n; j++ {
 | |
| 			units += int32(i)
 | |
| 			index2Units[ii] = units
 | |
| 			for iu <= units {
 | |
| 				units2Index[iu] = ii
 | |
| 				iu++
 | |
| 			}
 | |
| 			ii++
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type rangeCoder struct {
 | |
| 	br   io.ByteReader
 | |
| 	code uint32
 | |
| 	low  uint32
 | |
| 	rnge uint32
 | |
| }
 | |
| 
 | |
| func (r *rangeCoder) init(br io.ByteReader) error {
 | |
| 	r.br = br
 | |
| 	r.low = 0
 | |
| 	r.rnge = ^uint32(0)
 | |
| 	for i := 0; i < 4; i++ {
 | |
| 		c, err := r.br.ReadByte()
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		r.code = r.code<<8 | uint32(c)
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (r *rangeCoder) currentCount(scale uint32) uint32 {
 | |
| 	r.rnge /= scale
 | |
| 	return (r.code - r.low) / r.rnge
 | |
| }
 | |
| 
 | |
| func (r *rangeCoder) normalize() error {
 | |
| 	for {
 | |
| 		if r.low^(r.low+r.rnge) >= rangeTop {
 | |
| 			if r.rnge >= rangeBottom {
 | |
| 				return nil
 | |
| 			}
 | |
| 			r.rnge = -r.low & (rangeBottom - 1)
 | |
| 		}
 | |
| 		c, err := r.br.ReadByte()
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		r.code = r.code<<8 | uint32(c)
 | |
| 		r.rnge <<= 8
 | |
| 		r.low <<= 8
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (r *rangeCoder) decode(lowCount, highCount uint32) error {
 | |
| 	r.low += r.rnge * lowCount
 | |
| 	r.rnge *= highCount - lowCount
 | |
| 
 | |
| 	return r.normalize()
 | |
| }
 | |
| 
 | |
| type see2Context struct {
 | |
| 	summ  uint16
 | |
| 	shift byte
 | |
| 	count byte
 | |
| }
 | |
| 
 | |
| func newSee2Context(i uint16) see2Context {
 | |
| 	return see2Context{i << (periodBits - 4), (periodBits - 4), 4}
 | |
| }
 | |
| 
 | |
| func (s *see2Context) mean() uint32 {
 | |
| 	if s == nil {
 | |
| 		return 1
 | |
| 	}
 | |
| 	n := s.summ >> s.shift
 | |
| 	if n == 0 {
 | |
| 		return 1
 | |
| 	}
 | |
| 	s.summ -= n
 | |
| 	return uint32(n)
 | |
| }
 | |
| 
 | |
| func (s *see2Context) update() {
 | |
| 	if s == nil || s.shift >= periodBits {
 | |
| 		return
 | |
| 	}
 | |
| 	s.count--
 | |
| 	if s.count == 0 {
 | |
| 		s.summ += s.summ
 | |
| 		s.count = 3 << s.shift
 | |
| 		s.shift++
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type state struct {
 | |
| 	sym  byte
 | |
| 	freq byte
 | |
| 
 | |
| 	// succ can point to a context or byte in memory.
 | |
| 	// A context pointer is a positive integer. It is an index into the states
 | |
| 	// array that points to the first of two states which the context is
 | |
| 	// marshalled into.
 | |
| 	// A byte pointer is a negative integer. The magnitude represents the position
 | |
| 	// in bytes from the bottom of the memory. As memory is modelled as an array of
 | |
| 	// states, this is used to calculate which state, and where in the state the
 | |
| 	// byte is stored.
 | |
| 	// A zero value represents a nil pointer.
 | |
| 	succ int32
 | |
| }
 | |
| 
 | |
| // uint16 return a uint16 stored in the sym and freq fields of a state
 | |
| func (s state) uint16() uint16 { return uint16(s.sym) | uint16(s.freq)<<8 }
 | |
| 
 | |
| // setUint16 stores a uint16 in the sym and freq fields of a state
 | |
| func (s *state) setUint16(n uint16) { s.sym = byte(n); s.freq = byte(n >> 8) }
 | |
| 
 | |
| // A context is marshalled into a slice of two states.
 | |
| // The first state contains the number of states, and the suffix pointer.
 | |
| // If there is only one state, the second state contains that state.
 | |
| // If there is more than one state, the second state contains the summFreq
 | |
| // and the index to the slice of states.
 | |
| type context struct {
 | |
| 	i int32   // index into the states array for context
 | |
| 	s []state // slice of two states representing context
 | |
| 	a *subAllocator
 | |
| }
 | |
| 
 | |
| // succPtr returns a pointer value for the context to be stored in a state.succ
 | |
| func (c *context) succPtr() int32 { return c.i }
 | |
| 
 | |
| func (c *context) numStates() int { return int(c.s[0].uint16()) }
 | |
| 
 | |
| func (c *context) setNumStates(n int) { c.s[0].setUint16(uint16(n)) }
 | |
| 
 | |
| func (c *context) statesIndex() int32 { return c.s[1].succ }
 | |
| 
 | |
| func (c *context) setStatesIndex(n int32) { c.s[1].succ = n }
 | |
| 
 | |
| func (c *context) suffix() *context { return c.a.succContext(c.s[0].succ) }
 | |
| 
 | |
| func (c *context) setSuffix(sc *context) { c.s[0].succ = sc.i }
 | |
| 
 | |
| func (c *context) summFreq() uint16 { return c.s[1].uint16() }
 | |
| 
 | |
| func (c *context) setSummFreq(f uint16) { c.s[1].setUint16(f) }
 | |
| 
 | |
| func (c *context) notEq(ctx *context) bool { return c.i != ctx.i }
 | |
| 
 | |
| func (c *context) states() []state {
 | |
| 	if ns := int32(c.s[0].uint16()); ns != 1 {
 | |
| 		i := c.s[1].succ
 | |
| 		return c.a.states[i : i+ns]
 | |
| 	}
 | |
| 	return c.s[1:]
 | |
| }
 | |
| 
 | |
| // shrinkStates shrinks the state list down to size states
 | |
| func (c *context) shrinkStates(states []state, size int) []state {
 | |
| 	i1 := units2Index[(len(states)+1)>>1]
 | |
| 	i2 := units2Index[(size+1)>>1]
 | |
| 
 | |
| 	if size == 1 {
 | |
| 		// store state in context, and free states block
 | |
| 		n := c.statesIndex()
 | |
| 		c.s[1] = states[0]
 | |
| 		states = c.s[1:]
 | |
| 		c.a.addFreeBlock(n, i1)
 | |
| 	} else if i1 != i2 {
 | |
| 		if n := c.a.removeFreeBlock(i2); n > 0 {
 | |
| 			// allocate new block and copy
 | |
| 			copy(c.a.states[n:], states[:size])
 | |
| 			states = c.a.states[n:]
 | |
| 			// free old block
 | |
| 			c.a.addFreeBlock(c.statesIndex(), i1)
 | |
| 			c.setStatesIndex(n)
 | |
| 		} else {
 | |
| 			// split current block, and free units not needed
 | |
| 			n = c.statesIndex() + index2Units[i2]<<1
 | |
| 			u := index2Units[i1] - index2Units[i2]
 | |
| 			c.a.freeUnits(n, u)
 | |
| 		}
 | |
| 	}
 | |
| 	c.setNumStates(size)
 | |
| 	return states[:size]
 | |
| }
 | |
| 
 | |
| // expandStates expands the states list by one
 | |
| func (c *context) expandStates() []state {
 | |
| 	states := c.states()
 | |
| 	ns := len(states)
 | |
| 	if ns == 1 {
 | |
| 		s := states[0]
 | |
| 		n := c.a.allocUnits(1)
 | |
| 		if n == 0 {
 | |
| 			return nil
 | |
| 		}
 | |
| 		c.setStatesIndex(n)
 | |
| 		states = c.a.states[n:]
 | |
| 		states[0] = s
 | |
| 	} else if ns&0x1 == 0 {
 | |
| 		u := ns >> 1
 | |
| 		i1 := units2Index[u]
 | |
| 		i2 := units2Index[u+1]
 | |
| 		if i1 != i2 {
 | |
| 			n := c.a.allocUnits(i2)
 | |
| 			if n == 0 {
 | |
| 				return nil
 | |
| 			}
 | |
| 			copy(c.a.states[n:], states)
 | |
| 			c.a.addFreeBlock(c.statesIndex(), i1)
 | |
| 			c.setStatesIndex(n)
 | |
| 			states = c.a.states[n:]
 | |
| 		}
 | |
| 	}
 | |
| 	c.setNumStates(ns + 1)
 | |
| 	return states[:ns+1]
 | |
| }
 | |
| 
 | |
| type subAllocator struct {
 | |
| 	// memory for allocation is split into two heaps
 | |
| 
 | |
| 	heap1MaxBytes int32 // maximum bytes available in heap1
 | |
| 	heap1Lo       int32 // heap1 bottom in number of bytes
 | |
| 	heap1Hi       int32 // heap1 top in number of bytes
 | |
| 	heap2Lo       int32 // heap2 bottom index in states
 | |
| 	heap2Hi       int32 // heap2 top index in states
 | |
| 	glueCount     int
 | |
| 
 | |
| 	// Each freeList entry contains an index into states for the beginning
 | |
| 	// of a free block. The first state in that block may contain an index
 | |
| 	// to another free block and so on. The size of the free block in units
 | |
| 	// (2 states) for that freeList index can be determined from the
 | |
| 	// index2Units array.
 | |
| 	freeList [nIndexes]int32
 | |
| 
 | |
| 	// Instead of bytes, memory is represented by a slice of states.
 | |
| 	// context's are marshalled to and from a pair of states.
 | |
| 	// multiple bytes are stored in a state.
 | |
| 	states []state
 | |
| }
 | |
| 
 | |
| func (a *subAllocator) init(maxMB int) {
 | |
| 	bytes := int32(maxMB) << 20
 | |
| 	heap2Units := bytes / 8 / unitSize * 7
 | |
| 	a.heap1MaxBytes = bytes - heap2Units*unitSize
 | |
| 	// Add one for the case when bytes are not a multiple of unitSize
 | |
| 	heap1Units := a.heap1MaxBytes/unitSize + 1
 | |
| 	// Calculate total size in state's. Add 1 unit so we can reserve the first unit.
 | |
| 	// This will allow us to use the zero index as a nil pointer.
 | |
| 	n := int(1+heap1Units+heap2Units) * 2
 | |
| 	if cap(a.states) > n {
 | |
| 		a.states = a.states[:n]
 | |
| 	} else {
 | |
| 		a.states = make([]state, n)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (a *subAllocator) restart() {
 | |
| 	// Pad heap1 start by 1 unit and enough bytes so that there is no
 | |
| 	// gap between heap1 end and heap2 start.
 | |
| 	a.heap1Lo = unitSize + (unitSize - a.heap1MaxBytes%unitSize)
 | |
| 	a.heap1Hi = unitSize + (a.heap1MaxBytes/unitSize+1)*unitSize
 | |
| 	a.heap2Lo = a.heap1Hi / unitSize * 2
 | |
| 	a.heap2Hi = int32(len(a.states))
 | |
| 	a.glueCount = 0
 | |
| 	for i := range a.freeList {
 | |
| 		a.freeList[i] = 0
 | |
| 	}
 | |
| 	for i := range a.states {
 | |
| 		a.states[i] = state{}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // pushByte puts a byte on the heap and returns a state.succ index that
 | |
| // can be used to retrieve it.
 | |
| func (a *subAllocator) pushByte(c byte) int32 {
 | |
| 	si := a.heap1Lo / 6 // state index
 | |
| 	oi := a.heap1Lo % 6 // byte position in state
 | |
| 	switch oi {
 | |
| 	case 0:
 | |
| 		a.states[si].sym = c
 | |
| 	case 1:
 | |
| 		a.states[si].freq = c
 | |
| 	default:
 | |
| 		n := (uint(oi) - 2) * 8
 | |
| 		mask := ^(uint32(0xFF) << n)
 | |
| 		succ := uint32(a.states[si].succ) & mask
 | |
| 		succ |= uint32(c) << n
 | |
| 		a.states[si].succ = int32(succ)
 | |
| 	}
 | |
| 	a.heap1Lo++
 | |
| 	if a.heap1Lo >= a.heap1Hi {
 | |
| 		return 0
 | |
| 	}
 | |
| 	return -a.heap1Lo
 | |
| }
 | |
| 
 | |
| // popByte reverses the previous pushByte
 | |
| func (a *subAllocator) popByte() { a.heap1Lo-- }
 | |
| 
 | |
| // succByte returns a byte from the heap given a state.succ index
 | |
| func (a *subAllocator) succByte(i int32) byte {
 | |
| 	i = -i
 | |
| 	si := i / 6
 | |
| 	oi := i % 6
 | |
| 	switch oi {
 | |
| 	case 0:
 | |
| 		return a.states[si].sym
 | |
| 	case 1:
 | |
| 		return a.states[si].freq
 | |
| 	default:
 | |
| 		n := (uint(oi) - 2) * 8
 | |
| 		succ := uint32(a.states[si].succ) >> n
 | |
| 		return byte(succ & 0xff)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // succContext returns a context given a state.succ index
 | |
| func (a *subAllocator) succContext(i int32) *context {
 | |
| 	if i <= 0 {
 | |
| 		return nil
 | |
| 	}
 | |
| 	return &context{i: i, s: a.states[i : i+2 : i+2], a: a}
 | |
| }
 | |
| 
 | |
| // succIsNil returns whether a state.succ points to nothing
 | |
| func (a *subAllocator) succIsNil(i int32) bool { return i == 0 }
 | |
| 
 | |
| // nextByteAddr takes a state.succ value representing a pointer
 | |
| // to a byte, and returns the next bytes address
 | |
| func (a *subAllocator) nextByteAddr(n int32) int32 { return n - 1 }
 | |
| 
 | |
| func (a *subAllocator) removeFreeBlock(i byte) int32 {
 | |
| 	n := a.freeList[i]
 | |
| 	if n != 0 {
 | |
| 		a.freeList[i] = a.states[n].succ
 | |
| 		a.states[n] = state{}
 | |
| 	}
 | |
| 	return n
 | |
| }
 | |
| 
 | |
| func (a *subAllocator) addFreeBlock(n int32, i byte) {
 | |
| 	a.states[n].succ = a.freeList[i]
 | |
| 	a.freeList[i] = n
 | |
| }
 | |
| 
 | |
| func (a *subAllocator) freeUnits(n, u int32) {
 | |
| 	i := units2Index[u]
 | |
| 	if u != index2Units[i] {
 | |
| 		i--
 | |
| 		a.addFreeBlock(n, i)
 | |
| 		u -= index2Units[i]
 | |
| 		n += index2Units[i] << 1
 | |
| 		i = units2Index[u]
 | |
| 	}
 | |
| 	a.addFreeBlock(n, i)
 | |
| }
 | |
| 
 | |
| func (a *subAllocator) glueFreeBlocks() {
 | |
| 	var freeIndex int32
 | |
| 
 | |
| 	for i, n := range a.freeList {
 | |
| 		s := state{succ: freeMark}
 | |
| 		s.setUint16(uint16(index2Units[i]))
 | |
| 		for n != 0 {
 | |
| 			states := a.states[n:]
 | |
| 			states[1].succ = freeIndex
 | |
| 			freeIndex = n
 | |
| 			n = states[0].succ
 | |
| 			states[0] = s
 | |
| 		}
 | |
| 		a.freeList[i] = 0
 | |
| 	}
 | |
| 
 | |
| 	for i := freeIndex; i != 0; i = a.states[i+1].succ {
 | |
| 		if a.states[i].succ != freeMark {
 | |
| 			continue
 | |
| 		}
 | |
| 		u := int32(a.states[i].uint16())
 | |
| 		states := a.states[i+u<<1:]
 | |
| 		for len(states) > 0 && states[0].succ == freeMark {
 | |
| 			u += int32(states[0].uint16())
 | |
| 			if u > maxUint16 {
 | |
| 				break
 | |
| 			}
 | |
| 			states[0].succ = 0
 | |
| 			a.states[i].setUint16(uint16(u))
 | |
| 			states = a.states[i+u<<1:]
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	for n := freeIndex; n != 0; n = a.states[n+1].succ {
 | |
| 		if a.states[n].succ != freeMark {
 | |
| 			continue
 | |
| 		}
 | |
| 		a.states[n].succ = 0
 | |
| 		u := int32(a.states[n].uint16())
 | |
| 		m := n
 | |
| 		for u > 128 {
 | |
| 			a.addFreeBlock(m, nIndexes-1)
 | |
| 			u -= 128
 | |
| 			m += 256
 | |
| 		}
 | |
| 		a.freeUnits(m, u)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (a *subAllocator) allocUnitsRare(index byte) int32 {
 | |
| 	if a.glueCount == 0 {
 | |
| 		a.glueCount = 255
 | |
| 		a.glueFreeBlocks()
 | |
| 		if n := a.removeFreeBlock(index); n > 0 {
 | |
| 			return n
 | |
| 		}
 | |
| 	}
 | |
| 	// try to find a larger free block and split it
 | |
| 	for i := index + 1; i < nIndexes; i++ {
 | |
| 		if n := a.removeFreeBlock(i); n > 0 {
 | |
| 			u := index2Units[i] - index2Units[index]
 | |
| 			a.freeUnits(n+index2Units[index]<<1, u)
 | |
| 			return n
 | |
| 		}
 | |
| 	}
 | |
| 	a.glueCount--
 | |
| 
 | |
| 	// try to allocate units from the top of heap1
 | |
| 	n := a.heap1Hi - index2Units[index]*unitSize
 | |
| 	if n > a.heap1Lo {
 | |
| 		a.heap1Hi = n
 | |
| 		return a.heap1Hi / unitSize * 2
 | |
| 	}
 | |
| 	return 0
 | |
| }
 | |
| 
 | |
| func (a *subAllocator) allocUnits(i byte) int32 {
 | |
| 	// try to allocate a free block
 | |
| 	if n := a.removeFreeBlock(i); n > 0 {
 | |
| 		return n
 | |
| 	}
 | |
| 	// try to allocate from the bottom of heap2
 | |
| 	n := index2Units[i] << 1
 | |
| 	if a.heap2Lo+n <= a.heap2Hi {
 | |
| 		lo := a.heap2Lo
 | |
| 		a.heap2Lo += n
 | |
| 		return lo
 | |
| 	}
 | |
| 	return a.allocUnitsRare(i)
 | |
| }
 | |
| 
 | |
| func (a *subAllocator) newContext(s state, suffix *context) *context {
 | |
| 	var n int32
 | |
| 	if a.heap2Lo < a.heap2Hi {
 | |
| 		// allocate from top of heap2
 | |
| 		a.heap2Hi -= 2
 | |
| 		n = a.heap2Hi
 | |
| 	} else if n = a.removeFreeBlock(1); n == 0 {
 | |
| 		if n = a.allocUnitsRare(1); n == 0 {
 | |
| 			return nil
 | |
| 		}
 | |
| 	}
 | |
| 	c := &context{i: n, s: a.states[n : n+2 : n+2], a: a}
 | |
| 	c.s[0] = state{}
 | |
| 	c.setNumStates(1)
 | |
| 	c.s[1] = s
 | |
| 	if suffix != nil {
 | |
| 		c.setSuffix(suffix)
 | |
| 	}
 | |
| 	return c
 | |
| }
 | |
| 
 | |
| func (a *subAllocator) newContextSize(ns int) *context {
 | |
| 	c := a.newContext(state{}, nil)
 | |
| 	c.setNumStates(ns)
 | |
| 	i := units2Index[(ns+1)>>1]
 | |
| 	n := a.allocUnits(i)
 | |
| 	c.setStatesIndex(n)
 | |
| 	return c
 | |
| }
 | |
| 
 | |
| type model struct {
 | |
| 	maxOrder    int
 | |
| 	orderFall   int
 | |
| 	initRL      int
 | |
| 	runLength   int
 | |
| 	prevSuccess byte
 | |
| 	escCount    byte
 | |
| 	prevSym     byte
 | |
| 	initEsc     byte
 | |
| 	minC        *context
 | |
| 	maxC        *context
 | |
| 	rc          rangeCoder
 | |
| 	a           subAllocator
 | |
| 	charMask    [256]byte
 | |
| 	binSumm     [128][64]uint16
 | |
| 	see2Cont    [25][16]see2Context
 | |
| }
 | |
| 
 | |
| func (m *model) restart() {
 | |
| 	for i := range m.charMask {
 | |
| 		m.charMask[i] = 0
 | |
| 	}
 | |
| 	m.escCount = 1
 | |
| 
 | |
| 	if m.maxOrder < 12 {
 | |
| 		m.initRL = -m.maxOrder - 1
 | |
| 	} else {
 | |
| 		m.initRL = -12 - 1
 | |
| 	}
 | |
| 	m.orderFall = m.maxOrder
 | |
| 	m.runLength = m.initRL
 | |
| 	m.prevSuccess = 0
 | |
| 
 | |
| 	m.a.restart()
 | |
| 
 | |
| 	c := m.a.newContextSize(256)
 | |
| 	c.setSummFreq(257)
 | |
| 	states := c.states()
 | |
| 	for i := range states {
 | |
| 		states[i] = state{sym: byte(i), freq: 1}
 | |
| 	}
 | |
| 	m.minC = c
 | |
| 	m.maxC = c
 | |
| 	m.prevSym = 0
 | |
| 
 | |
| 	for i := range m.binSumm {
 | |
| 		for j, esc := range initBinEsc {
 | |
| 			n := binScale - esc/(uint16(i)+2)
 | |
| 			for k := j; k < len(m.binSumm[i]); k += len(initBinEsc) {
 | |
| 				m.binSumm[i][k] = n
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	for i := range m.see2Cont {
 | |
| 		see := newSee2Context(5*uint16(i) + 10)
 | |
| 		for j := range m.see2Cont[i] {
 | |
| 			m.see2Cont[i][j] = see
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (m *model) init(br io.ByteReader, reset bool, maxOrder, maxMB int) error {
 | |
| 	err := m.rc.init(br)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	if !reset {
 | |
| 		if m.minC == nil {
 | |
| 			return errCorruptPPM
 | |
| 		}
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	m.a.init(maxMB)
 | |
| 
 | |
| 	if maxOrder == 1 {
 | |
| 		return errCorruptPPM
 | |
| 	}
 | |
| 	m.maxOrder = maxOrder
 | |
| 	m.restart()
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (m *model) rescale(s *state) *state {
 | |
| 	if s.freq <= maxFreq {
 | |
| 		return s
 | |
| 	}
 | |
| 	c := m.minC
 | |
| 
 | |
| 	var summFreq uint16
 | |
| 
 | |
| 	s.freq += 4
 | |
| 	states := c.states()
 | |
| 	escFreq := c.summFreq() + 4
 | |
| 
 | |
| 	for i := range states {
 | |
| 		f := states[i].freq
 | |
| 		escFreq -= uint16(f)
 | |
| 		if m.orderFall != 0 {
 | |
| 			f++
 | |
| 		}
 | |
| 		f >>= 1
 | |
| 		summFreq += uint16(f)
 | |
| 		states[i].freq = f
 | |
| 
 | |
| 		if i == 0 || f <= states[i-1].freq {
 | |
| 			continue
 | |
| 		}
 | |
| 		j := i - 1
 | |
| 		for j > 0 && f > states[j-1].freq {
 | |
| 			j--
 | |
| 		}
 | |
| 		t := states[i]
 | |
| 		copy(states[j+1:i+1], states[j:i])
 | |
| 		states[j] = t
 | |
| 	}
 | |
| 
 | |
| 	i := len(states) - 1
 | |
| 	for states[i].freq == 0 {
 | |
| 		i--
 | |
| 		escFreq++
 | |
| 	}
 | |
| 	if i != len(states)-1 {
 | |
| 		states = c.shrinkStates(states, i+1)
 | |
| 	}
 | |
| 	s = &states[0]
 | |
| 	if i == 0 {
 | |
| 		for {
 | |
| 			s.freq -= s.freq >> 1
 | |
| 			escFreq >>= 1
 | |
| 			if escFreq <= 1 {
 | |
| 				return s
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	summFreq += escFreq - (escFreq >> 1)
 | |
| 	c.setSummFreq(summFreq)
 | |
| 	return s
 | |
| }
 | |
| 
 | |
| func (m *model) decodeBinSymbol() (*state, error) {
 | |
| 	c := m.minC
 | |
| 	s := &c.states()[0]
 | |
| 
 | |
| 	ns := c.suffix().numStates()
 | |
| 	i := m.prevSuccess + ns2BSIndex[ns-1] + byte(m.runLength>>26)&0x20
 | |
| 	if m.prevSym >= 64 {
 | |
| 		i += 8
 | |
| 	}
 | |
| 	if s.sym >= 64 {
 | |
| 		i += 2 * 8
 | |
| 	}
 | |
| 	bs := &m.binSumm[s.freq-1][i]
 | |
| 	mean := (*bs + 1<<(periodBits-2)) >> periodBits
 | |
| 
 | |
| 	if m.rc.currentCount(binScale) < uint32(*bs) {
 | |
| 		err := m.rc.decode(0, uint32(*bs))
 | |
| 		if s.freq < 128 {
 | |
| 			s.freq++
 | |
| 		}
 | |
| 		*bs += 1<<intBits - mean
 | |
| 		m.prevSuccess = 1
 | |
| 		m.runLength++
 | |
| 		return s, err
 | |
| 	}
 | |
| 	err := m.rc.decode(uint32(*bs), binScale)
 | |
| 	*bs -= mean
 | |
| 	m.initEsc = expEscape[*bs>>10]
 | |
| 	m.charMask[s.sym] = m.escCount
 | |
| 	m.prevSuccess = 0
 | |
| 	return nil, err
 | |
| }
 | |
| 
 | |
| func (m *model) decodeSymbol1() (*state, error) {
 | |
| 	c := m.minC
 | |
| 	states := c.states()
 | |
| 	scale := uint32(c.summFreq())
 | |
| 	// protect against divide by zero
 | |
| 	// TODO: look at why this happens, may be problem elsewhere
 | |
| 	if scale == 0 {
 | |
| 		return nil, errCorruptPPM
 | |
| 	}
 | |
| 	count := m.rc.currentCount(scale)
 | |
| 	m.prevSuccess = 0
 | |
| 
 | |
| 	var n uint32
 | |
| 	for i := range states {
 | |
| 		s := &states[i]
 | |
| 		n += uint32(s.freq)
 | |
| 		if n <= count {
 | |
| 			continue
 | |
| 		}
 | |
| 		err := m.rc.decode(n-uint32(s.freq), n)
 | |
| 		s.freq += 4
 | |
| 		c.setSummFreq(uint16(scale + 4))
 | |
| 		if i == 0 {
 | |
| 			if 2*n > scale {
 | |
| 				m.prevSuccess = 1
 | |
| 				m.runLength++
 | |
| 			}
 | |
| 		} else {
 | |
| 			if s.freq <= states[i-1].freq {
 | |
| 				return s, err
 | |
| 			}
 | |
| 			states[i-1], states[i] = states[i], states[i-1]
 | |
| 			s = &states[i-1]
 | |
| 		}
 | |
| 		return m.rescale(s), err
 | |
| 	}
 | |
| 
 | |
| 	for _, s := range states {
 | |
| 		m.charMask[s.sym] = m.escCount
 | |
| 	}
 | |
| 	return nil, m.rc.decode(n, scale)
 | |
| }
 | |
| 
 | |
| func (m *model) makeEscFreq(c *context, numMasked int) *see2Context {
 | |
| 	ns := c.numStates()
 | |
| 	if ns == 256 {
 | |
| 		return nil
 | |
| 	}
 | |
| 	diff := ns - numMasked
 | |
| 
 | |
| 	var i int
 | |
| 	if m.prevSym >= 64 {
 | |
| 		i = 8
 | |
| 	}
 | |
| 	if diff < c.suffix().numStates()-ns {
 | |
| 		i++
 | |
| 	}
 | |
| 	if int(c.summFreq()) < 11*ns {
 | |
| 		i += 2
 | |
| 	}
 | |
| 	if numMasked > diff {
 | |
| 		i += 4
 | |
| 	}
 | |
| 	return &m.see2Cont[ns2Index[diff-1]][i]
 | |
| }
 | |
| 
 | |
| func (m *model) decodeSymbol2(numMasked int) (*state, error) {
 | |
| 	c := m.minC
 | |
| 
 | |
| 	see := m.makeEscFreq(c, numMasked)
 | |
| 	scale := see.mean()
 | |
| 
 | |
| 	var i int
 | |
| 	var hi uint32
 | |
| 	states := c.states()
 | |
| 	sl := make([]*state, len(states)-numMasked)
 | |
| 	for j := range sl {
 | |
| 		for m.charMask[states[i].sym] == m.escCount {
 | |
| 			i++
 | |
| 		}
 | |
| 		hi += uint32(states[i].freq)
 | |
| 		sl[j] = &states[i]
 | |
| 		i++
 | |
| 	}
 | |
| 
 | |
| 	scale += hi
 | |
| 	count := m.rc.currentCount(scale)
 | |
| 
 | |
| 	if count >= scale {
 | |
| 		return nil, errCorruptPPM
 | |
| 	}
 | |
| 	if count >= hi {
 | |
| 		err := m.rc.decode(hi, scale)
 | |
| 		if see != nil {
 | |
| 			see.summ += uint16(scale)
 | |
| 		}
 | |
| 		for _, s := range sl {
 | |
| 			m.charMask[s.sym] = m.escCount
 | |
| 		}
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	hi = uint32(sl[0].freq)
 | |
| 	for hi <= count {
 | |
| 		sl = sl[1:]
 | |
| 		hi += uint32(sl[0].freq)
 | |
| 	}
 | |
| 	s := sl[0]
 | |
| 
 | |
| 	err := m.rc.decode(hi-uint32(s.freq), hi)
 | |
| 
 | |
| 	see.update()
 | |
| 
 | |
| 	m.escCount++
 | |
| 	m.runLength = m.initRL
 | |
| 
 | |
| 	s.freq += 4
 | |
| 	c.setSummFreq(c.summFreq() + 4)
 | |
| 	return m.rescale(s), err
 | |
| }
 | |
| 
 | |
| func (c *context) findState(sym byte) *state {
 | |
| 	var i int
 | |
| 	states := c.states()
 | |
| 	for i = range states {
 | |
| 		if states[i].sym == sym {
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 	return &states[i]
 | |
| }
 | |
| 
 | |
| func (m *model) createSuccessors(s, ss *state) *context {
 | |
| 	var sl []*state
 | |
| 
 | |
| 	if m.orderFall != 0 {
 | |
| 		sl = append(sl, s)
 | |
| 	}
 | |
| 
 | |
| 	c := m.minC
 | |
| 	for suff := c.suffix(); suff != nil; suff = c.suffix() {
 | |
| 		c = suff
 | |
| 
 | |
| 		if ss == nil {
 | |
| 			ss = c.findState(s.sym)
 | |
| 		}
 | |
| 		if ss.succ != s.succ {
 | |
| 			c = m.a.succContext(ss.succ)
 | |
| 			break
 | |
| 		}
 | |
| 		sl = append(sl, ss)
 | |
| 		ss = nil
 | |
| 	}
 | |
| 
 | |
| 	if len(sl) == 0 {
 | |
| 		return c
 | |
| 	}
 | |
| 
 | |
| 	var up state
 | |
| 	up.sym = m.a.succByte(s.succ)
 | |
| 	up.succ = m.a.nextByteAddr(s.succ)
 | |
| 
 | |
| 	states := c.states()
 | |
| 	if len(states) > 1 {
 | |
| 		s = c.findState(up.sym)
 | |
| 
 | |
| 		cf := uint16(s.freq) - 1
 | |
| 		s0 := c.summFreq() - uint16(len(states)) - cf
 | |
| 
 | |
| 		if 2*cf <= s0 {
 | |
| 			if 5*cf > s0 {
 | |
| 				up.freq = 2
 | |
| 			} else {
 | |
| 				up.freq = 1
 | |
| 			}
 | |
| 		} else {
 | |
| 			up.freq = byte(1 + (2*cf+3*s0-1)/(2*s0))
 | |
| 		}
 | |
| 	} else {
 | |
| 		up.freq = states[0].freq
 | |
| 	}
 | |
| 
 | |
| 	for i := len(sl) - 1; i >= 0; i-- {
 | |
| 		c = m.a.newContext(up, c)
 | |
| 		if c == nil {
 | |
| 			return nil
 | |
| 		}
 | |
| 		sl[i].succ = c.succPtr()
 | |
| 	}
 | |
| 	return c
 | |
| }
 | |
| 
 | |
| func (m *model) update(s *state) {
 | |
| 	if m.orderFall == 0 {
 | |
| 		if c := m.a.succContext(s.succ); c != nil {
 | |
| 			m.minC = c
 | |
| 			m.maxC = c
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if m.escCount == 0 {
 | |
| 		m.escCount = 1
 | |
| 		for i := range m.charMask {
 | |
| 			m.charMask[i] = 0
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	var ss *state // matching minC.suffix state
 | |
| 
 | |
| 	if s.freq < maxFreq/4 && m.minC.suffix() != nil {
 | |
| 		c := m.minC.suffix()
 | |
| 		states := c.states()
 | |
| 
 | |
| 		var i int
 | |
| 		if len(states) > 1 {
 | |
| 			for states[i].sym != s.sym {
 | |
| 				i++
 | |
| 			}
 | |
| 			if i > 0 && states[i].freq >= states[i-1].freq {
 | |
| 				states[i-1], states[i] = states[i], states[i-1]
 | |
| 				i--
 | |
| 			}
 | |
| 			if states[i].freq < maxFreq-9 {
 | |
| 				states[i].freq += 2
 | |
| 				c.setSummFreq(c.summFreq() + 2)
 | |
| 			}
 | |
| 		} else if states[0].freq < 32 {
 | |
| 			states[0].freq++
 | |
| 		}
 | |
| 		ss = &states[i] // save later for createSuccessors
 | |
| 	}
 | |
| 
 | |
| 	if m.orderFall == 0 {
 | |
| 		c := m.createSuccessors(s, ss)
 | |
| 		if c == nil {
 | |
| 			m.restart()
 | |
| 		} else {
 | |
| 			m.minC = c
 | |
| 			m.maxC = c
 | |
| 			s.succ = c.succPtr()
 | |
| 		}
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	succ := m.a.pushByte(s.sym)
 | |
| 	if m.a.succIsNil(succ) {
 | |
| 		m.restart()
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	var minC *context
 | |
| 	if m.a.succIsNil(s.succ) {
 | |
| 		s.succ = succ
 | |
| 		minC = m.minC
 | |
| 	} else {
 | |
| 		minC = m.a.succContext(s.succ)
 | |
| 		if minC == nil {
 | |
| 			minC = m.createSuccessors(s, ss)
 | |
| 			if minC == nil {
 | |
| 				m.restart()
 | |
| 				return
 | |
| 			}
 | |
| 		}
 | |
| 		m.orderFall--
 | |
| 		if m.orderFall == 0 {
 | |
| 			succ = minC.succPtr()
 | |
| 			if m.maxC.notEq(m.minC) {
 | |
| 				m.a.popByte()
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	n := m.minC.numStates()
 | |
| 	s0 := int(m.minC.summFreq()) - n - int(s.freq-1)
 | |
| 	for c := m.maxC; c.notEq(m.minC); c = c.suffix() {
 | |
| 		var summFreq uint16
 | |
| 
 | |
| 		states := c.expandStates()
 | |
| 		if states == nil {
 | |
| 			m.restart()
 | |
| 			return
 | |
| 		}
 | |
| 		if ns := len(states) - 1; ns != 1 {
 | |
| 			summFreq = c.summFreq()
 | |
| 			if 4*ns <= n && int(summFreq) <= 8*ns {
 | |
| 				summFreq += 2
 | |
| 			}
 | |
| 			if 2*ns < n {
 | |
| 				summFreq++
 | |
| 			}
 | |
| 		} else {
 | |
| 			p := &states[0]
 | |
| 			if p.freq < maxFreq/4-1 {
 | |
| 				p.freq += p.freq
 | |
| 			} else {
 | |
| 				p.freq = maxFreq - 4
 | |
| 			}
 | |
| 			summFreq = uint16(p.freq) + uint16(m.initEsc)
 | |
| 			if n > 3 {
 | |
| 				summFreq++
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		cf := 2 * int(s.freq) * int(summFreq+6)
 | |
| 		sf := s0 + int(summFreq)
 | |
| 		var freq byte
 | |
| 		if cf >= 6*sf {
 | |
| 			switch {
 | |
| 			case cf >= 15*sf:
 | |
| 				freq = 7
 | |
| 			case cf >= 12*sf:
 | |
| 				freq = 6
 | |
| 			case cf >= 9*sf:
 | |
| 				freq = 5
 | |
| 			default:
 | |
| 				freq = 4
 | |
| 			}
 | |
| 			summFreq += uint16(freq)
 | |
| 		} else {
 | |
| 			switch {
 | |
| 			case cf >= 4*sf:
 | |
| 				freq = 3
 | |
| 			case cf > sf:
 | |
| 				freq = 2
 | |
| 			default:
 | |
| 				freq = 1
 | |
| 			}
 | |
| 			summFreq += 3
 | |
| 		}
 | |
| 		states[len(states)-1] = state{sym: s.sym, freq: freq, succ: succ}
 | |
| 		c.setSummFreq(summFreq)
 | |
| 	}
 | |
| 	m.minC = minC
 | |
| 	m.maxC = minC
 | |
| }
 | |
| 
 | |
| func (m *model) ReadByte() (byte, error) {
 | |
| 	if m.minC == nil {
 | |
| 		return 0, errCorruptPPM
 | |
| 	}
 | |
| 	var s *state
 | |
| 	var err error
 | |
| 	if m.minC.numStates() == 1 {
 | |
| 		s, err = m.decodeBinSymbol()
 | |
| 	} else {
 | |
| 		s, err = m.decodeSymbol1()
 | |
| 	}
 | |
| 	for s == nil && err == nil {
 | |
| 		n := m.minC.numStates()
 | |
| 		for m.minC.numStates() == n {
 | |
| 			m.orderFall++
 | |
| 			m.minC = m.minC.suffix()
 | |
| 			if m.minC == nil {
 | |
| 				return 0, errCorruptPPM
 | |
| 			}
 | |
| 		}
 | |
| 		s, err = m.decodeSymbol2(n)
 | |
| 	}
 | |
| 	if err != nil {
 | |
| 		return 0, err
 | |
| 	}
 | |
| 
 | |
| 	// save sym so it doesn't get overwritten by a possible restart()
 | |
| 	sym := s.sym
 | |
| 	m.update(s)
 | |
| 	m.prevSym = sym
 | |
| 	return sym, nil
 | |
| }
 |