forked from cheng/wallet
removed a the redundantly explicit std::uniques
from display_wallet.h and display_wallet.cpp They are now all wrapped in the long promised and long forgotten wrapper class. Long, long ago, I intended to implement the Pimpl idiom, but these days std::unique takes care of all that work for you. You just wrap your low level pimple class in a high level wrapper whose base class is an std_unique_ptr to to an instance of your low level class.
This commit is contained in:
parent
f819b98d9e
commit
ffa392b922
@ -150,6 +150,7 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="../src/app.cpp" />
|
||||
<ClCompile Include="../src/display_wallet.cpp" />
|
||||
<ClCompile Include="../src/db_accessors.cpp" />
|
||||
<ClCompile Include="../src/frame.cpp" />
|
||||
<ClCompile Include="../src/ILog.cpp" />
|
||||
<ClCompile Include="../src/ISqlit3Impl.cpp">
|
||||
|
@ -1,13 +1,8 @@
|
||||
#pragma once
|
||||
#include "ILog.h"
|
||||
// this is pure virtual interface base class between sqlite3, which speaks only C and utf8 char[]
|
||||
// this is an interface base class between sqlite3, which speaks only C and utf8 char[]
|
||||
// and wxWidgets which speaks only C++ and unicode strings.
|
||||
|
||||
// Usage: Call the factory function std::shared_ptr<ISqlite3> sqlite3_open(const char *) to get a shared
|
||||
// pointer to the // Sqlite3 database object. Then call the factory function
|
||||
// sqlite3_prepare(std::shared_ptr<ISqlite3>, const char *) to get a unique pointer to
|
||||
// a compiled SQL statement
|
||||
|
||||
// Its primary purpose is to avoid code that needs both the wxWidgets header files,
|
||||
// and the sqlite3.h header file.
|
||||
//
|
||||
@ -25,8 +20,6 @@
|
||||
// substantially more difficult in C++14, because one is effectively rolling one's own
|
||||
// unique pointer.
|
||||
//
|
||||
// It is therefore easier to implement a pure virtual base class with a virtual destructor and
|
||||
// factory function that returns a smart pointer to a member of the derived implementation
|
||||
//
|
||||
/* This code is at a low level abstraction, because it provides low level C++ interface to inherently low level C
|
||||
It is intended to be wrapped in higher level code that does not know about the nuts and bolts of sqlite3, but which supports throwing, templated functions, and all that.*/
|
||||
|
45
src/db_accessors.cpp
Normal file
45
src/db_accessors.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
#include "stdafx.h"
|
||||
namespace ro {
|
||||
static constexpr char SrcFilename[]{ "src/db_accessors.cpp" };
|
||||
|
||||
dbconnect::dbconnect(const wxFileName& filename) {
|
||||
if (!filename.IsOk() || !filename.HasName() || !filename.HasExt()) throw
|
||||
MyException("unexpected file name", __LINE__, __func__, SrcFilename);
|
||||
if (!filename.FileExists())throw MyException(
|
||||
std::string(filename.GetFullPath().ToUTF8()) + " does not exist.",
|
||||
__LINE__, __func__, SrcFilename);
|
||||
this->reset(Sqlite3_open(filename.GetFullPath().ToUTF8()));
|
||||
}
|
||||
|
||||
// move constructor
|
||||
dbconnect::dbconnect(dbconnect&& p) noexcept :std::unique_ptr<ISqlite3>(p.release()) {
|
||||
}
|
||||
|
||||
// Move assignment
|
||||
dbconnect& dbconnect::operator=(dbconnect&& p) noexcept {
|
||||
std::unique_ptr<ISqlite3>::reset(p.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
sql::sql(const std::unique_ptr<ISqlite3>& p, const char* sz) :
|
||||
std::unique_ptr<Icompiled_sql>(sqlite3_prepare(p.get(), sz)) {
|
||||
}
|
||||
|
||||
// move constructor
|
||||
sql::sql(sql&& p) noexcept :std::unique_ptr<Icompiled_sql>(p.release()) {
|
||||
}
|
||||
|
||||
// Move assignment
|
||||
sql& sql::operator=(sql&& p) noexcept {
|
||||
std::unique_ptr<Icompiled_sql>::reset(p.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
sql::sql(Icompiled_sql* p) :
|
||||
std::unique_ptr<Icompiled_sql>(p) {
|
||||
}
|
||||
|
||||
sql::sql(std::unique_ptr<Icompiled_sql>&& p) :
|
||||
std::unique_ptr<Icompiled_sql>(p.release()) {
|
||||
}
|
||||
}
|
@ -15,26 +15,43 @@ namespace ro {
|
||||
|
||||
static_assert(is_sqlite3_field_type<int>::value);
|
||||
|
||||
//Owns a database connection and closes it when it is deconstructed
|
||||
//Has move semantics
|
||||
class dbconnect : public std::unique_ptr<ISqlite3> {
|
||||
public:
|
||||
dbconnect(const wxFileName&); //And here we wrap our Cish implementation in C++ish implementation
|
||||
dbconnect() = delete;
|
||||
~dbconnect() = default; //Our base class takes care of it
|
||||
// copy constructor
|
||||
dbconnect(const dbconnect& a) = delete; //Move semantics
|
||||
// move constructor
|
||||
dbconnect(dbconnect&& p) noexcept;
|
||||
// copy assignment
|
||||
dbconnect& operator=(const dbconnect) = delete; //Move semantics
|
||||
// Move assignment
|
||||
dbconnect& operator=(dbconnect&& p) noexcept;
|
||||
};
|
||||
|
||||
//Owns a compiled sql statement and destroys it when it is deconstructed.
|
||||
//Has move semantics.
|
||||
class sql : public std::unique_ptr<Icompiled_sql> {
|
||||
public:
|
||||
class monostate {};
|
||||
sql() = delete;
|
||||
sql(ISqlite3* p, const char* sz) :std::unique_ptr<Icompiled_sql>(sqlite3_prepare(p, sz)) {}
|
||||
sql(const std::unique_ptr<ISqlite3>& p, const char* sz) :std::unique_ptr<Icompiled_sql>(sqlite3_prepare(p.get(), sz)) {}
|
||||
sql(const std::unique_ptr<ISqlite3>& p, const char* sz);
|
||||
// copy constructor
|
||||
sql(const sql& a) = delete;
|
||||
// move constructor
|
||||
sql(sql&& p) noexcept :std::unique_ptr<Icompiled_sql>(p.release()) { }
|
||||
sql(sql&& p) noexcept;
|
||||
// copy assignment
|
||||
sql& operator=(const sql) = delete;
|
||||
// Move assignment
|
||||
sql& operator=(sql&& p) noexcept {
|
||||
std::unique_ptr<Icompiled_sql>::reset(p.release());
|
||||
}
|
||||
sql(Icompiled_sql* p) :std::unique_ptr<Icompiled_sql>(p) {}
|
||||
sql(std::unique_ptr<Icompiled_sql>&& p) :std::unique_ptr<Icompiled_sql>(p.release()) { }
|
||||
sql& operator=(sql&& p) noexcept;
|
||||
sql(Icompiled_sql* p);
|
||||
sql(std::unique_ptr<Icompiled_sql>&& p);
|
||||
~sql() = default;
|
||||
|
||||
template <typename T>auto column(int i) const {
|
||||
if constexpr (ro::blob_type<T>) {
|
||||
auto st = (*this)->Isqlite3_column_blob(i);
|
||||
|
@ -1,23 +1,19 @@
|
||||
#include "stdafx.h"
|
||||
using ro::base58;
|
||||
static constexpr char SrcFilename[]{ "src/display_wallet.cpp" };
|
||||
|
||||
display_wallet::display_wallet(wxWindow* parent, wxFileName& walletfile) :
|
||||
wxPanel(parent, myID_WALLET_UI, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, wxT("Wallet")),
|
||||
m_db(nullptr), m_DisplayWalletEditMenu(1)
|
||||
m_db(walletfile), m_DisplayWalletEditMenu(1),
|
||||
m_read_names_and_keys(m_db, R"|(SELECT * FROM "UserZookoIDs"; )|"),
|
||||
m_read_from_misc(m_db),
|
||||
m_find_position(m_db, R"|( SELECT COUNT(*) FROM UserZookoIDs WHERE LOWER("name")<LOWER(?1) AND "name"<?1;)|")
|
||||
{
|
||||
wxLogMessage(wxT("Loading %s"), walletfile.GetFullPath());
|
||||
try {
|
||||
if (!walletfile.IsOk() || !walletfile.HasName() || !walletfile.HasExt()) throw MyException("unexpected file name", __LINE__, __func__, SrcFilename);
|
||||
if (!walletfile.FileExists())throw MyException(
|
||||
walletfile.GetFullPath().append(" does not exist.").ToUTF8(),
|
||||
__LINE__, __func__, SrcFilename);
|
||||
m_db.reset(Sqlite3_open(walletfile.GetFullPath().ToUTF8()));
|
||||
m_insert_name.reset(new sql_insert_name(m_db));
|
||||
m_read_from_misc.reset(new sql_read_from_misc(m_db));
|
||||
m_read_names_and_keys.reset(new ro::sql(m_db, R"|(SELECT * FROM "UserZookoIDs" )|"));
|
||||
if (!(*m_read_from_misc)(1) || m_read_from_misc->value<int64_t>() != WALLET_FILE_IDENTIFIER)throw MyException(sz_unrecognizable_wallet_file_format);
|
||||
if (!(*m_read_from_misc)(2) || m_read_from_misc->value<int64_t>() != WALLET_FILE_SCHEMA_VERSION_0_0 || !(*m_read_from_misc)(4))throw MyException(sz_unrecognized_wallet_schema);
|
||||
m_MasterSecret= *(m_read_from_misc->value<ristretto255::scalar>());
|
||||
if (!m_read_from_misc(1) || m_read_from_misc.value<int64_t>() != WALLET_FILE_IDENTIFIER)throw MyException(sz_unrecognizable_wallet_file_format);
|
||||
if (!m_read_from_misc(2) || m_read_from_misc.value<int64_t>() != WALLET_FILE_SCHEMA_VERSION_0_0 || !m_read_from_misc(4))throw MyException(sz_unrecognized_wallet_schema);
|
||||
m_MasterSecret= *(m_read_from_misc.value<ristretto255::scalar>());
|
||||
ILogMessage(std::format("\t\tmaster secret: #{}", ro::base58(m_MasterSecret).operator const char* ()).c_str());
|
||||
if(!m_MasterSecret.valid()) throw MyException(sz_cold_wallets_not_yet_implemented, __LINE__, __func__, SrcFilename);
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
@ -102,10 +98,10 @@ void display_wallet::refresh_from_database() {
|
||||
m_lsizer->Clear(true);
|
||||
m_rsizer->Clear(true);
|
||||
try {
|
||||
m_read_names_and_keys->reset();
|
||||
while (m_read_names_and_keys->step() == Icompiled_sql::ROW) {
|
||||
std::string name = m_read_names_and_keys->column<const char*>(0);
|
||||
auto pubkey = *(m_read_names_and_keys->column<ristretto255::point>(1));
|
||||
m_read_names_and_keys.reset();
|
||||
while (m_read_names_and_keys.step() == Icompiled_sql::ROW) {
|
||||
std::string name = m_read_names_and_keys.column<const char*>(0);
|
||||
auto pubkey = *(m_read_names_and_keys.column<ristretto255::point>(1));
|
||||
if (m_MasterSecret(name).timesBase() != pubkey)throw MyException(std::string(sz_public_key_of) + name + sz_fails_to_correspond);
|
||||
m_lSizer->Add(
|
||||
new wxStaticText(
|
||||
|
@ -6,10 +6,11 @@ public:
|
||||
~display_wallet();
|
||||
private:
|
||||
typedef MenuLink<display_wallet> MenuLink;
|
||||
std::unique_ptr<ISqlite3> m_db;
|
||||
std::unique_ptr <sql_read_from_misc> m_read_from_misc;
|
||||
std::unique_ptr <ro::sql> m_read_names_and_keys;
|
||||
ro::dbconnect m_db;
|
||||
sql_read_from_misc m_read_from_misc;
|
||||
ro::sql m_read_names_and_keys;
|
||||
std::unique_ptr <sql_insert_name> m_insert_name;
|
||||
ro::sql m_find_position;
|
||||
|
||||
ristretto255::CMasterSecret m_MasterSecret;
|
||||
wxBoxSizer* m_lSizer;
|
||||
|
Loading…
Reference in New Issue
Block a user