sparrow 1.0.0
Loading...
Searching...
No Matches
primitive_data_access.hpp
Go to the documentation of this file.
1// Copyright 2024 Man Group Operations Limited
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma once
16
20#include "sparrow/u8_buffer.hpp"
21
22namespace sparrow
23{
24 template <typename T>
25 concept trivial_copyable_type = std::is_trivially_copyable_v<T> && std::is_standard_layout_v<T>;
26
27 namespace details
28 {
34 template <trivial_copyable_type T>
36 {
37 public:
38
40 using inner_reference = T&;
41 using inner_const_reference = const T&;
44
47
53 primitive_data_access(arrow_proxy& proxy, size_t data_buffer_index);
54
55 // This class is meant to be use as a private member of array classes,
56 // and holds a inner_pointer to the arrow_proxy of the array. Therefore we
57 // forbid the copy and the move semantics to:
58 // - force the array constructors to call the primitive_data_access
59 // constructor taking an arrow_proxy
60 // - force the arra assignment operators to call the reset_proxy
61 // method.
66
67 [[nodiscard]] constexpr inner_pointer data();
68 [[nodiscard]] constexpr inner_const_pointer data() const;
69
70 [[nodiscard]] constexpr inner_reference value(size_t i);
71 [[nodiscard]] constexpr inner_const_reference value(size_t i) const;
72
73 [[nodiscard]] constexpr value_iterator value_begin();
74 [[nodiscard]] constexpr value_iterator value_end();
75
76 [[nodiscard]] constexpr const_value_iterator value_cbegin() const;
77 [[nodiscard]] constexpr const_value_iterator value_cend() const;
78
79 constexpr void resize_values(size_t new_length, const T& value);
80
81 constexpr value_iterator insert_value(const_value_iterator pos, T value, size_t count);
82 constexpr value_iterator insert_value(size_t idx, T value, size_t count);
83
84 // Template parameter InputIt must be an value_iterator type that iterates over elements of type T
85 template <mpl::iterator_of_type<T> InputIt>
86 constexpr value_iterator insert_values(const_value_iterator pos, InputIt first, InputIt last);
87
88 template <mpl::iterator_of_type<T> InputIt>
89 constexpr value_iterator insert_values(size_t idx, InputIt first, InputIt last);
90
91 constexpr value_iterator erase_values(const_value_iterator pos, size_t count);
92 constexpr value_iterator erase_values(size_t idx, size_t count);
93
94 constexpr void reset_proxy(arrow_proxy& proxy);
95
96 template <std::ranges::input_range RANGE>
97 [[nodiscard]] static constexpr u8_buffer<T> make_data_buffer(RANGE&& r);
98
99 [[nodiscard]] static constexpr u8_buffer<T> make_data_buffer(size_t n, const T& value);
100
101 private:
102
103 [[nodiscard]] constexpr buffer_adaptor<T, buffer<uint8_t>&> get_data_buffer();
104
105 [[nodiscard]] arrow_proxy& get_proxy();
106 [[nodiscard]] const arrow_proxy& get_proxy() const;
107
108 arrow_proxy* p_proxy;
109 size_t m_data_buffer_index;
110 };
111
112 template <>
114 {
115 public:
116
123
126
127 primitive_data_access(arrow_proxy& proxy, size_t data_buffer_index);
128
133
134 [[nodiscard]] inner_reference value(size_t i);
135 [[nodiscard]] inner_const_reference value(size_t i) const;
136
137 [[nodiscard]] value_iterator value_begin();
138 [[nodiscard]] value_iterator value_end();
139
140 [[nodiscard]] const_value_iterator value_cbegin() const;
141 [[nodiscard]] const_value_iterator value_cend() const;
142
143 void resize_values(size_t new_length, bool value);
144
145 value_iterator insert_value(const_value_iterator pos, bool value, size_t count);
146 value_iterator insert_value(size_t idx, bool value, size_t count);
147
148 // Template parameter InputIt must be an value_iterator type that iterates over elements of type T
149 template <mpl::iterator_of_type<bool> InputIt>
150 constexpr value_iterator insert_values(const_value_iterator pos, InputIt first, InputIt last);
151
152 template <mpl::iterator_of_type<bool> InputIt>
153 constexpr value_iterator insert_values(size_t idx, InputIt first, InputIt last);
154
156 value_iterator erase_values(size_t idx, size_t count);
157
158 void reset_proxy(arrow_proxy& proxy);
159
160 template <std::ranges::input_range RANGE>
161 [[nodiscard]] static u8_buffer<bool> make_data_buffer(RANGE&& r);
162
163 [[nodiscard]] static u8_buffer<bool> make_data_buffer(size_t size, bool value);
164
165 private:
166
167 using bitset_adaptor = non_owning_dynamic_bitset<std::uint8_t>;
168 using difference_type = typename bitset_adaptor::difference_type;
169 using adaptor_iterator = typename bitset_adaptor::iterator;
170 using const_adaptor_iterator = typename bitset_adaptor::const_iterator;
171
172 template <class F>
173 [[nodiscard]] static u8_buffer<bool> make_data_buffer(size_t size, F init_func);
174
175 [[nodiscard]] size_t get_offset(size_t i) const;
176
177 [[nodiscard]] adaptor_iterator adaptor_begin();
178 [[nodiscard]] adaptor_iterator adaptor_end();
179
180 [[nodiscard]] const_adaptor_iterator adaptor_cbegin() const;
181 [[nodiscard]] const_adaptor_iterator adaptor_cend() const;
182
183 [[nodiscard]] arrow_proxy& get_proxy();
184 [[nodiscard]] const arrow_proxy& get_proxy() const;
185
186 [[nodiscard]] bitset_view get_data_view();
187 [[nodiscard]] bitset_adaptor get_data_adaptor();
188
189 void update_data_view();
190
191 arrow_proxy* p_proxy;
192 size_t m_data_buffer_index;
193 bitset_view m_view;
194 buffer<std::uint8_t> m_dummy_buffer;
195 bitset_adaptor m_adaptor;
196 };
197
198 /****************************************
199 * primitiva_data_access implementation *
200 ****************************************/
201
202 template <trivial_copyable_type T>
204 : p_proxy(&proxy)
205 , m_data_buffer_index(data_buffer_index)
206 {
207 }
208
209 template <trivial_copyable_type T>
210 [[nodiscard]] constexpr auto primitive_data_access<T>::data() -> inner_pointer
211 {
212 return get_proxy().buffers()[m_data_buffer_index].template data<T>()
213 + static_cast<size_t>(get_proxy().offset());
214 }
215
216 template <trivial_copyable_type T>
217 [[nodiscard]] constexpr auto primitive_data_access<T>::data() const -> inner_const_pointer
218 {
219 return get_proxy().buffers()[m_data_buffer_index].template data<T>()
220 + static_cast<size_t>(get_proxy().offset());
221 }
222
223 template <trivial_copyable_type T>
224 [[nodiscard]] constexpr auto primitive_data_access<T>::value(size_t i) -> inner_reference
225 {
226 SPARROW_ASSERT_TRUE(i < get_proxy().length());
227 return data()[i];
228 }
229
230 template <trivial_copyable_type T>
231 [[nodiscard]] constexpr auto primitive_data_access<T>::value(size_t i) const -> inner_const_reference
232 {
233 SPARROW_ASSERT_TRUE(i < get_proxy().length());
234 return data()[i];
235 }
236
237 template <trivial_copyable_type T>
239 {
240 return value_iterator{data()};
241 }
242
243 template <trivial_copyable_type T>
244 [[nodiscard]] constexpr auto primitive_data_access<T>::value_end() -> value_iterator
245 {
246 return sparrow::next(value_begin(), get_proxy().length());
247 }
248
249 template <trivial_copyable_type T>
250 [[nodiscard]] constexpr auto primitive_data_access<T>::value_cbegin() const -> const_value_iterator
251 {
252 return const_value_iterator{data()};
253 }
254
255 template <trivial_copyable_type T>
256 [[nodiscard]] constexpr auto primitive_data_access<T>::value_cend() const -> const_value_iterator
257 {
258 return sparrow::next(value_cbegin(), get_proxy().length());
259 }
260
261 template <trivial_copyable_type T>
262 constexpr void primitive_data_access<T>::resize_values(size_t new_length, const T& value)
263 {
264 const size_t new_size = new_length + static_cast<size_t>(get_proxy().offset());
265 get_data_buffer().resize(new_size, value);
266 }
267
268 template <trivial_copyable_type T>
271 {
273 const const_value_iterator value_cend{sparrow::next(value_cbegin, get_proxy().length())};
276 const auto distance = std::distance(value_cbegin, sparrow::next(pos, get_proxy().offset()));
277 get_data_buffer().insert(pos, count, value);
279 return sparrow::next(value_begin, distance);
280 }
281
282 template <trivial_copyable_type T>
283 constexpr auto primitive_data_access<T>::insert_value(size_t idx, T value, size_t count)
285 {
286 SPARROW_ASSERT_TRUE(idx <= get_proxy().length());
287 const const_value_iterator begin{data()};
288 const const_value_iterator it = sparrow::next(begin, idx);
289 return insert_value(it, value, count);
290 }
291
292 // Template parameter InputIt must be an value_iterator type that iterates over elements of type T
293 template <trivial_copyable_type T>
294 template <mpl::iterator_of_type<T> InputIt>
295 constexpr auto
298 {
300 const const_value_iterator value_cend{sparrow::next(value_cbegin, get_proxy().length())};
303 const auto distance = std::distance(value_cbegin, sparrow::next(pos, get_proxy().offset()));
304 get_data_buffer().insert(pos, first, last);
306 return sparrow::next(value_begin, distance);
307 }
308
309 template <trivial_copyable_type T>
310 template <mpl::iterator_of_type<T> InputIt>
311 constexpr auto primitive_data_access<T>::insert_values(size_t idx, InputIt first, InputIt last)
313 {
314 SPARROW_ASSERT_TRUE(idx <= get_proxy().length());
315 const const_value_iterator begin{data()};
316 const const_value_iterator it = sparrow::next(begin, idx);
317 return insert_values(it, first, last);
318 }
319
320 template <trivial_copyable_type T>
323 {
325 const const_value_iterator value_cend{sparrow::next(value_cbegin, get_proxy().length())};
328 const auto distance = static_cast<size_t>(
329 std::distance(value_cbegin, sparrow::next(pos, get_proxy().offset()))
330 );
331 auto data_buffer = get_data_buffer();
332 const auto first = sparrow::next(data_buffer.cbegin(), distance);
333 const auto last = sparrow::next(first, count);
334 data_buffer.erase(first, last);
336 return sparrow::next(value_begin, distance);
337 }
338
339 template <trivial_copyable_type T>
340 constexpr auto primitive_data_access<T>::erase_values(size_t idx, size_t count) -> value_iterator
341 {
342 SPARROW_ASSERT_TRUE(idx <= get_proxy().length());
343 const const_value_iterator cbegin{data()};
344 const const_value_iterator it = sparrow::next(cbegin, idx);
345 erase_values(it, count);
346 return sparrow::next(value_iterator{data()}, idx);
347 }
348
349 template <trivial_copyable_type T>
351 {
352 p_proxy = &proxy;
353 }
354
355 template <trivial_copyable_type T>
356 template <std::ranges::input_range RANGE>
358 {
359 return u8_buffer<T>(std::forward<RANGE>(r));
360 }
361
362 template <trivial_copyable_type T>
363 [[nodiscard]] constexpr u8_buffer<T>
365 {
366 return u8_buffer<T>(size, value);
367 }
368
369 template <trivial_copyable_type T>
370 [[nodiscard]] constexpr buffer_adaptor<T, buffer<uint8_t>&> primitive_data_access<T>::get_data_buffer()
371 {
372 auto& buffers = get_proxy().get_array_private_data()->buffers();
373 return make_buffer_adaptor<T>(buffers[m_data_buffer_index]);
374 }
375
376 template <trivial_copyable_type T>
377 [[nodiscard]] arrow_proxy& primitive_data_access<T>::get_proxy()
378 {
379 return *p_proxy;
380 }
381
382 template <trivial_copyable_type T>
383 [[nodiscard]] const arrow_proxy& primitive_data_access<T>::get_proxy() const
384 {
385 return *p_proxy;
386 }
387
388 /**********************************************
389 * primitive_data_access<bool> implementation *
390 **********************************************/
391
393 : p_proxy(&proxy)
394 , m_data_buffer_index(data_buffer_index)
395 , m_view(get_data_view())
396 , m_dummy_buffer()
397 , m_adaptor(get_data_adaptor())
398 {
399 }
400
401 [[nodiscard]] inline auto primitive_data_access<bool>::value(size_t i) -> inner_reference
402 {
403 return m_view[get_offset(i)];
404 }
405
406 [[nodiscard]] inline auto primitive_data_access<bool>::value(size_t i) const -> inner_const_reference
407 {
408 return m_view[get_offset(i)];
409 }
410
412 {
413 return sparrow::next(m_view.begin(), get_offset(0u));
414 }
415
417 {
418 return m_view.end();
419 }
420
422 {
423 return sparrow::next(m_view.cbegin(), get_offset(0u));
424 }
425
427 {
428 return m_view.cend();
429 }
430
431 inline void primitive_data_access<bool>::resize_values(size_t new_length, bool value)
432 {
433 m_adaptor.resize(get_offset(new_length), value);
434 update_data_view();
435 }
436
437 inline auto
440 {
441 auto ins_iter = sparrow::next(adaptor_cbegin(), std::distance(value_cbegin(), pos));
442 auto res = m_adaptor.insert(ins_iter, count, value);
443 update_data_view();
444 return sparrow::next(value_begin(), std::distance(adaptor_begin(), res));
445 }
446
447 inline auto primitive_data_access<bool>::insert_value(size_t idx, bool value, size_t count)
449 {
450 auto iter = sparrow::next(adaptor_cbegin(), static_cast<difference_type>(idx));
451 auto res = m_adaptor.insert(iter, count, value);
452 update_data_view();
453 return sparrow::next(value_begin(), std::distance(adaptor_begin(), res));
454 }
455
456 // Template parameter InputIt must be an value_iterator type that iterates over elements of type T
457 template <mpl::iterator_of_type<bool> InputIt>
458 constexpr auto
461 {
462 auto ins_iter = sparrow::next(adaptor_cbegin(), std::distance(value_cbegin(), pos));
463 auto res = m_adaptor.insert(ins_iter, first, last);
464 update_data_view();
465 return sparrow::next(value_begin(), std::distance(adaptor_begin(), res));
466 }
467
468 template <mpl::iterator_of_type<bool> InputIt>
469 constexpr auto primitive_data_access<bool>::insert_values(size_t idx, InputIt first, InputIt last)
471 {
472 auto iter = sparrow::next(adaptor_cbegin(), static_cast<difference_type>(idx));
473 auto res = m_adaptor.insert(iter, first, last);
474 update_data_view();
475 return sparrow::next(value_begin(), std::distance(adaptor_begin(), res));
476 }
477
480 {
481 auto iter = sparrow::next(adaptor_cbegin(), std::distance(value_cbegin(), pos));
482 auto iter_end = sparrow::next(iter, count);
483 auto res = m_adaptor.erase(iter, iter_end);
484 update_data_view();
485 return sparrow::next(value_begin(), std::distance(adaptor_begin(), res));
486 }
487
488 inline auto primitive_data_access<bool>::erase_values(size_t idx, size_t count) -> value_iterator
489 {
490 auto iter = sparrow::next(adaptor_cbegin(), idx);
491 auto iter_end = sparrow::next(iter, count);
492 auto res = m_adaptor.erase(iter, iter_end);
493 update_data_view();
494 return sparrow::next(value_begin(), std::distance(adaptor_begin(), res));
495 }
496
498 {
499 p_proxy = &proxy;
500 m_view = get_data_view();
501 m_adaptor = get_data_adaptor();
502 }
503
504 template <std::ranges::input_range RANGE>
506 {
507 auto size = static_cast<size_t>(std::ranges::distance(r));
508 auto init_func = [&r](bitset_view& v)
509 {
510 std::copy(r.begin(), r.end(), v.begin());
511 };
512 return make_data_buffer(size, init_func);
513 }
514
515 [[nodiscard]] inline u8_buffer<bool>
517 {
518 auto init_func = [&value](bitset_view& v)
519 {
520 std::fill(v.begin(), v.end(), value);
521 };
522 return make_data_buffer(size, init_func);
523 }
524
525 template <class F>
526 [[nodiscard]] inline u8_buffer<bool>
527 primitive_data_access<bool>::make_data_buffer(size_t size, F init_func)
528 {
529 std::size_t block_nb = size / 8;
530 if (block_nb * 8 < size)
531 {
532 ++block_nb;
533 }
534 u8_buffer<bool> res(block_nb);
535 std::uint8_t* buffer = reinterpret_cast<std::uint8_t*>(res.data());
536 bitset_view v(buffer, size);
537 init_func(v);
538 return res;
539 }
540
541 [[nodiscard]] inline size_t primitive_data_access<bool>::get_offset(size_t i) const
542 {
543 return i + get_proxy().offset();
544 }
545
546 [[nodiscard]] inline auto primitive_data_access<bool>::adaptor_begin() -> adaptor_iterator
547 {
548 return sparrow::next(m_adaptor.begin(), get_offset(0u));
549 }
550
551 [[nodiscard]] inline auto primitive_data_access<bool>::adaptor_end() -> adaptor_iterator
552 {
553 return m_adaptor.end();
554 }
555
556 [[nodiscard]] inline auto primitive_data_access<bool>::adaptor_cbegin() const -> const_adaptor_iterator
557 {
558 return sparrow::next(m_adaptor.cbegin(), get_offset(0u));
559 }
560
561 [[nodiscard]] inline auto primitive_data_access<bool>::adaptor_cend() const -> const_adaptor_iterator
562 {
563 return m_adaptor.cend();
564 }
565
566 [[nodiscard]] inline arrow_proxy& primitive_data_access<bool>::get_proxy()
567 {
568 return *p_proxy;
569 }
570
571 [[nodiscard]] inline const arrow_proxy& primitive_data_access<bool>::get_proxy() const
572 {
573 return *p_proxy;
574 }
575
576 [[nodiscard]] inline auto primitive_data_access<bool>::get_data_view() -> bitset_view
577 {
578 auto& proxy = get_proxy();
579 size_t size = proxy.length() + proxy.offset();
580 return bitset_view(proxy.buffers()[m_data_buffer_index].data(), size);
581 }
582
583 [[nodiscard]] inline auto primitive_data_access<bool>::get_data_adaptor() -> bitset_adaptor
584 {
585 auto& proxy = get_proxy();
586 if (proxy.is_created_with_sparrow())
587 {
588 size_t size = proxy.length() + proxy.offset();
589 return bitset_adaptor(&(proxy.get_array_private_data()->buffers()[m_data_buffer_index]), size);
590 }
591 else
592 {
593 return bitset_adaptor(&m_dummy_buffer, 0u);
594 }
595 }
596
598 {
599 m_view = bitset_view(get_proxy().buffers()[m_data_buffer_index].data(), m_adaptor.size());
600 }
601 }
602}
Class which has internally a reference to a contiguous container of a certain type and provides an AP...
Object that owns a piece of contiguous memory.
Definition buffer.hpp:113
static u8_buffer< bool > make_data_buffer(RANGE &&r)
primitive_data_access(arrow_proxy &proxy, size_t data_buffer_index)
constexpr value_iterator insert_values(const_value_iterator pos, InputIt first, InputIt last)
primitive_data_access & operator=(primitive_data_access &&)=delete
typename bitset_view::const_reference inner_const_reference
typename bitset_view::const_iterator const_value_iterator
primitive_data_access(const primitive_data_access &)=delete
primitive_data_access(primitive_data_access &&)=delete
primitive_data_access & operator=(const primitive_data_access &)=delete
constexpr value_iterator insert_values(size_t idx, InputIt first, InputIt last)
Data access class for trivial copyable types.
constexpr void resize_values(size_t new_length, const T &value)
constexpr value_iterator insert_values(size_t idx, InputIt first, InputIt last)
primitive_data_access & operator=(const primitive_data_access &)=delete
constexpr value_iterator erase_values(const_value_iterator pos, size_t count)
constexpr value_iterator erase_values(size_t idx, size_t count)
primitive_data_access(primitive_data_access &&)=delete
constexpr inner_const_reference value(size_t i) const
constexpr inner_reference value(size_t i)
constexpr value_iterator insert_values(const_value_iterator pos, InputIt first, InputIt last)
static constexpr u8_buffer< T > make_data_buffer(size_t n, const T &value)
constexpr const_value_iterator value_cend() const
constexpr void reset_proxy(arrow_proxy &proxy)
constexpr value_iterator insert_value(size_t idx, T value, size_t count)
pointer_iterator< inner_const_pointer > const_value_iterator
primitive_data_access(arrow_proxy &proxy, size_t data_buffer_index)
Constructor for primitive_data_access.
static constexpr u8_buffer< T > make_data_buffer(RANGE &&r)
primitive_data_access & operator=(primitive_data_access &&)=delete
constexpr value_iterator insert_value(const_value_iterator pos, T value, size_t count)
constexpr inner_const_pointer data() const
primitive_data_access(const primitive_data_access &)=delete
pointer_iterator< inner_pointer > value_iterator
constexpr const_value_iterator value_cbegin() const
bitset_iterator< self_type, true > const_iterator
typename storage_type_without_cvrefpointer::difference_type difference_type
A non-owning view to a dynamic size sequence of bits stored in external memory.
This buffer class is used as storage buffer for all sparrow arrays.
#define SPARROW_ASSERT_TRUE(expr__)
constexpr std::size_t size(typelist< T... >={})
Gets the count of types contained in a typelist.
Definition mp_utils.hpp:216
constexpr InputIt next(InputIt it, Distance n)
Definition iterator.hpp:503
auto make_buffer_adaptor(FromBufferRef &buf)