mirror of https://github.com/stella-emu/stella.git
Reimplement export / load of per-ROM properties.
This commit is contained in:
parent
14739497a1
commit
e8330f5600
|
@ -32,6 +32,7 @@ MODULE_OBJS := \
|
|||
src/common/sdl_blitter/BilinearBlitter.o \
|
||||
src/common/sdl_blitter/QisBlitter.o \
|
||||
src/common/sdl_blitter/BlitterFactory.o \
|
||||
src/common/repository/KeyValueRepositoryPropertyFile.o \
|
||||
|
||||
MODULE_DIRS += \
|
||||
src/common
|
||||
|
|
|
@ -31,9 +31,9 @@ class KeyValueRepository
|
|||
|
||||
virtual std::map<string, Variant> load() = 0;
|
||||
|
||||
virtual void save(const std::map<string, Variant>& values) = 0;
|
||||
virtual bool save(const std::map<string, Variant>& values) = 0;
|
||||
|
||||
virtual void 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;
|
||||
};
|
||||
|
|
|
@ -72,7 +72,7 @@ std::map<string, Variant> KeyValueRepositoryConfigfile::load()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void KeyValueRepositoryConfigfile::save(const std::map<string, Variant>& values)
|
||||
bool KeyValueRepositoryConfigfile::save(const std::map<string, Variant>& values)
|
||||
{
|
||||
stringstream out;
|
||||
out << "; Stella configuration file" << endl
|
||||
|
@ -97,9 +97,13 @@ void KeyValueRepositoryConfigfile::save(const std::map<string, Variant>& values)
|
|||
try
|
||||
{
|
||||
myFile.write(out);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
Logger::error("ERROR: Couldn't save to settings file " + myFile.getShortPath());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,9 @@ class KeyValueRepositoryConfigfile : public KeyValueRepository
|
|||
|
||||
std::map<string, Variant> load() override;
|
||||
|
||||
void save(const std::map<string, Variant>& values) override;
|
||||
bool save(const std::map<string, Variant>& values) override;
|
||||
|
||||
void save(const string& key, const Variant& value) override {}
|
||||
bool save(const string& key, const Variant& value) override { return false; }
|
||||
|
||||
void remove(const string& key) override {}
|
||||
|
||||
|
|
|
@ -28,9 +28,9 @@ class KeyValueRepositoryNoop : public KeyValueRepository
|
|||
return std::map<string, Variant>();
|
||||
}
|
||||
|
||||
void save(const std::map<string, Variant>& values) override {}
|
||||
bool save(const std::map<string, Variant>& values) override { return false; }
|
||||
|
||||
void save(const string& key, const Variant& value) override {}
|
||||
bool save(const string& key, const Variant& value) override { return false; }
|
||||
|
||||
void remove(const string& key) override {}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
//============================================================================
|
||||
//
|
||||
// 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-2020 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 {
|
||||
|
||||
string readQuotedString(istream& in)
|
||||
{
|
||||
// Read characters until we see a quote
|
||||
char c;
|
||||
while(in.get(c))
|
||||
if(c == '"')
|
||||
break;
|
||||
|
||||
// Read characters until we see the close quote
|
||||
string s;
|
||||
while(in.get(c))
|
||||
{
|
||||
if((c == '\\') && (in.peek() == '"'))
|
||||
in.get(c);
|
||||
else if((c == '\\') && (in.peek() == '\\'))
|
||||
in.get(c);
|
||||
else if(c == '"')
|
||||
break;
|
||||
else if(c == '\r')
|
||||
continue;
|
||||
|
||||
s += c;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void writeQuotedString(ostream& out, const string& s)
|
||||
{
|
||||
out.put('"');
|
||||
for(uInt32 i = 0; i < s.length(); ++i)
|
||||
{
|
||||
if(s[i] == '\\')
|
||||
{
|
||||
out.put('\\');
|
||||
out.put('\\');
|
||||
}
|
||||
else if(s[i] == '\"')
|
||||
{
|
||||
out.put('\\');
|
||||
out.put('"');
|
||||
}
|
||||
else
|
||||
out.put(s[i]);
|
||||
}
|
||||
out.put('"');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
KeyValueRepositoryPropertyFile::KeyValueRepositoryPropertyFile(const FilesystemNode& node)
|
||||
: myNode(node)
|
||||
{}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
std::map<string, Variant> KeyValueRepositoryPropertyFile::load()
|
||||
{
|
||||
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(;;)
|
||||
{
|
||||
// Get the key associated with this property
|
||||
key = readQuotedString(in);
|
||||
|
||||
// Make sure the stream is still okay
|
||||
if(!in) return map;
|
||||
|
||||
// A null key signifies the end of the property list
|
||||
if(key == "")
|
||||
break;
|
||||
|
||||
// Get the value associated with this property
|
||||
value = readQuotedString(in);
|
||||
|
||||
// Make sure the stream is still okay
|
||||
if(!in)
|
||||
return map;
|
||||
|
||||
map[key] = value;
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool KeyValueRepositoryPropertyFile::save(const std::map<string, Variant>& values)
|
||||
{
|
||||
if (values.size() == 0) return true;
|
||||
|
||||
stringstream out;
|
||||
|
||||
for (auto& [key, value]: values) {
|
||||
writeQuotedString(out, key);
|
||||
out.put(' ');
|
||||
writeQuotedString(out, value.toString());
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
//============================================================================
|
||||
//
|
||||
// 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-2020 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_PROPERTY_FILE_HXX
|
||||
#define KEY_VALUE_REPOSITORY_PROPERTY_FILE_HXX
|
||||
|
||||
#include "repository/KeyValueRepository.hxx"
|
||||
#include "FSNode.hxx"
|
||||
#include "bspf.hxx"
|
||||
|
||||
class KeyValueRepositoryPropertyFile : public KeyValueRepository {
|
||||
public:
|
||||
KeyValueRepositoryPropertyFile(const FilesystemNode& node);
|
||||
|
||||
std::map<string, Variant> load() 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:
|
||||
|
||||
const FilesystemNode& myNode;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -34,14 +34,14 @@ std::map<string, Variant> AbstractKeyValueRepositorySqlite::load()
|
|||
stmt.reset();
|
||||
}
|
||||
catch (const SqliteError& err) {
|
||||
Logger::info(err.what());
|
||||
Logger::error(err.what());
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void AbstractKeyValueRepositorySqlite::save(const std::map<string, Variant>& values)
|
||||
bool AbstractKeyValueRepositorySqlite::save(const std::map<string, Variant>& values)
|
||||
{
|
||||
try {
|
||||
SqliteTransaction tx{database()};
|
||||
|
@ -54,23 +54,31 @@ void AbstractKeyValueRepositorySqlite::save(const std::map<string, Variant>& val
|
|||
}
|
||||
|
||||
tx.commit();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (const SqliteError& err) {
|
||||
Logger::info(err.what());
|
||||
Logger::error(err.what());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void AbstractKeyValueRepositorySqlite::save(const string& key, const Variant& value)
|
||||
bool AbstractKeyValueRepositorySqlite::save(const string& key, const Variant& value)
|
||||
{
|
||||
try {
|
||||
SqliteStatement& stmt{stmtInsert(key, value.toString())};
|
||||
|
||||
stmt.step();
|
||||
stmt.reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (const SqliteError& err) {
|
||||
Logger::info(err.what());
|
||||
Logger::error(err.what());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,6 +92,6 @@ void AbstractKeyValueRepositorySqlite::remove(const string& key)
|
|||
stmt.reset();
|
||||
}
|
||||
catch (const SqliteError& err) {
|
||||
Logger::info(err.what());
|
||||
Logger::error(err.what());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,9 +12,9 @@ class AbstractKeyValueRepositorySqlite : public KeyValueRepository
|
|||
|
||||
std::map<string, Variant> load() override;
|
||||
|
||||
void save(const std::map<string, Variant>& values) override;
|
||||
bool save(const std::map<string, Variant>& values) override;
|
||||
|
||||
void save(const string& key, const Variant& value) override;
|
||||
bool save(const string& key, const Variant& value) override;
|
||||
|
||||
void remove(const string& key) override;
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ bool CompositeKeyValueRepositorySqlite::has(const string& key)
|
|||
|
||||
return rowCount > 0;
|
||||
} catch (const SqliteError& err) {
|
||||
Logger::info(err.what());
|
||||
Logger::error(err.what());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ void CompositeKeyValueRepositorySqlite::remove(const string& key)
|
|||
.step();
|
||||
}
|
||||
catch (const SqliteError& err) {
|
||||
Logger::info(err.what());
|
||||
Logger::error(err.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ bool SettingsDb::initialize()
|
|||
myPropertyRepository->initialize();
|
||||
}
|
||||
catch (const SqliteError& err) {
|
||||
Logger::info("sqlite DB " + databaseFileName() + " failed to initialize: " + err.what());
|
||||
Logger::error("sqlite DB " + databaseFileName() + " failed to initialize: " + err.what());
|
||||
|
||||
myDb.reset();
|
||||
mySettingsRepository.reset();
|
||||
|
|
|
@ -75,11 +75,11 @@ void SqliteDatabase::initialize()
|
|||
break;
|
||||
|
||||
case SQLITE_MISUSE:
|
||||
Logger::info("failed to checkpoint WAL on " + myDatabaseFile + " - WAL probably unavailable");
|
||||
Logger::error("failed to checkpoint WAL on " + myDatabaseFile + " - WAL probably unavailable");
|
||||
break;
|
||||
|
||||
default:
|
||||
Logger::info("failed to checkpoint WAL on " + myDatabaseFile + " : " + sqlite3_errmsg(myHandle));
|
||||
Logger::error("failed to checkpoint WAL on " + myDatabaseFile + " : " + sqlite3_errmsg(myHandle));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ void Properties::load(KeyValueRepository& repo)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Properties::save(KeyValueRepository& repo) const
|
||||
bool Properties::save(KeyValueRepository& repo) const
|
||||
{
|
||||
std::map<string, Variant> props;
|
||||
|
||||
|
@ -56,7 +56,7 @@ void Properties::save(KeyValueRepository& repo) const
|
|||
props[ourPropertyNames[i]] = myProperties[i];
|
||||
}
|
||||
|
||||
repo.save(props);
|
||||
return repo.save(props);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -84,7 +84,7 @@ class Properties
|
|||
public:
|
||||
void load(KeyValueRepository& repo);
|
||||
|
||||
void save(KeyValueRepository& repo) const;
|
||||
bool save(KeyValueRepository& repo) const;
|
||||
|
||||
/**
|
||||
Get the value assigned to the specified key. If the key does
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "Props.hxx"
|
||||
#include "PropsSet.hxx"
|
||||
#include "repository/CompositeKeyValueRepositoryNoop.hxx"
|
||||
#include "repository/KeyValueRepositoryPropertyFile.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PropertiesSet::PropertiesSet() : myRepository{make_shared<CompositeKeyValueRepositoryNoop>()} {}
|
||||
|
@ -142,6 +143,8 @@ void PropertiesSet::insert(const Properties& properties, bool save)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PropertiesSet::loadPerROM(const FilesystemNode& rom, const string& md5)
|
||||
{
|
||||
Properties props;
|
||||
|
||||
// Handle ROM properties, do some error checking
|
||||
// Only add to the database when necessary
|
||||
bool toInsert = false;
|
||||
|
@ -149,14 +152,14 @@ void PropertiesSet::loadPerROM(const FilesystemNode& rom, const string& md5)
|
|||
// First, does this ROM have a per-ROM properties entry?
|
||||
// If so, load it into the database
|
||||
FilesystemNode propsNode(rom.getPathWithExt(".pro"));
|
||||
// CSTODO
|
||||
#if 0
|
||||
if(propsNode.exists())
|
||||
load(propsNode, false);
|
||||
#endif
|
||||
if (propsNode.exists()) {
|
||||
KeyValueRepositoryPropertyFile repo(propsNode);
|
||||
props.load(repo);
|
||||
|
||||
insert(props, false);
|
||||
}
|
||||
|
||||
// Next, make sure we have a valid md5 and name
|
||||
Properties props;
|
||||
if(!getMD5(md5, props))
|
||||
{
|
||||
props.set(PropType::Cart_MD5, md5);
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "Widget.hxx"
|
||||
#include "Font.hxx"
|
||||
|
||||
#include "repository/KeyValueRepositoryPropertyFile.hxx"
|
||||
#include "FrameBuffer.hxx"
|
||||
#include "TIASurface.hxx"
|
||||
#include "TIA.hxx"
|
||||
|
@ -1334,22 +1335,12 @@ void GameInfoDialog::exportCurrentPropertiesToDisk(const FilesystemNode& node)
|
|||
{
|
||||
saveProperties();
|
||||
|
||||
// CSTODO
|
||||
#if 0
|
||||
stringstream out;
|
||||
out << myGameProperties;
|
||||
KeyValueRepositoryPropertyFile repo(node);
|
||||
|
||||
try
|
||||
{
|
||||
node.write(out);
|
||||
if (myGameProperties.save(repo))
|
||||
instance().frameBuffer().showTextMessage("ROM properties exported");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
else
|
||||
instance().frameBuffer().showTextMessage("Error exporting ROM properties");
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
Loading…
Reference in New Issue