mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-29 09:05:41 +00:00
Changed Config::Node::Create() to Add() and added a Set() method (for INI semantics). Turned Test_Config.cpp into a proper unit test reporting pass/fail for each test.
This commit is contained in:
parent
2e069af603
commit
24c341120a
|
@ -95,6 +95,7 @@ namespace Util
|
|||
|
||||
Node &Node::Get(const std::string &path)
|
||||
{
|
||||
// This is probably dangerous and we should just have a non-const []
|
||||
return const_cast<Node &>(operator[](path));
|
||||
}
|
||||
|
||||
|
@ -103,34 +104,50 @@ namespace Util
|
|||
return operator[](path);
|
||||
}
|
||||
|
||||
void Node::Print(size_t indent_level) const
|
||||
std::string Node::ToString(size_t indent_level) const
|
||||
{
|
||||
std::fill_n(std::ostream_iterator<char>(std::cout), 2 * indent_level, ' ');
|
||||
std::cout << m_key;
|
||||
std::ostringstream os;
|
||||
std::fill_n(std::ostream_iterator<char>(os), 2 * indent_level, ' ');
|
||||
os << m_key;
|
||||
if (m_value.length())
|
||||
std::cout << '=' << m_value;
|
||||
std::cout << " children={";
|
||||
os << '=' << m_value;
|
||||
os << " children={";
|
||||
for (auto v: m_children)
|
||||
std::cout << ' ' << v.first;
|
||||
std::cout << " }" << std::endl;
|
||||
os << ' ' << v.first;
|
||||
os << " }" << std::endl;
|
||||
for (Ptr_t child = m_first_child; child; child = child->m_next_sibling)
|
||||
child->Print(indent_level + 1);
|
||||
os << child->ToString(indent_level + 1);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
Node &Node::Create(const std::string &key)
|
||||
void Node::Print(size_t indent_level) const
|
||||
{
|
||||
std::cout << ToString(indent_level);
|
||||
}
|
||||
|
||||
Node &Node::Add(const std::string &key)
|
||||
{
|
||||
Ptr_t node = std::make_shared<Node>(key);
|
||||
AddChild(node);
|
||||
return *node;
|
||||
}
|
||||
|
||||
Node &Node::Create(const std::string &key, const std::string &value)
|
||||
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);
|
||||
if (node.Empty())
|
||||
Add(key, value);
|
||||
else
|
||||
node.SetValue(value);
|
||||
}
|
||||
|
||||
// Adds a newly-created node (which, among other things, implies no
|
||||
// children) as a child
|
||||
void Node::AddChild(Ptr_t &node)
|
||||
|
@ -218,11 +235,11 @@ namespace Util
|
|||
q.pop();
|
||||
|
||||
// Create a config entry for this XML element
|
||||
Util::Config::Node *node = &parent_node->Create(element->Name(), element->GetText() ? std::string(element->GetText()) : std::string());
|
||||
Util::Config::Node *node = &parent_node->Add(element->Name(), element->GetText() ? std::string(element->GetText()) : std::string());
|
||||
|
||||
// Create entries for each attribute
|
||||
for (const XMLAttribute *a = element->FirstAttribute(); a != 0; a = a->Next())
|
||||
node->Create(a->Name(), a->Value());
|
||||
node->Add(a->Name(), a->Value());
|
||||
|
||||
// Push all child elements
|
||||
for (const XMLElement *e = element->FirstChildElement(); e != 0; e = e->NextSiblingElement())
|
||||
|
@ -304,7 +321,7 @@ namespace Util
|
|||
// In INI files, we do not allow multiple settings with the same key. If
|
||||
// a setting is specified multiple times, previous ones are overwritten.
|
||||
if (current_section[lvalue].Empty())
|
||||
current_section.Create(lvalue, rvalue);
|
||||
current_section.Add(lvalue, rvalue);
|
||||
else
|
||||
current_section.Get(lvalue).SetValue(rvalue);
|
||||
}
|
||||
|
@ -347,7 +364,7 @@ namespace Util
|
|||
current_section = &global;
|
||||
else if (global[section].Empty())
|
||||
{
|
||||
Node &new_section = global.Create(section);
|
||||
Node &new_section = global.Add(section);
|
||||
current_section = &new_section;
|
||||
}
|
||||
else
|
||||
|
@ -388,10 +405,13 @@ namespace Util
|
|||
if (it->IsLeaf())
|
||||
{
|
||||
// INI semantics: take care to only create a single setting per key
|
||||
merged.Set(key, value);
|
||||
/*
|
||||
if (merged[key].Empty())
|
||||
merged.Create(key, value);
|
||||
merged.Add(key, value);
|
||||
else
|
||||
merged.Get(key).SetValue(value);
|
||||
*/
|
||||
}
|
||||
}
|
||||
// Merge in settings from section y
|
||||
|
@ -401,10 +421,13 @@ namespace Util
|
|||
auto &value = it->Value();
|
||||
if (it->IsLeaf())
|
||||
{
|
||||
merged.Set(key, value);
|
||||
/*
|
||||
if (merged[key].Empty())
|
||||
merged.Create(key, value);
|
||||
merged.Add(key, value);
|
||||
else
|
||||
merged.Get(key).SetValue(value);
|
||||
*/
|
||||
}
|
||||
}
|
||||
return merged_ptr;
|
||||
|
|
|
@ -186,11 +186,11 @@ namespace Util
|
|||
const Node &operator[](const std::string &path) const;
|
||||
const Node &Get(const std::string &path) const;
|
||||
void Print(size_t indent_level = 0) const;
|
||||
//TODO: this API is confusing. Create() -> Add() and add a Set() which
|
||||
// modifies existing settings if they exist (INI semantics should
|
||||
// use this).
|
||||
Node &Create(const std::string &key);
|
||||
Node &Create(const std::string &key, const std::string &value);
|
||||
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);
|
||||
void Set(const std::string &key, const std::string &value);
|
||||
Node(const std::string &key);
|
||||
Node(const std::string &key, const std::string &value);
|
||||
Node(const Node &that);
|
||||
|
|
|
@ -1,8 +1,18 @@
|
|||
#include "Util/NewConfig.h"
|
||||
#include <iostream>
|
||||
|
||||
static void PrintTestResults(std::vector<std::pair<std::string, bool>> results)
|
||||
{
|
||||
std::cout << "TEST RESULTS" << std::endl;
|
||||
std::cout << "------------" << std::endl;
|
||||
for (auto v: results)
|
||||
std::cout << v.first << ": " << (v.second ? "passed" : "FAILED") << std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::vector<std::pair<std::string, bool>> test_results;
|
||||
|
||||
/*
|
||||
* Creates a config tree corresponding to the following:
|
||||
*
|
||||
|
@ -21,41 +31,44 @@ int main()
|
|||
* </game>
|
||||
*/
|
||||
Util::Config::Node::Ptr_t root = std::make_shared<Util::Config::Node>("global");
|
||||
auto &game = root->Create("game");
|
||||
game.Create("name", "scud");
|
||||
auto &roms = game.Create("roms");
|
||||
auto &crom1 = roms.Create("crom");
|
||||
crom1.Create("name", "foo.bin");
|
||||
crom1.Create("offset", "0");
|
||||
auto &crom2 = roms.Create("crom");
|
||||
crom2.Create("name", "bar.bin");
|
||||
crom2.Create("offset", "2");
|
||||
auto &game = root->Add("game");
|
||||
game.Add("name", "scud");
|
||||
auto &roms = game.Add("roms");
|
||||
auto &crom1 = roms.Add("crom");
|
||||
crom1.Add("name", "foo.bin");
|
||||
crom1.Add("offset", "0");
|
||||
auto &crom2 = roms.Add("crom");
|
||||
crom2.Add("name", "bar.bin");
|
||||
crom2.Add("offset", "2");
|
||||
|
||||
const char *expected_output =
|
||||
"global children={ game } \n"
|
||||
" game children={ name roms } \n"
|
||||
" name=scud children={ } \n"
|
||||
" roms children={ crom } \n"
|
||||
" crom children={ name offset } \n"
|
||||
" name=foo.bin children={ } \n"
|
||||
" offset=0 children={ } \n"
|
||||
" crom children={ name offset } \n"
|
||||
" name=bar.bin children={ } \n"
|
||||
" offset=2 children={ } \n";
|
||||
"global children={ game }\n"
|
||||
" game children={ name roms }\n"
|
||||
" name=scud children={ }\n"
|
||||
" roms children={ crom }\n"
|
||||
" crom children={ name offset }\n"
|
||||
" name=foo.bin children={ }\n"
|
||||
" offset=0 children={ }\n"
|
||||
" crom children={ name offset }\n"
|
||||
" name=bar.bin children={ }\n"
|
||||
" offset=2 children={ }\n";
|
||||
std::cout << "Expected output:" << std::endl << std::endl << expected_output << std::endl;
|
||||
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 });
|
||||
|
||||
// Expect second crom: bar.bin
|
||||
auto &global = *root;
|
||||
std::cout << "game/roms/crom/name=" << global["game/roms/crom/name"].Value() << " (expected: bar.bin)" << std::endl << std::endl;
|
||||
test_results.push_back({ "Lookup", global["game/roms/crom/name"].Value() == "bar.bin" });
|
||||
|
||||
// Make a copy
|
||||
std::cout << "Copy:" << std::endl << std::endl;
|
||||
Util::Config::Node::Ptr_t copy = std::make_shared<Util::Config::Node>(*root);
|
||||
copy->Print();
|
||||
std::cout << std::endl;
|
||||
test_results.push_back({ "Copy", copy->ToString() == root->ToString() });
|
||||
|
||||
// Parse from XML
|
||||
const char *xml =
|
||||
|
@ -76,55 +89,58 @@ int main()
|
|||
" </roms> \n"
|
||||
"</game> \n";
|
||||
const char *expected_xml_config_tree =
|
||||
"xml children={ game } \n"
|
||||
" game children={ name roms } \n"
|
||||
" name=scud children={ } \n"
|
||||
" roms children={ region } \n"
|
||||
" region children={ byte_swap file name stride } \n"
|
||||
" name=crom children={ } \n"
|
||||
" stride=8 children={ } \n"
|
||||
" byte_swap=true children={ } \n"
|
||||
" file children={ crc32 name offset } \n"
|
||||
" offset=0 children={ } \n"
|
||||
" name=epr-19734.20 children={ } \n"
|
||||
" crc32=0xBE897336 children={ } \n"
|
||||
" file children={ crc32 name offset } \n"
|
||||
" offset=2 children={ } \n"
|
||||
" name=epr-19733.19 children={ } \n"
|
||||
" crc32=0x6565E29A children={ } \n"
|
||||
" file children={ crc32 name offset } \n"
|
||||
" offset=4 children={ } \n"
|
||||
" name=epr-19732.18 children={ } \n"
|
||||
" crc32=0x23E864BB children={ } \n"
|
||||
" file children={ crc32 name offset } \n"
|
||||
" offset=6 children={ } \n"
|
||||
" name=epr-19731.17 children={ } \n"
|
||||
" crc32=0x3EE6447E children={ } \n"
|
||||
" region children={ byte_swap file name stride } \n"
|
||||
" name=banked_crom children={ } \n"
|
||||
" stride=8 children={ } \n"
|
||||
" byte_swap=true children={ } \n"
|
||||
" file children={ crc32 name offset } \n"
|
||||
" offset=0x0000000 children={ } \n"
|
||||
" name=mpr-20364.4 children={ } \n"
|
||||
" crc32=0xA2A68EF2 children={ } \n"
|
||||
" file children={ crc32 name offset } \n"
|
||||
" offset=0x0000002 children={ } \n"
|
||||
" name=mpr-20363.3 children={ } \n"
|
||||
" crc32=0x3E3CC6FF children={ } \n"
|
||||
" file children={ crc32 name offset } \n"
|
||||
" offset=0x0000004 children={ } \n"
|
||||
" name=mpr-20362.2 children={ } \n"
|
||||
" crc32=0xF7E60DFD children={ } \n"
|
||||
" file children={ crc32 name offset } \n"
|
||||
" offset=0x0000006 children={ } \n"
|
||||
" name=mpr-20361.1 children={ } \n"
|
||||
" crc32=0xDDB66C2F children={ } \n";
|
||||
"xml children={ game }\n"
|
||||
" game children={ name roms }\n"
|
||||
" name=scud children={ }\n"
|
||||
" roms children={ region }\n"
|
||||
" region children={ byte_swap file name stride }\n"
|
||||
" name=crom children={ }\n"
|
||||
" stride=8 children={ }\n"
|
||||
" byte_swap=true children={ }\n"
|
||||
" file children={ crc32 name offset }\n"
|
||||
" offset=0 children={ }\n"
|
||||
" name=epr-19734.20 children={ }\n"
|
||||
" crc32=0xBE897336 children={ }\n"
|
||||
" file children={ crc32 name offset }\n"
|
||||
" offset=2 children={ }\n"
|
||||
" name=epr-19733.19 children={ }\n"
|
||||
" crc32=0x6565E29A children={ }\n"
|
||||
" file children={ crc32 name offset }\n"
|
||||
" offset=4 children={ }\n"
|
||||
" name=epr-19732.18 children={ }\n"
|
||||
" crc32=0x23E864BB children={ }\n"
|
||||
" file children={ crc32 name offset }\n"
|
||||
" offset=6 children={ }\n"
|
||||
" name=epr-19731.17 children={ }\n"
|
||||
" crc32=0x3EE6447E children={ }\n"
|
||||
" region children={ byte_swap file name stride }\n"
|
||||
" name=banked_crom children={ }\n"
|
||||
" stride=8 children={ }\n"
|
||||
" byte_swap=true children={ }\n"
|
||||
" file children={ crc32 name offset }\n"
|
||||
" offset=0x0000000 children={ }\n"
|
||||
" name=mpr-20364.4 children={ }\n"
|
||||
" crc32=0xA2A68EF2 children={ }\n"
|
||||
" file children={ crc32 name offset }\n"
|
||||
" offset=0x0000002 children={ }\n"
|
||||
" name=mpr-20363.3 children={ }\n"
|
||||
" crc32=0x3E3CC6FF children={ }\n"
|
||||
" file children={ crc32 name offset }\n"
|
||||
" offset=0x0000004 children={ }\n"
|
||||
" name=mpr-20362.2 children={ }\n"
|
||||
" crc32=0xF7E60DFD children={ }\n"
|
||||
" file children={ crc32 name offset }\n"
|
||||
" offset=0x0000006 children={ }\n"
|
||||
" name=mpr-20361.1 children={ }\n"
|
||||
" crc32=0xDDB66C2F children={ }\n";
|
||||
std::cout << "Expected output:" << std::endl << std::endl << expected_xml_config_tree << std::endl;
|
||||
std::cout << "Actual config tree:" << std::endl << std::endl;
|
||||
Util::Config::Node::Ptr_t xml_config = Util::Config::FromXML(xml);
|
||||
xml_config->Print();
|
||||
std::cout << std::endl;
|
||||
test_results.push_back({ "XML", xml_config->ToString() == expected_xml_config_tree });
|
||||
|
||||
PrintTestResults(test_results);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in a new issue