main
Raw Download raw file
  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}