main
1// Copyright 2014-2022 Ulrich Kunitz. 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
5package lzma
6
7// states defines the overall state count
8const states = 12
9
10// State maintains the full state of the operation encoding or decoding
11// process.
12type state struct {
13 rep [4]uint32
14 isMatch [states << maxPosBits]prob
15 isRepG0Long [states << maxPosBits]prob
16 isRep [states]prob
17 isRepG0 [states]prob
18 isRepG1 [states]prob
19 isRepG2 [states]prob
20 litCodec literalCodec
21 lenCodec lengthCodec
22 repLenCodec lengthCodec
23 distCodec distCodec
24 state uint32
25 posBitMask uint32
26 Properties Properties
27}
28
29// initProbSlice initializes a slice of probabilities.
30func initProbSlice(p []prob) {
31 for i := range p {
32 p[i] = probInit
33 }
34}
35
36// Reset sets all state information to the original values.
37func (s *state) Reset() {
38 p := s.Properties
39 *s = state{
40 Properties: p,
41 // dict: s.dict,
42 posBitMask: (uint32(1) << uint(p.PB)) - 1,
43 }
44 initProbSlice(s.isMatch[:])
45 initProbSlice(s.isRep[:])
46 initProbSlice(s.isRepG0[:])
47 initProbSlice(s.isRepG1[:])
48 initProbSlice(s.isRepG2[:])
49 initProbSlice(s.isRepG0Long[:])
50 s.litCodec.init(p.LC, p.LP)
51 s.lenCodec.init()
52 s.repLenCodec.init()
53 s.distCodec.init()
54}
55
56// newState creates a new state from the give Properties.
57func newState(p Properties) *state {
58 s := &state{Properties: p}
59 s.Reset()
60 return s
61}
62
63// deepcopy initializes s as a deep copy of the source.
64func (s *state) deepcopy(src *state) {
65 if s == src {
66 return
67 }
68 s.rep = src.rep
69 s.isMatch = src.isMatch
70 s.isRepG0Long = src.isRepG0Long
71 s.isRep = src.isRep
72 s.isRepG0 = src.isRepG0
73 s.isRepG1 = src.isRepG1
74 s.isRepG2 = src.isRepG2
75 s.litCodec.deepcopy(&src.litCodec)
76 s.lenCodec.deepcopy(&src.lenCodec)
77 s.repLenCodec.deepcopy(&src.repLenCodec)
78 s.distCodec.deepcopy(&src.distCodec)
79 s.state = src.state
80 s.posBitMask = src.posBitMask
81 s.Properties = src.Properties
82}
83
84// cloneState creates a new clone of the give state.
85func cloneState(src *state) *state {
86 s := new(state)
87 s.deepcopy(src)
88 return s
89}
90
91// updateStateLiteral updates the state for a literal.
92func (s *state) updateStateLiteral() {
93 switch {
94 case s.state < 4:
95 s.state = 0
96 return
97 case s.state < 10:
98 s.state -= 3
99 return
100 }
101 s.state -= 6
102}
103
104// updateStateMatch updates the state for a match.
105func (s *state) updateStateMatch() {
106 if s.state < 7 {
107 s.state = 7
108 } else {
109 s.state = 10
110 }
111}
112
113// updateStateRep updates the state for a repetition.
114func (s *state) updateStateRep() {
115 if s.state < 7 {
116 s.state = 8
117 } else {
118 s.state = 11
119 }
120}
121
122// updateStateShortRep updates the state for a short repetition.
123func (s *state) updateStateShortRep() {
124 if s.state < 7 {
125 s.state = 9
126 } else {
127 s.state = 11
128 }
129}
130
131// states computes the states of the operation codec.
132func (s *state) states(dictHead int64) (state1, state2, posState uint32) {
133 state1 = s.state
134 posState = uint32(dictHead) & s.posBitMask
135 state2 = (s.state << maxPosBits) | posState
136 return
137}
138
139// litState computes the literal state.
140func (s *state) litState(prev byte, dictHead int64) uint32 {
141 lp, lc := uint(s.Properties.LP), uint(s.Properties.LC)
142 litState := ((uint32(dictHead) & ((1 << lp) - 1)) << lc) |
143 (uint32(prev) >> (8 - lc))
144 return litState
145}