161 using variant_type = multi_array_variant_t<T, g_table_max_dimensions>;
163 template <
typename OutputPort>
164 static bool read(variant_type& buffer,
const index_vec_type& cursor, OutputPort& output)
167 [&](
auto& arr) ->
bool {
168 constexpr std::size_t Dim = std::remove_reference_t<
decltype(arr)>::dimensionality;
170 if(cursor.size() != Dim)
173 if(arr.num_elements() == 0)
176 const auto* shape = arr.shape();
186 static void set(variant_type& buffer,
const index_vec_type& cursor,
const T& value)
190 constexpr std::size_t Dim = std::remove_reference_t<
decltype(arr)>::dimensionality;
192 if(cursor.size() != Dim)
198 const auto* shape = arr.shape();
203 boost::array<std::size_t, Dim> new_extents;
204 if(arr.num_elements() == 0)
206 for(std::size_t i = 0; i < Dim; ++i)
207 new_extents[i] =
static_cast<std::size_t
>(cursor[i]) + 1;
213 arr.resize(new_extents);
221 static extent_vec_type get_shape(
const variant_type& buffer)
224 [](
const auto& arr) -> extent_vec_type {
225 constexpr std::size_t Dim = std::remove_reference_t<
decltype(arr)>::dimensionality;
226 extent_vec_type result;
227 const auto* shape = arr.shape();
228 for(std::size_t i = 0; i < Dim; ++i)
229 result.push_back(shape[i]);
235 static std::size_t num_elements(
const variant_type& buffer)
237 return ossia::visit([](
const auto& arr) {
return arr.num_elements(); }, buffer);
240 static void clear(variant_type& buffer)
244 constexpr std::size_t Dim = std::remove_reference_t<
decltype(arr)>::dimensionality;
245 boost::array<std::size_t, Dim> zero_extents;
246 zero_extents.fill(0);
247 arr.resize(zero_extents);
252 static void resize(variant_type& buffer,
const extent_vec_type& extents)
256 constexpr std::size_t Dim = std::remove_reference_t<
decltype(arr)>::dimensionality;
258 if(extents.size() != Dim)
261 boost::array<std::size_t, Dim> new_extents;
262 for(std::size_t i = 0; i < Dim; ++i)
263 new_extents[i] = extents[i];
264 arr.resize(new_extents);
269 static void fill(variant_type& buffer,
const T& value)
272 [&](
auto& arr) { std::fill(arr.data(), arr.data() + arr.num_elements(), value); },
276 static std::vector<T> to_vector(
const variant_type& buffer)
279 [](
const auto& arr) -> std::vector<T> {
280 return std::vector<T>(arr.data(), arr.data() + arr.num_elements());
287 static ossia::value dump(
const variant_type& buffer)
290 [](
const auto& arr) -> ossia::value {
291 constexpr std::size_t Dim
292 = std::remove_reference_t<
decltype(arr)>::dimensionality;
293 return dump_impl<Dim>(arr);
300 template <std::
size_t Dim,
typename Array>
301 static ossia::value dump_impl(
const Array& arr)
303 const auto* shape = arr.shape();
305 if constexpr(Dim == 1)
308 std::vector<ossia::value> result;
309 result.reserve(shape[0]);
310 for(std::size_t i = 0; i < shape[0]; ++i)
311 result.push_back(arr[i]);
317 std::vector<ossia::value> result;
318 result.reserve(shape[0]);
319 for(std::size_t i = 0; i < shape[0]; ++i)
321 result.push_back(dump_impl<Dim - 1>(arr[i]));
331 using variant_type = multi_array_variant_t<T, g_table_max_dimensions>;
333 static void change_dimensions(variant_type& buffer, std::size_t new_dims)
335 if(new_dims < 1 || new_dims > g_table_max_dimensions)
339 boost::mp11::mp_with_index<g_table_max_dimensions>(new_dims - 1, [&](
auto I) {
340 constexpr std::size_t Dim = I.value + 1;
341 using new_array_type = boost::multi_array<T, Dim>;
344 new_array_type new_arr;
345 buffer = std::move(new_arr);
349 static std::size_t current_dimensions(
const variant_type& buffer)
352 [](
const auto& arr) -> std::size_t {
353 return std::remove_reference_t<
decltype(arr)>::dimensionality;
363 halp_meta(name,
"Table")
364 halp_meta(author,
"ossia team")
365 halp_meta(category,
"Control/Data processing")
366 halp_meta(description,
"Store arbitrary data in an N-dimensional table (1-16D)")
367 halp_meta(c_name,
"avnd_table_nd")
368 halp_meta(uuid,
"98418d3a-58c3-4d1f-b716-83c0988174c3")
369 halp_meta(manual_url,
"https://ossia.io/score-docs/processes/table.html")
371 using value_type = ossia::value;
377 struct : halp::val_port<
"Read", std::optional<index_vec_type>>
379 void update(
Table& t)
383 if(ops::read(t.buffer, *value, t.outputs.output))
386 t.outputs.output.value = ossia::value{};
390 struct : halp::val_port<
"Set cell", std::vector<ossia::value>>
392 void update(
Table& t)
398 const std::size_t dims = dim_changer::current_dimensions(t.buffer);
399 if(value.size() != dims + 1)
402 index_vec_type indices;
403 for(std::size_t i = 0; i < dims; i++)
404 indices.push_back(ossia::convert<int>(value[i]));
406 ops::set(t.buffer, indices, value.back());
410 struct : halp::val_port<
"Clear cell", index_vec_type>
412 void update(
Table& t) { t.clear_cell(value); }
415 struct : halp::val_port<
"Resize", extent_vec_type>
417 void update(
Table& t) { t.resize(value); }
420 struct : halp::val_port<
"Fill", ossia::value>
422 void update(
Table& t) { ops::fill(t.buffer, value); }
425 struct : halp::spinbox_i32<
"Dimensions", halp::range{1, 16, 1}>
427 void update(
Table& t)
429 if(value >= 1 && value <= 16)
431 const std::size_t current = dim_changer::current_dimensions(t.buffer);
432 if(
static_cast<std::size_t
>(value) != current)
434 dim_changer::change_dimensions(t.buffer, value);
439 halp::maintained_button<
"Clear"> clear;
440 halp::maintained_button<
"Lock"> lock;
441 struct : halp::impulse_button<
"Dump">
443 void update(
Table& t) { t.outputs.output.value = ops::dump(t.buffer); }
445 halp::toggle<
"Preserve"> preserve;
451 halp::val_port<
"Output", ossia::value> output;
452 halp::val_port<
"Shape", extent_vec_type> shape;
453 halp::val_port<
"Size", int64_t> size;
456 detail::multi_array_variant_t<value_type, g_table_max_dimensions> buffer;
458 void clear_cell(
const index_vec_type& indices)
460 ops::set(buffer, indices, ossia::value{});
463 void resize(
const extent_vec_type& extents)
465 const std::size_t current_dims = dim_changer::current_dimensions(buffer);
466 if(extents.size() != current_dims)
468 ops::resize(buffer, extents);
479 auto shape = ops::get_shape(buffer);
480 outputs.shape.value.clear();
482 outputs.shape.value.push_back(
static_cast<int64_t
>(s));
484 outputs.size.value =
static_cast<int64_t
>(ops::num_elements(buffer));