Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
3.3 KiB
145 lines
3.3 KiB
// Copyright 2014-2021 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 |
|
}
|
|
|