1// Copyright 2014-2021 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} 146