8{
9 const auto& source_layout =
source.layout();
11
12 if (source_layout.stride_bytes() != target_layout.stride_bytes()
13 || source_layout.fields().size() != target_layout.fields().size()) {
15 "CompositeInsertion: incompatible layout");
16 return std::nullopt;
17 }
18
19 for (
size_t i = 0; i < target_layout.fields().
size(); ++i) {
20 const auto&
src = source_layout.fields()[i];
21 const auto&
dst = target_layout.fields()[i];
23 ||
src.offset_bytes !=
dst.offset_bytes ||
src.size_bytes !=
dst.size_bytes) {
25 "CompositeInsertion: incompatible field '{}'",
dst.name);
26 return std::nullopt;
27 }
28 }
29
30 const auto& source_elements = std::get<std::vector<uint8_t>>(*
source.m_rows);
31 const size_t stride = target_layout.stride_bytes();
32 const auto element_begin = source_elements.begin() +
static_cast<ptrdiff_t
>(
source.m_index * stride);
33
34 std::vector<uint8_t> element(element_begin, element_begin + static_cast<ptrdiff_t>(stride));
35 std::vector<std::pair<size_t, std::string>> texts;
36 std::vector<std::pair<size_t, std::vector<uint8_t>>> blobs;
37 size_t additional_text = 0;
38 size_t additional_blob = 0;
39
40 for (
size_t i = 0; i < source_layout.fields().
size(); ++i) {
41 const auto& field = source_layout.fields()[i];
42 if (!
source.has(field.name))
43 continue;
44 if (field.type ==
typeid(detail::CompositeDynamic) && !
source.value(field.name))
45 return std::nullopt;
46 if (field.type == typeid(std::string)
47 || (field.type ==
typeid(detail::CompositeDynamic) &&
source.text(field.name))) {
49 if (!
value ||
value->size() > std::numeric_limits<size_t>::max() - additional_text)
50 return std::nullopt;
51 additional_text +=
value->size();
52 texts.emplace_back(i, std::string(*
value));
53 } else if (field.type == typeid(std::vector<uint8_t>)
54 || (field.type ==
typeid(detail::CompositeDynamic) &&
source.blob(field.name))) {
56 if (!
value ||
value->size() > std::numeric_limits<size_t>::max() - additional_blob)
57 return std::nullopt;
58 additional_blob +=
value->size();
59 blobs.emplace_back(i, std::vector<uint8_t>(
value->begin(),
value->end()));
60 }
61 }
62
63 auto& target_elements = std::get<std::vector<uint8_t>>(
m_array->
m_rows);
64 auto& target_text = std::get<std::vector<uint8_t>>(
m_array->
m_text);
65 auto& target_blob = std::get<std::vector<uint8_t>>(
m_array->
m_blob);
66
67 if (stride > target_elements.max_size() - target_elements.size()
68 || additional_text > target_text.max_size() - target_text.size()
69 || additional_blob > target_blob.max_size() - target_blob.size())
70 return std::nullopt;
71
72 target_elements.reserve(target_elements.size() + stride);
73 target_text.reserve(target_text.size() + additional_text);
74 target_blob.reserve(target_blob.size() + additional_blob);
75
77 std::memcpy(target_elements.data() +
index * stride, element.data(), stride);
78
79 for (
const auto& [field_index,
value] : texts)
81 for (
const auto& [field_index,
value] : blobs)
83
85}
#define MF_WARN(comp, ctx,...)
size_t append()
Append one zero-initialized element with no fields present.
bool set_text(size_t index, std::string_view field_name, std::string_view value)
Write UTF-8 bytes to a std::string field.
bool set_blob(size_t index, std::string_view field_name, std::span< const uint8_t > value)
Write binary bytes to a fixed or dynamic BLOB field.
@ Runtime
General runtime operations (default fallback)
@ Kakshya
Containers[Signalsource, Stream, File], Regions, DataProcessors.