MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
CompositeContainer.hpp
Go to the documentation of this file.
1#pragma once
2
8
9namespace MayaFlux::Kakshya {
10
11/**
12 * @class CompositeContainer
13 * @brief Owns composite data and a bounded, independently owned window.
14 *
15 * Elements share one CompositeLayout and remain packed in the two NDData-backed
16 * stores of CompositeArray. Insertion, slices, and traversals operate directly
17 * on that array. materialize_next() copies a bounded selection into a second
18 * CompositeArray, rebasing selected text offsets into its own text store.
19 * Each traversal owns its own position and window size.
20 *
21 * Specializes NDDataContainer<CompositeArray> directly, not
22 * SignalSourceContainer, so it carries no ProcessingState and no
23 * DataProcessor attach/detach lifecycle. On-demand, non-recurring access
24 * goes through DataFieldTraversal<CompositeArray> instead, obtained via
25 * traverse().
26 *
27 * Usage:
28 * @code
29 * CompositeLayout layout;
30 * layout.add_field<std::string>("name");
31 * layout.add_field<double>("score");
32 * CompositeContainer container(std::move(layout), 64);
33 * auto insertion = container.insert();
34 * auto row = insertion.append();
35 * insertion.set_text(row, "name", "Ada");
36 * insertion.set(row, "score", 0.95);
37 *
38 * auto traversal = container.traverse(32);
39 * auto scores = traversal.window_to_nddata<double>("score");
40 * container.materialize_next();
41 * auto first = container.get_materialized_data().at(0);
42 * @endcode
43 *
44 * @note Views and traversal objects borrow the source array. Changes to
45 * source storage can invalidate them according to CompositeArray's rules.
46 */
47class MAYAFLUX_API CompositeContainer : public NDDataContainer<CompositeArray> {
48public:
50
51 /**
52 * @brief Construct empty source and materialized arrays with one layout.
53 * @param layout Field layout to finalize for both arrays.
54 * @param batch_size Maximum elements copied by materialize_next(); zero
55 * is normalized to one.
56 * @throws std::invalid_argument If the layout has no fields.
57 * @throws std::length_error If the layout's stride is too large.
58 */
59 explicit CompositeContainer(CompositeLayout layout, size_t batch_size = 1);
60
61 /**
62 * @brief Take ownership of an existing composite array.
63 * @param data Array to move into the container.
64 * @param batch_size Maximum elements copied by materialize_next(); zero
65 * is normalized to one.
66 */
67 explicit CompositeContainer(CompositeArray data, size_t batch_size = 1);
68
69 /** @brief Borrow the complete array. */
70 [[nodiscard]] const CompositeArray& get_data() const noexcept { return m_data; }
71
72 /** @brief Borrow the most recently materialized owning window. */
73 [[nodiscard]] const CompositeArray& get_materialized_data() const noexcept { return m_materialized_data; }
74
75 /**
76 * @brief Create an insertion adapter for the array.
77 * @return Adapter borrowing this container's storage.
78 * @note Appending or writing text may invalidate borrowed views.
79 */
80 [[nodiscard]] CompositeInsertion insert() noexcept { return CompositeInsertion(m_data); }
81
82 /**
83 * @brief Create an independent traversal over elements.
84 * @param batch_size Elements per traversal window; zero is normalized to one.
85 * @return Traversal borrowing this container's array.
86 */
87 [[nodiscard]] DataFieldTraversal<CompositeArray> traverse(size_t batch_size = 1) const noexcept
88 {
89 return DataFieldTraversal<CompositeArray>(m_data, batch_size);
90 }
91
92 /**
93 * @brief Borrow consecutive elements without copying.
94 * @param start First element index.
95 * @param count Number of elements.
96 * @return Slice, or std::nullopt if the range is invalid.
97 */
98 [[nodiscard]] std::optional<CompositeSlice> slice(size_t start, size_t count) const
99 {
100 return m_data.slice(start, count);
101 }
102
103 /**
104 * @brief Borrow elements selected by a one-dimensional Region.
105 * @param region Inclusive element bounds and optional attributes.
106 * @return Slice, or std::nullopt if the region is invalid.
107 */
108 [[nodiscard]] std::optional<CompositeSlice> slice(const Region& region) const
109 {
110 return m_data.slice(region);
111 }
112
113 /**
114 * @brief Copy the next bounded window into independent storage.
115 * @return True if a nonempty window was copied; false at the end or if
116 * an element could not be copied. On failure, the prior window and current
117 * position are preserved.
118 * @note Selected text is copied into the window's own text store.
119 */
120 [[nodiscard]] bool materialize_next();
121
122 /**
123 * @brief Set the next source position for materialize_next().
124 * @param row Zero-based element index, clamped to the array size.
125 */
126 void seek(size_t row) noexcept { m_next_element = std::min(row, m_data.size()); }
127
128 /** @brief Next element index for materialize_next(). */
129 [[nodiscard]] size_t position() const noexcept { return m_next_element; }
130
131 /** @brief Whether materialize_next() has no more elements. */
132 [[nodiscard]] bool at_end() const noexcept { return m_next_element >= m_data.size(); }
133
134 /**
135 * @brief Set the maximum number of elements copied per call.
136 * @param rows Maximum window size; zero is normalized to one.
137 */
138 void set_batch_size(size_t rows) noexcept { m_batch_size = rows == 0 ? 1 : rows; }
139
140 /** @brief Maximum elements copied by one materialize_next() call. */
141 [[nodiscard]] size_t batch_size() const noexcept { return m_batch_size; }
142
143 /** @brief Describe the array's element axis. */
144 [[nodiscard]] std::vector<DataDimension> get_dimensions() const override;
145
146 /** @brief Number of composite elements. */
147 [[nodiscard]] uint64_t get_total_elements() const override { return m_data.size(); }
148
149 /** @brief Packed composite elements use row-major storage. */
150 [[nodiscard]] MemoryLayout get_memory_layout() const override { return MemoryLayout::ROW_MAJOR; }
151
152 /** @brief Layout changes are not supported for packed composite elements. */
154
155 /** @brief This container has no frame axis. */
156 [[nodiscard]] uint64_t get_frame_size() const override { return 0; }
157
158 /** @brief This container has no frame axis. */
159 [[nodiscard]] uint64_t get_num_frames() const override { return 0; }
160
161 /**
162 * @brief Copy a one-dimensional Region into an owning CompositeArray.
163 * @param region Inclusive element range.
164 * @return One array containing the selected elements, or empty on failure.
165 */
166 [[nodiscard]] std::vector<CompositeArray> get_region_data(const Region& region) const override;
167
168 /**
169 * @brief Copy the valid regions of a group into separate arrays.
170 * @param group Regions to select.
171 * @return One owning array per valid region; shorter than
172 * group.regions.size() when a region fails to slice or copy, since
173 * failures are skipped rather than represented as an empty entry.
174 */
175 [[nodiscard]] std::vector<CompositeArray> get_region_group_data(const RegionGroup& group) const override;
176
177 /**
178 * @brief Copy valid one-dimensional segments into separate arrays.
179 * @param segments Source regions with offsets and element counts.
180 * @return One owning array per valid segment; shorter than
181 * segments.size() when a segment is malformed, out of bounds, or fails
182 * to copy, since failures are skipped rather than represented as an
183 * empty entry.
184 */
185 [[nodiscard]] std::vector<CompositeArray> get_segments_data(const std::vector<RegionSegment>& segments) const override;
186
187 /**
188 * @brief Replace a Region with an equal number of compatible elements.
189 * @param region Inclusive destination range.
190 * @param data Arrays whose combined element count must equal the range.
191 * @note Invalid ranges, counts, or layouts leave the source unchanged.
192 */
193 void set_region_data(const Region& region, const std::vector<CompositeArray>& data) override;
194
195 /** @brief Composite elements have no single scalar value type. */
196 [[nodiscard]] std::type_index value_element_type() const override { return typeid(void); }
197
198 /** @brief Store or replace a named region group. */
199 void add_region_group(const RegionGroup& group) override;
200
201 /** @brief Return a named region group, or an empty group if absent. */
202 [[nodiscard]] RegionGroup get_region_group(const std::string& name) const override;
203
204 /** @brief Copy all named region groups. */
205 [[nodiscard]] std::unordered_map<std::string, RegionGroup> get_all_region_groups() const override
206 {
207 return m_region_groups;
208 }
209
210 /** @brief Remove a named region group if present. */
211 void remove_region_group(const std::string& name) override;
212
213 /** @brief Valid element regions are already resident in the array. */
214 [[nodiscard]] bool is_region_loaded(const Region& region) const override;
215
216 /** @brief Elements are already resident in the array. */
217 void load_region(const Region&) override { }
218
219 /** @brief Elements remain resident until clear() is called. */
220 void unload_region(const Region&) override { }
221
222 /** @brief Map an element coordinate to its linear index. */
223 [[nodiscard]] uint64_t coordinates_to_linear_index(const std::vector<uint64_t>& coordinates) const override;
224
225 /** @brief Map a linear element index to one-dimensional coordinates. */
226 [[nodiscard]] std::vector<uint64_t> linear_index_to_coordinates(uint64_t linear_index) const override;
227
228 /** @brief Remove all elements while retaining the field layout. */
229 void clear() override;
230
231 /** @brief Borrow the packed element bytes, or nullptr when empty. */
232 [[nodiscard]] const void* get_raw_data() const override;
233
234 /** @brief Whether the array contains any elements. */
235 [[nodiscard]] bool has_data() const override { return !m_data.empty(); }
236
237 /** @brief Mutable dimensional metadata. */
238 [[nodiscard]] ContainerDataStructure& get_structure() override { return m_structure; }
239
240 /** @brief Dimensional metadata. */
241 [[nodiscard]] const ContainerDataStructure& get_structure() const override { return m_structure; }
242
243 /** @brief Replace dimensional metadata. */
244 void set_structure(ContainerDataStructure structure) override { m_structure = std::move(structure); }
245
246protected:
247 /** @brief No frame span is available for composite elements. */
248 [[nodiscard]] auto get_frame_span_impl(uint64_t) const -> DataSpanVariant override
249 {
250 return std::span<const uint8_t> {};
251 }
252
253 /** @brief No frame copies are available for composite elements. */
254 void get_frames_impl(void*, size_t, uint64_t, uint64_t, const std::type_info&) const override { }
255
256 /** @brief Read fields through Composite::get() or Composite::text(). */
257 void get_value_impl(const std::vector<uint64_t>&, void*, const std::type_info&) const override { }
258
259 /** @brief Write fields through CompositeInsertion. */
260 void set_value_impl(const std::vector<uint64_t>&, const void*, const std::type_info&) override { }
261
262private:
265 size_t m_next_element {};
267 ContainerDataStructure m_structure { DataModality::TENSOR_ND, OrganizationStrategy::INTERLEAVED };
268 std::unordered_map<std::string, RegionGroup> m_region_groups;
269};
270
271}
uint32_t rows
std::string name
Definition VKDevice.cpp:123
size_t count
Owns a sequence of values that share a CompositeLayout.
const ContainerDataStructure & get_structure() const override
Dimensional metadata.
std::unordered_map< std::string, RegionGroup > m_region_groups
void set_batch_size(size_t rows) noexcept
Set the maximum number of elements copied per call.
void load_region(const Region &) override
Elements are already resident in the array.
void get_frames_impl(void *, size_t, uint64_t, uint64_t, const std::type_info &) const override
No frame copies are available for composite elements.
std::optional< CompositeSlice > slice(const Region &region) const
Borrow elements selected by a one-dimensional Region.
void set_value_impl(const std::vector< uint64_t > &, const void *, const std::type_info &) override
Write fields through CompositeInsertion.
void unload_region(const Region &) override
Elements remain resident until clear() is called.
void seek(size_t row) noexcept
Set the next source position for materialize_next().
MemoryLayout get_memory_layout() const override
Packed composite elements use row-major storage.
uint64_t get_num_frames() const override
This container has no frame axis.
void set_memory_layout(MemoryLayout) override
Layout changes are not supported for packed composite elements.
const CompositeArray & get_materialized_data() const noexcept
Borrow the most recently materialized owning window.
std::type_index value_element_type() const override
Composite elements have no single scalar value type.
const CompositeArray & get_data() const noexcept
Borrow the complete array.
CompositeInsertion insert() noexcept
Create an insertion adapter for the array.
uint64_t get_frame_size() const override
This container has no frame axis.
auto get_frame_span_impl(uint64_t) const -> DataSpanVariant override
No frame span is available for composite elements.
DataFieldTraversal< CompositeArray > traverse(size_t batch_size=1) const noexcept
Create an independent traversal over elements.
ContainerDataStructure & get_structure() override
Mutable dimensional metadata.
uint64_t get_total_elements() const override
Number of composite elements.
bool has_data() const override
Whether the array contains any elements.
std::optional< CompositeSlice > slice(size_t start, size_t count) const
Borrow consecutive elements without copying.
bool at_end() const noexcept
Whether materialize_next() has no more elements.
size_t batch_size() const noexcept
Maximum elements copied by one materialize_next() call.
size_t position() const noexcept
Next element index for materialize_next().
void get_value_impl(const std::vector< uint64_t > &, void *, const std::type_info &) const override
Read fields through Composite::get() or Composite::text().
void set_structure(ContainerDataStructure structure) override
Replace dimensional metadata.
std::unordered_map< std::string, RegionGroup > get_all_region_groups() const override
Copy all named region groups.
Owns composite data and a bounded, independently owned window.
Mutable insertion adapter for a CompositeArray.
Shared field description and byte layout for a CompositeArray.
Definition Composite.hpp:52
On-demand windowing and field operations over an indexed array.
Abstract interface for N-dimensional data containers.
void remove_region_group(std::unordered_map< std::string, RegionGroup > &groups, const std::string &name)
Remove a RegionGroup by name from a group map.
std::optional< RegionGroup > get_region_group(const std::unordered_map< std::string, RegionGroup > &groups, const std::string &name)
Get a RegionGroup by name from a group map.
typename detail::span_const_from_vector_variant< DataVariant >::type DataSpanVariant
Definition NDData.hpp:625
MemoryLayout
Memory layout for multi-dimensional data.
Definition NDData.hpp:33
void add_region_group(std::unordered_map< std::string, RegionGroup > &groups, const RegionGroup &group)
Add a RegionGroup to a group map.
Container structure for consistent dimension ordering.
Organizes related signal regions into a categorized collection.
Represents a point or span in N-dimensional space.
Definition Region.hpp:73