From ffa392b92221b8e22449b669c476e3658396dec6 Mon Sep 17 00:00:00 2001 From: Cheng Date: Sat, 11 Nov 2023 22:27:59 +0000 Subject: [PATCH] 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. --- msvc/wallet.vcxproj | 1 + src/ISqlite3.h | 9 +-------- src/db_accessors.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++ src/db_accessors.h | 31 ++++++++++++++++++++++------- src/display_wallet.cpp | 28 +++++++++++--------------- src/display_wallet.h | 7 ++++--- 6 files changed, 87 insertions(+), 34 deletions(-) create mode 100644 src/db_accessors.cpp diff --git a/msvc/wallet.vcxproj b/msvc/wallet.vcxproj index d4424b6..c4f4483 100644 --- a/msvc/wallet.vcxproj +++ b/msvc/wallet.vcxproj @@ -150,6 +150,7 @@ + diff --git a/src/ISqlite3.h b/src/ISqlite3.h index 87a2750..4c31833 100644 --- a/src/ISqlite3.h +++ b/src/ISqlite3.h @@ -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 sqlite3_open(const char *) to get a shared -// pointer to the // Sqlite3 database object. Then call the factory function -// sqlite3_prepare(std::shared_ptr, 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.*/ diff --git a/src/db_accessors.cpp b/src/db_accessors.cpp new file mode 100644 index 0000000..c076ef9 --- /dev/null +++ b/src/db_accessors.cpp @@ -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(p.release()) { + } + + // Move assignment + dbconnect& dbconnect::operator=(dbconnect&& p) noexcept { + std::unique_ptr::reset(p.release()); + return *this; + } + + sql::sql(const std::unique_ptr& p, const char* sz) : + std::unique_ptr(sqlite3_prepare(p.get(), sz)) { + } + + // move constructor + sql::sql(sql&& p) noexcept :std::unique_ptr(p.release()) { + } + + // Move assignment + sql& sql::operator=(sql&& p) noexcept { + std::unique_ptr::reset(p.release()); + return *this; + } + + sql::sql(Icompiled_sql* p) : + std::unique_ptr(p) { + } + + sql::sql(std::unique_ptr&& p) : + std::unique_ptr(p.release()) { + } +} \ No newline at end of file diff --git a/src/db_accessors.h b/src/db_accessors.h index 4091fda..6a1f4a1 100644 --- a/src/db_accessors.h +++ b/src/db_accessors.h @@ -15,26 +15,43 @@ namespace ro { static_assert(is_sqlite3_field_type::value); + //Owns a database connection and closes it when it is deconstructed + //Has move semantics + class dbconnect : public std::unique_ptr { + 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 { public: class monostate {}; + sql() = delete; sql(ISqlite3* p, const char* sz) :std::unique_ptr(sqlite3_prepare(p, sz)) {} - sql(const std::unique_ptr& p, const char* sz) :std::unique_ptr(sqlite3_prepare(p.get(), sz)) {} + sql(const std::unique_ptr& p, const char* sz); // copy constructor sql(const sql& a) = delete; // move constructor - sql(sql&& p) noexcept :std::unique_ptr(p.release()) { } + sql(sql&& p) noexcept; // copy assignment sql& operator=(const sql) = delete; // Move assignment - sql& operator=(sql&& p) noexcept { - std::unique_ptr::reset(p.release()); - } - sql(Icompiled_sql* p) :std::unique_ptr(p) {} - sql(std::unique_ptr&& p) :std::unique_ptr(p.release()) { } + sql& operator=(sql&& p) noexcept; + sql(Icompiled_sql* p); + sql(std::unique_ptr&& p); ~sql() = default; + template auto column(int i) const { if constexpr (ro::blob_type) { auto st = (*this)->Isqlite3_column_blob(i); diff --git a/src/display_wallet.cpp b/src/display_wallet.cpp index 0a3ee71..f11dbaa 100644 --- a/src/display_wallet.cpp +++ b/src/display_wallet.cpp @@ -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")value() != WALLET_FILE_IDENTIFIER)throw MyException(sz_unrecognizable_wallet_file_format); - if (!(*m_read_from_misc)(2) || m_read_from_misc->value() != WALLET_FILE_SCHEMA_VERSION_0_0 || !(*m_read_from_misc)(4))throw MyException(sz_unrecognized_wallet_schema); - m_MasterSecret= *(m_read_from_misc->value()); + if (!m_read_from_misc(1) || m_read_from_misc.value() != WALLET_FILE_IDENTIFIER)throw MyException(sz_unrecognizable_wallet_file_format); + if (!m_read_from_misc(2) || m_read_from_misc.value() != WALLET_FILE_SCHEMA_VERSION_0_0 || !m_read_from_misc(4))throw MyException(sz_unrecognized_wallet_schema); + m_MasterSecret= *(m_read_from_misc.value()); 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(0); - auto pubkey = *(m_read_names_and_keys->column(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(0); + auto pubkey = *(m_read_names_and_keys.column(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( diff --git a/src/display_wallet.h b/src/display_wallet.h index 1573bc6..3461ee4 100644 --- a/src/display_wallet.h +++ b/src/display_wallet.h @@ -6,10 +6,11 @@ public: ~display_wallet(); private: typedef MenuLink MenuLink; - std::unique_ptr m_db; - std::unique_ptr m_read_from_misc; - std::unique_ptr 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 m_insert_name; + ro::sql m_find_position; ristretto255::CMasterSecret m_MasterSecret; wxBoxSizer* m_lSizer;