MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
DataFieldTraversal.hpp
Go to the documentation of this file.
1#pragma once
2
3namespace MayaFlux::Kakshya {
4
5/**
6 * @brief Array with optional-like element and contiguous slice access.
7 * @tparam Array Array type whose elements and slices can be borrowed.
8 */
9template <typename Array>
10concept FieldArray = requires(const Array& array, size_t index, size_t count) {
11 { array.size() } -> std::convertible_to<size_t>;
12 { static_cast<bool>(array.at(index)) } -> std::same_as<bool>;
13 *array.at(index);
14 { static_cast<bool>(array.slice(index, count)) } -> std::same_as<bool>;
15 { array.slice(index, count)->size() } -> std::convertible_to<size_t>;
16 *array.slice(index, count)->at(index);
17};
18
19/**
20 * @class DataFieldTraversal
21 * @brief On-demand windowing and field operations over an indexed array.
22 *
23 * A traversal maintains an independent position and batch size without
24 * owning the array. Field projection is available when the array and its
25 * slices provide to_nddata<T>(field_name). The same traversal works with any
26 * FieldArray; neither it nor the array needs to name a concrete record format.
27 *
28 * Usage:
29 * @code
30 * DataFieldTraversal traversal(items, 64);
31 * while (!traversal.at_end()) {
32 * auto scores = traversal.window_to_nddata<double>("score");
33 * traversal.for_each_in_window([](const auto& item) {
34 * auto name = item.text("name");
35 * });
36 * traversal.advance();
37 * }
38 * @endcode
39 *
40 * @tparam Array Indexed array satisfying FieldArray.
41 * @note Borrowed elements and windows remain subject to the array's own
42 * lifetime and invalidation rules. Keep the array at a stable address while
43 * using a traversal.
44 */
45template <FieldArray Array>
47public:
48 /**
49 * @brief Borrow an array and set the initial window size.
50 * @param array Array that must outlive this traversal.
51 * @param batch_size Elements per window; zero is normalized to one.
52 */
53 explicit DataFieldTraversal(const Array& array, size_t batch_size = 1) noexcept
54 : m_array(&array)
56 {
57 }
58
59 /**
60 * @brief Borrow the current window, including a short final window.
61 * @return Optional-like slice from the current position to the next
62 * batch boundary or the end of the array.
63 */
64 [[nodiscard]] auto current() const
65 {
66 return m_array->slice(m_position, std::min(m_batch_size, remaining()));
67 }
68
69 /**
70 * @brief Move forward without passing the end of the array.
71 * @param rows Number of elements to advance; zero uses batch_size().
72 */
73 void advance(size_t rows = 0)
74 {
75 const auto step = rows == 0 ? m_batch_size : rows;
76 m_position += std::min(step, remaining());
77 }
78
79 /**
80 * @brief Set the position, clamped to the end of the array.
81 * @param row Zero-based element position.
82 */
83 void seek(size_t row) { m_position = std::min(row, m_array->size()); }
84
85 /** @brief Current zero-based element position. */
86 [[nodiscard]] size_t position() const noexcept { return m_position; }
87
88 /** @brief Whether there are no elements after the current position. */
89 [[nodiscard]] bool at_end() const { return m_position >= m_array->size(); }
90
91 /** @brief Number of elements after the current position. */
92 [[nodiscard]] size_t remaining() const
93 {
94 return m_position < m_array->size() ? m_array->size() - m_position : 0;
95 }
96
97 /**
98 * @brief Set the window size for subsequent operations.
99 * @param rows Elements per window; zero is normalized to one.
100 */
101 void set_batch_size(size_t rows) noexcept { m_batch_size = rows == 0 ? 1 : rows; }
102
103 /** @brief Current window size. */
104 [[nodiscard]] size_t batch_size() const noexcept { return m_batch_size; }
105
106 /**
107 * @brief Derive homogeneous NDData from one field across the entire array.
108 * @tparam ValueT Exact field value type supported by the array.
109 * @param field_name Field to project.
110 * @return The array's owning projection result.
111 */
112 template <typename ValueT>
113 [[nodiscard]] auto to_nddata(std::string_view field_name) const
114 requires requires(const Array& array, std::string_view name) {
115 array.template to_nddata<ValueT>(name);
116 }
117 {
118 return m_array->template to_nddata<ValueT>(field_name);
119 }
120
121 /**
122 * @brief Derive homogeneous NDData from one field in the current window.
123 * @tparam ValueT Exact field value type supported by the slice.
124 * @param field_name Field to project.
125 * @return The slice's owning projection result, or an empty result when
126 * the current slice cannot be obtained.
127 */
128 template <typename ValueT>
129 [[nodiscard]] auto window_to_nddata(std::string_view field_name) const
130 requires requires(const Array& array, std::string_view name) {
131 array.slice(size_t {}, size_t {})->template to_nddata<ValueT>(name);
132 }
133 {
134 auto window = current();
135 using Result = decltype(window->template to_nddata<ValueT>(field_name));
136 return window ? window->template to_nddata<ValueT>(field_name) : Result {};
137 }
138
139 /**
140 * @brief Apply a callable to each available element in the array.
141 * @tparam Fn Callable accepting a borrowed element.
142 * @param fn Operation to apply in element order.
143 * @note An index where at() returns disengaged is skipped entirely, not
144 * visited with a default value. fn may be called fewer than size() times.
145 */
146 template <typename Fn>
147 void for_each(Fn&& fn) const
148 {
149 for (size_t i = 0; i < m_array->size(); ++i) {
150 if (auto element = m_array->at(i))
151 std::invoke(fn, *element);
152 }
153 }
154
155 /**
156 * @brief Apply a callable to each available element in the current window.
157 * @tparam Fn Callable accepting a borrowed element.
158 * @param fn Operation to apply in slice order.
159 * @note An index where at() returns disengaged is skipped entirely, not
160 * visited with a default value. fn may be called fewer than the window's
161 * size() times.
162 */
163 template <typename Fn>
164 void for_each_in_window(Fn&& fn) const
165 {
166 auto window = current();
167 if (!window)
168 return;
169
170 for (size_t i = 0; i < window->size(); ++i) {
171 if (auto element = window->at(i))
172 std::invoke(fn, *element);
173 }
174 }
175
176 /**
177 * @brief Fold all available elements into an accumulator.
178 * @tparam Acc Accumulator type.
179 * @tparam Fn Callable returning the next accumulator from the current
180 * accumulator and a borrowed element.
181 * @param init Initial accumulator.
182 * @param fn Fold operation applied in element order.
183 * @return Final accumulator.
184 * @note An index where at() returns disengaged is skipped entirely; fn is
185 * not invoked for it, not even with a default-constructed element.
186 */
187 template <typename Acc, typename Fn>
188 [[nodiscard]] Acc reduce(Acc init, Fn&& fn) const
189 {
190 for (size_t i = 0; i < m_array->size(); ++i) {
191 if (auto element = m_array->at(i))
192 init = std::invoke(fn, std::move(init), *element);
193 }
194 return init;
195 }
196
197private:
198 const Array* m_array;
199 size_t m_position {};
201};
202
203}
uint32_t rows
std::weak_ptr< Core::Window > window
Definition Picker.cpp:23
std::string name
Definition VKDevice.cpp:123
uint32_t index
Definition VKDevice.cpp:122
size_t count
void for_each_in_window(Fn &&fn) const
Apply a callable to each available element in the current window.
bool at_end() const
Whether there are no elements after the current position.
auto window_to_nddata(std::string_view field_name) const
Derive homogeneous NDData from one field in the current window.
void seek(size_t row)
Set the position, clamped to the end of the array.
void advance(size_t rows=0)
Move forward without passing the end of the array.
Acc reduce(Acc init, Fn &&fn) const
Fold all available elements into an accumulator.
size_t position() const noexcept
Current zero-based element position.
void for_each(Fn &&fn) const
Apply a callable to each available element in the array.
auto to_nddata(std::string_view field_name) const
Derive homogeneous NDData from one field across the entire array.
size_t batch_size() const noexcept
Current window size.
void set_batch_size(size_t rows) noexcept
Set the window size for subsequent operations.
auto current() const
Borrow the current window, including a short final window.
size_t remaining() const
Number of elements after the current position.
DataFieldTraversal(const Array &array, size_t batch_size=1) noexcept
Borrow an array and set the initial window size.
On-demand windowing and field operations over an indexed array.
Array with optional-like element and contiguous slice access.