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
  7import "errors"
  8
  9// maxPosBits defines the number of bits of the position value that are used to
 10// to compute the posState value. The value is used to select the tree codec
 11// for length encoding and decoding.
 12const maxPosBits = 4
 13
 14// minMatchLen and maxMatchLen give the minimum and maximum values for
 15// encoding and decoding length values. minMatchLen is also used as base
 16// for the encoded length values.
 17const (
 18	minMatchLen = 2
 19	maxMatchLen = minMatchLen + 16 + 256 - 1
 20)
 21
 22// lengthCodec support the encoding of the length value.
 23type lengthCodec struct {
 24	choice [2]prob
 25	low    [1 << maxPosBits]treeCodec
 26	mid    [1 << maxPosBits]treeCodec
 27	high   treeCodec
 28}
 29
 30// deepcopy initializes the lc value as deep copy of the source value.
 31func (lc *lengthCodec) deepcopy(src *lengthCodec) {
 32	if lc == src {
 33		return
 34	}
 35	lc.choice = src.choice
 36	for i := range lc.low {
 37		lc.low[i].deepcopy(&src.low[i])
 38	}
 39	for i := range lc.mid {
 40		lc.mid[i].deepcopy(&src.mid[i])
 41	}
 42	lc.high.deepcopy(&src.high)
 43}
 44
 45// init initializes a new length codec.
 46func (lc *lengthCodec) init() {
 47	for i := range lc.choice {
 48		lc.choice[i] = probInit
 49	}
 50	for i := range lc.low {
 51		lc.low[i] = makeTreeCodec(3)
 52	}
 53	for i := range lc.mid {
 54		lc.mid[i] = makeTreeCodec(3)
 55	}
 56	lc.high = makeTreeCodec(8)
 57}
 58
 59// Encode encodes the length offset. The length offset l can be compute by
 60// subtracting minMatchLen (2) from the actual length.
 61//
 62//	l = length - minMatchLen
 63func (lc *lengthCodec) Encode(e *rangeEncoder, l uint32, posState uint32,
 64) (err error) {
 65	if l > maxMatchLen-minMatchLen {
 66		return errors.New("lengthCodec.Encode: l out of range")
 67	}
 68	if l < 8 {
 69		if err = lc.choice[0].Encode(e, 0); err != nil {
 70			return
 71		}
 72		return lc.low[posState].Encode(e, l)
 73	}
 74	if err = lc.choice[0].Encode(e, 1); err != nil {
 75		return
 76	}
 77	if l < 16 {
 78		if err = lc.choice[1].Encode(e, 0); err != nil {
 79			return
 80		}
 81		return lc.mid[posState].Encode(e, l-8)
 82	}
 83	if err = lc.choice[1].Encode(e, 1); err != nil {
 84		return
 85	}
 86	if err = lc.high.Encode(e, l-16); err != nil {
 87		return
 88	}
 89	return nil
 90}
 91
 92// Decode reads the length offset. Add minMatchLen to compute the actual length
 93// to the length offset l.
 94func (lc *lengthCodec) Decode(d *rangeDecoder, posState uint32,
 95) (l uint32, err error) {
 96	var b uint32
 97	if b, err = lc.choice[0].Decode(d); err != nil {
 98		return
 99	}
100	if b == 0 {
101		l, err = lc.low[posState].Decode(d)
102		return
103	}
104	if b, err = lc.choice[1].Decode(d); err != nil {
105		return
106	}
107	if b == 0 {
108		l, err = lc.mid[posState].Decode(d)
109		l += 8
110		return
111	}
112	l, err = lc.high.Decode(d)
113	l += 16
114	return
115}