1// Copyright 2014-2019 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// initState initializes the state. 57func initState(s *state, p Properties) { 58 *s = state{Properties: p} 59 s.Reset() 60} 61 62// newState creates a new state from the give Properties. 63func newState(p Properties) *state { 64 s := &state{Properties: p} 65 s.Reset() 66 return s 67} 68 69// deepcopy initializes s as a deep copy of the source. 70func (s *state) deepcopy(src *state) { 71 if s == src { 72 return 73 } 74 s.rep = src.rep 75 s.isMatch = src.isMatch 76 s.isRepG0Long = src.isRepG0Long 77 s.isRep = src.isRep 78 s.isRepG0 = src.isRepG0 79 s.isRepG1 = src.isRepG1 80 s.isRepG2 = src.isRepG2 81 s.litCodec.deepcopy(&src.litCodec) 82 s.lenCodec.deepcopy(&src.lenCodec) 83 s.repLenCodec.deepcopy(&src.repLenCodec) 84 s.distCodec.deepcopy(&src.distCodec) 85 s.state = src.state 86 s.posBitMask = src.posBitMask 87 s.Properties = src.Properties 88} 89 90// cloneState creates a new clone of the give state. 91func cloneState(src *state) *state { 92 s := new(state) 93 s.deepcopy(src) 94 return s 95} 96 97// updateStateLiteral updates the state for a literal. 98func (s *state) updateStateLiteral() { 99 switch { 100 case s.state < 4: 101 s.state = 0 102 return 103 case s.state < 10: 104 s.state -= 3 105 return 106 } 107 s.state -= 6 108} 109 110// updateStateMatch updates the state for a match. 111func (s *state) updateStateMatch() { 112 if s.state < 7 { 113 s.state = 7 114 } else { 115 s.state = 10 116 } 117} 118 119// updateStateRep updates the state for a repetition. 120func (s *state) updateStateRep() { 121 if s.state < 7 { 122 s.state = 8 123 } else { 124 s.state = 11 125 } 126} 127 128// updateStateShortRep updates the state for a short repetition. 129func (s *state) updateStateShortRep() { 130 if s.state < 7 { 131 s.state = 9 132 } else { 133 s.state = 11 134 } 135} 136 137// states computes the states of the operation codec. 138func (s *state) states(dictHead int64) (state1, state2, posState uint32) { 139 state1 = s.state 140 posState = uint32(dictHead) & s.posBitMask 141 state2 = (s.state << maxPosBits) | posState 142 return 143} 144 145// litState computes the literal state. 146func (s *state) litState(prev byte, dictHead int64) uint32 { 147 lp, lc := uint(s.Properties.LP), uint(s.Properties.LC) 148 litState := ((uint32(dictHead) & ((1 << lp) - 1)) << lc) | 149 (uint32(prev) >> (8 - lc)) 150 return litState 151} 152