forked from fraugster/parquet-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
packed_array.go
101 lines (85 loc) · 2.01 KB
/
packed_array.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
package goparquet
import (
"errors"
"fmt"
)
// packedArray is a bitmap encoded array mainly for repetition and definition
// levels, which normally have low values (~<10), a []uint16 array is not the
// most memory efficient structure due to the large number of values. Memory
// storage requirements for the packed array are ~1/8th compared to
// []uint16 array.
type packedArray struct {
count int
bw int
data []byte
buf [8]int32
bufPos int
writer pack8int32Func
reader unpack8int32Func
}
// This function is only for testing, as it flushes first, so be careful!
func (pa *packedArray) toArray() []int32 {
ret := make([]int32, pa.count)
for i := range ret {
ret[i], _ = pa.at(i)
}
return ret
}
func (pa *packedArray) reset(bw int) {
if bw < 0 || bw > 32 {
panic("invalid bit width")
}
pa.bw = bw
pa.count = 0
pa.bufPos = 0
pa.data = pa.data[:0]
pa.writer = pack8Int32FuncByWidth[bw]
pa.reader = unpack8Int32FuncByWidth[bw]
}
func (pa *packedArray) flush() {
for i := pa.bufPos; i < 8; i++ {
pa.buf[i] = 0
}
pa.data = append(pa.data, pa.writer(pa.buf)...)
pa.bufPos = 0
}
func (pa *packedArray) appendSingle(v int32) {
if pa.bufPos == 8 {
pa.flush()
}
pa.buf[pa.bufPos] = v
pa.bufPos++
pa.count++
}
func (pa *packedArray) at(pos int) (int32, error) {
if pos < 0 || pos >= pa.count {
return 0, errors.New("out of range")
}
if pa.bw == 0 {
return 0, nil
}
block := (pos / 8) * pa.bw
idx := pos % 8
if block >= len(pa.data) {
return pa.buf[idx], nil
}
buf := pa.reader(pa.data[block : block+pa.bw])
return buf[idx], nil
}
func (pa *packedArray) appendArray(other *packedArray) {
if other == nil {
return
}
if pa.bw != other.bw {
panic(fmt.Sprintf("Can not append array with different bit width : %d and %d", pa.bw, other.bw))
}
if cap(pa.data) < len(pa.data)+len(other.data)+1 {
data := make([]byte, len(pa.data), len(pa.data)+len(other.data)+1)
copy(data, pa.data)
pa.data = data
}
for i := 0; i < other.count; i++ {
v, _ := other.at(i)
pa.appendSingle(v)
}
}