summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/fud_c_file.hpp39
-rw-r--r--include/fud_result.hpp24
-rw-r--r--include/fud_sqlite.hpp36
-rw-r--r--include/fud_string.hpp79
4 files changed, 150 insertions, 28 deletions
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 <cstdint>
#include <cstdio>
@@ -155,7 +155,8 @@ class CFile {
return self.m_file;
}
- FudStatus setPermissions(Permissions permissions) {
+ FudStatus setPermissions(Permissions permissions)
+ {
auto& self = static_cast<Derived&>(*this);
if (!self.isOpen()) {
return FudStatus::OperationInvalid;
@@ -383,14 +384,20 @@ class CFile {
} // namespace detail
+class CBinaryFile;
+using CBinaryFileResult = Result<CBinaryFile, FudStatus>;
+
class CBinaryFile : public detail::CFile<CBinaryFile> {
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> {
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<CTextFile, FudStatus>;
+
class CTextFile : public detail::CFile<CTextFile> {
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> {
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 <typename F>
+ static ResultType okay(const Result<T, F>& okayRes) {
+ return ResultType{okayRes.getOkay()};
+ }
+
+ template <typename F>
+ static ResultType okay(Result<T, F>&& okayRes) {
+ return ResultType{okayRes.takeOkay()};
+ }
+
+ template <typename U>
+ static ResultType error(const Result<U, E>& errorRes) {
+ return ResultType{errorRes.getError()};
+ }
+
+ template <typename U>
+ static ResultType error(Result<U, E>&& 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<E>(m_value);
}
- [[nodiscard]] const T&& getOkay() const&&
+ [[nodiscard]] T&& takeOkay()
{
return std::move(std::get<T>(m_value));
}
- [[nodiscard]] const E&& getError() const&&
+ [[nodiscard]] E&& takeError()
{
return std::move(std::get<E>(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 <fud_result.hpp>
#include <fud_status.hpp>
#include <fud_string.hpp>
+#include <memory>
#include <sqlite3.h>
namespace fud {
@@ -34,11 +35,19 @@ enum class SqliteOpenMode : int
ReadWriteCreate = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
};
+class SqliteErrorMsg;
+
+class SqliteDb;
+using SqliteDbResult = Result<SqliteDb, FudStatus>;
+
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<SqliteErrorMsg> 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<SqliteStatement, FudStatus> 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<String, FudStatus>;
+
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 <typename... Strings>
+ static StringResult makeFromCString(Strings... cStrings)
+ {
+ size_t totalLength = 0;
+ Array<size_t, sizeof...(cStrings)> lengths{};
+ Array<const char*, sizeof...(cStrings)> 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<decltype(cStringItem), const char*>) {
+ cString = cStringItem;
+ } else if constexpr (std::is_same_v<decltype(cStringItem), const utf8*>) {
+ cString = reinterpret_cast<const char*>(cStringItem);
+ } else {
+ static_assert(!std::is_same_v<decltype(cStringItem), const char*>);
+ }
+ strPointers[index] = cString;
+
+ auto lengthResult = cStringLength(cString);
+ if (lengthResult < 0 || lengthResult >= SSIZE_MAX) {
+ return StringResult::error(FudStatus::InvalidInput);
+ }
+ auto stringLength = static_cast<size_t>(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<utf8*>(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;