| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <optional> | ||
| 4 | #include <variant> | ||
| 5 | #include <vector> | ||
| 6 | |||
| 7 | #include <yaml-cpp/yaml.h> | ||
| 8 | |||
| 9 | #include "ConfigFileReader.h" | ||
| 10 | |||
| 11 | namespace iguana { | ||
| 12 | |||
| 13 | /// @brief A YAMLReader based on yaml-cpp | ||
| 14 | class YAMLReader : public ConfigFileReader | ||
| 15 | { | ||
| 16 | |||
| 17 | public: | ||
| 18 | |||
| 19 | /// A function `f : Node A -> Node B` which searches `YAML::Node A` for a specific `YAML::Node B`, returning it | ||
| 20 | using node_finder_t = std::function<YAML::Node(YAML::Node const)>; | ||
| 21 | |||
| 22 | /// Variant for identifying a `YAML::Node`: | ||
| 23 | /// - `std::string`: the key name of the node | ||
| 24 | /// - `node_finder_t`: how to find the node | ||
| 25 | using node_id_t = std::variant<std::string, node_finder_t>; | ||
| 26 | |||
| 27 | /// Representation of a path of `YAML::Node`s in a `YAML::Node` tree, _e.g._, in a YAML file. | ||
| 28 | using node_path_t = std::deque<node_id_t>; | ||
| 29 | |||
| 30 | /// @param name of this reader (for `Logger`) | ||
| 31 | 47 | YAMLReader(std::string_view name = "config") | |
| 32 | 47 | : ConfigFileReader(name) | |
| 33 | 47 | {} | |
| 34 | 47 | ~YAMLReader() {} | |
| 35 | |||
| 36 | /// Parse the YAML files added by `ConfigFileReader::AddFile` | ||
| 37 | void LoadFiles(); | ||
| 38 | |||
| 39 | /// Read a scalar value from a `YAML::Node` | ||
| 40 | /// @param node the `YAML::Node` to read | ||
| 41 | /// @return the scalar, if found | ||
| 42 | template <typename SCALAR> | ||
| 43 | std::optional<SCALAR> GetScalar(YAML::Node node); | ||
| 44 | |||
| 45 | /// Read a scalar value from a `YAML::Node` path; searches all currently loaded config files. | ||
| 46 | /// @param node_path the `YAML::Node` path | ||
| 47 | /// @return the scalar, if found | ||
| 48 | template <typename SCALAR> | ||
| 49 | std::optional<SCALAR> GetScalar(node_path_t node_path); | ||
| 50 | |||
| 51 | /// Read a vector value from a `YAML::Node` | ||
| 52 | /// @param node the `YAML::Node` to read | ||
| 53 | /// @return the vector, if found | ||
| 54 | template <typename SCALAR> | ||
| 55 | std::optional<std::vector<SCALAR>> GetVector(YAML::Node node); | ||
| 56 | |||
| 57 | /// Read a vector value from a `YAML::Node` path; searches all currently loaded config files. | ||
| 58 | /// @param node_path the `YAML::Node` path | ||
| 59 | /// @return the vector, if found | ||
| 60 | template <typename SCALAR> | ||
| 61 | std::optional<std::vector<SCALAR>> GetVector(node_path_t node_path); | ||
| 62 | |||
| 63 | /// Create a function to search a `YAML::Node` for a sub-`YAML::Node` such that | ||
| 64 | /// the scalar `val` is within a range specified by `key` | ||
| 65 | /// @param key the key of the sub-`YAML::Node` to use as the range (its value must be a 2-vector) | ||
| 66 | /// @param val the scalar value to check | ||
| 67 | /// @returns the search function | ||
| 68 | template <typename SCALAR> | ||
| 69 | node_finder_t InRange(std::string const& key, SCALAR val); | ||
| 70 | |||
| 71 | private: | ||
| 72 | |||
| 73 | /// Search a tree of `YAML::Node`s for a node specified by a `node_path_t` | ||
| 74 | /// @param node the root `YAML::Node` | ||
| 75 | /// @param node_path the path of `YAML::Node` identifiers | ||
| 76 | /// @returns either the found `YAML::Node`, or an empty (null) `YAML::Node` if one is not found | ||
| 77 | YAML::Node FindNode(YAML::Node node, node_path_t node_path); | ||
| 78 | |||
| 79 | /// Stack of `YAML::Node`s used to open files, together with their file names | ||
| 80 | std::deque<std::pair<YAML::Node, std::string>> m_configs; | ||
| 81 | }; | ||
| 82 | } | ||
| 83 |