Config::Node::Add() now supports nested keys (e.g., Add("foo/bar/baz", "0") will create three nested config nodes)

This commit is contained in:
Bart Trzynadlowski 2016-07-09 15:19:17 +00:00
parent 24c341120a
commit a84aacf80b
3 changed files with 47 additions and 23 deletions

View file

@ -125,20 +125,26 @@ namespace Util
std::cout << ToString(indent_level);
}
Node &Node::Add(const std::string &key)
Node &Node::Add(const std::string &path, const std::string &value)
{
Ptr_t node = std::make_shared<Node>(key);
AddChild(node);
std::vector<std::string> keys = Util::Format(path).Split('/');
Node *parent = this;
Ptr_t node;
for (size_t i = 0; i < keys.size(); i++)
{
// Create node at this level
node = std::make_shared<Node>(keys[i]);
// The leaf node gets the value
if (i == keys.size() - 1)
node->SetValue(value);
// Attach node to parent and move down to next nesting level: last
// created node is new parent
AddChild(*parent, node);
parent = node.get();
}
return *node;
}
Node &Node::Add(const std::string &key, const std::string &value)
{
Ptr_t node = std::make_shared<Node>(key, value);
AddChild(node);
return *node;
}
void Node::Set(const std::string &key, const std::string &value)
{
Node &node = Get(key);
@ -150,19 +156,19 @@ namespace Util
// Adds a newly-created node (which, among other things, implies no
// children) as a child
void Node::AddChild(Ptr_t &node)
void Node::AddChild(Node &parent, Ptr_t &node)
{
if (!m_last_child)
if (!parent.m_last_child)
{
m_first_child = node;
m_last_child = node;
parent.m_first_child = node;
parent.m_last_child = node;
}
else
{
m_last_child->m_next_sibling = node;
m_last_child = node;
parent.m_last_child->m_next_sibling = node;
parent.m_last_child = node;
}
m_children[node->m_key] = node;
parent.m_children[node->m_key] = node;
}
/*
@ -203,7 +209,7 @@ namespace Util
for (Ptr_t child = that.m_first_child; child; child = child->m_next_sibling)
{
Ptr_t copied_child = std::make_shared<Node>(*child);
AddChild(copied_child);
AddChild(*this, copied_child);
}
}

View file

@ -25,7 +25,7 @@ namespace Util
std::string m_value;
static Node s_empty_node; // key, value, and children must always be empty
void AddChild(Ptr_t &node);
void AddChild(Node &parent, Ptr_t &node);
Node(); // prohibit accidental/unintentional creation of blank nodes
friend Ptr_t CreateEmpty();
@ -187,9 +187,7 @@ namespace Util
const Node &Get(const std::string &path) const;
void Print(size_t indent_level = 0) const;
std::string ToString(size_t indent_level = 0) const;
//TODO: Add() needs to accept and correctly handle nested keys (e.g., "foo/bar/baz")
Node &Add(const std::string &key);
Node &Add(const std::string &key, const std::string &value);
Node &Add(const std::string &key, const std::string &value = "");
void Set(const std::string &key, const std::string &value);
Node(const std::string &key);
Node(const std::string &key, const std::string &value);

View file

@ -56,7 +56,7 @@ int main()
std::cout << "Actual config tree:" << std::endl << std::endl;
root->Print();
std::cout << std::endl;
test_results.push_back({ "Manual Creation", root->ToString() == expected_output });
test_results.push_back({ "Manual", root->ToString() == expected_output });
// Expect second crom: bar.bin
auto &global = *root;
@ -140,6 +140,26 @@ int main()
std::cout << std::endl;
test_results.push_back({ "XML", xml_config->ToString() == expected_xml_config_tree });
// Create a nested key
{
Util::Config::Node::Ptr_t config = Util::Config::CreateEmpty();
config->Add("foo/bar/baz", "bart");
config->Print();
std::cout << std::endl;
test_results.push_back({ "Nested key 1", config->Get("foo/bar/baz").Value() == "bart" });
config->Get("foo/bar/baz").Set("x", "xx");
config->Get("foo/bar/baz").Set("y/z", "zz");
config->Print();
std::cout << std::endl;
test_results.push_back({ "Nested key 2", config->Get("foo/bar/baz/x").Value() == "xx" });
test_results.push_back({ "Nested key 3", config->Get("foo/bar/baz/y/z").Value() == "zz" });
config->Add("a/b/c");
config->Get("a/b/c").SetValue("d");
config->Print();
std::cout << std::endl;
test_results.push_back({ "Nested key 4", config->Get("a/b/c").Value() == "d" });
}
PrintTestResults(test_results);
return 0;
}