23enum class NodeType : uint8_t
34using NodeValue = std::string;
35using NodeProperty = std::pair<std::string, class Node>;
36using NodeProperties = std::vector<NodeProperty>;
57 constexpr Format(int8_t s,
char nl,
char spc,
bool inlineArr)
65 std::string GetIndentation(int8_t indentLevel)
const
77 Node& operator=(const
Node&) = default;
78 Node& operator=(
Node&&) noexcept = default;
81 [[nodiscard]] const NodeValue& GetValue() const noexcept;
82 void SetValue(const NodeValue& value);
83 void SetValue(NodeValue&& value);
85 [[nodiscard]] NodeType GetType() const noexcept;
86 void SetType(NodeType type);
90 [[nodiscard]]
bool IsValid() const noexcept;
92 [[nodiscard]] const NodeProperties& GetProperties() const noexcept;
93 NodeProperties& GetProperties();
95 [[nodiscard]]
bool HasProperty(const std::
string& name) const;
96 [[nodiscard]] const
Node* GetProperty(const std::
string& name) const;
97 void SetProperty(const std::
string& name, const
Node& node);
98 bool RemoveProperty(const std::
string& name);
101 Node& operator[](const std::
string& key);
102 const
Node& operator[](const std::
string& key) const;
105 Node& operator[](
size_t index);
106 const
Node& operator[](
size_t index) const;
109 template <typename T>
117 template <
typename T>
118 void Set(
const T& in)
126 return properties_.begin();
130 return properties_.end();
134 return properties_.begin();
138 return properties_.end();
142 [[nodiscard]]
size_t Size() const noexcept
144 return properties_.size();
163 if (node.value_ ==
"true" || node.value_ ==
"1")
167 else if (node.value_ ==
"false" || node.value_ ==
"0")
173 ASSERT(
false,
"Invalid boolean value: {}", node.value_);
181 node.SetValue(b ?
"true" :
"false");
182 node.SetType(NodeType::Boolean);
186 static bool ParseYAML(Node& node, std::string_view str);
187 static bool WriteYAML(
const Node& node, std::ostream& stream,
const Format& format =
Format::minified);
190 void EnsureObjectStateForMutation();
191 static Node YAMLToNode(
const YAML::Node& yaml);
193 NodeProperties properties_;
195 NodeType type_ = NodeType::Null;
202requires std::is_arithmetic_v<T> Node& operator<<(Node& node,
const T& value)
205 auto [ptr, ec] = std::to_chars(buffer, buffer +
sizeof(buffer), value);
206 ASSERT(ec == std::errc(),
"Conversion to string failed");
207 node.SetValue(std::string(buffer, ptr));
208 if constexpr (std::is_integral_v<T>)
210 node.SetType(NodeType::Integer);
212 else if constexpr (std::is_floating_point_v<T>)
214 node.SetType(NodeType::Decimal);
220requires std::is_arithmetic_v<T>
221void operator>>(
const Node& node, T& value)
223 const std::string& s = node.GetValue();
224 auto result = std::from_chars(s.data(), s.data() + s.size(), value);
225 ASSERT(result.ec == std::errc(),
"Conversion failed for value: {}", s);
228inline Node& operator<<(Node& node,
const std::string& value)
230 node.SetValue(value);
231 node.SetType(NodeType::String);
235inline const Node& operator>>(
const Node& node, std::string& value)
237 value = node.GetValue();
242Node& operator<<(Node& node,
const std::vector<T>& vec)
244 node.SetType(NodeType::Array);
245 auto& props = node.GetProperties();
247 for (
const T& item : vec)
251 props.emplace_back(
"", child);
257void operator>>(
const Node& node, std::vector<T>& vec)
259 ASSERT(node.GetType() == NodeType::Array,
"Node is not an array");
261 for (
const auto& [key, child] : node.GetProperties())
265 vec.push_back(std::move(item));
270Node& operator<<(Node& node,
const std::map<std::string, T>& mapData)
272 node.SetType(NodeType::Object);
273 auto& props = node.GetProperties();
275 for (
const auto& [key, value] : mapData)
279 props.emplace_back(key, child);
285void operator>>(
const Node& node, std::map<std::string, T>& mapData)
287 ASSERT(node.GetType() == NodeType::Object,
"Node is not an object");
289 for (
const auto& [key, child] : node.GetProperties())
293 mapData.emplace(key, std::move(item));
297inline bool operator==(
const Node& lhs,
const Node& rhs)
299 return lhs.GetType() == rhs.GetType() && lhs.GetValue() == rhs.GetValue() && lhs.GetProperties() == rhs.GetProperties();
302inline bool operator!=(
const Node& lhs,
const Node& rhs)
304 return !(lhs == rhs);
307inline bool operator<(
const Node& lhs,
const Node& rhs)
309 if (lhs.GetType() != rhs.GetType())
311 return lhs.GetType() < rhs.GetType();
313 if (lhs.GetValue() != rhs.GetValue())
315 return lhs.GetValue() < rhs.GetValue();
317 return lhs.GetProperties() < rhs.GetProperties();
322requires std::is_enum_v<T>
323const Node& operator>>(
const Node& node, T&
object)
325 using Underlying = std::underlying_type_t<T>;
328 object =
static_cast<T
>(value);
333requires std::is_enum_v<T> Node& operator<<(Node& node, T
object)
335 return node << static_cast<std::underlying_type_t<T>>(object);
338inline const Node& operator>>(
const Node& node, std::pair<std::string, std::string>& p)
340 ASSERT(node.GetType() == NodeType::Object,
"Expected object type for a pair");
341 const auto& props = node.GetProperties();
342 ASSERT(props.size() == 1,
"Expected exactly one property for a pair");
343 p.first = props[0].first;
344 props[0].second >> p.second;
348inline Node& operator<<(Node& node,
const std::pair<std::string, std::string>& p)
350 node.SetType(NodeType::Object);
351 auto& props = node.GetProperties();
354 valueNode << p.second;
355 props.emplace_back(p.first, valueNode);
Provides assertion and panic mechanisms with optional custom formatting.
#define ASSERT(condition,...)
Asserts that a condition is true.
Definition assert.h:163
Represents a hierarchical node capable of storing various data types and supporting YAML serializatio...
Definition node.h:45
friend Node & operator<<(Node &node, const Node &in)
Copy content from one node to another.
Definition node.h:155
friend const Node & operator>>(const Node &node, Node &out)
Copy the node's content.
Definition node.h:148