4#include "PixelBullet/Filesystem/String.hpp"
26 enum class NodeType : uint8_t
40 using NodeValue = std::string;
41 using NodeProperty = std::pair<std::string, class Node>;
42 using NodeProperties = std::vector<NodeProperty>;
63 constexpr Format(int8_t s,
char nl,
char spc,
bool inlineArr)
71 std::string GetIndentation(int8_t indentLevel)
const
83 Node& operator=(const
Node&) = default;
84 Node& operator=(
Node&&) noexcept = default;
87 [[nodiscard]] const NodeValue& GetValue() const noexcept;
88 void SetValue(const NodeValue& value);
89 void SetValue(NodeValue&& value);
91 [[nodiscard]] NodeType GetType() const noexcept;
92 void SetType(NodeType type);
96 [[nodiscard]]
bool IsValid() const noexcept;
98 [[nodiscard]] const NodeProperties& GetProperties() const noexcept;
99 NodeProperties& GetProperties();
101 [[nodiscard]]
bool HasProperty(const std::
string& name) const;
102 [[nodiscard]] const
Node* GetProperty(const std::
string& name) const;
103 void SetProperty(const std::
string& name, const
Node& node);
104 bool RemoveProperty(const std::
string& name);
107 Node& operator[](const std::
string& key);
108 const
Node& operator[](const std::
string& key) const;
111 Node& operator[](
size_t index);
112 const
Node& operator[](
size_t index) const;
115 template <typename T>
123 template <
typename T>
124 void Set(
const T& in)
132 return m_Properties.begin();
136 return m_Properties.end();
140 return m_Properties.begin();
144 return m_Properties.end();
148 [[nodiscard]]
size_t size() const noexcept
150 return m_Properties.size();
169 if (node.m_Value ==
"true" || node.m_Value ==
"1")
173 else if (node.m_Value ==
"false" || node.m_Value ==
"0")
179 ASSERT(
false,
"Invalid boolean value: {}", node.m_Value);
187 node.m_Value = b ?
"true" :
"false";
188 node.m_Type = NodeType::Boolean;
192 static bool ParseYAML(Node& node, std::string_view str);
193 static bool WriteYAML(
const Node& node, std::ostream& stream,
const Format& format =
Format::Minified);
196 static Node YAMLToNode(
const YAML::Node& yaml);
197 static YAML::Node NodeToYAML(
const Node& node);
199 NodeProperties m_Properties;
201 NodeType m_Type = NodeType::Null;
207 template <
typename T>
208 requires std::is_arithmetic_v<T>
209 Node& operator<<(Node& node,
const T& value)
212 auto [ptr, ec] = std::to_chars(buffer, buffer +
sizeof(buffer), value);
213 ASSERT(ec == std::errc(),
"Conversion to string failed");
214 node.SetValue(std::string(buffer, ptr));
215 if constexpr (std::is_integral_v<T>)
217 node.SetType(NodeType::Integer);
219 else if constexpr (std::is_floating_point_v<T>)
221 node.SetType(NodeType::Decimal);
226 template <
typename T>
227 requires std::is_arithmetic_v<T>
228 void operator>>(
const Node& node, T& value)
230 const std::string& s = node.GetValue();
231 auto result = std::from_chars(s.data(), s.data() + s.size(), value);
232 ASSERT(result.ec == std::errc(),
"Conversion failed for value: {}", s);
235 inline Node& operator<<(Node& node,
const std::string& value)
237 node.SetValue(value);
238 node.SetType(NodeType::String);
242 inline const Node& operator>>(
const Node& node, std::string& value)
244 value = node.GetValue();
248 template <
typename T>
249 Node& operator<<(Node& node,
const std::vector<T>& vec)
251 node.SetType(NodeType::Array);
252 auto& props = node.GetProperties();
254 for (
const T& item : vec)
258 props.emplace_back(
"", child);
263 template <
typename T>
264 void operator>>(
const Node& node, std::vector<T>& vec)
266 ASSERT(node.GetType() == NodeType::Array,
"Node is not an array");
268 for (
const auto& [key, child] : node.GetProperties())
272 vec.push_back(std::move(item));
276 template <
typename T>
277 Node& operator<<(Node& node,
const std::map<std::string, T>& mapData)
279 node.SetType(NodeType::Object);
280 auto& props = node.GetProperties();
282 for (
const auto& [key, value] : mapData)
286 props.emplace_back(key, child);
291 template <
typename T>
292 void operator>>(
const Node& node, std::map<std::string, T>& mapData)
294 ASSERT(node.GetType() == NodeType::Object,
"Node is not an object");
296 for (
const auto& [key, child] : node.GetProperties())
300 mapData.emplace(key, std::move(item));
304 inline bool operator==(
const Node& lhs,
const Node& rhs)
306 return lhs.GetType() == rhs.GetType() && lhs.GetValue() == rhs.GetValue() &&
307 lhs.GetProperties() == rhs.GetProperties();
310 inline bool operator!=(
const Node& lhs,
const Node& rhs)
312 return !(lhs == rhs);
315 inline bool operator<(
const Node& lhs,
const Node& rhs)
317 if (lhs.GetType() != rhs.GetType())
319 return lhs.GetType() < rhs.GetType();
321 if (lhs.GetValue() != rhs.GetValue())
323 return lhs.GetValue() < rhs.GetValue();
325 return lhs.GetProperties() < rhs.GetProperties();
329 template <
typename T>
330 requires std::is_enum_v<T>
331 const Node& operator>>(
const Node& node, T&
object)
333 object = String::From<T>(node.GetValue());
337 template <
typename T>
338 requires std::is_enum_v<T>
339 Node& operator<<(Node& node, T
object)
341 node.SetValue(String::To(
object));
342 node.SetType(NodeType::Integer);
346 inline const Node& operator>>(
const Node& node, std::pair<std::string, std::string>& p)
348 ASSERT(node.GetType() == NodeType::Object,
"Expected object type for a pair");
349 const auto& props = node.GetProperties();
350 ASSERT(props.size() == 1,
"Expected exactly one property for a pair");
351 p.first = props[0].first;
352 props[0].second >> p.second;
356 inline Node& operator<<(Node& node,
const std::pair<std::string, std::string>& p)
358 node.SetType(NodeType::Object);
359 auto& props = node.GetProperties();
362 valueNode << p.second;
363 props.emplace_back(p.first, valueNode);
367 inline Node& operator<<(Node& node,
const glm::vec3& v)
369 node.SetType(NodeType::Array);
370 auto& props = node.GetProperties();
377 props.emplace_back(
"", std::move(x));
378 props.emplace_back(
"", std::move(y));
379 props.emplace_back(
"", std::move(z));
383 inline void operator>>(
const Node& node, glm::vec3& v)
385 ASSERT(node.GetType() == NodeType::Array,
"Node is not an array");
386 const auto& props = node.GetProperties();
387 ASSERT(props.size() >= 3,
"Insufficient elements for glm::vec3");
388 props[0].second >> v.x;
389 props[1].second >> v.y;
390 props[2].second >> v.z;
Provides assertion and panic mechanisms with optional custom formatting.
#define ASSERT(condition,...)
Asserts that a condition is true.
Definition Assert.hpp:151
Represents a hierarchical node capable of storing various data types and supporting YAML serializatio...
Definition Node.hpp:51
friend Node & operator<<(Node &node, const Node &in)
Copy content from one node to another.
Definition Node.hpp:161
friend const Node & operator>>(const Node &node, Node &out)
Copy the node's content.
Definition Node.hpp:154