Skip to content

Commit

Permalink
JSON serialized storage of properties table.
Browse files Browse the repository at this point in the history
  • Loading branch information
DirtyHairy committed Jan 1, 2021
1 parent 2724ce3 commit 37abfb3
Show file tree
Hide file tree
Showing 22 changed files with 496 additions and 88 deletions.
4 changes: 3 additions & 1 deletion .vscode/settings.json
Expand Up @@ -101,6 +101,8 @@
"ranges": "cpp",
"stop_token": "cpp",
"version": "cpp",
"shared_mutex": "cpp"
"shared_mutex": "cpp",
"compare": "cpp",
"concepts": "cpp"
}
}
2 changes: 2 additions & 0 deletions src/common/module.mk
Expand Up @@ -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
Expand Down
77 changes: 77 additions & 0 deletions src/common/repository/CompositeKVRJsonAdapter.cxx
@@ -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);
}
41 changes: 41 additions & 0 deletions src/common/repository/CompositeKVRJsonAdapter.hxx
@@ -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
18 changes: 18 additions & 0 deletions src/common/repository/KeyValueRepository.hxx
Expand Up @@ -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:
Expand All @@ -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
6 changes: 1 addition & 5 deletions src/common/repository/KeyValueRepositoryConfigfile.hxx
Expand Up @@ -21,7 +21,7 @@
#include "FSNode.hxx"
#include "KeyValueRepository.hxx"

class KeyValueRepositoryConfigfile : public KeyValueRepository
class KeyValueRepositoryConfigfile : public KeyValueRepositoryAtomic
{
public:

Expand All @@ -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;
Expand Down
99 changes: 99 additions & 0 deletions src/common/repository/KeyValueRepositoryFile.hxx
@@ -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
81 changes: 81 additions & 0 deletions src/common/repository/KeyValueRepositoryJsonFile.cxx
@@ -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 comments on commit 37abfb3

Please sign in to comment.