6 std::vector<BlockName> keys;
7 for (
auto& [k, _] : this->data_)
13std::map<BlockName, DBNode::Value>
DBNode::getGroup(
const std::vector<BlockName>& keys)
const {
14 const DBNode* currentDBNode =
this;
15 for (
const auto& key : keys) {
16 auto it = std::find_if(currentDBNode->data_.begin(), currentDBNode->data_.end(),
17 [&](
const auto& pair) {
18 return pair.first == key;
20 if (it == currentDBNode->data_.end() || !std::holds_alternative<std::shared_ptr<DBNode>>(it->second)) {
21 std::stringstream path;
22 for(
auto& k : keys) path << k <<
" ";
23 throw std::runtime_error(
"Key path not found: " + path.str());
25 currentDBNode = std::get<std::shared_ptr<DBNode>>(it->second).
get();
27 return currentDBNode->data_;
30void DBNode::setGroup(
const std::vector<BlockName>& keys,
const std::map<BlockName, Value>& groupData) {
31 DBNode* currentDBNode =
this;
32 for (
const auto& key : keys) {
33 auto it = std::find_if(currentDBNode->data_.begin(), currentDBNode->data_.end(),
34 [&](
const auto& pair) {
35 return pair.first == key;
38 if (it == currentDBNode->data_.end()) {
39 currentDBNode->data_[key] = std::make_shared<DBNode>();
40 it = std::find_if(currentDBNode->data_.begin(), currentDBNode->data_.end(),
41 [&](
const auto& pair) {
42 return pair.first == key;
46 auto& value = it->second;
47 if (!std::holds_alternative<std::shared_ptr<DBNode>>(value)) {
48 value = std::make_shared<DBNode>();
50 currentDBNode = std::get<std::shared_ptr<DBNode>>(value).
get();
52 currentDBNode->data_ = groupData;
57 for (
auto it = data_.begin(); it != data_.end(); ++it) {
58 const auto& [key, value] = *it;
60 std::cout << std::string(level + 2,
' ') <<
"\"" << key <<
"\": ";
62 if (std::holds_alternative<std::vector<std::shared_ptr<DBNode>>>(value)) {
63 const auto& list = std::get<std::vector<std::shared_ptr<DBNode>>>(value);
65 bool isFinalList =
true;
66 for (
const auto& node : list) {
67 if (!node->contains(
"")) {
75 for (
size_t i = 0; i < list.size(); ++i) {
76 list[i]->printValue(list[i]->
get(
""), level + 4);
77 if (i < list.size() - 1) std::cout <<
", ";
83 for (
size_t i = 0; i < list.size(); ++i) {
84 std::cout << std::string(level + 4,
' ');
85 list[i]->printJSON(level + 4);
86 if (i < list.size() - 1) std::cout <<
",";
89 std::cout << std::string(level + 2,
' ') <<
"]";
92 printValue(value, level);
95 if (std::next(it) != data_.end()) {
100 std::cout << std::string(level,
' ') <<
"}";
107 for (
auto it = data_.begin(); it != data_.end(); ++it) {
108 const auto& key = it->first;
109 const auto& value = it->second;
111 os << std::string(level + 2,
' ') <<
"\"" << key <<
"\": ";
113 if (std::holds_alternative<std::vector<std::shared_ptr<DBNode>>>(value)) {
114 const auto& list = std::get<std::vector<std::shared_ptr<DBNode>>>(value);
116 bool isFinalList =
true;
117 for (
const auto& node : list) {
118 if (!node || !node->contains(
"")) { isFinalList =
false;
break; }
123 for (
size_t i = 0; i < list.size(); ++i) {
124 printValueToStream(os, list[i]->
get(
""), level + 4);
125 if (i + 1 < list.size()) os <<
", ";
130 for (
size_t i = 0; i < list.size(); ++i) {
131 os << std::string(level + 4,
' ');
132 list[i]->printJSONToStream(os, level + 4);
133 if (i + 1 < list.size()) os <<
",";
136 os << std::string(level + 2,
' ') <<
"]";
139 printValueToStream(os, value, level);
142 if (std::next(it) != data_.end()) os <<
",";
145 os << std::string(level,
' ') <<
"}";
149 for (
const auto& [key, value] : data_) {
150 if (std::holds_alternative<std::vector<std::shared_ptr<DBNode>>>(value)) {
151 const auto& list = std::get<std::vector<std::shared_ptr<DBNode>>>(value);
152 std::cout << std::string(level,
' ') << key <<
":\n";
154 bool isFinalList =
true;
155 for (
const auto& node : list) {
156 if (!node || !node->contains(
"")) { isFinalList =
false;
break; }
160 for (
const auto& node : list) {
161 std::cout << std::string(level + 2,
' ') <<
"- ";
162 printScalarYAML(node->get(
""));
166 for (
const auto& node : list) {
167 std::cout << std::string(level + 2,
' ') <<
"- ";
170 node->printYAML(level + 4);
172 std::cout <<
"null\n";
179 if (std::holds_alternative<std::shared_ptr<DBNode>>(value)) {
180 auto child = std::get<std::shared_ptr<DBNode>>(value);
181 std::cout << std::string(level,
' ') << key <<
":\n";
182 if (child) child->printYAML(level + 2);
183 else std::cout << std::string(level + 2,
' ') <<
"null\n";
187 std::cout << std::string(level,
' ') << key <<
": ";
188 printScalarYAML(value);
193bool DBNode::isListDBNode(
const std::shared_ptr<DBNode>& node)
const {
194 if (!node || node->data_.empty())
return false;
195 return std::holds_alternative<std::vector<std::shared_ptr<DBNode>>>(node->data_.begin()->second);
199void DBNode::printValue(
const Value& value,
int level)
const {
200 if (std::holds_alternative<BlockName>(value)) {
201 std::cout <<
"\"" << std::get<BlockName>(value) <<
"\"";
202 }
else if (std::holds_alternative<int>(value)) {
203 std::cout << std::get<int>(value);
204 }
else if (std::holds_alternative<double>(value)) {
205 std::cout << std::get<double>(value);
206 }
else if (std::holds_alternative<bool>(value)) {
207 std::cout << (std::get<bool>(value) ?
"true" :
"false");
208 }
else if (std::holds_alternative<std::shared_ptr<DBNode>>(value)) {
209 std::get<std::shared_ptr<DBNode>>(value)->
printJSON(level + 2);
210 }
else if (std::holds_alternative<std::vector<std::shared_ptr<DBNode>>>(value)) {
211 const auto& list = std::get<std::vector<std::shared_ptr<DBNode>>>(value);
213 for (
size_t i = 0; i < list.size(); ++i) {
214 std::cout << std::string(level + 2,
' ');
215 list[i]->printJSON(level + 2);
216 if (i < list.size() - 1) std::cout <<
",";
219 std::cout << std::string(level,
' ') <<
"]";
224void DBNode::printValueToStream(std::ostream& os,
const Value& value,
int level)
const {
225 if (std::holds_alternative<BlockName>(value)) {
226 os <<
"\"" << std::get<BlockName>(value) <<
"\"";
227 }
else if (std::holds_alternative<int>(value)) {
228 os << std::get<int>(value);
229 }
else if (std::holds_alternative<double>(value)) {
230 os << std::get<double>(value);
231 }
else if (std::holds_alternative<bool>(value)) {
232 os << (std::get<bool>(value) ?
"true" :
"false");
233 }
else if (std::holds_alternative<std::shared_ptr<DBNode>>(value)) {
234 auto ptr = std::get<std::shared_ptr<DBNode>>(value);
235 if (ptr) ptr->printJSONToStream(os, level + 2);
237 }
else if (std::holds_alternative<std::vector<std::shared_ptr<DBNode>>>(value)) {
238 const auto& list = std::get<std::vector<std::shared_ptr<DBNode>>>(value);
240 for (
size_t i = 0; i < list.size(); ++i) {
241 os << std::string(level + 2,
' ');
242 if (list[i]) list[i]->printJSONToStream(os, level + 2);
244 if (i + 1 < list.size()) os <<
",";
247 os << std::string(level,
' ') <<
"]";
251void DBNode::printScalarYAML(
const Value& value)
const {
252 if (std::holds_alternative<BlockName>(value)) {
253 std::cout << std::get<BlockName>(value);
254 }
else if (std::holds_alternative<int>(value)) {
255 std::cout << std::get<int>(value);
256 }
else if (std::holds_alternative<double>(value)) {
257 std::cout << std::get<double>(value);
258 }
else if (std::holds_alternative<bool>(value)) {
259 std::cout << (std::get<bool>(value) ?
"true" :
"false");
264 return std::any_of(data_.begin(), data_.end(),
265 [&](
const auto& pair) {
266 return pair.first == key;
274void DBNode::printScalarYAMLToStream(std::ostream& os,
const Value& value)
const {
275 if (std::holds_alternative<BlockName>(value)) {
276 os << std::get<BlockName>(value);
277 }
else if (std::holds_alternative<int>(value)) {
278 os << std::get<int>(value);
279 }
else if (std::holds_alternative<double>(value)) {
280 os << std::get<double>(value);
281 }
else if (std::holds_alternative<bool>(value)) {
282 os << (std::get<bool>(value) ?
"true" :
"false");
287 for (
const auto& [key, value] : data_) {
288 if (std::holds_alternative<std::vector<std::shared_ptr<DBNode>>>(value)) {
289 const auto& list = std::get<std::vector<std::shared_ptr<DBNode>>>(value);
290 os << std::string(level,
' ') << key <<
":\n";
292 bool isFinalList =
true;
293 for (
const auto& node : list) {
294 if (!node || !node->contains(
"")) { isFinalList =
false;
break; }
298 for (
const auto& node : list) {
299 os << std::string(level + 2,
' ') <<
"- ";
300 printScalarYAMLToStream(os, node->get(
""));
304 for (
const auto& node : list) {
305 os << std::string(level + 2,
' ') <<
"- ";
308 node->printYAMLToStream(os, level + 4);
317 if (std::holds_alternative<std::shared_ptr<DBNode>>(value)) {
318 auto child = std::get<std::shared_ptr<DBNode>>(value);
319 os << std::string(level,
' ') << key <<
":\n";
320 if (child) child->printYAMLToStream(os, level + 2);
321 else os << std::string(level + 2,
' ') <<
"null\n";
325 os << std::string(level,
' ') << key <<
": ";
326 printScalarYAMLToStream(os, value);
Hierarchical key–value tree with JSON/YAML serialization.
std::variant< std::monostate, double, int64_t, bool, std::string > Value
Block identifier with alias support.
void setGroup(const std::vector< BlockName > &keys, const std::map< BlockName, Value > &groupData)
Sets the content of a whole sub-tree from a map of values.
Value get(Keys &&... keys) const
Retrieves a value from the node using a sequence of keys.
void printYAMLToStream(std::ostream &os, int level=0) const
Prints the node in YAML format to a given output stream.
DBNode()
Default constructor.
std::map< BlockName, Value > getGroup(const std::vector< BlockName > &keys) const
Retrieves a whole sub-tree as a map from a path of keys.
int countChildren() const
Returns the number of direct children of this node.
std::vector< BlockName > get_keys()
Returns all the keys stored at the current node level.
bool contains(const BlockName &key) const
Checks whether the node contains a direct child with the given key.
void printJSON(int level=0) const
Prints the node in JSON format to std::cout.
void printYAML(int level=0) const
Prints the node in YAML format to std::cout.
void printJSONToStream(std::ostream &os, int level=0) const
Prints the node in JSON format to a given output stream.