]>
Commit | Line | Data |
---|---|---|
1d09f67e TL |
1 | // Licensed to the Apache Software Foundation (ASF) under one |
2 | // or more contributor license agreements. See the NOTICE file | |
3 | // distributed with this work for additional information | |
4 | // regarding copyright ownership. The ASF licenses this file | |
5 | // to you under the Apache License, Version 2.0 (the | |
6 | // "License"); you may not use this file except in compliance | |
7 | // with the License. You may obtain a copy of the License at | |
8 | // | |
9 | // http://www.apache.org/licenses/LICENSE-2.0 | |
10 | // | |
11 | // Unless required by applicable law or agreed to in writing, software | |
12 | // distributed under the License is distributed on an "AS IS" BASIS, | |
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | // See the License for the specific language governing permissions and | |
15 | // limitations under the License. | |
16 | ||
17 | package array // import "github.com/apache/arrow/go/v6/arrow/array" | |
18 | ||
19 | import ( | |
20 | "fmt" | |
21 | "strings" | |
22 | "sync/atomic" | |
23 | ||
24 | "github.com/apache/arrow/go/v6/arrow" | |
25 | "github.com/apache/arrow/go/v6/arrow/bitutil" | |
26 | "github.com/apache/arrow/go/v6/arrow/decimal128" | |
27 | "github.com/apache/arrow/go/v6/arrow/internal/debug" | |
28 | "github.com/apache/arrow/go/v6/arrow/memory" | |
29 | ) | |
30 | ||
31 | // A type which represents an immutable sequence of 128-bit decimal values. | |
32 | type Decimal128 struct { | |
33 | array | |
34 | ||
35 | values []decimal128.Num | |
36 | } | |
37 | ||
38 | func NewDecimal128Data(data *Data) *Decimal128 { | |
39 | a := &Decimal128{} | |
40 | a.refCount = 1 | |
41 | a.setData(data) | |
42 | return a | |
43 | } | |
44 | ||
45 | func (a *Decimal128) Value(i int) decimal128.Num { return a.values[i] } | |
46 | ||
47 | func (a *Decimal128) Values() []decimal128.Num { return a.values } | |
48 | ||
49 | func (a *Decimal128) String() string { | |
50 | o := new(strings.Builder) | |
51 | o.WriteString("[") | |
52 | for i := 0; i < a.Len(); i++ { | |
53 | if i > 0 { | |
54 | fmt.Fprintf(o, " ") | |
55 | } | |
56 | switch { | |
57 | case a.IsNull(i): | |
58 | o.WriteString("(null)") | |
59 | default: | |
60 | fmt.Fprintf(o, "%v", a.Value(i)) | |
61 | } | |
62 | } | |
63 | o.WriteString("]") | |
64 | return o.String() | |
65 | } | |
66 | ||
67 | func (a *Decimal128) setData(data *Data) { | |
68 | a.array.setData(data) | |
69 | vals := data.buffers[1] | |
70 | if vals != nil { | |
71 | a.values = arrow.Decimal128Traits.CastFromBytes(vals.Bytes()) | |
72 | beg := a.array.data.offset | |
73 | end := beg + a.array.data.length | |
74 | a.values = a.values[beg:end] | |
75 | } | |
76 | } | |
77 | ||
78 | func arrayEqualDecimal128(left, right *Decimal128) bool { | |
79 | for i := 0; i < left.Len(); i++ { | |
80 | if left.IsNull(i) { | |
81 | continue | |
82 | } | |
83 | if left.Value(i) != right.Value(i) { | |
84 | return false | |
85 | } | |
86 | } | |
87 | return true | |
88 | } | |
89 | ||
90 | type Decimal128Builder struct { | |
91 | builder | |
92 | ||
93 | dtype *arrow.Decimal128Type | |
94 | data *memory.Buffer | |
95 | rawData []decimal128.Num | |
96 | } | |
97 | ||
98 | func NewDecimal128Builder(mem memory.Allocator, dtype *arrow.Decimal128Type) *Decimal128Builder { | |
99 | return &Decimal128Builder{ | |
100 | builder: builder{refCount: 1, mem: mem}, | |
101 | dtype: dtype, | |
102 | } | |
103 | } | |
104 | ||
105 | // Release decreases the reference count by 1. | |
106 | // When the reference count goes to zero, the memory is freed. | |
107 | func (b *Decimal128Builder) Release() { | |
108 | debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases") | |
109 | ||
110 | if atomic.AddInt64(&b.refCount, -1) == 0 { | |
111 | if b.nullBitmap != nil { | |
112 | b.nullBitmap.Release() | |
113 | b.nullBitmap = nil | |
114 | } | |
115 | if b.data != nil { | |
116 | b.data.Release() | |
117 | b.data = nil | |
118 | b.rawData = nil | |
119 | } | |
120 | } | |
121 | } | |
122 | ||
123 | func (b *Decimal128Builder) Append(v decimal128.Num) { | |
124 | b.Reserve(1) | |
125 | b.UnsafeAppend(v) | |
126 | } | |
127 | ||
128 | func (b *Decimal128Builder) UnsafeAppend(v decimal128.Num) { | |
129 | bitutil.SetBit(b.nullBitmap.Bytes(), b.length) | |
130 | b.rawData[b.length] = v | |
131 | b.length++ | |
132 | } | |
133 | ||
134 | func (b *Decimal128Builder) AppendNull() { | |
135 | b.Reserve(1) | |
136 | b.UnsafeAppendBoolToBitmap(false) | |
137 | } | |
138 | ||
139 | func (b *Decimal128Builder) UnsafeAppendBoolToBitmap(isValid bool) { | |
140 | if isValid { | |
141 | bitutil.SetBit(b.nullBitmap.Bytes(), b.length) | |
142 | } else { | |
143 | b.nulls++ | |
144 | } | |
145 | b.length++ | |
146 | } | |
147 | ||
148 | // AppendValues will append the values in the v slice. The valid slice determines which values | |
149 | // in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty, | |
150 | // all values in v are appended and considered valid. | |
151 | func (b *Decimal128Builder) AppendValues(v []decimal128.Num, valid []bool) { | |
152 | if len(v) != len(valid) && len(valid) != 0 { | |
153 | panic("len(v) != len(valid) && len(valid) != 0") | |
154 | } | |
155 | ||
156 | if len(v) == 0 { | |
157 | return | |
158 | } | |
159 | ||
160 | b.Reserve(len(v)) | |
161 | if len(v) > 0 { | |
162 | arrow.Decimal128Traits.Copy(b.rawData[b.length:], v) | |
163 | } | |
164 | b.builder.unsafeAppendBoolsToBitmap(valid, len(v)) | |
165 | } | |
166 | ||
167 | func (b *Decimal128Builder) init(capacity int) { | |
168 | b.builder.init(capacity) | |
169 | ||
170 | b.data = memory.NewResizableBuffer(b.mem) | |
171 | bytesN := arrow.Decimal128Traits.BytesRequired(capacity) | |
172 | b.data.Resize(bytesN) | |
173 | b.rawData = arrow.Decimal128Traits.CastFromBytes(b.data.Bytes()) | |
174 | } | |
175 | ||
176 | // Reserve ensures there is enough space for appending n elements | |
177 | // by checking the capacity and calling Resize if necessary. | |
178 | func (b *Decimal128Builder) Reserve(n int) { | |
179 | b.builder.reserve(n, b.Resize) | |
180 | } | |
181 | ||
182 | // Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(), | |
183 | // additional memory will be allocated. If n is smaller, the allocated memory may reduced. | |
184 | func (b *Decimal128Builder) Resize(n int) { | |
185 | nBuilder := n | |
186 | if n < minBuilderCapacity { | |
187 | n = minBuilderCapacity | |
188 | } | |
189 | ||
190 | if b.capacity == 0 { | |
191 | b.init(n) | |
192 | } else { | |
193 | b.builder.resize(nBuilder, b.init) | |
194 | b.data.Resize(arrow.Decimal128Traits.BytesRequired(n)) | |
195 | b.rawData = arrow.Decimal128Traits.CastFromBytes(b.data.Bytes()) | |
196 | } | |
197 | } | |
198 | ||
199 | // NewArray creates a Decimal128 array from the memory buffers used by the builder and resets the Decimal128Builder | |
200 | // so it can be used to build a new array. | |
201 | func (b *Decimal128Builder) NewArray() Interface { | |
202 | return b.NewDecimal128Array() | |
203 | } | |
204 | ||
205 | // NewDecimal128Array creates a Decimal128 array from the memory buffers used by the builder and resets the Decimal128Builder | |
206 | // so it can be used to build a new array. | |
207 | func (b *Decimal128Builder) NewDecimal128Array() (a *Decimal128) { | |
208 | data := b.newData() | |
209 | a = NewDecimal128Data(data) | |
210 | data.Release() | |
211 | return | |
212 | } | |
213 | ||
214 | func (b *Decimal128Builder) newData() (data *Data) { | |
215 | bytesRequired := arrow.Decimal128Traits.BytesRequired(b.length) | |
216 | if bytesRequired > 0 && bytesRequired < b.data.Len() { | |
217 | // trim buffers | |
218 | b.data.Resize(bytesRequired) | |
219 | } | |
220 | data = NewData(b.dtype, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0) | |
221 | b.reset() | |
222 | ||
223 | if b.data != nil { | |
224 | b.data.Release() | |
225 | b.data = nil | |
226 | b.rawData = nil | |
227 | } | |
228 | ||
229 | return | |
230 | } | |
231 | ||
232 | var ( | |
233 | _ Interface = (*Decimal128)(nil) | |
234 | _ Builder = (*Decimal128Builder)(nil) | |
235 | ) |