mirror of https://github.com/stella-emu/stella.git
JSON serialized storage of properties table.
This commit is contained in:
parent
2724ce30ee
commit
37abfb3dfe
|
@ -101,6 +101,8 @@
|
|||
"ranges": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"version": "cpp",
|
||||
"shared_mutex": "cpp"
|
||||
"shared_mutex": "cpp",
|
||||
"compare": "cpp",
|
||||
"concepts": "cpp"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ MODULE_OBJS := \
|
|||
src/common/sdl_blitter/QisBlitter.o \
|
||||
src/common/sdl_blitter/BlitterFactory.o \
|
||||
src/common/repository/KeyValueRepositoryPropertyFile.o \
|
||||
src/common/repository/KeyValueRepositoryJsonFile.o \
|
||||
src/common/repository/CompositeKVRJsonAdapter.o
|
||||
|
||||
MODULE_DIRS += \
|
||||
src/common
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
//============================================================================
|
||||
//
|
||||
// SSSS tt lll lll
|
||||
// SS SS tt ll ll
|
||||
// SS tttttt eeee ll ll aaaa
|
||||
// SSSS tt ee ee ll ll aa
|
||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "CompositeKVRJsonAdapter.hxx"
|
||||
#include "repository/KeyValueRepositoryJsonFile.hxx"
|
||||
|
||||
namespace {
|
||||
class ProxyRepository : public KeyValueRepository {
|
||||
public:
|
||||
ProxyRepository(KeyValueRepositoryAtomic& kvr, const string& key)
|
||||
: myKvr(kvr), myKey(key)
|
||||
{}
|
||||
|
||||
std::map<string, Variant> load() override {
|
||||
if (!myKvr.has(myKey)) return std::map<string, Variant>();
|
||||
|
||||
string serialized;
|
||||
myKvr.get(myKey, serialized);
|
||||
|
||||
stringstream in{serialized};
|
||||
|
||||
return KeyValueRepositoryJsonFile::load(in);
|
||||
}
|
||||
|
||||
bool save(const std::map<string, Variant>& values) override {
|
||||
stringstream out;
|
||||
|
||||
if (!KeyValueRepositoryJsonFile::save(out, values)) return false;
|
||||
|
||||
return myKvr.save(myKey, out.str());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
KeyValueRepositoryAtomic& myKvr;
|
||||
const string& myKey;
|
||||
};
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
CompositeKVRJsonAdapter::CompositeKVRJsonAdapter(KeyValueRepositoryAtomic& kvr)
|
||||
: myKvr(kvr)
|
||||
{}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
shared_ptr<KeyValueRepository> CompositeKVRJsonAdapter::get(const string& key)
|
||||
{
|
||||
return make_shared<ProxyRepository>(myKvr, key);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CompositeKVRJsonAdapter::has(const string& key)
|
||||
{
|
||||
return myKvr.has(key);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CompositeKVRJsonAdapter::remove(const string& key)
|
||||
{
|
||||
return myKvr.remove(key);
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
//============================================================================
|
||||
//
|
||||
// SSSS tt lll lll
|
||||
// SS SS tt ll ll
|
||||
// SS tttttt eeee ll ll aaaa
|
||||
// SSSS tt ee ee ll ll aa
|
||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#ifndef COMPOSITE_KVR_JSON_ADAPTER_HXX
|
||||
#define COMPOSITE_KVR_JSON_ADAPTER_HXX
|
||||
|
||||
#include "repository/CompositeKeyValueRepository.hxx"
|
||||
#include "repository/KeyValueRepository.hxx"
|
||||
#include "bspf.hxx"
|
||||
|
||||
class CompositeKVRJsonAdapter : public CompositeKeyValueRepository {
|
||||
public:
|
||||
|
||||
CompositeKVRJsonAdapter(KeyValueRepositoryAtomic& kvr);
|
||||
|
||||
shared_ptr<KeyValueRepository> get(const string& key) override;
|
||||
|
||||
bool has(const string& key) override;
|
||||
|
||||
void remove(const string& key) override;
|
||||
|
||||
private:
|
||||
|
||||
KeyValueRepositoryAtomic& myKvr;
|
||||
};
|
||||
|
||||
#endif // COMPOSITE_KVR_JSON_ADAPTER_HXX
|
|
@ -23,6 +23,11 @@
|
|||
#include "Variant.hxx"
|
||||
#include "bspf.hxx"
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Woverloaded-virtual"
|
||||
|
||||
class KeyValueRepositoryAtomic;
|
||||
|
||||
class KeyValueRepository
|
||||
{
|
||||
public:
|
||||
|
@ -33,9 +38,22 @@ class KeyValueRepository
|
|||
|
||||
virtual bool save(const std::map<string, Variant>& values) = 0;
|
||||
|
||||
virtual KeyValueRepositoryAtomic* atomic() { return nullptr; }
|
||||
};
|
||||
|
||||
class KeyValueRepositoryAtomic : public KeyValueRepository {
|
||||
public:
|
||||
virtual bool has(const string& key) = 0;
|
||||
|
||||
virtual bool get(const string& key, string& value) = 0;
|
||||
|
||||
virtual bool save(const string& key, const Variant& value) = 0;
|
||||
|
||||
virtual void remove(const string& key) = 0;
|
||||
|
||||
KeyValueRepositoryAtomic* atomic() override { return this; }
|
||||
};
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
#endif // KEY_VALUE_REPOSITORY_HXX
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "FSNode.hxx"
|
||||
#include "KeyValueRepository.hxx"
|
||||
|
||||
class KeyValueRepositoryConfigfile : public KeyValueRepository
|
||||
class KeyValueRepositoryConfigfile : public KeyValueRepositoryAtomic
|
||||
{
|
||||
public:
|
||||
|
||||
|
@ -31,10 +31,6 @@ class KeyValueRepositoryConfigfile : public KeyValueRepository
|
|||
|
||||
bool save(const std::map<string, Variant>& values) override;
|
||||
|
||||
bool save(const string& key, const Variant& value) override { return false; }
|
||||
|
||||
void remove(const string& key) override {}
|
||||
|
||||
private:
|
||||
|
||||
FilesystemNode myFile;
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
//============================================================================
|
||||
//
|
||||
// SSSS tt lll lll
|
||||
// SS SS tt ll ll
|
||||
// SS tttttt eeee ll ll aaaa
|
||||
// SSSS tt ee ee ll ll aa
|
||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#ifndef KEY_VALUE_REPOSITORY_FILE_HXX
|
||||
#define KEY_VALUE_REPOSITORY_FILE_HXX
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "KeyValueRepository.hxx"
|
||||
#include "Logger.hxx"
|
||||
#include "FSNode.hxx"
|
||||
#include "bspf.hxx"
|
||||
|
||||
template<class T>
|
||||
class KeyValueRepositoryFile : public KeyValueRepository {
|
||||
public:
|
||||
KeyValueRepositoryFile(const FilesystemNode& node);
|
||||
|
||||
std::map<string, Variant> load() override;
|
||||
|
||||
bool save(const std::map<string, Variant>& values) override;
|
||||
|
||||
protected:
|
||||
|
||||
const FilesystemNode& myNode;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPLEMEMNTATION
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
template<class T>
|
||||
KeyValueRepositoryFile<T>::KeyValueRepositoryFile(const FilesystemNode& node)
|
||||
: myNode(node)
|
||||
{}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
template<class T>
|
||||
std::map<string, Variant> KeyValueRepositoryFile<T>::load()
|
||||
{
|
||||
if (!myNode.exists()) return std::map<string, Variant>();
|
||||
|
||||
stringstream in;
|
||||
|
||||
try {
|
||||
myNode.read(in);
|
||||
return T::load(in);
|
||||
}
|
||||
catch (const runtime_error& err) {
|
||||
Logger::error(err.what());
|
||||
|
||||
return std::map<string, Variant>();
|
||||
}
|
||||
catch (...) {
|
||||
return std::map<string, Variant>();
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
template<class T>
|
||||
bool KeyValueRepositoryFile<T>::save(const std::map<string, Variant>& values)
|
||||
{
|
||||
if (values.size() == 0) return true;
|
||||
|
||||
stringstream out;
|
||||
|
||||
try {
|
||||
T::save(out, values);
|
||||
myNode.write(out);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (const runtime_error& err) {
|
||||
Logger::error(err.what());
|
||||
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // KEY_VALUE_REPOSITORY_FILE
|
|
@ -0,0 +1,81 @@
|
|||
//============================================================================
|
||||
//
|
||||
// SSSS tt lll lll
|
||||
// SS SS tt ll ll
|
||||
// SS tttttt eeee ll ll aaaa
|
||||
// SSSS tt ee ee ll ll aa
|
||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include "repository/KeyValueRepositoryJsonFile.hxx"
|
||||
#include "Logger.hxx"
|
||||
#include "json_lib.hxx"
|
||||
|
||||
using nlohmann::json;
|
||||
|
||||
namespace {
|
||||
json jsonIfValid(const string& s) {
|
||||
json parsed = json::parse(s, nullptr, false);
|
||||
|
||||
return parsed.is_discarded() ? json(s) : parsed;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
KeyValueRepositoryJsonFile::KeyValueRepositoryJsonFile(const FilesystemNode& node)
|
||||
: KeyValueRepositoryFile<KeyValueRepositoryJsonFile>(node)
|
||||
{}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
std::map<string, Variant> KeyValueRepositoryJsonFile::load(istream& in)
|
||||
{
|
||||
try {
|
||||
std::map<string, Variant> map;
|
||||
|
||||
json deserialized = json::parse(in);
|
||||
|
||||
if (!deserialized.is_object()) {
|
||||
Logger::error("KeyVallueRepositoryJsonFile: not an object");
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
for (const auto& [key, value] : deserialized.items())
|
||||
map[key] = value.is_string() ? value.get<string>() : value.dump();
|
||||
|
||||
return map;
|
||||
}
|
||||
catch (const json::exception& err) {
|
||||
Logger::error("KeyValueRepositoryJsonFile: error during deserialization: " + string(err.what()));
|
||||
|
||||
return std::map<string, Variant>();
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool KeyValueRepositoryJsonFile::save(ostream& out, const std::map<string, Variant>& values)
|
||||
{
|
||||
try {
|
||||
json serializedJson = json::object();
|
||||
|
||||
for (const auto& [key, value] : values)
|
||||
serializedJson[key] = jsonIfValid(value.toString());
|
||||
|
||||
out << serializedJson.dump(2);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (const json::exception& err) {
|
||||
Logger::error("KeyValueRepositoryJsonFile: error during serialization: " + string(err.what()));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
//============================================================================
|
||||
//
|
||||
// SSSS tt lll lll
|
||||
// SS SS tt ll ll
|
||||
// SS tttttt eeee ll ll aaaa
|
||||
// SSSS tt ee ee ll ll aa
|
||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#ifndef KEY_VALUE_REPOSITORY_JSON_FILE_HXX
|
||||
#define KEY_VALUE_REPOSITORY_JSON_FILE_HXX
|
||||
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
|
||||
#include "repository/KeyValueRepositoryFile.hxx"
|
||||
#include "bspf.hxx"
|
||||
|
||||
class KeyValueRepositoryJsonFile : public KeyValueRepositoryFile<KeyValueRepositoryJsonFile> {
|
||||
public:
|
||||
KeyValueRepositoryJsonFile(const FilesystemNode& node);
|
||||
|
||||
static std::map<string, Variant> load(istream& in);
|
||||
|
||||
static bool save(ostream& out, const std::map<string, Variant>& values);
|
||||
};
|
||||
|
||||
#endif // KEY_VALUE_REPOSITORY_JSON_FILE_HXX
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include "KeyValueRepository.hxx"
|
||||
|
||||
class KeyValueRepositoryNoop : public KeyValueRepository
|
||||
class KeyValueRepositoryNoop : public KeyValueRepositoryAtomic
|
||||
{
|
||||
public:
|
||||
|
||||
|
@ -28,6 +28,10 @@ class KeyValueRepositoryNoop : public KeyValueRepository
|
|||
return std::map<string, Variant>();
|
||||
}
|
||||
|
||||
bool has(const string& key) override { return false; }
|
||||
|
||||
bool get(const string& key, string& value) override { return false; }
|
||||
|
||||
bool save(const std::map<string, Variant>& values) override { return false; }
|
||||
|
||||
bool save(const string& key, const Variant& value) override { return false; }
|
||||
|
|
|
@ -8,20 +8,14 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
|
||||
#include "repository/KeyValueRepositoryPropertyFile.hxx"
|
||||
#include "Logger.hxx"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -77,30 +71,14 @@ namespace {
|
|||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
KeyValueRepositoryPropertyFile::KeyValueRepositoryPropertyFile(const FilesystemNode& node)
|
||||
: myNode(node)
|
||||
: KeyValueRepositoryFile<KeyValueRepositoryPropertyFile>(node)
|
||||
{}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
std::map<string, Variant> KeyValueRepositoryPropertyFile::load()
|
||||
std::map<string, Variant> KeyValueRepositoryPropertyFile::load(istream& in)
|
||||
{
|
||||
std::map<string, Variant> map;
|
||||
|
||||
if (!myNode.exists()) return map;
|
||||
|
||||
stringstream in;
|
||||
|
||||
try {
|
||||
myNode.read(in);
|
||||
}
|
||||
catch (const runtime_error& err) {
|
||||
Logger::error(err.what());
|
||||
|
||||
return map;
|
||||
}
|
||||
catch (...) {
|
||||
return map;
|
||||
}
|
||||
|
||||
// Loop reading properties
|
||||
string key, value;
|
||||
for(;;)
|
||||
|
@ -129,12 +107,8 @@ std::map<string, Variant> KeyValueRepositoryPropertyFile::load()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool KeyValueRepositoryPropertyFile::save(const std::map<string, Variant>& values)
|
||||
bool KeyValueRepositoryPropertyFile::save(ostream& out, const std::map<string, Variant>& values)
|
||||
{
|
||||
if (values.size() == 0) return true;
|
||||
|
||||
stringstream out;
|
||||
|
||||
for (auto& [key, value]: values) {
|
||||
writeQuotedString(out, key);
|
||||
out.put(' ');
|
||||
|
@ -142,22 +116,5 @@ bool KeyValueRepositoryPropertyFile::save(const std::map<string, Variant>& value
|
|||
out.put('\n');
|
||||
}
|
||||
|
||||
writeQuotedString(out, "");
|
||||
out.put('\n');
|
||||
out.put('\n');
|
||||
|
||||
try {
|
||||
myNode.write(out);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (const runtime_error& err) {
|
||||
Logger::error(err.what());
|
||||
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -18,25 +18,19 @@
|
|||
#ifndef KEY_VALUE_REPOSITORY_PROPERTY_FILE_HXX
|
||||
#define KEY_VALUE_REPOSITORY_PROPERTY_FILE_HXX
|
||||
|
||||
#include "repository/KeyValueRepository.hxx"
|
||||
#include "FSNode.hxx"
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
|
||||
#include "repository/KeyValueRepositoryFile.hxx"
|
||||
#include "bspf.hxx"
|
||||
|
||||
class KeyValueRepositoryPropertyFile : public KeyValueRepository {
|
||||
class KeyValueRepositoryPropertyFile : public KeyValueRepositoryFile<KeyValueRepositoryPropertyFile> {
|
||||
public:
|
||||
KeyValueRepositoryPropertyFile(const FilesystemNode& node);
|
||||
|
||||
std::map<string, Variant> load() override;
|
||||
static std::map<string, Variant> load(istream& in);
|
||||
|
||||
bool save(const std::map<string, Variant>& values) override;
|
||||
|
||||
bool save(const string& key, const Variant& value) override { return false; }
|
||||
|
||||
void remove(const string& key) override {}
|
||||
|
||||
private:
|
||||
|
||||
const FilesystemNode& myNode;
|
||||
static bool save(ostream& out, const std::map<string, Variant>& values);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // KEY_VALUE_REPOSITORY_PROPERTY_FILE_HXX
|
||||
|
|
|
@ -40,6 +40,47 @@ std::map<string, Variant> AbstractKeyValueRepositorySqlite::load()
|
|||
return values;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool AbstractKeyValueRepositorySqlite::has(const string& key)
|
||||
{
|
||||
try {
|
||||
SqliteStatement& stmt{stmtCount(key)};
|
||||
|
||||
if (!stmt.step()) throw new SqliteError("count failed");
|
||||
|
||||
const bool result = stmt.columnInt(0) != 0;
|
||||
stmt.reset();
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (const SqliteError& err) {
|
||||
Logger::error(err.what());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool AbstractKeyValueRepositorySqlite::get(const string& key, string& value)
|
||||
{
|
||||
try {
|
||||
SqliteStatement& stmt{stmtSelectOne(key)};
|
||||
|
||||
if (!stmt.step()) return false;
|
||||
value = stmt.columnText(0);
|
||||
|
||||
stmt.reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (const SqliteError& err) {
|
||||
Logger::error(err.what());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool AbstractKeyValueRepositorySqlite::save(const std::map<string, Variant>& values)
|
||||
{
|
||||
|
|
|
@ -6,10 +6,14 @@
|
|||
#include "SqliteDatabase.hxx"
|
||||
#include "SqliteStatement.hxx"
|
||||
|
||||
class AbstractKeyValueRepositorySqlite : public KeyValueRepository
|
||||
class AbstractKeyValueRepositorySqlite : public KeyValueRepositoryAtomic
|
||||
{
|
||||
public:
|
||||
|
||||
bool has(const string& key) override;
|
||||
|
||||
bool get(const string& key, string& value) override;
|
||||
|
||||
std::map<string, Variant> load() override;
|
||||
|
||||
bool save(const std::map<string, Variant>& values) override;
|
||||
|
@ -23,6 +27,8 @@ class AbstractKeyValueRepositorySqlite : public KeyValueRepository
|
|||
virtual SqliteStatement& stmtInsert(const string& key, const string& value) = 0;
|
||||
virtual SqliteStatement& stmtSelect() = 0;
|
||||
virtual SqliteStatement& stmtDelete(const string& key) = 0;
|
||||
virtual SqliteStatement& stmtCount(const string& key) = 0;
|
||||
virtual SqliteStatement& stmtSelectOne(const string& key) = 0;
|
||||
virtual SqliteDatabase& database() = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -35,15 +35,15 @@ shared_ptr<KeyValueRepository> CompositeKeyValueRepositorySqlite::get(const stri
|
|||
bool CompositeKeyValueRepositorySqlite::has(const string& key)
|
||||
{
|
||||
try {
|
||||
myStmtCount->reset();
|
||||
myStmtCount->bind(1, key.c_str());
|
||||
myStmtCountSet->reset();
|
||||
myStmtCountSet->bind(1, key.c_str());
|
||||
|
||||
if (!myStmtCount->step())
|
||||
if (!myStmtCountSet->step())
|
||||
throw new SqliteError("count failed");
|
||||
|
||||
Int32 rowCount = myStmtCount->columnInt(0);
|
||||
Int32 rowCount = myStmtCountSet->columnInt(0);
|
||||
|
||||
myStmtCount->reset();
|
||||
myStmtCountSet->reset();
|
||||
|
||||
return rowCount > 0;
|
||||
} catch (const SqliteError& err) {
|
||||
|
@ -78,9 +78,11 @@ void CompositeKeyValueRepositorySqlite::initialize()
|
|||
|
||||
myStmtInsert = make_unique<SqliteStatement>(myDb, "INSERT OR REPLACE INTO `" + myTableName + "` VALUES (?, ?, ?)");
|
||||
myStmtSelect = make_unique<SqliteStatement>(myDb, "SELECT `key2`, `VALUE` FROM `" + myTableName + "` WHERE `key1` = ?");
|
||||
myStmtCount = make_unique<SqliteStatement>(myDb, "SELECT COUNT(*) FROM `" + myTableName + "` WHERE `key1` = ?");
|
||||
myStmtCountSet = make_unique<SqliteStatement>(myDb, "SELECT COUNT(*) FROM `" + myTableName + "` WHERE `key1` = ?");
|
||||
myStmtDelete = make_unique<SqliteStatement>(myDb, "DELETE FROM `" + myTableName + "` WHERE `key1` = ? AND `key2` = ?");
|
||||
myStmtDeleteSet = make_unique<SqliteStatement>(myDb, "DELETE FROM `" + myTableName + "` WHERE `key1` = ?");
|
||||
myStmtSelectOne = make_unique<SqliteStatement>(myDb, "SELECT `value` FROM `" + myTableName + "` WHERE `key1` = ? AND `key2` = ?");
|
||||
myStmtCount = make_unique<SqliteStatement>(myDb, "SELECT COUNT(`key1`) FROM `" + myTableName + "` WHERE `key1` = ? AND `key2` = ?");
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -121,6 +123,25 @@ SqliteStatement& CompositeKeyValueRepositorySqlite::ProxyRepository::stmtDelete(
|
|||
.bind(2, key.c_str());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SqliteStatement& CompositeKeyValueRepositorySqlite::ProxyRepository::stmtSelectOne(const string& key)
|
||||
{
|
||||
myRepo.myStmtSelectOne->reset();
|
||||
|
||||
return (*myRepo.myStmtSelectOne)
|
||||
.bind(1, myKey.c_str())
|
||||
.bind(2, key.c_str());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SqliteStatement& CompositeKeyValueRepositorySqlite::ProxyRepository::stmtCount(const string& key)
|
||||
{
|
||||
myRepo.myStmtCount->reset();
|
||||
|
||||
return (*myRepo.myStmtCount)
|
||||
.bind(1, myKey.c_str())
|
||||
.bind(2, key.c_str());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SqliteDatabase& CompositeKeyValueRepositorySqlite::ProxyRepository::database()
|
||||
|
|
|
@ -49,6 +49,8 @@ class CompositeKeyValueRepositorySqlite : public CompositeKeyValueRepository {
|
|||
SqliteStatement& stmtInsert(const string& key, const string& value) override;
|
||||
SqliteStatement& stmtSelect() override;
|
||||
SqliteStatement& stmtDelete(const string& key) override;
|
||||
SqliteStatement& stmtCount(const string& key) override;
|
||||
SqliteStatement& stmtSelectOne(const string& key) override;
|
||||
SqliteDatabase& database() override;
|
||||
|
||||
private:
|
||||
|
@ -71,9 +73,11 @@ class CompositeKeyValueRepositorySqlite : public CompositeKeyValueRepository {
|
|||
|
||||
unique_ptr<SqliteStatement> myStmtInsert;
|
||||
unique_ptr<SqliteStatement> myStmtSelect;
|
||||
unique_ptr<SqliteStatement> myStmtCount;
|
||||
unique_ptr<SqliteStatement> myStmtCountSet;
|
||||
unique_ptr<SqliteStatement> myStmtDelete;
|
||||
unique_ptr<SqliteStatement> myStmtDeleteSet;
|
||||
unique_ptr<SqliteStatement> myStmtSelectOne;
|
||||
unique_ptr<SqliteStatement> myStmtCount;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -53,6 +53,24 @@ SqliteStatement& KeyValueRepositorySqlite::stmtDelete(const string& key)
|
|||
.bind(1, key.c_str());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SqliteStatement& KeyValueRepositorySqlite::stmtCount(const string& key)
|
||||
{
|
||||
myStmtCount->reset();
|
||||
|
||||
return (*myStmtCount)
|
||||
.bind(1, key.c_str());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SqliteStatement& KeyValueRepositorySqlite::stmtSelectOne(const string& key)
|
||||
{
|
||||
myStmtSelectOne->reset();
|
||||
|
||||
return (*myStmtSelectOne)
|
||||
.bind(1, key.c_str());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SqliteDatabase& KeyValueRepositorySqlite::database()
|
||||
{
|
||||
|
@ -67,6 +85,8 @@ void KeyValueRepositorySqlite::initialize()
|
|||
);
|
||||
|
||||
myStmtInsert = make_unique<SqliteStatement>(myDb, "INSERT OR REPLACE INTO `" + myTableName + "` VALUES (?, ?)");
|
||||
myStmtSelect = make_unique<SqliteStatement>(myDb, "SELECT `key`, `VALUE` FROM `" + myTableName + "`");
|
||||
myStmtSelect = make_unique<SqliteStatement>(myDb, "SELECT `key`, `value` FROM `" + myTableName + "`");
|
||||
myStmtDelete = make_unique<SqliteStatement>(myDb, "DELETE FROM `" + myTableName + "` WHERE `key` = ?");
|
||||
myStmtSelectOne = make_unique<SqliteStatement>(myDb, "SELECT `value` FROM `" + myTableName + "` WHERE `key` = ?");
|
||||
myStmtCount = make_unique<SqliteStatement>(myDb, "SELECT COUNT(`key`) FROM `" + myTableName + "` WHERE `key` = ?");
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ class KeyValueRepositorySqlite : public AbstractKeyValueRepositorySqlite
|
|||
SqliteStatement& stmtSelect() override;
|
||||
SqliteStatement& stmtDelete(const string& key) override;
|
||||
SqliteDatabase& database() override;
|
||||
SqliteStatement& stmtCount(const string& key) override;
|
||||
SqliteStatement& stmtSelectOne(const string& key) override;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -46,6 +48,8 @@ class KeyValueRepositorySqlite : public AbstractKeyValueRepositorySqlite
|
|||
unique_ptr<SqliteStatement> myStmtInsert;
|
||||
unique_ptr<SqliteStatement> myStmtSelect;
|
||||
unique_ptr<SqliteStatement> myStmtDelete;
|
||||
unique_ptr<SqliteStatement> myStmtSelectOne;
|
||||
unique_ptr<SqliteStatement> myStmtCount;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -36,8 +36,10 @@ bool SettingsDb::initialize()
|
|||
mySettingsRepository = make_unique<KeyValueRepositorySqlite>(*myDb, "settings");
|
||||
mySettingsRepository->initialize();
|
||||
|
||||
myPropertyRepository = make_unique<CompositeKeyValueRepositorySqlite>(*myDb, "properties");
|
||||
myPropertyRepository->initialize();
|
||||
myPropertyRepositoryHost = make_unique<KeyValueRepositorySqlite>(*myDb, "properties");
|
||||
myPropertyRepositoryHost->initialize();
|
||||
|
||||
myPropertyRepository = make_unique<CompositeKVRJsonAdapter>(*myPropertyRepositoryHost);
|
||||
}
|
||||
catch (const SqliteError& err) {
|
||||
Logger::error("sqlite DB " + databaseFileName() + " failed to initialize: " + err.what());
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "bspf.hxx"
|
||||
#include "SqliteDatabase.hxx"
|
||||
#include "KeyValueRepositorySqlite.hxx"
|
||||
#include "CompositeKeyValueRepositorySqlite.hxx"
|
||||
#include "repository/CompositeKVRJsonAdapter.hxx"
|
||||
|
||||
class SettingsDb
|
||||
{
|
||||
|
@ -44,7 +44,8 @@ class SettingsDb
|
|||
|
||||
shared_ptr<SqliteDatabase> myDb;
|
||||
unique_ptr<KeyValueRepositorySqlite> mySettingsRepository;
|
||||
unique_ptr<CompositeKeyValueRepositorySqlite> myPropertyRepository;
|
||||
unique_ptr<KeyValueRepositorySqlite> myPropertyRepositoryHost;
|
||||
unique_ptr<CompositeKVRJsonAdapter> myPropertyRepository;
|
||||
};
|
||||
|
||||
#endif // SETTINGS_DB_HXX
|
||||
|
|
|
@ -50,11 +50,12 @@ bool Properties::save(KeyValueRepository& repo) const
|
|||
std::map<string, Variant> props;
|
||||
|
||||
for (size_t i = 0; i < static_cast<size_t>(PropType::NumTypes); i++) {
|
||||
if (myProperties[i] == ourDefaultProperties[i])
|
||||
repo.remove(ourPropertyNames[i]);
|
||||
else
|
||||
if (myProperties[i] == ourDefaultProperties[i]) {
|
||||
if (repo.atomic()) repo.atomic()->remove(ourPropertyNames[i]);
|
||||
} else {
|
||||
props[ourPropertyNames[i]] = myProperties[i];
|
||||
}
|
||||
}
|
||||
|
||||
return repo.save(props);
|
||||
}
|
||||
|
|
|
@ -717,7 +717,7 @@ void Settings::setValue(const string& key, const Variant& value, bool persist)
|
|||
{
|
||||
auto it = myPermanentSettings.find(key);
|
||||
if(it != myPermanentSettings.end()) {
|
||||
if (persist && it->second != value) myRespository->save(key, value);
|
||||
if (persist && it->second != value && myRespository->atomic()) myRespository->atomic()->save(key, value);
|
||||
it->second = value;
|
||||
}
|
||||
else
|
||||
|
@ -760,5 +760,6 @@ void Settings::migrate()
|
|||
{
|
||||
while (getInt(SETTINGS_VERSION_KEY) < SETTINGS_VERSION) migrateOne();
|
||||
|
||||
myRespository->save(SETTINGS_VERSION_KEY, SETTINGS_VERSION);
|
||||
if (myRespository->atomic())
|
||||
myRespository->atomic()->save(SETTINGS_VERSION_KEY, SETTINGS_VERSION);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue