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",
|
"ranges": "cpp",
|
||||||
"stop_token": "cpp",
|
"stop_token": "cpp",
|
||||||
"version": "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/QisBlitter.o \
|
||||||
src/common/sdl_blitter/BlitterFactory.o \
|
src/common/sdl_blitter/BlitterFactory.o \
|
||||||
src/common/repository/KeyValueRepositoryPropertyFile.o \
|
src/common/repository/KeyValueRepositoryPropertyFile.o \
|
||||||
|
src/common/repository/KeyValueRepositoryJsonFile.o \
|
||||||
|
src/common/repository/CompositeKVRJsonAdapter.o
|
||||||
|
|
||||||
MODULE_DIRS += \
|
MODULE_DIRS += \
|
||||||
src/common
|
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 "Variant.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Woverloaded-virtual"
|
||||||
|
|
||||||
|
class KeyValueRepositoryAtomic;
|
||||||
|
|
||||||
class KeyValueRepository
|
class KeyValueRepository
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -33,9 +38,22 @@ class KeyValueRepository
|
||||||
|
|
||||||
virtual bool save(const std::map<string, Variant>& values) = 0;
|
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 bool save(const string& key, const Variant& value) = 0;
|
||||||
|
|
||||||
virtual void remove(const string& key) = 0;
|
virtual void remove(const string& key) = 0;
|
||||||
|
|
||||||
|
KeyValueRepositoryAtomic* atomic() override { return this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
#endif // KEY_VALUE_REPOSITORY_HXX
|
#endif // KEY_VALUE_REPOSITORY_HXX
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "FSNode.hxx"
|
#include "FSNode.hxx"
|
||||||
#include "KeyValueRepository.hxx"
|
#include "KeyValueRepository.hxx"
|
||||||
|
|
||||||
class KeyValueRepositoryConfigfile : public KeyValueRepository
|
class KeyValueRepositoryConfigfile : public KeyValueRepositoryAtomic
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -31,10 +31,6 @@ class KeyValueRepositoryConfigfile : public KeyValueRepository
|
||||||
|
|
||||||
bool save(const std::map<string, Variant>& values) override;
|
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:
|
private:
|
||||||
|
|
||||||
FilesystemNode myFile;
|
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"
|
#include "KeyValueRepository.hxx"
|
||||||
|
|
||||||
class KeyValueRepositoryNoop : public KeyValueRepository
|
class KeyValueRepositoryNoop : public KeyValueRepositoryAtomic
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -28,6 +28,10 @@ class KeyValueRepositoryNoop : public KeyValueRepository
|
||||||
return std::map<string, Variant>();
|
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 std::map<string, Variant>& values) override { return false; }
|
||||||
|
|
||||||
bool save(const string& key, const Variant& value) 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
|
// SS SS tt ee ll ll aa aa
|
||||||
// SSSS ttt eeeee llll llll aaaaa
|
// 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
|
// and the Stella Team
|
||||||
//
|
//
|
||||||
// See the file "License.txt" for information on usage and redistribution of
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include <istream>
|
|
||||||
#include <ostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include "repository/KeyValueRepositoryPropertyFile.hxx"
|
#include "repository/KeyValueRepositoryPropertyFile.hxx"
|
||||||
#include "Logger.hxx"
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -77,30 +71,14 @@ namespace {
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
KeyValueRepositoryPropertyFile::KeyValueRepositoryPropertyFile(const FilesystemNode& node)
|
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;
|
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
|
// Loop reading properties
|
||||||
string key, value;
|
string key, value;
|
||||||
for(;;)
|
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) {
|
for (auto& [key, value]: values) {
|
||||||
writeQuotedString(out, key);
|
writeQuotedString(out, key);
|
||||||
out.put(' ');
|
out.put(' ');
|
||||||
|
@ -142,22 +116,5 @@ bool KeyValueRepositoryPropertyFile::save(const std::map<string, Variant>& value
|
||||||
out.put('\n');
|
out.put('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
writeQuotedString(out, "");
|
|
||||||
out.put('\n');
|
|
||||||
out.put('\n');
|
|
||||||
|
|
||||||
try {
|
|
||||||
myNode.write(out);
|
|
||||||
|
|
||||||
return true;
|
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
|
// SS SS tt ee ll ll aa aa
|
||||||
// SSSS ttt eeeee llll llll aaaaa
|
// 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
|
// and the Stella Team
|
||||||
//
|
//
|
||||||
// See the file "License.txt" for information on usage and redistribution of
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
@ -18,25 +18,19 @@
|
||||||
#ifndef KEY_VALUE_REPOSITORY_PROPERTY_FILE_HXX
|
#ifndef KEY_VALUE_REPOSITORY_PROPERTY_FILE_HXX
|
||||||
#define KEY_VALUE_REPOSITORY_PROPERTY_FILE_HXX
|
#define KEY_VALUE_REPOSITORY_PROPERTY_FILE_HXX
|
||||||
|
|
||||||
#include "repository/KeyValueRepository.hxx"
|
#include <istream>
|
||||||
#include "FSNode.hxx"
|
#include <ostream>
|
||||||
|
|
||||||
|
#include "repository/KeyValueRepositoryFile.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
|
||||||
class KeyValueRepositoryPropertyFile : public KeyValueRepository {
|
class KeyValueRepositoryPropertyFile : public KeyValueRepositoryFile<KeyValueRepositoryPropertyFile> {
|
||||||
public:
|
public:
|
||||||
KeyValueRepositoryPropertyFile(const FilesystemNode& node);
|
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;
|
static bool save(ostream& out, const std::map<string, Variant>& values);
|
||||||
|
|
||||||
bool save(const string& key, const Variant& value) override { return false; }
|
|
||||||
|
|
||||||
void remove(const string& key) override {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
const FilesystemNode& myNode;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // KEY_VALUE_REPOSITORY_PROPERTY_FILE_HXX
|
||||||
|
|
|
@ -40,6 +40,47 @@ std::map<string, Variant> AbstractKeyValueRepositorySqlite::load()
|
||||||
return values;
|
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)
|
bool AbstractKeyValueRepositorySqlite::save(const std::map<string, Variant>& values)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,10 +6,14 @@
|
||||||
#include "SqliteDatabase.hxx"
|
#include "SqliteDatabase.hxx"
|
||||||
#include "SqliteStatement.hxx"
|
#include "SqliteStatement.hxx"
|
||||||
|
|
||||||
class AbstractKeyValueRepositorySqlite : public KeyValueRepository
|
class AbstractKeyValueRepositorySqlite : public KeyValueRepositoryAtomic
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
bool has(const string& key) override;
|
||||||
|
|
||||||
|
bool get(const string& key, string& value) override;
|
||||||
|
|
||||||
std::map<string, Variant> load() override;
|
std::map<string, Variant> load() override;
|
||||||
|
|
||||||
bool save(const std::map<string, Variant>& values) 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& stmtInsert(const string& key, const string& value) = 0;
|
||||||
virtual SqliteStatement& stmtSelect() = 0;
|
virtual SqliteStatement& stmtSelect() = 0;
|
||||||
virtual SqliteStatement& stmtDelete(const string& key) = 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;
|
virtual SqliteDatabase& database() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -35,15 +35,15 @@ shared_ptr<KeyValueRepository> CompositeKeyValueRepositorySqlite::get(const stri
|
||||||
bool CompositeKeyValueRepositorySqlite::has(const string& key)
|
bool CompositeKeyValueRepositorySqlite::has(const string& key)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
myStmtCount->reset();
|
myStmtCountSet->reset();
|
||||||
myStmtCount->bind(1, key.c_str());
|
myStmtCountSet->bind(1, key.c_str());
|
||||||
|
|
||||||
if (!myStmtCount->step())
|
if (!myStmtCountSet->step())
|
||||||
throw new SqliteError("count failed");
|
throw new SqliteError("count failed");
|
||||||
|
|
||||||
Int32 rowCount = myStmtCount->columnInt(0);
|
Int32 rowCount = myStmtCountSet->columnInt(0);
|
||||||
|
|
||||||
myStmtCount->reset();
|
myStmtCountSet->reset();
|
||||||
|
|
||||||
return rowCount > 0;
|
return rowCount > 0;
|
||||||
} catch (const SqliteError& err) {
|
} catch (const SqliteError& err) {
|
||||||
|
@ -78,9 +78,11 @@ void CompositeKeyValueRepositorySqlite::initialize()
|
||||||
|
|
||||||
myStmtInsert = make_unique<SqliteStatement>(myDb, "INSERT OR REPLACE INTO `" + myTableName + "` VALUES (?, ?, ?)");
|
myStmtInsert = make_unique<SqliteStatement>(myDb, "INSERT OR REPLACE INTO `" + myTableName + "` VALUES (?, ?, ?)");
|
||||||
myStmtSelect = make_unique<SqliteStatement>(myDb, "SELECT `key2`, `VALUE` FROM `" + myTableName + "` WHERE `key1` = ?");
|
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` = ?");
|
myStmtDelete = make_unique<SqliteStatement>(myDb, "DELETE FROM `" + myTableName + "` WHERE `key1` = ? AND `key2` = ?");
|
||||||
myStmtDeleteSet = make_unique<SqliteStatement>(myDb, "DELETE FROM `" + myTableName + "` WHERE `key1` = ?");
|
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());
|
.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()
|
SqliteDatabase& CompositeKeyValueRepositorySqlite::ProxyRepository::database()
|
||||||
|
|
|
@ -49,6 +49,8 @@ class CompositeKeyValueRepositorySqlite : public CompositeKeyValueRepository {
|
||||||
SqliteStatement& stmtInsert(const string& key, const string& value) override;
|
SqliteStatement& stmtInsert(const string& key, const string& value) override;
|
||||||
SqliteStatement& stmtSelect() override;
|
SqliteStatement& stmtSelect() override;
|
||||||
SqliteStatement& stmtDelete(const string& key) override;
|
SqliteStatement& stmtDelete(const string& key) override;
|
||||||
|
SqliteStatement& stmtCount(const string& key) override;
|
||||||
|
SqliteStatement& stmtSelectOne(const string& key) override;
|
||||||
SqliteDatabase& database() override;
|
SqliteDatabase& database() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -71,9 +73,11 @@ class CompositeKeyValueRepositorySqlite : public CompositeKeyValueRepository {
|
||||||
|
|
||||||
unique_ptr<SqliteStatement> myStmtInsert;
|
unique_ptr<SqliteStatement> myStmtInsert;
|
||||||
unique_ptr<SqliteStatement> myStmtSelect;
|
unique_ptr<SqliteStatement> myStmtSelect;
|
||||||
unique_ptr<SqliteStatement> myStmtCount;
|
unique_ptr<SqliteStatement> myStmtCountSet;
|
||||||
unique_ptr<SqliteStatement> myStmtDelete;
|
unique_ptr<SqliteStatement> myStmtDelete;
|
||||||
unique_ptr<SqliteStatement> myStmtDeleteSet;
|
unique_ptr<SqliteStatement> myStmtDeleteSet;
|
||||||
|
unique_ptr<SqliteStatement> myStmtSelectOne;
|
||||||
|
unique_ptr<SqliteStatement> myStmtCount;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,24 @@ SqliteStatement& KeyValueRepositorySqlite::stmtDelete(const string& key)
|
||||||
.bind(1, key.c_str());
|
.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()
|
SqliteDatabase& KeyValueRepositorySqlite::database()
|
||||||
{
|
{
|
||||||
|
@ -67,6 +85,8 @@ void KeyValueRepositorySqlite::initialize()
|
||||||
);
|
);
|
||||||
|
|
||||||
myStmtInsert = make_unique<SqliteStatement>(myDb, "INSERT OR REPLACE INTO `" + myTableName + "` VALUES (?, ?)");
|
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` = ?");
|
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& stmtSelect() override;
|
||||||
SqliteStatement& stmtDelete(const string& key) override;
|
SqliteStatement& stmtDelete(const string& key) override;
|
||||||
SqliteDatabase& database() override;
|
SqliteDatabase& database() override;
|
||||||
|
SqliteStatement& stmtCount(const string& key) override;
|
||||||
|
SqliteStatement& stmtSelectOne(const string& key) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -46,6 +48,8 @@ class KeyValueRepositorySqlite : public AbstractKeyValueRepositorySqlite
|
||||||
unique_ptr<SqliteStatement> myStmtInsert;
|
unique_ptr<SqliteStatement> myStmtInsert;
|
||||||
unique_ptr<SqliteStatement> myStmtSelect;
|
unique_ptr<SqliteStatement> myStmtSelect;
|
||||||
unique_ptr<SqliteStatement> myStmtDelete;
|
unique_ptr<SqliteStatement> myStmtDelete;
|
||||||
|
unique_ptr<SqliteStatement> myStmtSelectOne;
|
||||||
|
unique_ptr<SqliteStatement> myStmtCount;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,10 @@ bool SettingsDb::initialize()
|
||||||
mySettingsRepository = make_unique<KeyValueRepositorySqlite>(*myDb, "settings");
|
mySettingsRepository = make_unique<KeyValueRepositorySqlite>(*myDb, "settings");
|
||||||
mySettingsRepository->initialize();
|
mySettingsRepository->initialize();
|
||||||
|
|
||||||
myPropertyRepository = make_unique<CompositeKeyValueRepositorySqlite>(*myDb, "properties");
|
myPropertyRepositoryHost = make_unique<KeyValueRepositorySqlite>(*myDb, "properties");
|
||||||
myPropertyRepository->initialize();
|
myPropertyRepositoryHost->initialize();
|
||||||
|
|
||||||
|
myPropertyRepository = make_unique<CompositeKVRJsonAdapter>(*myPropertyRepositoryHost);
|
||||||
}
|
}
|
||||||
catch (const SqliteError& err) {
|
catch (const SqliteError& err) {
|
||||||
Logger::error("sqlite DB " + databaseFileName() + " failed to initialize: " + err.what());
|
Logger::error("sqlite DB " + databaseFileName() + " failed to initialize: " + err.what());
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "SqliteDatabase.hxx"
|
#include "SqliteDatabase.hxx"
|
||||||
#include "KeyValueRepositorySqlite.hxx"
|
#include "KeyValueRepositorySqlite.hxx"
|
||||||
#include "CompositeKeyValueRepositorySqlite.hxx"
|
#include "repository/CompositeKVRJsonAdapter.hxx"
|
||||||
|
|
||||||
class SettingsDb
|
class SettingsDb
|
||||||
{
|
{
|
||||||
|
@ -44,7 +44,8 @@ class SettingsDb
|
||||||
|
|
||||||
shared_ptr<SqliteDatabase> myDb;
|
shared_ptr<SqliteDatabase> myDb;
|
||||||
unique_ptr<KeyValueRepositorySqlite> mySettingsRepository;
|
unique_ptr<KeyValueRepositorySqlite> mySettingsRepository;
|
||||||
unique_ptr<CompositeKeyValueRepositorySqlite> myPropertyRepository;
|
unique_ptr<KeyValueRepositorySqlite> myPropertyRepositoryHost;
|
||||||
|
unique_ptr<CompositeKVRJsonAdapter> myPropertyRepository;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SETTINGS_DB_HXX
|
#endif // SETTINGS_DB_HXX
|
||||||
|
|
|
@ -50,11 +50,12 @@ bool Properties::save(KeyValueRepository& repo) const
|
||||||
std::map<string, Variant> props;
|
std::map<string, Variant> props;
|
||||||
|
|
||||||
for (size_t i = 0; i < static_cast<size_t>(PropType::NumTypes); i++) {
|
for (size_t i = 0; i < static_cast<size_t>(PropType::NumTypes); i++) {
|
||||||
if (myProperties[i] == ourDefaultProperties[i])
|
if (myProperties[i] == ourDefaultProperties[i]) {
|
||||||
repo.remove(ourPropertyNames[i]);
|
if (repo.atomic()) repo.atomic()->remove(ourPropertyNames[i]);
|
||||||
else
|
} else {
|
||||||
props[ourPropertyNames[i]] = myProperties[i];
|
props[ourPropertyNames[i]] = myProperties[i];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return repo.save(props);
|
return repo.save(props);
|
||||||
}
|
}
|
||||||
|
|
|
@ -717,7 +717,7 @@ void Settings::setValue(const string& key, const Variant& value, bool persist)
|
||||||
{
|
{
|
||||||
auto it = myPermanentSettings.find(key);
|
auto it = myPermanentSettings.find(key);
|
||||||
if(it != myPermanentSettings.end()) {
|
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;
|
it->second = value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -760,5 +760,6 @@ void Settings::migrate()
|
||||||
{
|
{
|
||||||
while (getInt(SETTINGS_VERSION_KEY) < SETTINGS_VERSION) migrateOne();
|
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