aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-12-07 15:29:33 +0100
committerLoek Le Blansch <loek@pipeframe.xyz>2024-12-07 15:29:33 +0100
commitf19f37ae3eff84161f86e62a26fbd8b68f8f91a9 (patch)
tree492ab107b375e51eef084b7be0f608b7f4fae319 /src
parentfdb4c99e139a264d4e15e6913a3756fc6cccb2f2 (diff)
make SaveManager no longer a singleton
Diffstat (limited to 'src')
-rw-r--r--src/crepe/manager/Mediator.h4
-rw-r--r--src/crepe/manager/SaveManager.cpp32
-rw-r--r--src/crepe/manager/SaveManager.h27
-rw-r--r--src/example/CMakeLists.txt2
-rw-r--r--src/example/asset_manager.cpp36
-rw-r--r--src/example/savemgr.cpp44
-rw-r--r--src/test/CMakeLists.txt1
-rw-r--r--src/test/SaveManagerTest.cpp41
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);
+}
+