diff options
author | Dominick Allen <djallen@librehumanitas.org> | 2025-01-04 12:02:45 -0600 |
---|---|---|
committer | Dominick Allen <djallen@librehumanitas.org> | 2025-01-04 12:02:45 -0600 |
commit | 1d357adfa19725ee69fb267a363f1fd217b1272f (patch) | |
tree | 8d8710ba8ba7dff0b3da6b073fbb94f1a7b03ec5 | |
parent | 0b400af9519444deef4cc6ad2c43c30e2092ab4f (diff) |
-rw-r--r-- | include/fud_allocator.hpp | 38 | ||||
-rw-r--r-- | include/fud_sqlite.hpp | 4 | ||||
-rw-r--r-- | include/fud_string.hpp | 19 | ||||
-rw-r--r-- | include/fud_string_view.hpp | 5 | ||||
-rw-r--r-- | include/fud_vector.hpp | 1 | ||||
-rw-r--r-- | source/fud_allocator.cpp | 2 | ||||
-rw-r--r-- | source/fud_csv.cpp | 1 | ||||
-rw-r--r-- | source/fud_sqlite.cpp | 24 | ||||
-rw-r--r-- | source/fud_string.cpp | 13 |
9 files changed, 78 insertions, 29 deletions
diff --git a/include/fud_allocator.hpp b/include/fud_allocator.hpp index 95e1d5a..99b33ce 100644 --- a/include/fud_allocator.hpp +++ b/include/fud_allocator.hpp @@ -22,7 +22,6 @@ #include "fud_status.hpp" #include <cstddef> -#include <limits> namespace fud { @@ -32,6 +31,7 @@ extern std::byte* fudAlloc(size_t size); /** \brief The default deallocation function for globalFudAllocator. */ extern void fudFree(std::byte* ptr); +// NOLINTBEGIN(cppcoreguidelines-special-member-functions) class alignas(std::max_align_t) Allocator { public: virtual ~Allocator() = default; @@ -40,7 +40,7 @@ class alignas(std::max_align_t) Allocator { virtual void deallocate(std::byte* pointer, size_t bytes) = 0; - virtual bool isEqual(const Allocator& rhs) const = 0; + [[nodiscard]] virtual bool isEqual(const Allocator& rhs) const = 0; }; constexpr bool operator==(const Allocator& lhs, const Allocator& rhs) @@ -50,40 +50,44 @@ constexpr bool operator==(const Allocator& lhs, const Allocator& rhs) class FudAllocator : public Allocator { public: - virtual ~FudAllocator() override = default; + ~FudAllocator() override = default; - virtual Result<std::byte*, FudStatus> allocate(size_t bytes, size_t alignment = alignof(std::max_align_t)) override; + Result<std::byte*, FudStatus> allocate(size_t bytes, size_t alignment = alignof(std::max_align_t)) override; - virtual void deallocate(std::byte* pointer, size_t bytes) override; + void deallocate(std::byte* pointer, size_t bytes) override; - virtual bool isEqual(const Allocator& rhs) const override; + [[nodiscard]] bool isEqual(const Allocator& rhs) const override; }; +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) extern FudAllocator globalFudAllocator; class NullAllocator : public Allocator { public: - virtual ~NullAllocator() override = default; + ~NullAllocator() override = default; - virtual Result<std::byte*, FudStatus> allocate(size_t bytes, size_t alignment = alignof(std::max_align_t)) override; + Result<std::byte*, FudStatus> allocate(size_t bytes, size_t alignment = alignof(std::max_align_t)) override; - virtual void deallocate(std::byte* pointer, size_t bytes) override; + void deallocate(std::byte* pointer, size_t bytes) override; - virtual bool isEqual(const Allocator& rhs) const override; + [[nodiscard]] bool isEqual(const Allocator& rhs) const override; }; +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) extern NullAllocator globalNullAllocator; template <size_t Size> class SimpleStackAllocator final : public Allocator { -private: + private: + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) std::byte m_memory[Size]{}; size_t m_allocated{0}; -public: - virtual ~SimpleStackAllocator() override final = default; + public: + ~SimpleStackAllocator() final = default; - virtual Result<std::byte*, FudStatus> allocate(size_t bytes, size_t alignment = alignof(std::max_align_t)) override final { + Result<std::byte*, FudStatus> allocate(size_t bytes, size_t alignment = alignof(std::max_align_t)) final + { using RetType = Result<std::byte*, FudStatus>; static_cast<void>(alignment); if (bytes > Size - m_allocated) { @@ -96,7 +100,7 @@ public: return RetType::okay(data); } - virtual void deallocate(std::byte* pointer, size_t bytes) override final + void deallocate(std::byte* pointer, size_t bytes) final { if (pointer + bytes != m_memory + m_allocated) { m_allocated = Size; @@ -105,11 +109,13 @@ public: m_allocated -= bytes; } - virtual bool isEqual(const Allocator& rhs) const override final { + [[nodiscard]] bool isEqual(const Allocator& rhs) const final + { return &rhs == this; } }; } // namespace fud +// NOLINTEND(cppcoreguidelines-special-member-functions) #endif diff --git a/include/fud_sqlite.hpp b/include/fud_sqlite.hpp index b2d2f5b..7ab3ef8 100644 --- a/include/fud_sqlite.hpp +++ b/include/fud_sqlite.hpp @@ -48,6 +48,8 @@ class SqliteDb { public: static SqliteDbResult make(const String& name, SqliteOpenMode mode, int extraFlags = 0); + static SqliteDbResult make(StringView name, SqliteOpenMode mode, int extraFlags = 0); + static SqliteDbResult make(const char* cStrName, SqliteOpenMode mode, int extraFlags = 0); SqliteDb(const SqliteDb&) = delete; @@ -81,6 +83,8 @@ class SqliteDb { } private: + static SqliteDbResult finishMake(SqliteOpenMode& mode, int& extraFlags, SqliteDb&& sqlDb); + // private methods FudStatus initialize(); diff --git a/include/fud_string.hpp b/include/fud_string.hpp index a20b067..4b3dbe2 100644 --- a/include/fud_string.hpp +++ b/include/fud_string.hpp @@ -31,6 +31,7 @@ #include <climits> #include <cstddef> +// NOLINTNEXTLINE(readability-magic-numbers) static_assert(CHAR_BIT == 8); /** @file */ @@ -132,6 +133,7 @@ class String { if constexpr (std::is_same_v<decltype(cStringItem), const char*>) { cString = cStringItem; } else if constexpr (std::is_same_v<decltype(cStringItem), const utf8*>) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) cString = reinterpret_cast<const char*>(cStringItem); } else { static_assert(!std::is_same_v<decltype(cStringItem), const char*>); @@ -155,6 +157,7 @@ class String { fudAssert(totalLength < maxStringLength); String output{}; + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) output.m_allocator = reinterpret_cast<uintptr_t>(allocator); utf8* data{nullptr}; size_t outputCapacity = totalLength + 1; @@ -208,6 +211,8 @@ class String { */ String& operator=(String&& rhs) noexcept; + static StringResult withAllocator(Allocator& allocator); + /** \brief Create a String by copying from an existing rhs, optionally * specifying a different allocator. If allocatorOption is NullOpt, the * allocator from rhs is used. @@ -269,12 +274,13 @@ class String { } /** \brief The underlying data as an explicit c string. */ - [[nodiscard]] inline const char* c_str() const + [[nodiscard]] const char* c_str() const { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return reinterpret_cast<const char*>(data()); } - [[nodiscard]] inline StringView asView() const + [[nodiscard]] StringView asView() const { return StringView(*this); } @@ -336,9 +342,9 @@ class String { FudStatus clear(); - const utf8* begin() const; + [[nodiscard]] const utf8* begin() const; - const utf8* end() const; + [[nodiscard]] const utf8* end() const; private: static constexpr size_t maxStringLength = (static_cast<size_t>(1) << 63) - 1; @@ -349,11 +355,13 @@ class String { [[nodiscard]] static bool allocatorValid(Allocator* allocator) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return (reinterpret_cast<uintptr_t>(allocator) & isLargeMask) == 0; } - Allocator* allocator() const + [[nodiscard]] Allocator* allocator() const { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast,performance-no-int-to-ptr) auto* allocPtr = reinterpret_cast<Allocator*>(m_allocator & allocatorMask); fudAssert(allocPtr != nullptr); return allocPtr; @@ -380,6 +388,7 @@ class String { /** \brief The allocator used to get storage for characters when the string * is large. */ + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) uintptr_t m_allocator{reinterpret_cast<uintptr_t>(&globalFudAllocator)}; using BufType = Array<utf8, SsoBufSize>; diff --git a/include/fud_string_view.hpp b/include/fud_string_view.hpp index d8f67ba..f71919d 100644 --- a/include/fud_string_view.hpp +++ b/include/fud_string_view.hpp @@ -129,6 +129,11 @@ struct StringView { return m_data + m_length; } + /** \brief Checks if one past the length is the null terminator character. + * + * \par WARNING: This function may invoke UB if the pointer to data plus its + * length does not belong to the data sequence. + */ [[nodiscard]] bool nullTerminated() const; [[nodiscard]] bool utf8Valid() const; diff --git a/include/fud_vector.hpp b/include/fud_vector.hpp index 760587b..0a9abf3 100644 --- a/include/fud_vector.hpp +++ b/include/fud_vector.hpp @@ -28,6 +28,7 @@ #include <cstddef> #include <functional> +#include <limits> #include <new> // IWYU pragma: keep (placement new) namespace fud { diff --git a/source/fud_allocator.cpp b/source/fud_allocator.cpp index 3f58fb0..08a64fa 100644 --- a/source/fud_allocator.cpp +++ b/source/fud_allocator.cpp @@ -43,6 +43,7 @@ bool FudAllocator::isEqual(const Allocator& rhs) const return &rhs == static_cast<const Allocator*>(this); } +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) FudAllocator globalFudAllocator{}; Result<std::byte*, FudStatus> NullAllocator::allocate(size_t bytes, size_t alignment) @@ -63,6 +64,7 @@ bool NullAllocator::isEqual(const Allocator& rhs) const return &rhs == static_cast<const Allocator*>(this); } +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) NullAllocator globalNullAllocator{}; } // namespace fud diff --git a/source/fud_csv.cpp b/source/fud_csv.cpp index 260a4ff..82935e4 100644 --- a/source/fud_csv.cpp +++ b/source/fud_csv.cpp @@ -141,7 +141,6 @@ FudStatus Csv::parseFromBufferedFile(Csv& csv, BufferedRegularFile& file, size_t FudStatus Csv::parseFromUnbufferedFile(Csv& csv, RegularFile&& file, size_t maxExtraAttempts) { - static_cast<void>(csv); constexpr size_t BufferSize = 256; SimpleStackAllocator<BufferSize> stackAllocator{}; TextBuffer textBuffer{stackAllocator}; diff --git a/source/fud_sqlite.cpp b/source/fud_sqlite.cpp index 735389f..4a7187f 100644 --- a/source/fud_sqlite.cpp +++ b/source/fud_sqlite.cpp @@ -26,23 +26,33 @@ SqliteDbResult SqliteDb::make(const String& name, SqliteOpenMode mode, int extra if (copyResult != FudStatus::Success) { return SqliteDbResult::error(copyResult); } - sqlDb.m_mode = mode; - sqlDb.m_extraFlags = extraFlags; - auto status = sqlDb.initialize(); - if (status != FudStatus::Success) { - return SqliteDbResult::error(status); + return finishMake(mode, extraFlags, std::move(sqlDb)); +} + +SqliteDbResult SqliteDb::make(StringView name, SqliteOpenMode mode, int extraFlags) +{ + SqliteDb sqlDb{}; + auto nameResult{String::from(name)}; + if (nameResult.isError()) { + return SqliteDbResult::error(nameResult.takeError()); } - return SqliteDbResult::okay(std::move(sqlDb)); + sqlDb.m_name = nameResult.takeOkay(); + return finishMake(mode, extraFlags, std::move(sqlDb)); } SqliteDbResult SqliteDb::make(const char* cStrName, SqliteOpenMode mode, int extraFlags) { + SqliteDb sqlDb{}; auto nameResult = String::makeFromCString(cStrName); if (nameResult.isError()) { return SqliteDbResult::error(nameResult); } - SqliteDb sqlDb{}; sqlDb.m_name = nameResult.takeOkay(); + return finishMake(mode, extraFlags, std::move(sqlDb)); +} + +SqliteDbResult SqliteDb::finishMake(SqliteOpenMode& mode, int& extraFlags, SqliteDb&& sqlDb) +{ sqlDb.m_mode = mode; sqlDb.m_extraFlags = extraFlags; auto status = sqlDb.initialize(); diff --git a/source/fud_string.cpp b/source/fud_string.cpp index 37a2a4b..a2a62f4 100644 --- a/source/fud_string.cpp +++ b/source/fud_string.cpp @@ -21,6 +21,19 @@ namespace fud { +StringResult String::withAllocator(Allocator& allocator) +{ + if (!String::allocatorValid(&allocator)) + { + return Error{FudStatus::ArgumentInvalid}; + } + + String output{}; + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + output.m_allocator = reinterpret_cast<uintptr_t>(&allocator); + return Okay{std::move(output)}; +} + StringResult String::makeFromCString(const char8_t* cString) { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) |