-
Notifications
You must be signed in to change notification settings - Fork 6
/
number_mask.go
222 lines (198 loc) · 6.33 KB
/
number_mask.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
package bytes
import (
"errors"
"fmt"
)
/**
* @Author: imuge
* @Date: 2020/5/21 6:00 下午
*/
var (
NUMBERMASK_NONE = NumberMask{}
NUMBERMASK_TINY = newNumberMask("TINY", 0) // TINY编码
NUMBERMASK_SHORT = newNumberMask("SHORT", 1) // SHORT编码
NUMBERMASK_NORMAL = newNumberMask("NORMAL", 2) // NORMAL编码
NUMBERMASK_LONG = newNumberMask("LONG", 3) // LONG编码
)
func GetNumberMask(name string) NumberMask {
switch name {
case NUMBERMASK_TINY.Name:
return NUMBERMASK_TINY
case NUMBERMASK_SHORT.Name:
return NUMBERMASK_SHORT
case NUMBERMASK_NORMAL.Name:
return NUMBERMASK_NORMAL
case NUMBERMASK_LONG.Name:
return NUMBERMASK_LONG
default:
panic(fmt.Sprintf("unknown number mask name:%s", name))
}
}
// 数值掩码;用于以更少的字节空间输出整数的字节数组
type NumberMask struct {
Name string
// 掩码位的个数
BIT_COUNT byte
// 头部长度的最大值
MAX_HEADER_LENGTH int32
// 最大边界值
MAX_BOUNDARY_SIZE int64
// 此常量对于 TINY、SHORT、NORMAL 有效
BOUNDARY_SIZE_0 int64
BOUNDARY_SIZE_1 int64
BOUNDARY_SIZE_2 int64
BOUNDARY_SIZE_3 int64
BOUNDARY_SIZE_4 int64
BOUNDARY_SIZE_5 int64
BOUNDARY_SIZE_6 int64
BOUNDARY_SIZE_7 int64
boundarySizes []int64
}
func newNumberMask(name string, bitCount byte) NumberMask {
mask := NumberMask{}
mask.Name = name
mask.BIT_COUNT = bitCount
mask.MAX_HEADER_LENGTH = 1 << bitCount
mask.boundarySizes = make([]int64, mask.MAX_HEADER_LENGTH)
for i := 0; i < int(mask.MAX_HEADER_LENGTH); i++ {
mask.boundarySizes[i] = mask.computeBoundarySize(int32(i + 1))
}
mask.MAX_BOUNDARY_SIZE = mask.boundarySizes[mask.MAX_HEADER_LENGTH-1]
if bitCount == 0 {
// TINY;
mask.BOUNDARY_SIZE_0 = mask.boundarySizes[0]
mask.BOUNDARY_SIZE_1 = -1
mask.BOUNDARY_SIZE_2 = -1
mask.BOUNDARY_SIZE_3 = -1
mask.BOUNDARY_SIZE_4 = -1
mask.BOUNDARY_SIZE_5 = -1
mask.BOUNDARY_SIZE_6 = -1
mask.BOUNDARY_SIZE_7 = -1
} else if bitCount == 1 {
// SHORT;
mask.BOUNDARY_SIZE_0 = mask.boundarySizes[0]
mask.BOUNDARY_SIZE_1 = mask.boundarySizes[1]
mask.BOUNDARY_SIZE_2 = -1
mask.BOUNDARY_SIZE_3 = -1
mask.BOUNDARY_SIZE_4 = -1
mask.BOUNDARY_SIZE_5 = -1
mask.BOUNDARY_SIZE_6 = -1
mask.BOUNDARY_SIZE_7 = -1
} else if bitCount == 2 {
// NORMAL;
mask.BOUNDARY_SIZE_0 = mask.boundarySizes[0]
mask.BOUNDARY_SIZE_1 = mask.boundarySizes[1]
mask.BOUNDARY_SIZE_2 = mask.boundarySizes[2]
mask.BOUNDARY_SIZE_3 = mask.boundarySizes[3]
mask.BOUNDARY_SIZE_4 = -1
mask.BOUNDARY_SIZE_5 = -1
mask.BOUNDARY_SIZE_6 = -1
mask.BOUNDARY_SIZE_7 = -1
} else if bitCount == 3 {
// LONG;
mask.BOUNDARY_SIZE_0 = mask.boundarySizes[0]
mask.BOUNDARY_SIZE_1 = mask.boundarySizes[1]
mask.BOUNDARY_SIZE_2 = mask.boundarySizes[2]
mask.BOUNDARY_SIZE_3 = mask.boundarySizes[3]
mask.BOUNDARY_SIZE_4 = mask.boundarySizes[4]
mask.BOUNDARY_SIZE_5 = mask.boundarySizes[5]
mask.BOUNDARY_SIZE_6 = mask.boundarySizes[6]
mask.BOUNDARY_SIZE_7 = mask.boundarySizes[7]
}
return mask
}
func (mask *NumberMask) Equals(mask2 NumberMask) bool {
return mask.Name == mask2.Name && mask.BIT_COUNT == mask2.BIT_COUNT
}
// 在指定的头部长度下能够表示的数据大小的临界值(不含)
// headerLength 值范围必须大于 0 ,且小于等于 MAX_HEADER_LENGTH
func (mask *NumberMask) GetBoundarySize(headerLength int32) int64 {
return mask.boundarySizes[headerLength-1]
}
func (mask *NumberMask) computeBoundarySize(headerLength int32) int64 {
boundarySize := 1 << (int64(headerLength)*8 - int64(mask.BIT_COUNT))
return int64(boundarySize)
}
// 获取能够表示指定的数值的掩码长度,即掩码所需的字节数
// number 要表示的数值;如果值范围超出掩码的有效范围,将引起恐慌
func (mask *NumberMask) GetMaskLength(number int64) int32 {
if number > -1 {
if number < mask.BOUNDARY_SIZE_0 {
return 1
}
if number < mask.BOUNDARY_SIZE_1 {
return 2
}
if number < mask.BOUNDARY_SIZE_2 {
return 3
}
if number < mask.BOUNDARY_SIZE_3 {
return 4
}
if number < mask.BOUNDARY_SIZE_4 {
return 5
}
if number < mask.BOUNDARY_SIZE_5 {
return 6
}
if number < mask.BOUNDARY_SIZE_6 {
return 7
}
if number < mask.BOUNDARY_SIZE_7 {
return 8
}
}
panic(fmt.Sprintf("Number is out of the illegal range! --[number=%d]", number))
}
// 生成指定数值的掩码
// number 要表示的数值;如果值范围超出掩码的有效范围,将引起恐慌
func (mask *NumberMask) GenerateMask(number int64) []byte {
// 计算掩码占用的字节长度;
maskLen := mask.GetMaskLength(number)
maskBytes := make([]byte, maskLen)
mask.writeMask(number, maskLen, maskBytes, 0)
return maskBytes
}
func (mask *NumberMask) writeMask(number int64, maskLen int32, buffer []byte, offset int32) int32 {
// 计算掩码占用的字节长度;
for i := maskLen; i > 0; i-- {
buffer[offset+i-1] = (byte)((number >> (8 * (maskLen - i))) & 0xFF)
}
// 计算头字节的标识位;
indicatorByte := (byte)((maskLen - 1) << (8 - mask.BIT_COUNT))
// 设置标识位;
buffer[offset] = indicatorByte | buffer[offset]
return maskLen
}
func (mask *NumberMask) WriteMask(number int64) []byte {
return mask.GenerateMask(number)
}
// 解析掩码的头字节获得该掩码实例的完整长度
// headByte 掩码的头字节;即掩码的字节序列的首个字节
// 返回掩码实例的完整长度
// 注:在字节流中,对首字节解析获取该值后减 1,可以得到该掩码后续要读取的字节长度
func (mask *NumberMask) ResolveMaskLength(headByte byte) (int32, error) {
len := int32(((headByte & 0xFF) >> (8 - mask.BIT_COUNT)) + 1)
if len < 1 {
return len, errors.New(fmt.Sprintf("Illegal length [%d] was resolved from the head byte of NumberMask!", len))
}
if len > mask.MAX_HEADER_LENGTH {
return len, errors.New(fmt.Sprintf("Illegal length [%d] was resolved from the head byte of NumberMask!", len))
}
return len, nil
}
// 从字节中解析掩码表示的数值
func (mask *NumberMask) ResolveMaskedNumber(markBytes []byte) (int64, error) {
maskLen, err := mask.ResolveMaskLength(markBytes[0])
if err != nil {
return 0, err
}
// 清除首字节的标识位;
numberHead := markBytes[0] & (0xFF >> mask.BIT_COUNT)
// 转换字节大小;
number := int64(numberHead & 0xFF)
for i := int32(1); i < maskLen; i++ {
number = number*256 + int64(markBytes[i]&0xFF)
}
return number, nil
}