From f3ac764684c64fbdd2094853a80b23e570cd5d9c Mon Sep 17 00:00:00 2001 From: Dominick Allen Date: Tue, 15 Oct 2024 20:56:26 -0500 Subject: Conver to using static constructors for string, sqlite, files. --- include/fud_c_file.hpp | 39 ++++++++++++++++--------- include/fud_result.hpp | 24 +++++++++++++-- include/fud_sqlite.hpp | 36 +++++++++++++++++++---- include/fud_string.hpp | 79 ++++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 150 insertions(+), 28 deletions(-) (limited to 'include') diff --git a/include/fud_c_file.hpp b/include/fud_c_file.hpp index c81a340..4905643 100644 --- a/include/fud_c_file.hpp +++ b/include/fud_c_file.hpp @@ -18,10 +18,10 @@ #ifndef FUD_C_FILE_HPP #define FUD_C_FILE_HPP +#include "fud_permissions.hpp" #include "fud_result.hpp" #include "fud_status.hpp" #include "fud_string.hpp" -#include "fud_permissions.hpp" #include #include @@ -155,7 +155,8 @@ class CFile { return self.m_file; } - FudStatus setPermissions(Permissions permissions) { + FudStatus setPermissions(Permissions permissions) + { auto& self = static_cast(*this); if (!self.isOpen()) { return FudStatus::OperationInvalid; @@ -383,14 +384,20 @@ class CFile { } // namespace detail +class CBinaryFile; +using CBinaryFileResult = Result; + class CBinaryFile : public detail::CFile { friend class CFile; public: - CBinaryFile(const String& filename, CFileMode mode); + static CBinaryFileResult make(const String& filename, CFileMode mode); + static CBinaryFileResult make(const String& filename, CFileMode mode, const char* extraFlags); - CBinaryFile(const String& filename, CFileMode mode, const String& extraFlags); + private: + CBinaryFile() = default; + public: CBinaryFile(const CBinaryFile& rhs) = delete; CBinaryFile(CBinaryFile&& rhs) noexcept; @@ -402,21 +409,26 @@ class CBinaryFile : public detail::CFile { CBinaryFile& operator=(CBinaryFile&& rhs) noexcept; private: - String m_filename; - String m_extraFlags{}; - String m_mode; - CFileMode m_modeFlags; + String m_filename{}; + String m_mode{}; + CFileMode m_modeFlags{}; FILE* m_file{nullptr}; }; +class CTextFile; +using CTextFileResult = Result; + class CTextFile : public detail::CFile { friend class CFile; public: - CTextFile(const String& filename, CFileMode mode); + static CTextFileResult make(const String& filename, CFileMode mode); + static CTextFileResult make(const String& filename, CFileMode mode, const char* extraFlags); - CTextFile(const String& filename, CFileMode mode, const String& extraFlags); + private: + CTextFile() = default; + public: CTextFile(const CTextFile& rhs) = delete; CTextFile(CTextFile&& rhs) noexcept; @@ -428,10 +440,9 @@ class CTextFile : public detail::CFile { CTextFile& operator=(CTextFile&& rhs) noexcept; private: - String m_filename; - String m_extraFlags{}; - String m_mode; - CFileMode m_modeFlags; + String m_filename{}; + String m_mode{}; + CFileMode m_modeFlags{}; FILE* m_file{nullptr}; }; diff --git a/include/fud_result.hpp b/include/fud_result.hpp index dae084a..3acf776 100644 --- a/include/fud_result.hpp +++ b/include/fud_result.hpp @@ -47,6 +47,26 @@ class [[nodiscard]] Result { return ResultType{std::move(error)}; } + template + static ResultType okay(const Result& okayRes) { + return ResultType{okayRes.getOkay()}; + } + + template + static ResultType okay(Result&& okayRes) { + return ResultType{okayRes.takeOkay()}; + } + + template + static ResultType error(const Result& errorRes) { + return ResultType{errorRes.getError()}; + } + + template + static ResultType error(Result&& errorRes) { + return ResultType{errorRes.takeError()}; + } + [[nodiscard]] constexpr bool isOkay() const { return (m_value.index() == 0); @@ -67,12 +87,12 @@ class [[nodiscard]] Result { return std::get(m_value); } - [[nodiscard]] const T&& getOkay() const&& + [[nodiscard]] T&& takeOkay() { return std::move(std::get(m_value)); } - [[nodiscard]] const E&& getError() const&& + [[nodiscard]] E&& takeError() { return std::move(std::get(m_value)); } diff --git a/include/fud_sqlite.hpp b/include/fud_sqlite.hpp index d879ed0..c56b4a1 100644 --- a/include/fud_sqlite.hpp +++ b/include/fud_sqlite.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include namespace fud { @@ -34,11 +35,19 @@ enum class SqliteOpenMode : int ReadWriteCreate = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE }; +class SqliteErrorMsg; + +class SqliteDb; +using SqliteDbResult = Result; + class SqliteDb { + private: + constexpr SqliteDb() = default; + public: - SqliteDb(const String& name, SqliteOpenMode mode, int extraFlags = 0); + static SqliteDbResult make(const String& name, SqliteOpenMode mode, int extraFlags = 0); - SqliteDb(const char* name, SqliteOpenMode mode, int extraFlags = 0); + static SqliteDbResult make(const char* cStrName, SqliteOpenMode mode, int extraFlags = 0); SqliteDb(const SqliteDb&) = delete; @@ -58,7 +67,7 @@ class SqliteDb { const String& statement, int (*callback)(void*, int, char**, char**), void* context, - String* errorMessage); + std::unique_ptr errorMessage); constexpr int errorCode() { @@ -70,16 +79,15 @@ class SqliteDb { return m_dbHandle; } - // private methods private: - void initialize(); + // private methods + FudStatus initialize(); [[nodiscard]] int open(); Result prepare(const String& sql); // private data members - private: String m_name{}; bool m_nameValid{false}; @@ -133,6 +141,22 @@ class SqliteStatement { sqlite3_stmt* m_preparedStatement{nullptr}; }; +class SqliteErrorMsg { + public: + constexpr SqliteErrorMsg() = default; + explicit constexpr SqliteErrorMsg(char* errorMsg) : m_errorMsg{errorMsg} + { + } + SqliteErrorMsg(const SqliteErrorMsg&) = delete; + SqliteErrorMsg(SqliteErrorMsg&& rhs) noexcept; + ~SqliteErrorMsg(); + SqliteErrorMsg& operator=(const SqliteErrorMsg&) = delete; + SqliteErrorMsg& operator=(SqliteErrorMsg&& rhs) noexcept; + + private: + char* m_errorMsg{nullptr}; +}; + } // namespace fud #endif diff --git a/include/fud_string.hpp b/include/fud_string.hpp index 1939c7d..6880cb7 100644 --- a/include/fud_string.hpp +++ b/include/fud_string.hpp @@ -18,6 +18,8 @@ #ifndef FUD_STRING_HPP #define FUD_STRING_HPP +#include "fud_assert.hpp" +#include "fud_result.hpp" #include "fud_status.hpp" #include "fud_string_view.hpp" #include "fud_utf8.hpp" @@ -32,13 +34,77 @@ namespace fud { constexpr size_t SSO_BUF_LENGTH = 15; constexpr size_t SSO_BUF_SIZE = SSO_BUF_LENGTH + 1; +using StringResult = Result; + class String { public: - String() = default; - explicit String(const utf8* cString); - explicit String(const char* cString); + static StringResult makeFromCString(const char* cString); + + static StringResult makeFromUtf8(const utf8* utf8String); + + template + static StringResult makeFromCString(Strings... cStrings) + { + size_t totalLength = 0; + Array lengths{}; + Array strPointers{}; + size_t index = 0; + for (const auto* cStringItem: {cStrings...}) { + // for (size_t index = 0; index < strPointers.size(); ++index) { + // const auto* cString = strPointers[index]; + const char* cString = nullptr; + if constexpr (std::is_same_v) { + cString = cStringItem; + } else if constexpr (std::is_same_v) { + cString = reinterpret_cast(cStringItem); + } else { + static_assert(!std::is_same_v); + } + strPointers[index] = cString; + + auto lengthResult = cStringLength(cString); + if (lengthResult < 0 || lengthResult >= SSIZE_MAX) { + return StringResult::error(FudStatus::InvalidInput); + } + auto stringLength = static_cast(lengthResult); + if (SIZE_MAX - totalLength < stringLength) { + return StringResult::error(FudStatus::Failure); + } + totalLength += stringLength; + lengths[index] = stringLength; + index++; + } + + String output{}; + auto* data = output.m_buffer.data(); + output.m_length = totalLength; + if (output.m_length >= output.m_capacity) { + output.m_capacity = output.m_length + 1; + data = static_cast(fudAlloc(output.m_capacity)); + if (data == nullptr) { + return StringResult::error(FudStatus::AllocFailure); + } + output.m_data = data; + } + + size_t cumulativeLength = 0; + for (size_t idx = 0; idx < strPointers.size(); ++idx) { + const auto* cString = strPointers[idx]; + auto copyStatus = copyMem(data, output.m_capacity - cumulativeLength, cString, lengths[idx]); + fudAssert(copyStatus == FudStatus::Success); + cumulativeLength += lengths[idx]; + } + + auto terminateStatus = output.nullTerminate(); + fudAssert(terminateStatus == FudStatus::Success); + + return StringResult::okay(std::move(output)); + } + + String() noexcept = default; String(const String& rhs); String(String&& rhs) noexcept; + ~String(); String& operator=(const String& rhs); @@ -109,7 +175,8 @@ class String { return m_capacity - 1U - m_length; } - [[nodiscard]] inline StringView asView() const { + [[nodiscard]] inline StringView asView() const + { return StringView(*this); } @@ -127,9 +194,9 @@ class String { FudStatus append(StringView source); - [[nodiscard]] String catenate(const String& rhs) const; + [[nodiscard]] StringResult catenate(const String& rhs) const; - [[nodiscard]] String catenate(const char* rhs) const; + [[nodiscard]] StringResult catenate(const char* rhs) const; [[nodiscard]] bool compare(const String& rhs) const; -- cgit v1.2.3