13#include <janus/core/JanusTypes.hpp>
14#include <janus/math/Quaternion.hpp>
15#include <yaml-cpp/yaml.h>
30 : std::runtime_error(
"YAML error at '" +
path +
"': " + msg),
33 [[nodiscard]]
const std::string &
path()
const {
return path_; }
56 return YamlNode(YAML::LoadFile(path), path);
57 }
catch (
const YAML::Exception &e) {
65 return YamlNode(YAML::Load(yaml_content),
"root");
66 }
catch (
const YAML::Exception &e) {
72 explicit YamlNode(YAML::Node node, std::string path =
"root")
73 : node_(std::move(node)), path_(std::move(path)) {}
81 return YamlNode(node_[key], path_ +
"." + key);
87 path_ +
"[" + std::to_string(index) +
"]");
91 [[nodiscard]]
bool Has(
const std::string &key)
const {
92 return node_[key].IsDefined();
96 [[nodiscard]]
bool IsDefined()
const {
return node_.IsDefined(); }
99 [[nodiscard]]
bool IsSequence()
const {
return node_.IsSequence(); }
102 [[nodiscard]]
bool IsMap()
const {
return node_.IsMap(); }
105 [[nodiscard]]
bool IsScalar()
const {
return node_.IsScalar(); }
108 [[nodiscard]]
bool IsNull()
const {
return node_.IsNull(); }
111 [[nodiscard]] std::size_t
Size()
const {
return node_.size(); }
114 [[nodiscard]]
const std::string &
Path()
const {
return path_; }
121 template <
typename T>
122 [[nodiscard]] T
Require(
const std::string &key)
const {
123 auto child = (*this)[key];
124 if (!child.IsDefined()) {
125 throw YamlError(child.Path(),
"required key not found");
127 return child.As<T>();
131 template <
typename T> [[nodiscard]] T
As()
const;
138 template <
typename T>
139 [[nodiscard]] T
Get(
const std::string &key,
const T &default_value)
const {
140 auto child = (*this)[key];
141 if (!child.IsDefined() || child.IsNull()) {
142 return default_value;
144 return child.As<T>();
148 template <
typename T>
149 [[nodiscard]] std::optional<T>
GetOptional(
const std::string &key)
const {
150 auto child = (*this)[key];
151 if (!child.IsDefined() || child.IsNull()) {
154 return child.As<T>();
162 template <
typename Func>
void ForEach(Func &&func)
const {
164 throw YamlError(path_,
"expected sequence for iteration");
166 for (std::size_t i = 0; i <
Size(); ++i) {
174 throw YamlError(path_,
"expected map for iteration");
176 for (
const auto &pair : node_) {
177 std::string key = pair.first.as<std::string>();
178 func(key,
YamlNode(pair.second, path_ +
"." + key));
183 template <
typename T> [[nodiscard]] std::vector<T>
ToVector()
const {
185 throw YamlError(path_,
"expected sequence for ToVector");
187 std::vector<T> result;
188 result.reserve(
Size());
189 for (std::size_t i = 0; i <
Size(); ++i) {
190 result.push_back((*
this)[i].
As<T>());
200 [[nodiscard]]
const YAML::Node &
Raw()
const {
return node_; }
214T
yaml_as(
const YAML::Node &node,
const std::string &path) {
217 }
catch (
const YAML::Exception &e) {
260 if (!IsSequence() || Size() != 3) {
261 throw YamlError(path_,
"expected sequence of 3 elements for Vec3");
263 return janus::Vec3<double>{(*this)[0].As<
double>(), (*
this)[1].As<
double>(),
264 (*
this)[2].As<
double>()};
269inline janus::Quaternion<double>
271 if (!IsSequence() || Size() != 4) {
273 path_,
"expected sequence of 4 elements for Quaternion [w,x,y,z]");
276 return janus::Quaternion<double>{
277 (*this)[0].As<
double>(), (*
this)[1].As<
double>(),
278 (*
this)[2].As<
double>(), (*
this)[3].As<
double>()};
285 throw YamlError(path_,
"expected sequence for Mat3");
288 janus::Mat3<double> m;
291 if (Size() == 3 && (*
this)[0].IsSequence()) {
292 for (
int i = 0; i < 3; ++i) {
293 auto row = (*this)[
static_cast<std::size_t
>(i)];
294 if (row.Size() != 3) {
295 throw YamlError(path_,
"Mat3 row " + std::to_string(i) +
296 " must have 3 elements");
298 for (
int j = 0; j < 3; ++j) {
299 m(i, j) = row[
static_cast<std::size_t
>(j)].As<double>();
307 for (
int i = 0; i < 3; ++i) {
308 for (
int j = 0; j < 3; ++j) {
310 (*this)[
static_cast<std::size_t
>(i * 3 + j)].As<double>();
317 "Mat3 must be 3x3 nested array or 9-element flat array");
325 return ToVector<double>();
330 return ToVector<int>();
336 return ToVector<std::string>();
Exception for YAML parsing/access errors.
Definition YamlNode.hpp:27
YamlError(const std::string &path, const std::string &msg)
Definition YamlNode.hpp:29
const std::string & path() const
Definition YamlNode.hpp:33
static YamlNode LoadFile(const std::string &path)
Load from file.
Definition YamlNode.hpp:54
void ForEachEntry(Func &&func) const
Iterate over map entries: func(key, node).
Definition YamlNode.hpp:172
std::size_t Size() const
Get sequence size.
Definition YamlNode.hpp:111
std::vector< T > ToVector() const
Convert sequence to vector.
Definition YamlNode.hpp:183
const std::string & Path() const
Get current path (for error messages).
Definition YamlNode.hpp:114
bool IsNull() const
Check if node is null.
Definition YamlNode.hpp:108
bool IsDefined() const
Check if node is defined.
Definition YamlNode.hpp:96
static YamlNode Parse(const std::string &yaml_content)
Parse from string.
Definition YamlNode.hpp:63
const YAML::Node & Raw() const
Get underlying yaml-cpp node.
Definition YamlNode.hpp:200
YamlNode operator[](std::size_t index) const
Access child by index (sequence).
Definition YamlNode.hpp:85
bool IsSequence() const
Check if node is a sequence.
Definition YamlNode.hpp:99
std::optional< T > GetOptional(const std::string &key) const
Get optional value (returns nullopt if missing).
Definition YamlNode.hpp:149
T Require(const std::string &key) const
Get required value (throws YamlError if missing or wrong type).
Definition YamlNode.hpp:122
YamlNode(YAML::Node node, std::string path="root")
Wrap an existing yaml-cpp node.
Definition YamlNode.hpp:72
void ForEach(Func &&func) const
Iterate over sequence elements.
Definition YamlNode.hpp:162
bool IsMap() const
Check if node is a map.
Definition YamlNode.hpp:102
bool Has(const std::string &key) const
Check if key exists.
Definition YamlNode.hpp:91
T As() const
Get required value from current node.
T Get(const std::string &key, const T &default_value) const
Get optional value with default.
Definition YamlNode.hpp:139
YamlNode operator[](const std::string &key) const
Access child by key (map).
Definition YamlNode.hpp:80
bool IsScalar() const
Check if node is a scalar.
Definition YamlNode.hpp:105
Definition YamlNode.hpp:211
T yaml_as(const YAML::Node &node, const std::string &path)
Definition YamlNode.hpp:214
Definition CSVExport.hpp:20