Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 30 additions & 12 deletions source/parser/config_reader/config_node_.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

namespace sim {

ConfigNode::ConfigNode(YAML::Node a_node, std::optional<std::string> a_name)
: m_node(std::move(a_node)), m_name(std::move(a_name)) {
ConfigNode::ConfigNode(YAML::Node a_node, std::optional<std::string> a_name,
std::optional<std::string> a_path_node)
: m_node(std::move(a_node)),
m_name(std::move(a_name)),
m_path_node(std::move(a_path_node)) {
if (!m_node) {
throw std::runtime_error(
"Can not construct ConfigNode: given YAML::Node is "
Expand All @@ -27,11 +30,16 @@ const std::string& ConfigNode::get_name_or_throw() const {
std::runtime_error ConfigNode::create_parsing_error(
std::string_view error) const {
std::stringstream ss;
ss << "Error while parsing node " << *this << ":\n";
ss << "Error while parsing node " << *this
<< "which is located by path:" << m_path_node.value() << ":\n";
Comment thread
S1mpotyaga marked this conversation as resolved.
Outdated
ss << error << '\n';
return std::runtime_error(ss.str());
}

const std::optional<std::string>& ConfigNode::get_path_node() const {
return m_path_node;
}

std::ostream& operator<<(std::ostream& out, const ConfigNode& node) {
YAML::Mark mark = node.m_node.Mark();
if (node.m_name) {
Expand Down Expand Up @@ -65,7 +73,9 @@ const std::string& ConfigNode::Tag() const noexcept { return m_node.Tag(); }
// size/iterator
std::size_t ConfigNode::size() const noexcept { return m_node.size(); }

ConfigNode::Iterator::Iterator(YAML::const_iterator a_it) : m_iterator(a_it) {}
ConfigNode::Iterator::Iterator(YAML::const_iterator a_it,
const ConfigNode* a_owner)
: m_iterator(a_it), m_owner(a_owner) {}

ConfigNode::Iterator& ConfigNode::Iterator::operator++() {
++m_iterator;
Expand Down Expand Up @@ -97,7 +107,7 @@ ConfigNode ConfigNode::Iterator::operator*() const {
// - value_1
// ...
YAML::Node node = *m_iterator;
return ConfigNode(node, std::nullopt);
return ConfigNode(node, std::nullopt, m_owner->m_path_node);
} else {
// iterator goes over "named" nodes like
// list:
Expand All @@ -112,35 +122,43 @@ ConfigNode ConfigNode::Iterator::operator*() const {
"nodes are invalid");
}
std::string key = key_node.as<std::string>();
return ConfigNode(value_node, key);
return ConfigNode(value_node, key, m_owner->m_path_node);
}
}

ConfigNode::Iterator ConfigNode::begin() const {
return Iterator(m_node.begin());
return Iterator(m_node.begin(), this);
}

ConfigNode::Iterator ConfigNode::end() const { return Iterator(m_node.end()); }
ConfigNode::Iterator ConfigNode::end() const {
return Iterator(m_node.end(), this);
}

ConfigNodeExpected ConfigNode::operator[](std::string_view key) const {
const YAML::Node child_node = m_node[key];
std::string current_path = std::string(key);
if (m_path_node.has_value()) {
current_path = m_path_node.value() + "\\" + std::string(key);
}
Comment thread
S1mpotyaga marked this conversation as resolved.
Outdated
if (!child_node) {
std::stringstream ss;
ss << "Key error: node " << *this << ":\n";
ss << "Key error: node " << *this
<< "which is located by path:" << current_path << ":\n";
ss << "does not have key `" << key << '`';
return std::unexpected(ss.str());
}
if (child_node.IsNull()) {
// if node is null, its name should be empty
return ConfigNodeExpected(
ConfigNode(std::move(child_node), std::nullopt));
ConfigNode(std::move(child_node), std::nullopt, current_path));
}
return ConfigNodeExpected(
ConfigNode(std::move(child_node), std::string(key)));
ConfigNode(std::move(child_node), std::string(key), current_path));
};

ConfigNode load_file(std::filesystem::path path) {
return ConfigNode(YAML::LoadFile(path.string()));
return ConfigNode(YAML::LoadFile(path.string()), std::nullopt,
path.string());
}

} // namespace sim
10 changes: 8 additions & 2 deletions source/parser/config_reader/config_node_.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ class ConfigNodeExpected;
class ConfigNode {
public:
explicit ConfigNode(YAML::Node a_node = YAML::Node(YAML::NodeType::Null),
std::optional<std::string> a_name = std::nullopt);
std::optional<std::string> a_name = std::nullopt,
std::optional<std::string> a_path_node = std::nullopt);

// Some functional over yaml-cpp

Expand All @@ -28,6 +29,8 @@ class ConfigNode {
[[nodiscard]] std::runtime_error create_parsing_error(
std::string_view error) const;

const std::optional<std::string>& get_path_node() const;

friend std::ostream& operator<<(std::ostream& out, const ConfigNode& node);

std::string to_string() const;
Expand Down Expand Up @@ -64,7 +67,7 @@ class ConfigNode {

class Iterator {
public:
Iterator(YAML::const_iterator a_it);
Iterator(YAML::const_iterator a_it, const ConfigNode* a_owner);
Comment thread
S1mpotyaga marked this conversation as resolved.
Outdated

Iterator& operator++();

Expand All @@ -79,6 +82,7 @@ class ConfigNode {
private:
// Invariant: m_stacktrace_node is not null
YAML::const_iterator m_iterator;
const ConfigNode* m_owner;
};

Iterator begin() const;
Expand All @@ -92,6 +96,8 @@ class ConfigNode {
const YAML::Node m_node;

const std::optional<std::string> m_name;

mutable std::optional<std::string> m_path_node;
Comment thread
S1mpotyaga marked this conversation as resolved.
Outdated
};

ConfigNode load_file(std::filesystem::path path);
Expand Down
4 changes: 4 additions & 0 deletions source/parser/config_reader/config_node_with_preset_.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ std::ostream& operator<<(std::ostream& out, const ConfigNodeWithPreset& node) {
return out << node.get_node();
}

const std::optional<std::string>& ConfigNodeWithPreset::get_path_node() const {
return m_node.get_path_node();
}

const std::string& ConfigNodeWithPreset::get_name_or_throw() const {
return m_node.get_name_or_throw();
}
Expand Down
4 changes: 4 additions & 0 deletions source/parser/config_reader/config_node_with_preset_.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class ConfigNodeWithPreset {
return as<T>().value_or_throw();
}

const std::optional<std::string>& get_path_node() const;

[[nodiscard]] const std::string& get_name_or_throw() const;

const std::optional<ConfigNode> get_presets_node() const noexcept;
Expand All @@ -47,6 +49,8 @@ class ConfigNodeWithPreset {
// m_preset - preset node which that is used to supplement fields of m_node
// m_presets_node - node it which preset node should be searched (id it
// needs)
// m_path_node - the place where this node is located. in the form of
// folder1.folder2.node1.node2
Comment thread
S1mpotyaga marked this conversation as resolved.
Outdated
const ConfigNode m_node;
const std::optional<ConfigNode> m_presets_node;
mutable std::optional<ConfigNode> m_preset;
Expand Down
61 changes: 61 additions & 0 deletions test/parser/topology/check_paths.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include <gtest/gtest.h>
Comment thread
S1mpotyaga marked this conversation as resolved.
Outdated

#include "parser/config_reader/config_node.hpp"
#include "parser/config_reader/config_node_with_preset.hpp"

namespace sim {
namespace test2 {

TEST(PathConfigNode, InsertedPath) {
Comment thread
S1mpotyaga marked this conversation as resolved.
Outdated
Comment thread
S1mpotyaga marked this conversation as resolved.
Outdated
YAML::Node root = YAML::Load(R"(
a:
b:
c: 1
)");
ConfigNode node(root, std::nullopt, "root");
auto a = node["a"].value();
auto b = a["b"].value();
auto c = b["c"].value();

ASSERT_EQ(b.get_path_node(), "root\\a\\b");
ASSERT_EQ(c.get_path_node(), "root\\a\\b\\c");
}

TEST(PathConfigNode, MissingKey) {
Comment thread
S1mpotyaga marked this conversation as resolved.
Outdated
std::filesystem::path bus_topology_path =
Comment thread
S1mpotyaga marked this conversation as resolved.
Outdated
std::filesystem::path(__FILE__).parent_path() / "bus_network.yml";
ConfigNode node = load_file(bus_topology_path);
auto result = node["connections"]["connection-1->1"].value();

ASSERT_EQ(result.get_path_node(),
bus_topology_path.string() + "\\connections\\connection-1->1");
}

TEST(PathConfigNodeWithPreset, InsertedPath) {
Comment thread
S1mpotyaga marked this conversation as resolved.
Outdated
YAML::Node root = YAML::Load(R"(
a:
b:
c: 1
)");
ConfigNode tmp(root, std::nullopt, "root");
ConfigNodeWithPreset node(tmp);
auto a = node["a"].value();
auto b = a["b"].value();
auto c = b["c"].value();

ASSERT_EQ(b.get_path_node(), "root\\a\\b");
ASSERT_EQ(c.get_path_node(), "root\\a\\b\\c");
}

TEST(PathConfigNodeWithPreset, MissingKey) {
Comment thread
S1mpotyaga marked this conversation as resolved.
Outdated
std::filesystem::path bus_topology_path =
std::filesystem::path(__FILE__).parent_path() / "bus_network.yml";
ConfigNodeWithPreset node = load_file_with_presets(bus_topology_path);
auto result = node["connections"]["connection-1->1"].value();

ASSERT_EQ(result.get_path_node(),
bus_topology_path.string() + "\\connections\\connection-1->1");
}

} // namespace test2
} // namespace sim
Loading