-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlzma_lit_coder.go
128 lines (114 loc) · 3 KB
/
lzma_lit_coder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright (c) 2010, Andrei Vieru. 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
type litSubCoder struct {
coders []uint16
}
func newLitSubCoder() *litSubCoder {
return &litSubCoder{
coders: initBitModels(0x300),
}
}
func (lsc *litSubCoder) decodeNormal(rd *rangeDecoder) byte {
symbol := uint32(1)
for symbol < 0x100 {
i := rd.decodeBit(lsc.coders, symbol)
symbol = symbol<<1 | i
}
return byte(symbol)
}
func (lsc *litSubCoder) decodeWithMatchByte(rd *rangeDecoder, matchByte byte) byte {
uMatchByte := uint32(matchByte)
symbol := uint32(1)
for symbol < 0x100 {
matchBit := (uMatchByte >> 7) & 1
uMatchByte <<= 1
bit := rd.decodeBit(lsc.coders, ((1+matchBit)<<8)+symbol)
symbol = (symbol << 1) | bit
if matchBit != bit {
for symbol < 0x100 {
i := rd.decodeBit(lsc.coders, symbol)
symbol = (symbol << 1) | i
}
break
}
}
return byte(symbol)
}
func (lsc *litSubCoder) encode(re *rangeEncoder, symbol byte) {
uSymbol := uint32(symbol)
context := uint32(1)
for i := uint32(7); int32(i) >= 0; i-- {
bit := (uSymbol >> i) & 1
re.encode(lsc.coders, context, bit)
context = context<<1 | bit
}
}
func (lsc *litSubCoder) encodeMatched(re *rangeEncoder, matchByte, symbol byte) {
uMatchByte := uint32(matchByte)
uSymbol := uint32(symbol)
context := uint32(1)
same := true
for i := uint32(7); int32(i) >= 0; i-- {
bit := (uSymbol >> i) & 1
state := context
if same == true {
matchBit := (uMatchByte >> i) & 1
state += (1 + matchBit) << 8
same = false
if matchBit == bit {
same = true
}
}
re.encode(lsc.coders, state, bit)
context = context<<1 | bit
}
}
func (lsc *litSubCoder) getPrice(matchMode bool, matchByte, symbol byte) uint32 {
uMatchByte := uint32(matchByte)
uSymbol := uint32(symbol)
price := uint32(0)
context := uint32(1)
i := uint32(7)
if matchMode == true {
for ; int32(i) >= 0; i-- {
matchBit := (uMatchByte >> i) & 1
bit := (uSymbol >> i) & 1
price += getPrice(lsc.coders[(1+matchBit)<<8+context], bit)
context = context<<1 | bit
if matchBit != bit {
i--
break
}
}
}
for ; int32(i) >= 0; i-- {
bit := (uSymbol >> i) & 1
price += getPrice(lsc.coders[context], bit)
context = context<<1 | bit
}
return price
}
type litCoder struct {
coders []*litSubCoder
numPrevBits uint32 // literal context bits // lc
// numPosBits uint32 // literal position state bits // lp
posMask uint32
}
func newLitCoder(numPosBits, numPrevBits uint32) *litCoder {
numStates := uint32(1) << (numPrevBits + numPosBits)
lc := &litCoder{
coders: make([]*litSubCoder, numStates),
numPrevBits: numPrevBits,
// numPosBits: numPosBits,
posMask: (1 << numPosBits) - 1,
}
for i := uint32(0); i < numStates; i++ {
lc.coders[i] = newLitSubCoder()
}
return lc
}
func (lc *litCoder) getSubCoder(pos uint32, prevByte byte) *litSubCoder {
return lc.coders[((pos&lc.posMask)<<lc.numPrevBits)+uint32(prevByte>>(8-lc.numPrevBits))]
}