17 halp_meta(name,
"Table (2D)")
18 halp_meta(author,
"ossia team")
19 halp_meta(category,
"Control/Data processing")
20 halp_meta(description,
"Store arbitrary data in a 2-dimensional table")
21 halp_meta(c_name,
"avnd_table_2d")
22 halp_meta(uuid,
"b8c4d2e3-5f60-7890-bcde-f01234567892")
23 halp_meta(manual_url,
"https://ossia.io/score-docs/processes/table.html")
25 using value_type = ossia::value;
26 using array_type = boost::multi_array<value_type, 2>;
30 struct : halp::val_port<
"Read", std::optional<std::pair<int64_t, int64_t>>>
36 if(t.read(value->first, value->second))
39 t.outputs.output.value = ossia::value{};
43 struct : halp::val_port<
"Read row", std::optional<int64_t>>
48 t.outputs.row_output.value = t.get_row(*value);
52 struct : halp::val_port<
"Read column", std::optional<int64_t>>
57 t.outputs.column_output.value = t.get_column(*value);
61 struct : halp::val_port<
"Set cell", std::vector<ossia::value>>
68 const int64_t row = ossia::convert<int>(value[0]);
69 const int64_t col = ossia::convert<int>(value[1]);
70 t.set(row, col, value[2]);
74 struct : halp::val_port<
"Set row", std::pair<int64_t, ossia::value>>
76 void update(
Table2D& t) { t.set_row(value.first, value.second); }
79 struct : halp::val_port<
"Set column", std::pair<int64_t, ossia::value>>
81 void update(
Table2D& t) { t.set_column(value.first, value.second); }
84 struct : halp::val_port<
"Clear cell", std::pair<int64_t, int64_t>>
86 void update(
Table2D& t) { t.clear_cell(value.first, value.second); }
89 struct : halp::val_port<
"Clear row", int64_t>
91 void update(
Table2D& t) { t.clear_row(value); }
94 struct : halp::val_port<
"Clear column", int64_t>
96 void update(
Table2D& t) { t.clear_column(value); }
99 struct : halp::val_port<
"Insert row", std::pair<int64_t, ossia::value>>
101 void update(
Table2D& t) { t.insert_row(value.first, value.second); }
104 struct : halp::val_port<
"Insert column", std::pair<int64_t, ossia::value>>
106 void update(
Table2D& t) { t.insert_column(value.first, value.second); }
109 struct : halp::val_port<
"Erase row", int64_t>
111 void update(
Table2D& t) { t.erase_row(value); }
114 struct : halp::val_port<
"Erase column", int64_t>
116 void update(
Table2D& t) { t.erase_column(value); }
119 struct : halp::val_port<
"Append row", ossia::value>
121 void update(
Table2D& t) { t.append_row(value); }
124 struct : halp::val_port<
"Append column", ossia::value>
126 void update(
Table2D& t) { t.append_column(value); }
129 struct : halp::val_port<
"Resize", std::pair<int64_t, int64_t>>
131 void update(
Table2D& t) { t.resize(value.first, value.second); }
134 struct : halp::val_port<
"Fill", ossia::value>
136 void update(
Table2D& t) { t.fill(value); }
139 struct : halp::val_port<
"Transpose",
bool>
148 halp::maintained_button<
"Clear"> clear;
149 halp::maintained_button<
"Lock"> lock;
150 struct : halp::impulse_button<
"Dump">
152 void update(
Table2D& t) { t.outputs.output.value = t.dump(); }
154 halp::toggle<
"Preserve"> preserve;
159 halp::val_port<
"Output", ossia::value> output;
160 halp::val_port<
"Row", std::vector<ossia::value>> row_output;
161 halp::val_port<
"Column", std::vector<ossia::value>> column_output;
162 halp::val_port<
"Rows", int64_t> rows;
163 halp::val_port<
"Columns", int64_t> columns;
164 halp::val_port<
"Size", int64_t> size;
169 std::size_t num_rows()
const {
return buffer.shape()[0]; }
170 std::size_t num_cols()
const {
return buffer.shape()[1]; }
172 bool in_bounds(int64_t row, int64_t col)
const
174 if(row < 0 || col < 0)
176 return static_cast<std::size_t
>(row) < num_rows()
177 &&
static_cast<std::size_t
>(col) < num_cols();
180 bool read(int64_t row, int64_t col)
182 if(!in_bounds(row, col))
185 outputs.output.value = buffer[row][col];
189 void set(int64_t row, int64_t col,
const value_type& value)
191 if(row < 0 || col < 0 || row >= INT_MAX || col >= INT_MAX)
194 const std::size_t r =
static_cast<std::size_t
>(row);
195 const std::size_t c =
static_cast<std::size_t
>(col);
197 const std::size_t cur_rows = num_rows();
198 const std::size_t cur_cols = num_cols();
200 if(r >= cur_rows || c >= cur_cols)
202 const std::size_t new_rows = std::max(cur_rows, r + 1);
203 const std::size_t new_cols = std::max(cur_cols, c + 1);
204 buffer.resize(boost::extents[new_rows][new_cols]);
207 buffer[r][c] = value;
210 std::vector<ossia::value> get_row(int64_t row)
const
212 if(row < 0 ||
static_cast<std::size_t
>(row) >= num_rows())
215 std::vector<ossia::value> result;
216 result.reserve(num_cols());
217 for(std::size_t c = 0; c < num_cols(); ++c)
218 result.push_back(buffer[row][c]);
222 std::vector<ossia::value> get_column(int64_t col)
const
224 if(col < 0 ||
static_cast<std::size_t
>(col) >= num_cols())
227 std::vector<ossia::value> result;
228 result.reserve(num_rows());
229 for(std::size_t r = 0; r < num_rows(); ++r)
230 result.push_back(buffer[r][col]);
234 void set_row(int64_t row,
const value_type& v)
236 if(row < 0 ||
static_cast<std::size_t
>(row) >= num_rows())
239 if(
auto* vec = v.target<std::vector<ossia::value>>())
241 const std::size_t count = std::min(vec->size(), num_cols());
242 for(std::size_t c = 0; c < count; ++c)
243 buffer[row][c] = (*vec)[c];
247 for(std::size_t c = 0; c < num_cols(); ++c)
252 void set_column(int64_t col,
const value_type& v)
254 if(col < 0 ||
static_cast<std::size_t
>(col) >= num_cols())
257 if(
auto* vec = v.target<std::vector<ossia::value>>())
259 const std::size_t count = std::min(vec->size(), num_rows());
260 for(std::size_t r = 0; r < count; ++r)
261 buffer[r][col] = (*vec)[r];
265 for(std::size_t r = 0; r < num_rows(); ++r)
270 void clear_cell(int64_t row, int64_t col)
272 if(!in_bounds(row, col))
274 buffer[row][col] = value_type{};
277 void clear_row(int64_t row)
279 if(row < 0 ||
static_cast<std::size_t
>(row) >= num_rows())
281 for(std::size_t c = 0; c < num_cols(); ++c)
282 buffer[row][c] = value_type{};
285 void clear_column(int64_t col)
287 if(col < 0 ||
static_cast<std::size_t
>(col) >= num_cols())
289 for(std::size_t r = 0; r < num_rows(); ++r)
290 buffer[r][col] = value_type{};
293 void insert_row(int64_t index,
const value_type& v)
298 const std::size_t idx =
static_cast<std::size_t
>(index);
299 const std::size_t rows = num_rows();
300 const std::size_t cols = num_cols();
305 buffer.resize(boost::extents[rows + 1][std::max(cols, std::size_t{1})]);
308 for(std::size_t r = rows; r > idx; --r)
309 for(std::size_t c = 0; c < buffer.shape()[1]; ++c)
310 buffer[r][c] = std::move(buffer[r - 1][c]);
313 if(
auto* vec = v.target<std::vector<ossia::value>>())
315 const std::size_t count = std::min(vec->size(), buffer.shape()[1]);
316 for(std::size_t c = 0; c < count; ++c)
317 buffer[idx][c] = (*vec)[c];
321 for(std::size_t c = 0; c < buffer.shape()[1]; ++c)
326 void insert_column(int64_t index,
const value_type& v)
331 const std::size_t idx =
static_cast<std::size_t
>(index);
332 const std::size_t rows = num_rows();
333 const std::size_t cols = num_cols();
339 buffer.resize(boost::extents[std::max(rows, std::size_t{1})][cols + 1]);
342 for(std::size_t r = 0; r < buffer.shape()[0]; ++r)
343 for(std::size_t c = cols; c > idx; --c)
344 buffer[r][c] = std::move(buffer[r][c - 1]);
347 if(
auto* vec = v.target<std::vector<ossia::value>>())
349 const std::size_t count = std::min(vec->size(), buffer.shape()[0]);
350 for(std::size_t r = 0; r < count; ++r)
351 buffer[r][idx] = (*vec)[r];
355 for(std::size_t r = 0; r < buffer.shape()[0]; ++r)
360 void erase_row(int64_t row)
362 if(row < 0 ||
static_cast<std::size_t
>(row) >= num_rows())
365 const std::size_t rows = num_rows();
366 const std::size_t cols = num_cols();
369 for(std::size_t r = row; r + 1 < rows; ++r)
370 for(std::size_t c = 0; c < cols; ++c)
371 buffer[r][c] = std::move(buffer[r + 1][c]);
373 buffer.resize(boost::extents[rows - 1][cols]);
376 void erase_column(int64_t col)
378 if(col < 0 ||
static_cast<std::size_t
>(col) >= num_cols())
381 const std::size_t rows = num_rows();
382 const std::size_t cols = num_cols();
384 for(std::size_t r = 0; r < rows; ++r)
385 for(std::size_t c = col; c + 1 < cols; ++c)
386 buffer[r][c] = std::move(buffer[r][c + 1]);
388 buffer.resize(boost::extents[rows][cols - 1]);
391 void append_row(
const value_type& v)
393 insert_row(
static_cast<int64_t
>(num_rows()), v);
396 void append_column(
const value_type& v)
398 insert_column(
static_cast<int64_t
>(num_cols()), v);
401 void resize(int64_t rows, int64_t cols)
403 if(rows < 0 || cols < 0)
406 boost::extents[
static_cast<std::size_t
>(rows)][
static_cast<std::size_t
>(cols)]);
409 void fill(
const value_type& value)
411 std::fill(buffer.data(), buffer.data() + buffer.num_elements(), value);
416 const std::size_t rows = num_rows();
417 const std::size_t cols = num_cols();
419 if(rows == 0 || cols == 0)
422 array_type new_buffer(boost::extents[cols][rows]);
424 for(std::size_t r = 0; r < rows; ++r)
425 for(std::size_t c = 0; c < cols; ++c)
426 new_buffer[c][r] = std::move(buffer[r][c]);
428 buffer = std::move(new_buffer);
431 void do_clear() { buffer.resize(boost::extents[0][0]); }
433 ossia::value dump()
const
435 std::vector<ossia::value> result;
436 const std::size_t rows = num_rows();
437 const std::size_t cols = num_cols();
439 result.reserve(rows);
440 for(std::size_t r = 0; r < rows; ++r)
442 std::vector<ossia::value> row;
444 for(std::size_t c = 0; c < cols; ++c)
445 row.push_back(buffer[r][c]);
446 result.push_back(std::move(row));
458 outputs.rows.value =
static_cast<int64_t
>(num_rows());
459 outputs.columns.value =
static_cast<int64_t
>(num_cols());
460 outputs.size.value =
static_cast<int64_t
>(buffer.num_elements());