Skip to content

Commit 74337f0

Browse files
committed
Move C++ layer to Node Tree architecture and delete CompactStructStore
1 parent ace342b commit 74337f0

31 files changed

Lines changed: 253 additions & 755 deletions

‎cpp/mexfunctions/readtomlMex.cpp‎

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class MexFunction : public matlab::mex::Function {
2929
std::istringstream iss(std::move(content));
3030
toml::ordered_value data = toml::parse<toml::ordered_type_config>(iss, filename);
3131

32-
outputs[0] = tableToCompactStruct(data);
32+
outputs[0] = tableToNode(data);
3333
}
3434

3535
private:
@@ -55,47 +55,33 @@ class MexFunction : public matlab::mex::Function {
5555
}
5656
}
5757

58-
matlab::data::Array tableToCompactStruct(const toml::ordered_value& table) {
58+
matlab::data::Array tableToNode(const toml::ordered_value& table) {
5959
const auto& tbl = table.as_table();
6060
size_t n = tbl.size();
6161

6262
auto keys = factory.createArray<matlab::data::MATLABString>({1, n});
6363
auto values = factory.createArray<matlab::data::Array>({1, n});
64-
std::vector<double> nullIdx, datetimeIdx;
6564

6665
size_t i = 0;
6766
for (const auto& [key, val] : tbl) {
6867
keys[0][i] = utf8ToMATLABString(key);
6968

7069
if (val.type() == toml::value_t::table) {
71-
values[0][i] = tableToCompactStruct(val);
70+
values[0][i] = tableToNode(val);
7271
} else if (val.type() == toml::value_t::array) {
7372
values[0][i] = convertArray(val.as_array());
7473
} else if (isDatetimeType(val.type())) {
75-
datetimeIdx.push_back(static_cast<double>(i + 1));
76-
values[0][i] = factory.createScalar(utf8ToMATLABString(datetimeToString(val)));
74+
values[0][i] = makeValueNode(factory,
75+
factory.createScalar(
76+
utf8ToMATLABString(datetimeToString(val))),
77+
"datetime");
7778
} else {
7879
values[0][i] = convertScalar(val);
7980
}
8081
++i;
8182
}
8283

83-
auto nullArr = toDoubleArray(nullIdx);
84-
auto dtArr = toDoubleArray(datetimeIdx);
85-
auto emptyArr = factory.createArray<double>({1, 0});
86-
87-
return makeCompactStruct(factory, keys, values, nullArr, dtArr, emptyArr);
88-
}
89-
90-
matlab::data::Array toDoubleArray(const std::vector<double>& vec) {
91-
if (vec.empty()) {
92-
return factory.createArray<double>({1, 0});
93-
}
94-
auto arr = factory.createArray<double>({1, vec.size()});
95-
for (size_t i = 0; i < vec.size(); ++i) {
96-
arr[0][i] = vec[i];
97-
}
98-
return arr;
84+
return makeTableNode(factory, keys, values);
9985
}
10086

10187
matlab::data::Array convertScalar(const toml::value& val) {
@@ -129,7 +115,7 @@ class MexFunction : public matlab::mex::Function {
129115
size_t count = arr.size();
130116
auto out = factory.createArray<matlab::data::Array>({1, count});
131117
for (size_t i = 0; i < count; ++i) {
132-
out[0][i] = tableToCompactStruct(arr[i]);
118+
out[0][i] = tableToNode(arr[i]);
133119
}
134120
return out;
135121
}
@@ -171,7 +157,7 @@ class MexFunction : public matlab::mex::Function {
171157
elems.reserve(arr.size());
172158
for (const auto& elem : arr) {
173159
if (elem.type() == toml::value_t::table) {
174-
elems.push_back(tableToCompactStruct(elem));
160+
elems.push_back(tableToNode(elem));
175161
} else if (elem.type() == toml::value_t::array) {
176162
elems.push_back(convertArray(elem.as_array()));
177163
} else if (isDatetimeType(elem.type())) {

‎cpp/mexfunctions/readyamlMex.cpp‎

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class MexFunction : public matlab::mex::Function {
4848
if (root.num_children() > 0) {
4949
outputs[0] = convertNode(root.first_child());
5050
} else {
51-
outputs[0] = makeEmptyCompactStruct();
51+
outputs[0] = makeEmptyTableNode();
5252
}
5353
} else {
5454
outputs[0] = convertNode(root);
@@ -60,12 +60,10 @@ class MexFunction : public matlab::mex::Function {
6060
return std::string(s.data(), s.size());
6161
}
6262

63-
matlab::data::Array makeEmptyCompactStruct() {
63+
matlab::data::Array makeEmptyTableNode() {
6464
auto keys = factory.createArray<matlab::data::MATLABString>({1, 0});
6565
auto values = factory.createArray<matlab::data::Array>({1, 0});
66-
auto empty = factory.createArray<double>({1, 0});
67-
68-
return makeCompactStruct(factory, keys, values, empty, empty, empty);
66+
return makeTableNode(factory, keys, values);
6967
}
7068

7169
// --- YAML 1.1 boolean detection ---
@@ -150,15 +148,14 @@ class MexFunction : public matlab::mex::Function {
150148
if (node.has_val()) {
151149
return convertTypedScalar(node);
152150
}
153-
return makeEmptyCompactStruct();
151+
return makeEmptyTableNode();
154152
}
155153

156154
matlab::data::Array convertMap(ryml::ConstNodeRef node) {
157155
size_t n = node.num_children();
158156

159157
auto keys = factory.createArray<matlab::data::MATLABString>({1, n});
160158
auto values = factory.createArray<matlab::data::Array>({1, n});
161-
std::vector<double> nullIdx;
162159

163160
size_t i = 0;
164161
for (ryml::ConstNodeRef child : node.children()) {
@@ -170,33 +167,19 @@ class MexFunction : public matlab::mex::Function {
170167
values[0][i] = convertSequence(child);
171168
} else if (child.has_val()) {
172169
if (child.val_is_null()) {
173-
nullIdx.push_back(static_cast<double>(i + 1));
174-
values[0][i] = factory.createArray<double>({0, 0});
170+
values[0][i] = makeValueNode(factory,
171+
factory.createArray<double>({0, 0}), "missing");
175172
} else {
176173
values[0][i] = convertTypedScalar(child);
177174
}
178175
} else {
179-
nullIdx.push_back(static_cast<double>(i + 1));
180-
values[0][i] = factory.createArray<double>({0, 0});
176+
values[0][i] = makeValueNode(factory,
177+
factory.createArray<double>({0, 0}), "missing");
181178
}
182179
++i;
183180
}
184181

185-
auto nullArr = toDoubleArray(nullIdx);
186-
auto emptyArr = factory.createArray<double>({1, 0});
187-
188-
return makeCompactStruct(factory, keys, values, nullArr, emptyArr, emptyArr);
189-
}
190-
191-
matlab::data::Array toDoubleArray(const std::vector<double>& vec) {
192-
if (vec.empty()) {
193-
return factory.createArray<double>({1, 0});
194-
}
195-
auto arr = factory.createArray<double>({1, vec.size()});
196-
for (size_t i = 0; i < vec.size(); ++i) {
197-
arr[0][i] = vec[i];
198-
}
199-
return arr;
182+
return makeTableNode(factory, keys, values);
200183
}
201184

202185
matlab::data::Array convertSequence(ryml::ConstNodeRef node) {
@@ -232,10 +215,6 @@ class MexFunction : public matlab::mex::Function {
232215
elems.push_back(convertNode(child));
233216
}
234217

235-
if (sequenceAsCell) {
236-
return makeCellArray(elems, count);
237-
}
238-
239218
return makeCellArray(elems, count);
240219
}
241220

‎cpp/mexfunctions/util.hpp‎

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,32 @@ void throwMexError(
1414
const std::string& id,
1515
const std::string& msg);
1616

17-
inline matlab::data::StructArray makeCompactStruct(
17+
inline matlab::data::StructArray makeTableNode(
1818
matlab::data::ArrayFactory& factory,
1919
matlab::data::Array keys,
20-
matlab::data::Array values,
21-
matlab::data::Array nullIndices,
22-
matlab::data::Array datetimeIndices,
23-
matlab::data::Array quotedIndices) {
24-
auto cs = factory.createStructArray({1, 1},
25-
{"Keys", "Values", "NullIndices", "DatetimeIndices", "QuotedIndices"});
26-
cs[0]["Keys"] = std::move(keys);
27-
cs[0]["Values"] = std::move(values);
28-
cs[0]["NullIndices"] = std::move(nullIndices);
29-
cs[0]["DatetimeIndices"] = std::move(datetimeIndices);
30-
cs[0]["QuotedIndices"] = std::move(quotedIndices);
31-
return cs;
20+
matlab::data::Array values) {
21+
auto node = factory.createStructArray({1, 1}, {"Keys", "Values"});
22+
node[0]["Keys"] = std::move(keys);
23+
node[0]["Values"] = std::move(values);
24+
return node;
25+
}
26+
27+
inline matlab::data::StructArray makeValueNode(
28+
matlab::data::ArrayFactory& factory,
29+
matlab::data::Array data,
30+
const std::string& type) {
31+
auto node = factory.createStructArray({1, 1}, {"Data", "Type"});
32+
node[0]["Data"] = std::move(data);
33+
node[0]["Type"] = factory.createScalar(utf8ToMATLABString(type));
34+
return node;
35+
}
36+
37+
inline bool structHasField(
38+
const matlab::data::StructArray& sa,
39+
const std::string& name) {
40+
matlab::data::MATLABFieldIdentifier target(name);
41+
for (const auto& f : sa.getFieldNames()) {
42+
if (f == target) return true;
43+
}
44+
return false;
3245
}

‎cpp/mexfunctions/writetomlMex.cpp‎

Lines changed: 72 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "toml.hpp"
44

55
#include <cmath>
6+
#include <sstream>
67
#include <vector>
78

89
using matlab::data::ArrayType;
@@ -26,7 +27,7 @@ class MexFunction : public matlab::mex::Function {
2627
if (inputs.size() < 1) {
2728
throwMexError(*engine, factory,
2829
"writetomlMex:InvalidInput",
29-
"CompactStruct data required.");
30+
"Node tree data required.");
3031
return;
3132
}
3233

@@ -95,68 +96,67 @@ class MexFunction : public matlab::mex::Function {
9596
getOptionDouble(opts, "Precision"));
9697
}
9798

98-
// --- Index set helper ---
99+
// --- Node tree dispatch ---
99100

100-
static std::vector<bool> buildIndexSet(
101-
const matlab::data::Array& indices, size_t n) {
102-
std::vector<bool> flags(n + 1, false);
103-
if (indices.getNumberOfElements() > 0) {
104-
matlab::data::TypedArray<double> idx = indices;
105-
for (auto v : idx) {
106-
size_t i = static_cast<size_t>(v);
107-
if (i >= 1 && i <= n) flags[i] = true;
108-
}
109-
}
110-
return flags;
111-
}
112-
113-
// --- Conversion from CompactStruct ---
114-
115-
toml::ordered_value convertTable(const matlab::data::Array& csArr) {
116-
matlab::data::StructArray cs(csArr);
101+
toml::ordered_value convertTable(const matlab::data::Array& nodeArr) {
102+
matlab::data::StructArray node(nodeArr);
117103

118104
matlab::data::TypedArray<matlab::data::MATLABString> keys =
119-
cs[0]["Keys"];
105+
node[0]["Keys"];
120106
matlab::data::TypedArray<matlab::data::Array> values =
121-
cs[0]["Values"];
107+
node[0]["Values"];
122108

123109
size_t n = keys.getNumberOfElements();
124-
auto isNull = buildIndexSet(cs[0]["NullIndices"], n);
125-
auto isDt = buildIndexSet(cs[0]["DatetimeIndices"], n);
126-
127110
toml::ordered_table tbl;
111+
128112
for (size_t i = 0; i < n; ++i) {
129113
std::string key = matlabStringToUtf8(keys[i]);
130-
131-
if (isNull[i + 1]) {
132-
continue;
133-
}
134-
135114
matlab::data::Array val = values[i];
136115

137-
if (isDt[i + 1]) {
138-
tbl.push_back({key, convertDatetime(val)});
139-
} else {
140-
tbl.push_back({key, convert(val)});
141-
}
116+
if (isMissingNode(val)) continue;
117+
118+
tbl.push_back({key, convert(val)});
142119
}
143120

144121
return toml::ordered_value(std::move(tbl));
145122
}
146123

124+
bool isMissingNode(const matlab::data::Array& val) {
125+
if (val.getType() != ArrayType::STRUCT) return false;
126+
matlab::data::StructArray sa(val);
127+
if (!structHasField(sa, "Data")) return false;
128+
if (!structHasField(sa, "Type")) return false;
129+
matlab::data::TypedArray<matlab::data::MATLABString> typeArr =
130+
sa[0]["Type"];
131+
return matlabStringToUtf8(typeArr[0]) == "missing";
132+
}
133+
147134
toml::ordered_value convert(const matlab::data::Array& val) {
148135
auto type = val.getType();
149136
size_t numel = val.getNumberOfElements();
150137

151138
if (type == ArrayType::STRUCT) {
152-
return convertTable(val);
139+
matlab::data::StructArray sa(val);
140+
if (structHasField(sa, "Keys")) {
141+
return convertTable(val);
142+
}
143+
if (structHasField(sa, "Data")) {
144+
return convertValueNodeData(sa);
145+
}
146+
throwMexError(*engine, factory,
147+
"writetomlMex:UnrecognizedNode",
148+
"Unrecognized struct in node tree.");
149+
return toml::ordered_value();
153150
}
154151

155152
if (type == ArrayType::CELL) {
156153
matlab::data::TypedArray<matlab::data::Array> cells = val;
157154
if (numel > 0 &&
158155
cells[0].getType() == ArrayType::STRUCT) {
159-
return convertObjectArray(val, numel);
156+
matlab::data::StructArray firstSa(cells[0]);
157+
if (structHasField(firstSa, "Keys")) {
158+
return convertObjectArray(val, numel);
159+
}
160160
}
161161
return convertCellArray(val, numel);
162162
}
@@ -221,6 +221,42 @@ class MexFunction : public matlab::mex::Function {
221221
}
222222
}
223223

224+
// --- ValueNode handling ---
225+
226+
toml::ordered_value convertValueNodeData(
227+
const matlab::data::StructArray& node) {
228+
if (structHasField(node, "Type")) {
229+
matlab::data::TypedArray<matlab::data::MATLABString> typeArr =
230+
node[0]["Type"];
231+
std::string nodeType = matlabStringToUtf8(typeArr[0]);
232+
233+
if (nodeType == "missing") {
234+
return toml::ordered_value();
235+
}
236+
237+
if (nodeType == "datetime") {
238+
matlab::data::Array data = node[0]["Data"];
239+
if (data.getType() == ArrayType::MATLAB_STRING) {
240+
std::string dtStr = matlabStringToUtf8(
241+
matlab::data::TypedArray<matlab::data::MATLABString>(
242+
data)[0]);
243+
return parseDatetimeFromString(dtStr);
244+
}
245+
return convertDatetime(data);
246+
}
247+
}
248+
249+
matlab::data::Array data = node[0]["Data"];
250+
return convert(data);
251+
}
252+
253+
toml::ordered_value parseDatetimeFromString(const std::string& dtStr) {
254+
std::string doc = "v = " + dtStr + "\n";
255+
std::istringstream iss(doc);
256+
auto parsed = toml::parse<toml::ordered_type_config>(iss, "");
257+
return parsed.at("v");
258+
}
259+
224260
// --- Scalar converters ---
225261

226262
toml::ordered_value convertDouble(double v) {

0 commit comments

Comments
 (0)