Loading...
Searching...
No Matches
GrowableBuffer.h
Go to the documentation of this file.
1// BSD 3-Clause License; see https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
2
3#ifndef AWKWARD_GROWABLEBUFFER_H_
4#define AWKWARD_GROWABLEBUFFER_H_
5
7
8#include <cstring>
9#include <vector>
10#include <memory>
11#include <numeric>
12#include <cmath>
13#include <iostream>
14#include <utility>
15#include <stdexcept>
16#include <stdint.h>
17
18namespace awkward {
19
20 template <typename PRIMITIVE>
24 class Panel {
25 public:
26
32 : ptr_(std::unique_ptr<PRIMITIVE[]>(new PRIMITIVE[reserved])),
33 length_(0),
34 reserved_(reserved),
35 next_(nullptr) {}
36
42 Panel(std::unique_ptr<PRIMITIVE[]> ptr, size_t length, size_t reserved)
43 : ptr_(std::move(ptr)),
44 length_(length),
45 reserved_(reserved),
46 next_(nullptr) {}
47
49 PRIMITIVE& operator[](size_t i) { return ptr_.get()[i]; }
50
53 Panel*
55 next_ = std::move(std::unique_ptr<Panel>(new Panel(reserved)));
56 return next_.get();
57 }
58
60 void
61 fill_panel(PRIMITIVE datum) {
62 ptr_.get()[length_++] = datum;
63 }
64
66 std::unique_ptr<Panel>&
67 next() {
68 return next_;
69 }
70
72 size_t
74 return length_;
75 }
76
78 size_t
80 return reserved_;
81 }
82
90 void
91 append(PRIMITIVE* to_ptr, size_t offset, size_t from, int64_t length) const noexcept {
92 memcpy(to_ptr + offset,
93 reinterpret_cast<void*>(ptr_.get() + from),
94 length * sizeof(PRIMITIVE) - from);
95 }
96
104 void
105 concatenate_to_from(PRIMITIVE* to_ptr, size_t offset, size_t from) const noexcept {
106 memcpy(to_ptr + offset,
107 reinterpret_cast<void*>(ptr_.get() + from),
108 length_ * sizeof(PRIMITIVE) - from);
109 if (next_) {
110 next_->concatenate_to(to_ptr, offset + length_);
111 }
112 }
113
120 void
121 concatenate_to(PRIMITIVE* to_ptr, size_t offset) const noexcept {
122 memcpy(to_ptr + offset,
123 reinterpret_cast<void*>(ptr_.get()),
124 length_ * sizeof(PRIMITIVE));
125 if (next_) {
126 next_->concatenate_to(to_ptr, offset + length_);
127 }
128 }
129
134 template <typename TO_PRIMITIVE>
135 void
136 copy_as(TO_PRIMITIVE* to_ptr, size_t offset) {
137 for (size_t i = 0; i < length_; i++) {
138 to_ptr[offset++] = static_cast<TO_PRIMITIVE>(ptr_.get()[i]);
139 }
140 if (next_) {
141 next_->copy_as(to_ptr, offset);
142 }
143 }
144
145 private:
147 std::unique_ptr<PRIMITIVE[]> ptr_;
148
150 size_t length_;
151
153 size_t reserved_;
154
156 std::unique_ptr<Panel> next_;
157 };
158
173 template <typename PRIMITIVE>
175 public:
181 return empty(options, 0);
182 }
183
191 empty(const BuilderOptions& options, int64_t minreserve) {
192 int64_t actual = options.initial();
193 if (actual < minreserve) {
194 actual = minreserve;
195 }
196 return GrowableBuffer(
197 options,
198 std::unique_ptr<PRIMITIVE[]>(new PRIMITIVE[(size_t)actual]),
199 0,
200 actual);
201 }
202
213 int64_t actual = options.initial();
214 if (actual < length) {
215 actual = length;
216 }
217 auto ptr = std::unique_ptr<PRIMITIVE[]>(new PRIMITIVE[(size_t)actual]);
218 PRIMITIVE* rawptr = ptr.get();
219 for (int64_t i = 0; i < length; i++) {
220 rawptr[i] = 0;
221 }
222 return GrowableBuffer(options, std::move(ptr), length, actual);
223 }
224
236 full(const BuilderOptions& options, PRIMITIVE value, int64_t length) {
237 int64_t actual = options.initial();
238 if (actual < length) {
239 actual = length;
240 }
241 auto ptr = std::unique_ptr<PRIMITIVE[]>(new PRIMITIVE[(size_t)actual]);
242 PRIMITIVE* rawptr = ptr.get();
243 for (int64_t i = 0; i < length; i++) {
244 rawptr[i] = value;
245 }
246 return GrowableBuffer<PRIMITIVE>(options, std::move(ptr), length, actual);
247 }
248
260 int64_t actual = options.initial();
261 if (actual < length) {
262 actual = length;
263 }
264 auto ptr = std::unique_ptr<PRIMITIVE[]>(new PRIMITIVE[(size_t)actual]);
265 PRIMITIVE* rawptr = ptr.get();
266 for (int64_t i = 0; i < length; i++) {
267 rawptr[i] = (PRIMITIVE)i;
268 }
269 return GrowableBuffer(options, std::move(ptr), length, actual);
270 }
271
277 template <typename TO_PRIMITIVE>
280 auto len = other.length();
281 int64_t actual =
282 (len < other.options_.initial()) ? other.options_.initial() : len;
283
284 auto ptr =
285 std::unique_ptr<TO_PRIMITIVE[]>(new TO_PRIMITIVE[(size_t)actual]);
286 TO_PRIMITIVE* rawptr = ptr.get();
287
288 other.panel_->copy_as(rawptr, 0);
289
291 BuilderOptions(actual, other.options().resize()),
292 std::move(ptr),
293 len,
294 actual);
295 }
296
308 std::unique_ptr<PRIMITIVE[]> ptr,
309 int64_t length,
310 int64_t reserved)
311 : options_(options),
312 length_(0),
313 panel_(std::unique_ptr<Panel<PRIMITIVE>>(new Panel<PRIMITIVE>(
314 std::move(ptr), (size_t)length, (size_t)reserved))),
315 ptr_(panel_.get()) {}
316
323 std::unique_ptr<PRIMITIVE[]>(
324 new PRIMITIVE[(size_t)options.initial()]),
325 0,
326 options.initial()) {}
327
332 : options_(other.options_),
333 length_(other.length_),
334 panel_(std::move(other.panel_)),
335 ptr_(other.ptr_) {}
336
342 size_t
343 length() const {
344 return length_ + ptr_->current_length();
345 }
346
348 const BuilderOptions&
349 options() const {
350 return options_;
351 }
352
355 void
357 panel_ = std::move(std::unique_ptr<Panel<PRIMITIVE>>(
358 new Panel<PRIMITIVE>((size_t)options_.initial())));
359 ptr_ = panel_.get();
360 }
361
363 PRIMITIVE
364 last() const {
365 if (ptr_->current_length() == 0) {
366 throw std::runtime_error("Buffer is empty");
367 } else {
368 return (*ptr_)[ptr_->current_length() - 1];
369 }
370 }
371
373 size_t
374 nbytes() const {
375 return length() * sizeof(PRIMITIVE);
376 }
377
383 void
384 append(PRIMITIVE datum) {
385 if (ptr_->current_length() == ptr_->reserved()) {
386 add_panel((size_t)ceil(ptr_->reserved() * options_.resize()));
387 }
388 fill_panel(datum);
389 }
390
397 void
398 extend(const PRIMITIVE* ptr, size_t size) {
399 size_t unfilled_items = ptr_->reserved() - ptr_->current_length();
400 if (size > unfilled_items) {
401 for (size_t i = 0; i < unfilled_items; i++) {
402 fill_panel(ptr[i]);
403 }
404 add_panel(size - unfilled_items > ptr_->reserved() ? size - unfilled_items
405 : ptr_->reserved());
406 for (size_t i = unfilled_items; i < size; i++) {
407 fill_panel(ptr[i]);
408 }
409 } else {
410 for (size_t i = 0; i < size; i++) {
411 fill_panel(ptr[i]);
412 }
413 }
414 }
415
417 PRIMITIVE&
418 append_and_get_ref(PRIMITIVE datum) {
419 append(datum);
420 return (*ptr_)[ptr_->current_length() - 1];
421 }
422
425 void
426 concatenate(PRIMITIVE* external_pointer) const noexcept {
427 if (external_pointer) {
428 panel_->concatenate_to(external_pointer, 0);
429 }
430 }
431
434 void
435 concatenate_from(PRIMITIVE* external_pointer, size_t to, size_t from) const noexcept {
436 if (external_pointer) {
437 panel_->concatenate_to_from(external_pointer, to, from);
438 }
439 }
440
442 void
443 append(PRIMITIVE* external_pointer, size_t offset, size_t from, int64_t length) const noexcept {
444 if (external_pointer) {
445 panel_->append(external_pointer, offset, from, length);
446 }
447 }
448
449 private:
451 void
452 fill_panel(PRIMITIVE datum) {
453 ptr_->fill_panel(datum);
454 }
455
458 void
459 add_panel(size_t reserved) {
460 length_ += ptr_->current_length();
461 ptr_ = ptr_->append_panel(reserved);
462 }
463
465 const BuilderOptions options_;
466
468 size_t length_;
469
471 std::unique_ptr<Panel<PRIMITIVE>> panel_;
472
476 Panel<PRIMITIVE>* ptr_;
477 };
478} // namespace awkward
479
480#endif // AWKWARD_GROWABLEBUFFER_H_
Discontiguous, one-dimensional buffer (which consists of multiple contiguous, one-dimensional panels)...
Definition: GrowableBuffer.h:174
static GrowableBuffer< PRIMITIVE > zeros(const BuilderOptions &options, int64_t length)
Creates a GrowableBuffer in which all elements are initialized to 0.
Definition: GrowableBuffer.h:212
void extend(const PRIMITIVE *ptr, size_t size)
Inserts an entire array into the panel(s), possibly triggering allocation of a new panel.
Definition: GrowableBuffer.h:398
static GrowableBuffer< TO_PRIMITIVE > copy_as(const GrowableBuffer< PRIMITIVE > &other)
Takes a (possibly multi-panels) GrowableBuffer<PRIMITIVE> and makes another (one panel) GrowableBuffe...
Definition: GrowableBuffer.h:279
PRIMITIVE last() const
Last element in last panel.
Definition: GrowableBuffer.h:364
void concatenate_from(PRIMITIVE *external_pointer, size_t to, size_t from) const noexcept
Copies and concatenates all accumulated data from multiple panels to one contiguously allocated exter...
Definition: GrowableBuffer.h:435
size_t nbytes() const
Currently used number of bytes.
Definition: GrowableBuffer.h:374
GrowableBuffer(GrowableBuffer &&other) noexcept
Move constructor.
Definition: GrowableBuffer.h:331
static GrowableBuffer< PRIMITIVE > full(const BuilderOptions &options, PRIMITIVE value, int64_t length)
Creates a GrowableBuffer in which all elements are initialized to a given value.
Definition: GrowableBuffer.h:236
const BuilderOptions & options() const
Return options of this GrowableBuffer.
Definition: GrowableBuffer.h:349
void concatenate(PRIMITIVE *external_pointer) const noexcept
Copies and concatenates all accumulated data from multiple panels to one contiguously allocated exter...
Definition: GrowableBuffer.h:426
PRIMITIVE & append_and_get_ref(PRIMITIVE datum)
Like append, but the type signature returns the reference to PRIMITIVE.
Definition: GrowableBuffer.h:418
size_t length() const
Currently used number of elements.
Definition: GrowableBuffer.h:343
static GrowableBuffer< PRIMITIVE > empty(const BuilderOptions &options, int64_t minreserve)
Creates an empty GrowableBuffer with a minimum reservation.
Definition: GrowableBuffer.h:191
void append(PRIMITIVE datum)
Inserts one datum into the panel, possibly triggering allocation of a new panel.
Definition: GrowableBuffer.h:384
static GrowableBuffer< PRIMITIVE > arange(const BuilderOptions &options, int64_t length)
Creates a GrowableBuffer in which the elements are initialized to numbers counting from 0 to length.
Definition: GrowableBuffer.h:259
void append(PRIMITIVE *external_pointer, size_t offset, size_t from, int64_t length) const noexcept
Copies data from a panel to one contiguously allocated external_pointer.
Definition: GrowableBuffer.h:443
GrowableBuffer(const BuilderOptions &options, std::unique_ptr< PRIMITIVE[]> ptr, int64_t length, int64_t reserved)
Creates a GrowableBuffer from a full set of parameters.
Definition: GrowableBuffer.h:307
static GrowableBuffer< PRIMITIVE > empty(const BuilderOptions &options)
Creates an empty GrowableBuffer.
Definition: GrowableBuffer.h:180
void clear()
Discards accumulated data, the #reserved returns to options.initial(), and a new #ptr is allocated.
Definition: GrowableBuffer.h:356
GrowableBuffer(const BuilderOptions &options)
Creates a GrowableBuffer by allocating a new buffer, taking an options #reserved from options.
Definition: GrowableBuffer.h:321
Definition: GrowableBuffer.h:24
void fill_panel(PRIMITIVE datum)
Inserts one datum into the panel.
Definition: GrowableBuffer.h:61
Panel * append_panel(size_t reserved)
Creates a new panel with slots equal to reserved and appends it after the current panel.
Definition: GrowableBuffer.h:54
Panel(std::unique_ptr< PRIMITIVE[]> ptr, size_t length, size_t reserved)
Creates a Panel from a full set of parameters.
Definition: GrowableBuffer.h:42
size_t current_length()
Currently used number of elements in the panel.
Definition: GrowableBuffer.h:73
std::unique_ptr< Panel > & next()
Pointer to the next panel.
Definition: GrowableBuffer.h:67
size_t reserved()
Currently allocated number of elements in the panel.
Definition: GrowableBuffer.h:79
void append(PRIMITIVE *to_ptr, size_t offset, size_t from, int64_t length) const noexcept
Copies the data from a panel to one contiguously allocated to_ptr.
Definition: GrowableBuffer.h:91
void concatenate_to_from(PRIMITIVE *to_ptr, size_t offset, size_t from) const noexcept
Copies and concatenates the accumulated data from multiple panels ptr_ to one contiguously allocated ...
Definition: GrowableBuffer.h:105
Panel(size_t reserved)
Creates a Panel by allocating a new panel, taking a reserved number of slots.
Definition: GrowableBuffer.h:31
PRIMITIVE & operator[](size_t i)
Overloads [] operator to access elements like an array.
Definition: GrowableBuffer.h:49
void copy_as(TO_PRIMITIVE *to_ptr, size_t offset)
Fills (one panel) GrowableBuffer<TO_PRIMITIVE> with the elements of (possibly multi-panels) GrowableB...
Definition: GrowableBuffer.h:136
void concatenate_to(PRIMITIVE *to_ptr, size_t offset) const noexcept
Copies and concatenates the accumulated data from multiple panels ptr_ to one contiguously allocated ...
Definition: GrowableBuffer.h:121
int64_t len(const T &self)
Definition: content.h:46
Definition: BitMaskedArray.h:15
Options< int64_t, double > BuilderOptions
Definition: BuilderOptions.h:63
Container for all configuration options needed by ArrayBuilder, GrowableBuffer, LayoutBuilder and the...
Definition: BuilderOptions.h:20
int64_t initial() const noexcept
The initial number of reserved entries for a GrowableBuffer.
Definition: BuilderOptions.h:41
double resize() const noexcept
The factor with which a GrowableBuffer is resized when its length reaches its reserved.
Definition: BuilderOptions.h:49