-
Notifications
You must be signed in to change notification settings - Fork 0
/
compressor.go
126 lines (116 loc) · 2.47 KB
/
compressor.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
package compressor
import (
"unsafe"
"github.com/NIR3X/varsizedint"
)
const (
MinChunkSize = 3
ChunkSame, ChunkMixed uint64 = 0, 1
)
func GetNextChunkSame(src []uint8, pos uint64, left, right *uint64) bool {
var (
chunkValue int16 = -1
chunkSize uint64 = 0
srcSize = uint64(len(src))
)
for i := pos; i < srcSize; i++ {
var curr = src[i]
if chunkValue == int16(curr) {
chunkSize++
}
if chunkValue != int16(curr) || i == srcSize-1 {
if chunkSize >= MinChunkSize {
if chunkValue == int16(curr) {
*right = i + 1
} else {
*right = i
}
return true
}
chunkValue = int16(curr)
chunkSize = 1
*left = i
}
}
return false
}
func PutChunkMixed(src []uint8, i *uint64, iEnd uint64, dest []uint8, destPos *uint64) {
var (
i_ = *i
destPos_ = *destPos
chunkMixedSize = iEnd - i_
)
if chunkMixedSize > 0 {
destPos_ += uint64(varsizedint.Encode(
dest[destPos_:],
(chunkMixedSize<<1)|ChunkMixed,
))
for j := uint64(0); j < chunkMixedSize; j++ {
dest[destPos_] = src[i_]
i_++
destPos_++
}
*i = i_
*destPos = destPos_
}
}
func Compress(src []uint8, pDest *[]uint8) uint64 {
var (
destPos uint64 = 0
srcSize = uint64(len(src))
dest = make([]uint8, srcSize*2)
)
for i := uint64(0); i < srcSize; i++ {
var left, right uint64 = 0, 0
if GetNextChunkSame(src, i, &left, &right) {
PutChunkMixed(src, &i, left, dest, &destPos)
var chunkSameSize = right - left
destPos += uint64(varsizedint.Encode(
dest[destPos:],
(chunkSameSize<<1)|ChunkSame,
))
dest[destPos] = src[left]
destPos += uint64(unsafe.Sizeof(src[left]))
i += chunkSameSize - 1
} else {
PutChunkMixed(src, &i, srcSize, dest, &destPos)
*pDest = dest
return destPos
}
}
*pDest = dest
return destPos
}
func Decompress(src, dest []uint8) uint64 {
var (
destPos uint64 = 0
srcSize = uint64(len(src))
)
for i := uint64(0); i < srcSize; {
var (
chunkSize = varsizedint.Decode(src[i:])
chunkType = chunkSize & 1
)
var chunkSizeSize = uint64(varsizedint.ParseSize(src[i:]))
i += chunkSizeSize
chunkSize >>= 1
switch chunkType {
case ChunkSame:
{
var chunkSameValue = src[i]
for j := uint64(0); j < chunkSize; j++ {
dest[destPos] = chunkSameValue
destPos++
}
i++
}
case ChunkMixed:
for j := uint64(0); j < chunkSize; j++ {
dest[destPos] = src[i]
destPos++
i++
}
}
}
return destPos
}