From 1b861eaa6127a0e297f9cbcbc649ba9ba395b5ac Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Mon, 22 Jan 2018 18:40:09 -1000 Subject: [PATCH] Non-clobbering YAML serialize operation --- hecl/extern/athena | 2 +- hecl/extern/boo | 2 +- hecl/include/hecl/CVarCommons.hpp | 4 +- hecl/lib/CVarManager.cpp | 92 ++++++++++++++++++++----------- 4 files changed, 65 insertions(+), 35 deletions(-) diff --git a/hecl/extern/athena b/hecl/extern/athena index de55c9acd..42b97e030 160000 --- a/hecl/extern/athena +++ b/hecl/extern/athena @@ -1 +1 @@ -Subproject commit de55c9acdfebb4f05310b24a0a5b865bcbc811b9 +Subproject commit 42b97e03064ad0dc37c5057a1f802e8c3c9190d4 diff --git a/hecl/extern/boo b/hecl/extern/boo index 25dc238c4..1d70723c9 160000 --- a/hecl/extern/boo +++ b/hecl/extern/boo @@ -1 +1 @@ -Subproject commit 25dc238c447f93ad706cfaa7396b5cb96779168e +Subproject commit 1d70723c985568eecfb9808329b53bb490c943f8 diff --git a/hecl/include/hecl/CVarCommons.hpp b/hecl/include/hecl/CVarCommons.hpp index cdfd4c2fe..6f5cb8685 100644 --- a/hecl/include/hecl/CVarCommons.hpp +++ b/hecl/include/hecl/CVarCommons.hpp @@ -19,14 +19,14 @@ using namespace std::literals; #define DEFAULT_GRAPHICS_API "OpenGL"sv #endif -class CVarCommons +struct CVarCommons { CVarManager& m_mgr; CVar* m_graphicsApi = nullptr; CVar* m_drawSamples = nullptr; CVar* m_texAnisotropy = nullptr; CVar* m_deepColor = nullptr; -public: + CVarCommons(CVarManager& manager) : m_mgr(manager) { m_graphicsApi = m_mgr.findOrMakeCVar("graphicsApi"sv, diff --git a/hecl/lib/CVarManager.cpp b/hecl/lib/CVarManager.cpp index 6179a475e..29cf05036 100755 --- a/hecl/lib/CVarManager.cpp +++ b/hecl/lib/CVarManager.cpp @@ -75,7 +75,6 @@ void CVarManager::deserialize(CVar* cvar) if (!cvar || (!cvar->isArchive() && !cvar->isInternalArchivable())) return; - CVarContainer container; #if _WIN32 hecl::SystemString filename = hecl::SystemString(m_store.getStoreRoot()) + _S('/') + com_configfile->toWideLiteral(); #else @@ -85,12 +84,33 @@ void CVarManager::deserialize(CVar* cvar) if (m_useBinary) { + CVarContainer container; filename += _S(".bin"); if (hecl::Stat(filename.c_str(), &st) || !S_ISREG(st.st_mode)) return; athena::io::FileReader reader(filename); if (reader.isOpen()) container.read(reader); + + if (container.cvars.size() > 0) + { + auto serialized = std::find_if(container.cvars.begin(), + container.cvars.end(), + [&cvar](const DNACVAR::CVar& c) { return c.m_name == cvar->name(); }); + + if (serialized != container.cvars.end()) + { + DNACVAR::CVar& tmp = *serialized; + + if (cvar->m_value != tmp.m_value) + { + cvar->unlock(); + cvar->fromLiteralToType(tmp.m_value, true); + cvar->m_wasDeserialized = true; + cvar->lock(); + } + } + } } else { @@ -99,25 +119,27 @@ void CVarManager::deserialize(CVar* cvar) return; athena::io::FileReader reader(filename); if (reader.isOpen()) - container.fromYAMLStream(reader); - } - - - if (container.cvars.size() > 0) - { - auto serialized = std::find_if(container.cvars.begin(), container.cvars.end(), [&cvar](const DNACVAR::CVar& c) -> bool - { return c.m_name == cvar->name(); }); - - if (serialized != container.cvars.end()) { - DNACVAR::CVar& tmp = *serialized; - - if (cvar->m_value != tmp.m_value) + athena::io::YAMLDocReader docReader; + if (docReader.parse(&reader)) { - cvar->unlock(); - cvar->fromLiteralToType(tmp.m_value, true); - cvar->m_wasDeserialized = true; - cvar->lock(); + std::unique_ptr root = docReader.releaseRootNode(); + auto serialized = std::find_if(root->m_mapChildren.begin(), + root->m_mapChildren.end(), + [&cvar](const auto& c) { return c.first == cvar->name(); }); + + if (serialized != root->m_mapChildren.end()) + { + const std::unique_ptr& tmp = serialized->second; + + if (cvar->m_value != tmp->m_scalarString) + { + cvar->unlock(); + cvar->fromLiteralToType(tmp->m_scalarString, true); + cvar->m_wasDeserialized = true; + cvar->lock(); + } + } } } } @@ -125,16 +147,6 @@ void CVarManager::deserialize(CVar* cvar) void CVarManager::serialize() { - CVarContainer container; - for (const std::pair& pair : m_cvars) - if (pair.second->isArchive() || (pair.second->isInternalArchivable() && pair.second->wasDeserialized() && !pair.second->hasDefaultValue())) - { - CVar tmp = *pair.second; - container.cvars.push_back(tmp); - } - - container.cvarCount = atUint32(container.cvars.size()); - #if _WIN32 hecl::SystemString filename = hecl::SystemString(m_store.getStoreRoot()) + _S('/') + com_configfile->toWideLiteral(); #else @@ -143,6 +155,13 @@ void CVarManager::serialize() if (m_useBinary) { + CVarContainer container; + for (const std::pair& pair : m_cvars) + if (pair.second->isArchive() || (pair.second->isInternalArchivable() && + pair.second->wasDeserialized() && !pair.second->hasDefaultValue())) + container.cvars.push_back(*pair.second); + container.cvarCount = atUint32(container.cvars.size()); + filename += _S(".bin"); athena::io::FileWriter writer(filename); if (writer.isOpen()) @@ -151,9 +170,20 @@ void CVarManager::serialize() else { filename += _S(".yaml"); - athena::io::FileWriter writer(filename); - if (writer.isOpen()) - container.toYAMLStream(writer); + + athena::io::FileReader r(filename); + athena::io::YAMLDocWriter docWriter(nullptr, r.isOpen() ? &r : nullptr); + r.close(); + + docWriter.setStyle(athena::io::YAMLNodeStyle::Block); + for (const std::pair& pair : m_cvars) + if (pair.second->isArchive() || (pair.second->isInternalArchivable() && + pair.second->wasDeserialized() && !pair.second->hasDefaultValue())) + docWriter.writeString(pair.second->name().data(), pair.second->toLiteral()); + + athena::io::FileWriter w(filename); + if (w.isOpen()) + docWriter.finish(&w); } }