summaryrefslogtreecommitdiff
path: root/vendor/github.com/ulikunitz/xz/lzma/state.go
blob: fbe3a3942559086e3380a352400910622c387e68 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Copyright 2014-2019 Ulrich Kunitz. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package lzma

// states defines the overall state count
const states = 12

// State maintains the full state of the operation encoding or decoding
// process.
type state struct {
	rep         [4]uint32
	isMatch     [states << maxPosBits]prob
	isRepG0Long [states << maxPosBits]prob
	isRep       [states]prob
	isRepG0     [states]prob
	isRepG1     [states]prob
	isRepG2     [states]prob
	litCodec    literalCodec
	lenCodec    lengthCodec
	repLenCodec lengthCodec
	distCodec   distCodec
	state       uint32
	posBitMask  uint32
	Properties  Properties
}

// initProbSlice initializes a slice of probabilities.
func initProbSlice(p []prob) {
	for i := range p {
		p[i] = probInit
	}
}

// Reset sets all state information to the original values.
func (s *state) Reset() {
	p := s.Properties
	*s = state{
		Properties: p,
		// dict:       s.dict,
		posBitMask: (uint32(1) << uint(p.PB)) - 1,
	}
	initProbSlice(s.isMatch[:])
	initProbSlice(s.isRep[:])
	initProbSlice(s.isRepG0[:])
	initProbSlice(s.isRepG1[:])
	initProbSlice(s.isRepG2[:])
	initProbSlice(s.isRepG0Long[:])
	s.litCodec.init(p.LC, p.LP)
	s.lenCodec.init()
	s.repLenCodec.init()
	s.distCodec.init()
}

// newState creates a new state from the give Properties.
func newState(p Properties) *state {
	s := &state{Properties: p}
	s.Reset()
	return s
}

// deepcopy initializes s as a deep copy of the source.
func (s *state) deepcopy(src *state) {
	if s == src {
		return
	}
	s.rep = src.rep
	s.isMatch = src.isMatch
	s.isRepG0Long = src.isRepG0Long
	s.isRep = src.isRep
	s.isRepG0 = src.isRepG0
	s.isRepG1 = src.isRepG1
	s.isRepG2 = src.isRepG2
	s.litCodec.deepcopy(&src.litCodec)
	s.lenCodec.deepcopy(&src.lenCodec)
	s.repLenCodec.deepcopy(&src.repLenCodec)
	s.distCodec.deepcopy(&src.distCodec)
	s.state = src.state
	s.posBitMask = src.posBitMask
	s.Properties = src.Properties
}

// cloneState creates a new clone of the give state.
func cloneState(src *state) *state {
	s := new(state)
	s.deepcopy(src)
	return s
}

// updateStateLiteral updates the state for a literal.
func (s *state) updateStateLiteral() {
	switch {
	case s.state < 4:
		s.state = 0
		return
	case s.state < 10:
		s.state -= 3
		return
	}
	s.state -= 6
}

// updateStateMatch updates the state for a match.
func (s *state) updateStateMatch() {
	if s.state < 7 {
		s.state = 7
	} else {
		s.state = 10
	}
}

// updateStateRep updates the state for a repetition.
func (s *state) updateStateRep() {
	if s.state < 7 {
		s.state = 8
	} else {
		s.state = 11
	}
}

// updateStateShortRep updates the state for a short repetition.
func (s *state) updateStateShortRep() {
	if s.state < 7 {
		s.state = 9
	} else {
		s.state = 11
	}
}

// states computes the states of the operation codec.
func (s *state) states(dictHead int64) (state1, state2, posState uint32) {
	state1 = s.state
	posState = uint32(dictHead) & s.posBitMask
	state2 = (s.state << maxPosBits) | posState
	return
}

// litState computes the literal state.
func (s *state) litState(prev byte, dictHead int64) uint32 {
	lp, lc := uint(s.Properties.LP), uint(s.Properties.LC)
	litState := ((uint32(dictHead) & ((1 << lp) - 1)) << lc) |
		(uint32(prev) >> (8 - lc))
	return litState
}