mirror of https://github.com/stella-emu/stella.git
Final refactoring & cleanup to generalize sqlite handling.
This commit is contained in:
parent
ed4529b164
commit
67005ef3e8
|
@ -15,86 +15,32 @@
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include <sqlite3.h>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#include "KeyValueRepositorySqlite.hxx"
|
#include "KeyValueRepositorySqlite.hxx"
|
||||||
#include "bspf.hxx"
|
#include "SqliteError.hxx"
|
||||||
|
|
||||||
#ifdef BSPF_WINDOWS
|
|
||||||
#define SEPARATOR "\"
|
|
||||||
#else
|
|
||||||
#define SEPARATOR "/"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
struct SqliteError {
|
|
||||||
SqliteError(const string _message) : message(_message) {}
|
|
||||||
|
|
||||||
const string message;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Statement {
|
|
||||||
public:
|
|
||||||
|
|
||||||
Statement(sqlite3* handle, string sql) : myStmt(nullptr)
|
|
||||||
{
|
|
||||||
if (sqlite3_prepare_v2(handle, sql.c_str(), -1, &myStmt, nullptr) != SQLITE_OK)
|
|
||||||
throw SqliteError(sqlite3_errmsg(handle));
|
|
||||||
}
|
|
||||||
|
|
||||||
~Statement()
|
|
||||||
{
|
|
||||||
if (myStmt) sqlite3_finalize(myStmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator sqlite3_stmt*() const { return myStmt; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
sqlite3_stmt* myStmt;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
Statement() = delete;
|
|
||||||
Statement(const Statement&) = delete;
|
|
||||||
Statement(Statement&&) = delete;
|
|
||||||
Statement& operator=(const Statement&) = delete;
|
|
||||||
Statement& operator=(Statement&&) = delete;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
KeyValueRepositorySqlite::KeyValueRepositorySqlite(
|
KeyValueRepositorySqlite::KeyValueRepositorySqlite(
|
||||||
const string& databaseDirectory,
|
SqliteDatabase& db,
|
||||||
const string& databaseName
|
const string& tableName
|
||||||
) : myDatabaseFile(databaseDirectory + SEPARATOR + databaseName + ".sqlite3"),
|
) : myTableName(tableName),
|
||||||
myIsFailed(false),
|
myDb(db)
|
||||||
myDbHandle(nullptr)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
KeyValueRepositorySqlite::~KeyValueRepositorySqlite()
|
|
||||||
{
|
|
||||||
if (myDbHandle) sqlite3_close(myDbHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
std::map<string, Variant> KeyValueRepositorySqlite::load()
|
std::map<string, Variant> KeyValueRepositorySqlite::load()
|
||||||
{
|
{
|
||||||
std::map<string, Variant> values;
|
std::map<string, Variant> values;
|
||||||
if (myIsFailed) return values;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
initializeDb();
|
myStmtSelect->reset();
|
||||||
Statement stmt(myDbHandle, "SELECT `key`, `VALUE` FROM `values`");
|
|
||||||
|
|
||||||
while (sqlite3_step(stmt) == SQLITE_ROW)
|
while (myStmtSelect->step())
|
||||||
values[reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0))] =
|
values[myStmtSelect->columnText(0)] = myStmtSelect->columnText(1);
|
||||||
reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1));
|
|
||||||
|
myStmtSelect->reset();
|
||||||
}
|
}
|
||||||
catch (SqliteError err) {
|
catch (SqliteError err) {
|
||||||
cout << "failed to load from sqlite DB " << myDatabaseFile << ": " << err.message << endl;
|
cout << err.message << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return values;
|
return values;
|
||||||
|
@ -103,66 +49,34 @@ std::map<string, Variant> KeyValueRepositorySqlite::load()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void KeyValueRepositorySqlite::save(const std::map<string, Variant>& values)
|
void KeyValueRepositorySqlite::save(const std::map<string, Variant>& values)
|
||||||
{
|
{
|
||||||
if (myIsFailed) return;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
initializeDb();
|
myStmtInsert->reset();
|
||||||
Statement stmt(myDbHandle, "INSERT OR REPLACE INTO `values` VALUES (?, ?)");
|
|
||||||
|
|
||||||
if (sqlite3_exec(myDbHandle, "BEGIN TRANSACTION", nullptr, nullptr, nullptr) != SQLITE_OK)
|
myDb.exec("BEGIN TRANSACTION");
|
||||||
throw SqliteError(sqlite3_errmsg(myDbHandle));
|
|
||||||
|
|
||||||
for (const auto& pair: values) {
|
for (const auto& pair: values) {
|
||||||
sqlite3_bind_text(stmt, 1, pair.first.c_str(), -1, SQLITE_STATIC);
|
(*myStmtInsert)
|
||||||
sqlite3_bind_text(stmt, 2, pair.second.toCString(), -1, SQLITE_STATIC);
|
.bind(1, pair.first.c_str())
|
||||||
sqlite3_step(stmt);
|
.bind(2, pair.second.toCString())
|
||||||
|
.step();
|
||||||
|
|
||||||
if (sqlite3_reset(stmt) != SQLITE_OK) throw SqliteError(sqlite3_errmsg(myDbHandle));
|
myStmtInsert->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sqlite3_exec(myDbHandle, "COMMIT", nullptr, nullptr, nullptr) != SQLITE_OK)
|
myDb.exec("COMMIT");
|
||||||
throw SqliteError(sqlite3_errmsg(myDbHandle));
|
|
||||||
}
|
}
|
||||||
catch (SqliteError err) {
|
catch (SqliteError err) {
|
||||||
cout << "failed to write to sqlite DB " << myDatabaseFile << ": " << err.message << endl;
|
cout << err.message << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void KeyValueRepositorySqlite::initializeDb()
|
void KeyValueRepositorySqlite::initialize()
|
||||||
{
|
{
|
||||||
if (myIsFailed || myDbHandle) return;
|
myDb.exec(
|
||||||
|
"CREATE TABLE IF NOT EXISTS `" + myTableName + "` (`key` TEXT PRIMARY KEY, `value` TEXT) WITHOUT ROWID"
|
||||||
|
);
|
||||||
|
|
||||||
bool dbInitialized = false;
|
myStmtInsert = make_unique<SqliteStatement>(myDb, "INSERT OR REPLACE INTO `" + myTableName + "` VALUES (?, ?)");
|
||||||
|
myStmtSelect = make_unique<SqliteStatement>(myDb, "SELECT `key`, `VALUE` FROM `" + myTableName + "`");
|
||||||
for (int tries = 1; tries < 3 && !dbInitialized; tries++) {
|
|
||||||
dbInitialized = (sqlite3_open(myDatabaseFile.c_str(), &myDbHandle) == SQLITE_OK);
|
|
||||||
|
|
||||||
dbInitialized = dbInitialized && (sqlite3_exec(
|
|
||||||
myDbHandle,
|
|
||||||
"CREATE TABLE IF NOT EXISTS `values` (`key` TEXT PRIMARY KEY, `value` TEXT) WITHOUT ROWID",
|
|
||||||
nullptr, nullptr, nullptr
|
|
||||||
) == SQLITE_OK);
|
|
||||||
|
|
||||||
if (!dbInitialized && tries == 1) {
|
|
||||||
cout << "sqlite DB " << myDatabaseFile << " seems to be corrupt, removing and retrying..." << endl;
|
|
||||||
|
|
||||||
remove(myDatabaseFile.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
myIsFailed = !dbInitialized;
|
|
||||||
|
|
||||||
if (myIsFailed) {
|
|
||||||
if (myDbHandle) {
|
|
||||||
string emsg = sqlite3_errmsg(myDbHandle);
|
|
||||||
|
|
||||||
sqlite3_close(myDbHandle);
|
|
||||||
myDbHandle = nullptr;
|
|
||||||
|
|
||||||
throw SqliteError(emsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw SqliteError("unable to initialize sqlite DB " + myDatabaseFile);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,34 +18,37 @@
|
||||||
#ifndef KEY_VALUE_REPOSITORY_SQLITE_HXX
|
#ifndef KEY_VALUE_REPOSITORY_SQLITE_HXX
|
||||||
#define KEY_VALUE_REPOSITORY_SQLITE_HXX
|
#define KEY_VALUE_REPOSITORY_SQLITE_HXX
|
||||||
|
|
||||||
#include <sqlite3.h>
|
#include "bspf.hxx"
|
||||||
|
|
||||||
#include "repository/KeyValueRepository.hxx"
|
#include "repository/KeyValueRepository.hxx"
|
||||||
|
#include "SqliteDatabase.hxx"
|
||||||
|
#include "SqliteStatement.hxx"
|
||||||
|
|
||||||
class KeyValueRepositorySqlite : public KeyValueRepository
|
class KeyValueRepositorySqlite : public KeyValueRepository
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
KeyValueRepositorySqlite(const string& databaseDirectory, const string& databaseName);
|
KeyValueRepositorySqlite(SqliteDatabase& db, const string& tableName);
|
||||||
|
|
||||||
~KeyValueRepositorySqlite();
|
|
||||||
|
|
||||||
virtual std::map<string, Variant> load();
|
virtual std::map<string, Variant> load();
|
||||||
|
|
||||||
virtual void save(const std::map<string, Variant>& values);
|
virtual void save(const std::map<string, Variant>& values);
|
||||||
|
|
||||||
private:
|
void initialize();
|
||||||
|
|
||||||
void initializeDb();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
string myDatabaseFile;
|
string myTableName;
|
||||||
|
SqliteDatabase& myDb;
|
||||||
|
|
||||||
bool myIsFailed;
|
unique_ptr<SqliteStatement> myStmtInsert;
|
||||||
|
unique_ptr<SqliteStatement> myStmtSelect;
|
||||||
|
|
||||||
sqlite3* myDbHandle;
|
private:
|
||||||
|
|
||||||
|
KeyValueRepositorySqlite(const KeyValueRepositorySqlite&) = delete;
|
||||||
|
KeyValueRepositorySqlite(KeyValueRepositorySqlite&&) = delete;
|
||||||
|
KeyValueRepositorySqlite& operator=(const KeyValueRepositorySqlite&) = delete;
|
||||||
|
KeyValueRepositorySqlite operator=(KeyValueRepositorySqlite&&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // KEY_VALUE_REPOSITORY_SQLITE_HXX
|
#endif // KEY_VALUE_REPOSITORY_SQLITE_HXX
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// 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-2019 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 "SettingsDb.hxx"
|
||||||
|
#include "SqliteError.hxx"
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
SettingsDb::SettingsDb(
|
||||||
|
const string& databaseDirectory,
|
||||||
|
const string& databaseName
|
||||||
|
) : myDatabaseDirectory(databaseDirectory),
|
||||||
|
myDatabaseName(databaseName)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool SettingsDb::initialize()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
myDb = make_unique<SqliteDatabase>(myDatabaseDirectory, myDatabaseName);
|
||||||
|
myDb->initialize();
|
||||||
|
|
||||||
|
mySettingsRepository = make_unique<KeyValueRepositorySqlite>(*myDb, "settings");
|
||||||
|
mySettingsRepository->initialize();
|
||||||
|
}
|
||||||
|
catch (SqliteError err) {
|
||||||
|
cout << "sqlite DB " << myDb->fileName() << " failed to initialize: " << err.message << endl;
|
||||||
|
|
||||||
|
myDb.reset();
|
||||||
|
mySettingsRepository.reset();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// 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-2019 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 SETTINGS_DB_HXX
|
||||||
|
#define SETTINGS_DB_HXX
|
||||||
|
|
||||||
|
#include "bspf.hxx"
|
||||||
|
#include "SqliteDatabase.hxx"
|
||||||
|
#include "KeyValueRepositorySqlite.hxx"
|
||||||
|
|
||||||
|
class SettingsDb
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
SettingsDb(const string& databaseDirectory, const string& databaseName);
|
||||||
|
|
||||||
|
bool initialize();
|
||||||
|
|
||||||
|
KeyValueRepository& settingsRepository() const { return *mySettingsRepository; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
string myDatabaseDirectory;
|
||||||
|
string myDatabaseName;
|
||||||
|
|
||||||
|
unique_ptr<SqliteDatabase> myDb;
|
||||||
|
unique_ptr<KeyValueRepositorySqlite> mySettingsRepository;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SETTINGS_DB_HXX
|
|
@ -0,0 +1,83 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// 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-2019 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 <cstdio>
|
||||||
|
|
||||||
|
#include "SqliteDatabase.hxx"
|
||||||
|
#include "SqliteError.hxx"
|
||||||
|
|
||||||
|
#ifdef BSPF_WINDOWS
|
||||||
|
#define SEPARATOR "\"
|
||||||
|
#else
|
||||||
|
#define SEPARATOR "/"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
SqliteDatabase::SqliteDatabase(
|
||||||
|
const string& databaseDirectory,
|
||||||
|
const string& databaseName
|
||||||
|
) : myDatabaseFile(databaseDirectory + SEPARATOR + databaseName + ".sqlite3"),
|
||||||
|
myHandle(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
SqliteDatabase::~SqliteDatabase()
|
||||||
|
{
|
||||||
|
if (myHandle) sqlite3_close_v2(myHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void SqliteDatabase::initialize()
|
||||||
|
{
|
||||||
|
if (myHandle) return;
|
||||||
|
|
||||||
|
bool dbInitialized = false;
|
||||||
|
|
||||||
|
for (int tries = 1; tries < 3 && !dbInitialized; tries++) {
|
||||||
|
dbInitialized = (sqlite3_open(myDatabaseFile.c_str(), &myHandle) == SQLITE_OK);
|
||||||
|
|
||||||
|
if (dbInitialized)
|
||||||
|
dbInitialized = sqlite3_exec(myHandle, "PRAGMA schema_version", nullptr, nullptr, nullptr) == SQLITE_OK;
|
||||||
|
|
||||||
|
if (!dbInitialized && tries == 1) {
|
||||||
|
cout << "sqlite DB " << myDatabaseFile << " seems to be corrupt, removing and retrying..." << endl;
|
||||||
|
|
||||||
|
remove(myDatabaseFile.c_str());
|
||||||
|
if (myHandle) sqlite3_close_v2(myHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dbInitialized) {
|
||||||
|
if (myHandle) {
|
||||||
|
string emsg = sqlite3_errmsg(myHandle);
|
||||||
|
|
||||||
|
sqlite3_close_v2(myHandle);
|
||||||
|
myHandle = nullptr;
|
||||||
|
|
||||||
|
throw SqliteError(emsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw SqliteError("unable to initialize sqlite DB for unknown reason");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void SqliteDatabase::exec(const string& sql) const
|
||||||
|
{
|
||||||
|
if (sqlite3_exec(myHandle, sql.c_str(), nullptr, nullptr, nullptr) != SQLITE_OK)
|
||||||
|
throw SqliteError(myHandle);
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// 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-2019 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 SQLITE_DATABASE_HXX
|
||||||
|
#define SQLITE_DATABASE_HXX
|
||||||
|
|
||||||
|
#include <sqlite3.h>
|
||||||
|
|
||||||
|
#include "bspf.hxx"
|
||||||
|
|
||||||
|
class SqliteDatabase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
SqliteDatabase(const string& databaseDirectory, const string& databaseName);
|
||||||
|
|
||||||
|
~SqliteDatabase();
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
|
||||||
|
const string fileName() const { return myDatabaseFile; }
|
||||||
|
|
||||||
|
operator sqlite3*() const { return myHandle; }
|
||||||
|
|
||||||
|
void exec(const string &sql) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
string myDatabaseFile;
|
||||||
|
|
||||||
|
sqlite3* myHandle;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
SqliteDatabase(const SqliteDatabase&) = delete;
|
||||||
|
SqliteDatabase(SqliteDatabase&&) = delete;
|
||||||
|
SqliteDatabase& operator=(const SqliteDatabase&) = delete;
|
||||||
|
SqliteDatabase& operator=(SqliteDatabase&&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SQLITE_DATABASE_HXX
|
|
@ -0,0 +1,32 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// 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-2019 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 SQLITE_ERROR_HXX
|
||||||
|
#define SQLITE_ERROR_HXX
|
||||||
|
|
||||||
|
#include <sqlite3.h>
|
||||||
|
#include "bspf.hxx"
|
||||||
|
|
||||||
|
struct SqliteError {
|
||||||
|
SqliteError(const string _message) : message(_message) {}
|
||||||
|
|
||||||
|
SqliteError(sqlite3* handle) : message(sqlite3_errmsg(handle)) {}
|
||||||
|
|
||||||
|
const string message;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SQLITE_ERROR_HXX
|
|
@ -0,0 +1,62 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// 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-2019 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 "SqliteStatement.hxx"
|
||||||
|
#include "SqliteError.hxx"
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
SqliteStatement::SqliteStatement(sqlite3* handle, string sql) : myStmt(nullptr), myHandle(handle)
|
||||||
|
{
|
||||||
|
if (sqlite3_prepare_v2(handle, sql.c_str(), -1, &myStmt, nullptr) != SQLITE_OK)
|
||||||
|
throw SqliteError(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
SqliteStatement::~SqliteStatement()
|
||||||
|
{
|
||||||
|
if (myStmt) sqlite3_finalize(myStmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
SqliteStatement& SqliteStatement::bind(int index, const string& value)
|
||||||
|
{
|
||||||
|
if (sqlite3_bind_text(myStmt, index, value.c_str(), -1, SQLITE_TRANSIENT) != SQLITE_OK)
|
||||||
|
throw SqliteError(myHandle);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
bool SqliteStatement::step() const
|
||||||
|
{
|
||||||
|
int result = sqlite3_step(myStmt);
|
||||||
|
|
||||||
|
if (result == SQLITE_ERROR) throw SqliteError(myHandle);
|
||||||
|
|
||||||
|
return result == SQLITE_ROW;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void SqliteStatement::reset() const
|
||||||
|
{
|
||||||
|
if (sqlite3_reset(myStmt) != SQLITE_OK) throw SqliteError(myHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
string SqliteStatement::columnText(int index) const
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const char*>(sqlite3_column_text(myStmt, index));
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// 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-2019 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 SQLITE_STATEMENT_HXX
|
||||||
|
#define SQLITE_STATEMENT_HXX
|
||||||
|
|
||||||
|
#include <sqlite3.h>
|
||||||
|
|
||||||
|
#include "bspf.hxx"
|
||||||
|
|
||||||
|
class SqliteStatement {
|
||||||
|
public:
|
||||||
|
|
||||||
|
SqliteStatement(sqlite3* handle, string sql);
|
||||||
|
|
||||||
|
~SqliteStatement();
|
||||||
|
|
||||||
|
operator sqlite3_stmt*() const { return myStmt; }
|
||||||
|
|
||||||
|
SqliteStatement& bind(int index, const string& value);
|
||||||
|
|
||||||
|
bool step() const;
|
||||||
|
|
||||||
|
void reset() const;
|
||||||
|
|
||||||
|
string columnText(int index) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
sqlite3_stmt* myStmt;
|
||||||
|
|
||||||
|
sqlite3* myHandle;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
SqliteStatement() = delete;
|
||||||
|
SqliteStatement(const SqliteStatement&) = delete;
|
||||||
|
SqliteStatement(SqliteStatement&&) = delete;
|
||||||
|
SqliteStatement& operator=(const SqliteStatement&) = delete;
|
||||||
|
SqliteStatement& operator=(SqliteStatement&&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SQLITE_STATEMENT_HXX
|
|
@ -1,7 +1,10 @@
|
||||||
MODULE := src/common/repository/sqlite
|
MODULE := src/common/repository/sqlite
|
||||||
|
|
||||||
MODULE_OBJS := \
|
MODULE_OBJS := \
|
||||||
src/common/repository/sqlite/KeyValueRepositorySqlite.o
|
src/common/repository/sqlite/KeyValueRepositorySqlite.o \
|
||||||
|
src/common/repository/sqlite/SettingsDb.o \
|
||||||
|
src/common/repository/sqlite/SqliteDatabase.o \
|
||||||
|
src/common/repository/sqlite/SqliteStatement.o
|
||||||
|
|
||||||
MODULE_DIRS += \
|
MODULE_DIRS += \
|
||||||
src/common/repository/sqlite
|
src/common/repository/sqlite
|
||||||
|
|
|
@ -105,6 +105,8 @@ OSystem::OSystem()
|
||||||
myBuildInfo = info.str();
|
myBuildInfo = info.str();
|
||||||
|
|
||||||
mySettings = MediaFactory::createSettings();
|
mySettings = MediaFactory::createSettings();
|
||||||
|
|
||||||
|
myPropSet = make_unique<PropertiesSet>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -115,8 +117,6 @@ OSystem::~OSystem()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool OSystem::create()
|
bool OSystem::create()
|
||||||
{
|
{
|
||||||
// Get updated paths for all configuration files
|
|
||||||
setConfigPaths();
|
|
||||||
ostringstream buf;
|
ostringstream buf;
|
||||||
buf << "Stella " << STELLA_VERSION << endl
|
buf << "Stella " << STELLA_VERSION << endl
|
||||||
<< " Features: " << myFeatures << endl
|
<< " Features: " << myFeatures << endl
|
||||||
|
@ -146,9 +146,6 @@ bool OSystem::create()
|
||||||
myEventHandler = MediaFactory::createEventHandler(*this);
|
myEventHandler = MediaFactory::createEventHandler(*this);
|
||||||
myEventHandler->initialize();
|
myEventHandler->initialize();
|
||||||
|
|
||||||
// Create the ROM properties database
|
|
||||||
myPropSet = make_unique<PropertiesSet>(myPropertiesFile);
|
|
||||||
|
|
||||||
#ifdef CHEATCODE_SUPPORT
|
#ifdef CHEATCODE_SUPPORT
|
||||||
myCheatManager = make_unique<CheatManager>(*this);
|
myCheatManager = make_unique<CheatManager>(*this);
|
||||||
myCheatManager->loadCheatDatabase();
|
myCheatManager->loadCheatDatabase();
|
||||||
|
@ -205,10 +202,20 @@ void OSystem::loadConfig(const Settings::Options& options)
|
||||||
load.makeDir();
|
load.makeDir();
|
||||||
myDefaultLoadDir = load.getShortPath();
|
myDefaultLoadDir = load.getShortPath();
|
||||||
|
|
||||||
|
// Get updated paths for all configuration files
|
||||||
|
setConfigPaths();
|
||||||
|
|
||||||
|
#ifdef SQLITE_SUPPORT
|
||||||
|
mySettingsDb = make_shared<SettingsDb>(myBaseDir, "settings");
|
||||||
|
if (!mySettingsDb->initialize()) mySettingsDb.reset();
|
||||||
|
#endif
|
||||||
|
|
||||||
mySettings->setRepository(createSettingsRepository());
|
mySettings->setRepository(createSettingsRepository());
|
||||||
|
|
||||||
logMessage("Loading config options ...", 2);
|
logMessage("Loading config options ...", 2);
|
||||||
mySettings->load(options);
|
mySettings->load(options);
|
||||||
|
|
||||||
|
myPropSet->load(myPropertiesFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -751,7 +758,9 @@ void OSystem::mainLoop()
|
||||||
shared_ptr<KeyValueRepository> OSystem::createSettingsRepository()
|
shared_ptr<KeyValueRepository> OSystem::createSettingsRepository()
|
||||||
{
|
{
|
||||||
#ifdef SQLITE_SUPPORT
|
#ifdef SQLITE_SUPPORT
|
||||||
return make_shared<KeyValueRepositorySqlite>(myBaseDir, "settings");
|
return mySettingsDb
|
||||||
|
? shared_ptr<KeyValueRepository>(mySettingsDb, &mySettingsDb->settingsRepository())
|
||||||
|
: make_shared<KeyValueRepositoryNoop>();
|
||||||
#else
|
#else
|
||||||
if (myConfigFile.empty())
|
if (myConfigFile.empty())
|
||||||
return make_shared<KeyValueRepositoryNoop>();
|
return make_shared<KeyValueRepositoryNoop>();
|
||||||
|
|
|
@ -52,6 +52,10 @@ class AudioSettings;
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "repository/KeyValueRepository.hxx"
|
#include "repository/KeyValueRepository.hxx"
|
||||||
|
|
||||||
|
#ifdef SQLITE_SUPPORT
|
||||||
|
#include "SettingsDb.hxx"
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This class provides an interface for accessing operating system specific
|
This class provides an interface for accessing operating system specific
|
||||||
functions. It also comprises an overall parent object, to which all the
|
functions. It also comprises an overall parent object, to which all the
|
||||||
|
@ -538,6 +542,10 @@ class OSystem
|
||||||
static string ourOverrideBaseDir;
|
static string ourOverrideBaseDir;
|
||||||
static bool ourOverrideBaseDirWithApp;
|
static bool ourOverrideBaseDirWithApp;
|
||||||
|
|
||||||
|
#ifdef SQLITE_SUPPORT
|
||||||
|
shared_ptr<SettingsDb> mySettingsDb;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
Creates the various framebuffers/renderers available in this system.
|
Creates the various framebuffers/renderers available in this system.
|
||||||
|
|
|
@ -23,12 +23,6 @@
|
||||||
#include "Props.hxx"
|
#include "Props.hxx"
|
||||||
#include "PropsSet.hxx"
|
#include "PropsSet.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
PropertiesSet::PropertiesSet(const string& propsfile)
|
|
||||||
{
|
|
||||||
load(propsfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void PropertiesSet::load(const string& filename)
|
void PropertiesSet::load(const string& filename)
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,11 +40,10 @@ class PropertiesSet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
Create a properties set object from the specified properties file.
|
Trivial constructor.
|
||||||
*/
|
*/
|
||||||
explicit PropertiesSet(const string& propsfile);
|
PropertiesSet() = default;
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
/**
|
||||||
Load properties from the specified file, and create an internal
|
Load properties from the specified file, and create an internal
|
||||||
searchable list.
|
searchable list.
|
||||||
|
@ -119,7 +118,6 @@ class PropertiesSet
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
PropertiesSet() = delete;
|
|
||||||
PropertiesSet(const PropertiesSet&) = delete;
|
PropertiesSet(const PropertiesSet&) = delete;
|
||||||
PropertiesSet(PropertiesSet&&) = delete;
|
PropertiesSet(PropertiesSet&&) = delete;
|
||||||
PropertiesSet& operator=(const PropertiesSet&) = delete;
|
PropertiesSet& operator=(const PropertiesSet&) = delete;
|
||||||
|
|
Loading…
Reference in New Issue