mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-29 09:05:41 +00:00
Config nodes: added the ability to clear out node values or create empty leaf nodes
This commit is contained in:
parent
043f901c80
commit
83144f80b7
|
@ -147,6 +147,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Util/NewConfig.h"
|
#include "Util/NewConfig.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace Util
|
namespace Util
|
||||||
{
|
{
|
||||||
|
@ -251,6 +252,34 @@ namespace Util
|
||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adds an empty node (no value and where Empty() will return true)
|
||||||
|
Node &Node::AddEmpty(const std::string &path)
|
||||||
|
{
|
||||||
|
std::vector<std::string> keys = Util::Format(path).Split('/');
|
||||||
|
Node *parent = this;
|
||||||
|
ptr_t node;
|
||||||
|
for (size_t i = 0; i < keys.size(); i++)
|
||||||
|
{
|
||||||
|
bool leaf = i == keys.size() - 1;
|
||||||
|
auto it = parent->m_children.find(keys[i]);
|
||||||
|
if (leaf || it == parent->m_children.end())
|
||||||
|
{
|
||||||
|
// Create node at this level and leave it empty
|
||||||
|
node = std::make_shared<Node>(keys[i]);
|
||||||
|
// Attach node to parent and move down to next nesting level: last
|
||||||
|
// created node is new parent
|
||||||
|
AddChild(*parent, node);
|
||||||
|
parent = node.get();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Descend deeper...
|
||||||
|
parent = it->second.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *node;
|
||||||
|
}
|
||||||
|
|
||||||
// Adds a newly-created node (which, among other things, implies no
|
// Adds a newly-created node (which, among other things, implies no
|
||||||
// children) as a child
|
// children) as a child
|
||||||
void Node::AddChild(Node &parent, ptr_t &node)
|
void Node::AddChild(Node &parent, ptr_t &node)
|
||||||
|
@ -340,5 +369,20 @@ namespace Util
|
||||||
{
|
{
|
||||||
//std::cout << ">>> Destroyed " << m_key << " (" << this << ")" << std::endl;
|
//std::cout << ">>> Destroyed " << m_key << " (" << this << ")" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrintConfigTree(const Node &config, int indent_level, int tab_stops)
|
||||||
|
{
|
||||||
|
std::fill_n(std::ostream_iterator<char>(std::cout), tab_stops * indent_level, ' ');
|
||||||
|
std::cout << config.Key();
|
||||||
|
if (config.Exists())
|
||||||
|
{
|
||||||
|
std::cout << " = " << config.ValueAs<std::string>();
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
for (const Node &child: config)
|
||||||
|
{
|
||||||
|
PrintConfigTree(child, indent_level + 1, tab_stops);
|
||||||
|
}
|
||||||
|
}
|
||||||
} // Config
|
} // Config
|
||||||
} // Util
|
} // Util
|
||||||
|
|
|
@ -36,6 +36,7 @@ namespace Util
|
||||||
|
|
||||||
void CheckEmptyOrMissing() const;
|
void CheckEmptyOrMissing() const;
|
||||||
const Node &MissingNode(const std::string &key) const;
|
const Node &MissingNode(const std::string &key) const;
|
||||||
|
Node &AddEmpty(const std::string &path);
|
||||||
void AddChild(Node &parent, ptr_t &node);
|
void AddChild(Node &parent, ptr_t &node);
|
||||||
void DeepCopy(const Node &that);
|
void DeepCopy(const Node &that);
|
||||||
void Swap(Node &rhs);
|
void Swap(Node &rhs);
|
||||||
|
@ -168,6 +169,11 @@ namespace Util
|
||||||
return m_value;
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void Clear()
|
||||||
|
{
|
||||||
|
m_value = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
inline void SetValue(const std::shared_ptr<GenericValue> &value)
|
inline void SetValue(const std::shared_ptr<GenericValue> &value)
|
||||||
{
|
{
|
||||||
m_value = value;
|
m_value = value;
|
||||||
|
@ -222,32 +228,9 @@ namespace Util
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Node &Add(const std::string &path, const T &value)
|
Node &Add(const std::string &path, const T &value)
|
||||||
{
|
{
|
||||||
std::vector<std::string> keys = Util::Format(path).Split('/');
|
Node &new_leaf_node = AddEmpty(path);
|
||||||
Node *parent = this;
|
new_leaf_node.SetValue(value);
|
||||||
ptr_t node;
|
return new_leaf_node;
|
||||||
for (size_t i = 0; i < keys.size(); i++)
|
|
||||||
{
|
|
||||||
bool leaf = i == keys.size() - 1;
|
|
||||||
auto it = parent->m_children.find(keys[i]);
|
|
||||||
if (leaf || it == parent->m_children.end())
|
|
||||||
{
|
|
||||||
// Create node at this level
|
|
||||||
node = std::make_shared<Node>(keys[i]);
|
|
||||||
// The leaf node gets the value
|
|
||||||
if (leaf)
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Descend deeper...
|
|
||||||
parent = it->second.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return *node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Node &Add(const std::string &path)
|
Node &Add(const std::string &path)
|
||||||
|
@ -266,6 +249,19 @@ namespace Util
|
||||||
Add(key, value);
|
Add(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetEmpty(const std::string &key)
|
||||||
|
{
|
||||||
|
Node *node = TryGet(key);
|
||||||
|
if (node)
|
||||||
|
{
|
||||||
|
node->Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddEmpty(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// True if value is empty (does not exist)
|
// True if value is empty (does not exist)
|
||||||
inline bool Empty() const
|
inline bool Empty() const
|
||||||
{
|
{
|
||||||
|
@ -312,6 +308,8 @@ namespace Util
|
||||||
Node(Node&& that) noexcept;
|
Node(Node&& that) noexcept;
|
||||||
~Node();
|
~Node();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void PrintConfigTree(const Node &config, int indent_level = 0, int tab_stops = 2);
|
||||||
} // Config
|
} // Config
|
||||||
} // Util
|
} // Util
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue