diff options
author | Loek Le Blansch <loek@pipeframe.xyz> | 2024-12-07 15:29:33 +0100 |
---|---|---|
committer | Loek Le Blansch <loek@pipeframe.xyz> | 2024-12-07 15:29:33 +0100 |
commit | f19f37ae3eff84161f86e62a26fbd8b68f8f91a9 (patch) | |
tree | 492ab107b375e51eef084b7be0f608b7f4fae319 /src | |
parent | fdb4c99e139a264d4e15e6913a3756fc6cccb2f2 (diff) |
make SaveManager no longer a singleton
Diffstat (limited to 'src')
-rw-r--r-- | src/crepe/manager/Mediator.h | 4 | ||||
-rw-r--r-- | src/crepe/manager/SaveManager.cpp | 32 | ||||
-rw-r--r-- | src/crepe/manager/SaveManager.h | 27 | ||||
-rw-r--r-- | src/example/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/example/asset_manager.cpp | 36 | ||||
-rw-r--r-- | src/example/savemgr.cpp | 44 | ||||
-rw-r--r-- | src/test/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/test/SaveManagerTest.cpp | 41 |
8 files changed, 69 insertions, 118 deletions
diff --git a/src/crepe/manager/Mediator.h b/src/crepe/manager/Mediator.h index 8094d80..6507a74 100644 --- a/src/crepe/manager/Mediator.h +++ b/src/crepe/manager/Mediator.h @@ -5,13 +5,13 @@ // TODO: remove these singletons: #include "../facade/SDLContext.h" #include "EventManager.h" -#include "SaveManager.h" #include "api/LoopTimer.h" namespace crepe { class ComponentManager; class SceneManager; +class SaveManager; /** * Struct to pass references to classes that would otherwise need to be singletons down to @@ -28,7 +28,7 @@ class SceneManager; struct Mediator { OptionalRef<ComponentManager> component_manager; OptionalRef<SceneManager> scene_manager; - OptionalRef<SaveManager> save_manager = SaveManager::get_instance(); + OptionalRef<SaveManager> save_manager; OptionalRef<EventManager> event_manager = EventManager::get_instance(); OptionalRef<SDLContext> sdl_context = SDLContext::get_instance(); OptionalRef<LoopTimer> timer = LoopTimer::get_instance(); diff --git a/src/crepe/manager/SaveManager.cpp b/src/crepe/manager/SaveManager.cpp index d4ed1c1..292e8fd 100644 --- a/src/crepe/manager/SaveManager.cpp +++ b/src/crepe/manager/SaveManager.cpp @@ -1,13 +1,24 @@ #include "../ValueBroker.h" #include "../api/Config.h" #include "../facade/DB.h" -#include "../util/Log.h" #include "SaveManager.h" using namespace std; using namespace crepe; +SaveManager::SaveManager(Mediator & mediator) : Manager(mediator) { + mediator.save_manager = *this; +} + +DB & SaveManager::get_db() { + if (this->db == nullptr) { + Config & cfg = Config::get_instance(); + this->db = make_unique<DB>(cfg.savemgr.location); + } + return *this->db; +} + template <> string SaveManager::serialize(const string & value) const noexcept { return value; @@ -90,22 +101,6 @@ int32_t SaveManager::deserialize(const string & value) const noexcept { return deserialize<int64_t>(value); } -SaveManager::SaveManager() { dbg_trace(); } - -SaveManager & SaveManager::get_instance() { - dbg_trace(); - static SaveManager instance; - return instance; -} - -DB & SaveManager::get_db() { - Config & cfg = Config::get_instance(); - // TODO: make this path relative to XDG_DATA_HOME on Linux and whatever the - // default equivalent is on Windows using some third party library - static DB db(cfg.savemgr.location); - return db; -} - bool SaveManager::has(const string & key) { DB & db = this->get_db(); return db.has(key); @@ -155,7 +150,8 @@ ValueBroker<T> SaveManager::get(const string & key) { return { [this, key](const T & target) { this->set<T>(key, target); }, [this, key, value]() mutable -> const T & { - value = this->deserialize<T>(this->get_db().get(key)); + DB & db = this->get_db(); + value = this->deserialize<T>(db.get(key)); return value; }, }; diff --git a/src/crepe/manager/SaveManager.h b/src/crepe/manager/SaveManager.h index 3d8c852..d13a97a 100644 --- a/src/crepe/manager/SaveManager.h +++ b/src/crepe/manager/SaveManager.h @@ -4,6 +4,8 @@ #include "../ValueBroker.h" +#include "Manager.h" + namespace crepe { class DB; @@ -18,7 +20,7 @@ class DB; * * The underlying database is a key-value store. */ -class SaveManager { +class SaveManager : public Manager { public: /** * \brief Get a read/write reference to a value and initialize it if it does not yet exist @@ -63,8 +65,8 @@ public: */ bool has(const std::string & key); -private: - SaveManager(); +public: + SaveManager(Mediator & mediator); virtual ~SaveManager() = default; private: @@ -90,25 +92,18 @@ private: T deserialize(const std::string & value) const noexcept; public: - // singleton - static SaveManager & get_instance(); SaveManager(const SaveManager &) = delete; SaveManager(SaveManager &&) = delete; SaveManager & operator=(const SaveManager &) = delete; SaveManager & operator=(SaveManager &&) = delete; +protected: + //! Create or return DB + virtual DB & get_db(); + private: - /** - * \brief Create an instance of DB and return its reference - * - * \returns DB instance - * - * This function exists because DB is a facade class, which can't directly be used in the API - * without workarounds - * - * TODO: better solution - */ - static DB & get_db(); + //! Database + std::unique_ptr<DB> db = nullptr; }; } // namespace crepe diff --git a/src/example/CMakeLists.txt b/src/example/CMakeLists.txt index 8ef71bb..5a93b1f 100644 --- a/src/example/CMakeLists.txt +++ b/src/example/CMakeLists.txt @@ -16,8 +16,6 @@ function(add_example target_name) add_dependencies(examples ${target_name}) endfunction() -add_example(asset_manager) -add_example(savemgr) add_example(rendering_particle) add_example(game) add_example(button) diff --git a/src/example/asset_manager.cpp b/src/example/asset_manager.cpp deleted file mode 100644 index 917b547..0000000 --- a/src/example/asset_manager.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include <crepe/api/AssetManager.h> -#include <crepe/api/Texture.h> -#include <crepe/facade/Sound.h> - -using namespace crepe; - -int main() { - - // this needs to be called before the asset manager otherwise the destructor of sdl is not in - // the right order - { Texture test("../asset/texture/img.png"); } - // FIXME: make it so the issue described by the above comment is not possible (i.e. the order - // in which internal classes are instantiated should not impact the way the engine works). - - auto & mgr = AssetManager::get_instance(); - - { - // TODO: [design] the Sound class can't be directly included by the user as it includes - // SoLoud headers. - auto bgm = mgr.cache<Sound>("../mwe/audio/bgm.ogg"); - auto sfx1 = mgr.cache<Sound>("../mwe/audio/sfx1.wav"); - auto sfx2 = mgr.cache<Sound>("../mwe/audio/sfx2.wav"); - - auto img = mgr.cache<Texture>("../asset/texture/img.png"); - auto img1 = mgr.cache<Texture>("../asset/texture/second.png"); - } - - { - auto bgm = mgr.cache<Sound>("../mwe/audio/bgm.ogg"); - auto sfx1 = mgr.cache<Sound>("../mwe/audio/sfx1.wav"); - auto sfx2 = mgr.cache<Sound>("../mwe/audio/sfx2.wav"); - - auto img = mgr.cache<Texture>("../asset/texture/img.png"); - auto img1 = mgr.cache<Texture>("../asset/texture/second.png"); - } -} diff --git a/src/example/savemgr.cpp b/src/example/savemgr.cpp deleted file mode 100644 index 65c4a34..0000000 --- a/src/example/savemgr.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/** \file - * - * Standalone example for usage of the save manager - */ - -#include <cassert> -#include <crepe/api/Config.h> -#include <crepe/api/SaveManager.h> -#include <crepe/util/Log.h> -#include <crepe/util/Proxy.h> - -using namespace crepe; - -// unrelated setup code -int _ = []() { - // make sure all log messages get printed - auto & cfg = Config::get_instance(); - cfg.log.level = Log::Level::TRACE; - - return 0; // satisfy compiler -}(); - -int main() { - const char * key = "mygame.test"; - - SaveManager & mgr = SaveManager::get_instance(); - - dbg_logf("has key = {}", mgr.has(key)); - ValueBroker<int> prop = mgr.get<int>(key, 0); - Proxy<int> val = mgr.get<int>(key, 0); - - dbg_logf("val = {}", mgr.get<int>(key).get()); - prop.set(1); - dbg_logf("val = {}", mgr.get<int>(key).get()); - val = 2; - dbg_logf("val = {}", mgr.get<int>(key).get()); - mgr.set<int>(key, 3); - dbg_logf("val = {}", mgr.get<int>(key).get()); - - dbg_logf("has key = {}", mgr.has(key)); - assert(true == mgr.has(key)); - - return 0; -} diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index c9cbac5..734e3ee 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -17,4 +17,5 @@ target_sources(test_main PUBLIC ScriptEventTest.cpp ScriptSceneTest.cpp Profiling.cpp + SaveManagerTest.cpp ) diff --git a/src/test/SaveManagerTest.cpp b/src/test/SaveManagerTest.cpp new file mode 100644 index 0000000..a1efc33 --- /dev/null +++ b/src/test/SaveManagerTest.cpp @@ -0,0 +1,41 @@ +#include <gtest/gtest.h> + +#include <crepe/manager/SaveManager.h> +#include <crepe/facade/DB.h> +#include <crepe/ValueBroker.h> + +using namespace std; +using namespace crepe; +using namespace testing; + +class SaveManagerTest : public Test { + Mediator m; + class TestSaveManager : public SaveManager { + using SaveManager::SaveManager; + + // in-memory database for testing + DB db{}; + virtual DB & get_db() override { return this->db; } + }; + +public: + TestSaveManager mgr{m}; +}; + +TEST_F(SaveManagerTest, ReadWrite) { + ASSERT_FALSE(mgr.has("foo")); + mgr.set<string>("foo", "bar"); + ASSERT_TRUE(mgr.has("foo")); + + ValueBroker value = mgr.get<string>("foo"); + EXPECT_EQ(value.get(), "bar"); +} + +TEST_F(SaveManagerTest, DefaultValue) { + ValueBroker value = mgr.get<int>("foo", 3); + + ASSERT_EQ(value.get(), 3); + value.set(5); + ASSERT_EQ(value.get(), 5); +} + |