diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/fud_allocator.hpp | 6 | ||||
-rw-r--r-- | include/fud_c_string.hpp | 15 | ||||
-rw-r--r-- | include/fud_file.hpp | 11 | ||||
-rw-r--r-- | include/fud_string.hpp | 32 | ||||
-rw-r--r-- | include/fud_vector.hpp | 35 |
5 files changed, 67 insertions, 32 deletions
diff --git a/include/fud_allocator.hpp b/include/fud_allocator.hpp index e4078ac..9b90deb 100644 --- a/include/fud_allocator.hpp +++ b/include/fud_allocator.hpp @@ -32,7 +32,7 @@ class alignas(std::max_align_t) Allocator { virtual Result<std::byte*, FudStatus> allocate(size_t bytes, size_t alignment = alignof(std::max_align_t)) = 0; - virtual FudStatus deallocate(std::byte* pointer, size_t bytes) = 0; + virtual void deallocate(std::byte* pointer, size_t bytes) = 0; virtual bool isEqual(const Allocator& rhs) const = 0; }; @@ -48,7 +48,7 @@ class FudAllocator : public Allocator { virtual Result<std::byte*, FudStatus> allocate(size_t bytes, size_t alignment = alignof(std::max_align_t)) override; - virtual FudStatus deallocate(std::byte* pointer, size_t bytes) override; + virtual void deallocate(std::byte* pointer, size_t bytes) override; virtual bool isEqual(const Allocator& rhs) const override; }; @@ -61,7 +61,7 @@ class NullAllocator : public Allocator { virtual Result<std::byte*, FudStatus> allocate(size_t bytes, size_t alignment = alignof(std::max_align_t)) override; - virtual FudStatus deallocate(std::byte* pointer, size_t bytes) override; + virtual void deallocate(std::byte* pointer, size_t bytes) override; virtual bool isEqual(const Allocator& rhs) const override; }; diff --git a/include/fud_c_string.hpp b/include/fud_c_string.hpp index d55ba30..a1ab51a 100644 --- a/include/fud_c_string.hpp +++ b/include/fud_c_string.hpp @@ -20,14 +20,17 @@ #include <climits> #include <cstddef> +#include <limits> #include <sys/types.h> namespace fud { +constexpr ssize_t MAX_C_STRING_LENGTH = std::numeric_limits<ssize_t>::max() - 1; + constexpr ssize_t cStringLength(const char* str, size_t maxLength) { - if (str == nullptr || maxLength > (SSIZE_MAX - 1)) { + if (str == nullptr || maxLength > MAX_C_STRING_LENGTH) { return -1; } @@ -46,13 +49,14 @@ constexpr ssize_t cStringLength(const char* str, size_t maxLength) constexpr ssize_t cStringLength(const char* str) { - constexpr auto maxLength = SSIZE_MAX - 1; - return cStringLength(str, maxLength); + return cStringLength(str, MAX_C_STRING_LENGTH); } constexpr ssize_t cStringLength(const char8_t* str, size_t maxLength) { - if (str == nullptr || maxLength > (SSIZE_MAX - 1)) { + // Cannot cast str to const char* without breaking constexpr + // return cStringLength(reinterpret_cast<const char*>(str), maxLength); + if (str == nullptr || maxLength > MAX_C_STRING_LENGTH) { return -1; } @@ -71,8 +75,7 @@ constexpr ssize_t cStringLength(const char8_t* str, size_t maxLength) constexpr ssize_t cStringLength(const char8_t* str) { - constexpr auto maxLength = SSIZE_MAX - 1; - return cStringLength(str, maxLength); + return cStringLength(str, MAX_C_STRING_LENGTH); } } // namespace fud diff --git a/include/fud_file.hpp b/include/fud_file.hpp index 51826a6..7a53468 100644 --- a/include/fud_file.hpp +++ b/include/fud_file.hpp @@ -165,10 +165,17 @@ class RegularFile { FileAccessMode m_modeFlags{}; }; +enum class ReadPolicy { + Unbuffered, + ReadAhead, +}; + class BufferedRegularFile { public: - DrainResult write(const void* source, size_t sourceSize, size_t length, size_t offset); - // DrainResult read(void* sink, ); + /** \brief Write from source to file as sink. */ + DrainResult write(const std::byte* source, size_t sourceSize, size_t length, size_t offset); + /** \brief Read from file as source to sink. */ + DrainResult read(std::byte* sink, size_t sinkSize, size_t length, size_t offset); private: Vector<std::byte> m_readBuffer{Vector<std::byte>::NullVector()}; Vector<std::byte> m_writeBuffer{Vector<std::byte>::NullVector()}; diff --git a/include/fud_string.hpp b/include/fud_string.hpp index 226bb89..59c434a 100644 --- a/include/fud_string.hpp +++ b/include/fud_string.hpp @@ -60,6 +60,8 @@ class String { * \returns FudStatus::AllocFailure if the allocator fails. */ static StringResult makeFromCString(const char* cString); + + /** @copydoc String::makeFromCString(const char* cString) */ static StringResult makeFromCString(const char8_t* cString); /** \brief Create a string from a C String, specifying the allocator. @@ -74,6 +76,8 @@ class String { * \returns FudStatus::AllocFailure if the allocator fails. */ static StringResult makeFromCString(const char* cString, Allocator* allocator); + + /** @copydoc String::makeFromCString(const char* cString, Allocator* allocator) */ static StringResult makeFromCString(const char8_t* cString, Allocator* allocator); /** \brief Create a string from concatenating multiple C Strings. @@ -187,20 +191,33 @@ class String { * fud allocator. */ String() noexcept = default; + /* The copy constructor is deleted because it is fallible. */ String(const String& rhs) = delete; + /** \brief Infallibly moves the string. */ String(String&& rhs) noexcept; - ~String(); + /* Destructors need no documentation. */ + ~String() noexcept; + /* The copy assignment operator not deleted because it is fallible. */ String& operator=(const String& rhs) = delete; + /** \brief Takes ownership of rhs, destroying the contents of this string in + * the process. The allocator is taken from rhs. + */ String& operator=(String&& rhs) noexcept; - static StringResult from(const String& rhs); + /** \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. + */ + static StringResult from(const String& rhs, Option<Allocator*> allocatorOption = NullOpt); + /** \brief Create a String by copying from a view, with the specified allocator. */ static StringResult from(StringView view, Allocator* allocator = &globalFudAllocator); + /** \brief Copy the contents of rhs, without modifying rhs. */ FudStatus copy(const String& rhs); /** \brief The raw length of the string's data, excluding the null terminator. */ @@ -246,12 +263,19 @@ class String { return reinterpret_cast<const char*>(data()); } + /** \brief Indicates if the contents of the string form a valid sequence of + * UTF8 code points. */ [[nodiscard]] bool utf8Valid() const; + /** \brief Attempts to reserve newCapacity bytes of storage. */ FudStatus reserve(size_t newCapacity); + /** \brief Returns the last character in the sequence if the length is + * greater than zero. */ [[nodiscard]] Option<utf8> back(); + /** \brief Returns the remaining capacity for characters excluding the null + * terminating byte. */ [[nodiscard]] size_t remainingLength() const { if (length() > capacity()) { @@ -312,7 +336,9 @@ class String { Allocator* allocator() const { - return reinterpret_cast<Allocator*>(m_allocator & allocatorMask); + auto* allocPtr = reinterpret_cast<Allocator*>(m_allocator & allocatorMask); + fudAssert(allocPtr != nullptr); + return allocPtr; } [[nodiscard]] bool nullTerminated() const; diff --git a/include/fud_vector.hpp b/include/fud_vector.hpp index 52876fd..53b2625 100644 --- a/include/fud_vector.hpp +++ b/include/fud_vector.hpp @@ -39,6 +39,7 @@ class Vector { public: constexpr Vector() noexcept = default; + constexpr explicit Vector(Allocator& allocator) noexcept : m_allocator{&allocator} {} constexpr Vector(const Vector<T>& rhs) = delete; constexpr Vector(Vector<T>&& rhs) noexcept : m_allocator(rhs.m_allocator), m_data(rhs.m_data), m_length{rhs.m_length}, m_capacity{rhs.m_capacity} @@ -121,12 +122,12 @@ class Vector { Vector<T> output{}; auto status = initializeWithCapacity(output, count, allocator); if (status != FudStatus::Success) { - return status; + return FudError{status}; } - return output; + return Okay<Vector<T>>{std::move(output)}; } - static Result<Vector<T>, FudStatus> initializeWithSize( + static FudStatus initializeWithSize( Vector<T>& output, size_t count, Allocator* allocator = &globalFudAllocator) @@ -145,7 +146,8 @@ class Vector { const auto* ptr = new (output.m_data + index) T(); fudAssert(ptr != nullptr); } - return output; + + return FudStatus::Success; } template <typename Builder> @@ -157,20 +159,20 @@ class Vector { Vector<T> output{}; auto status = initializeWithSizeFallible(output, count, std::forward<Builder>(builder), allocator); if (status != FudStatus::Success) { - return status; + return FudError{status}; } - return output; + return Okay<Vector<T>>{std::move(output)}; } template <typename Builder> - static Result<Vector<T>, FudStatus> initializeWithSizeFallible( + static FudStatus initializeWithSizeFallible( Vector<T>& output, size_t count, Builder&& builder, Allocator* allocator = &globalFudAllocator) { - using BuilderResult = decltype(std::forward<Builder>(builder)()); - static_assert(std::is_same_v<BuilderResult, FudStatus>()); + // using BuilderResult = decltype(std::forward<Builder>(builder)(T{})); + // static_assert(std::is_same_v<BuilderResult, FudStatus>); auto status = Vector::initializeWithCapacity(output, count, allocator); if (status != FudStatus::Success) { @@ -180,13 +182,13 @@ class Vector { output.m_length = count; for (size_t index = 0; index < count; ++index) { - auto builderResult{std::forward<Builder>(builder)(output.m_data[index])}; - if (builderResult.isError()) { - return builderResult.takeError(); + auto builderStatus{std::forward<Builder>(builder)(output.m_data[index])}; + if (builderStatus != FudStatus::Success) { + return builderStatus; } } - return output; + return FudStatus::Success; } static Result<Vector<T>, FudStatus> from(const Vector<T>& rhs, Option<Allocator*> allocatorOption = NullOpt) @@ -356,7 +358,7 @@ class Vector { auto status = FudStatus::Success; if (m_capacity > 0) { - status = m_allocator->deallocate(reinterpret_cast<std::byte*>(m_data), m_capacity); + m_allocator->deallocate(reinterpret_cast<std::byte*>(m_data), m_capacity); } m_data = dataPtr; @@ -672,10 +674,7 @@ class Vector { auto status = clear(); if (m_data != nullptr && m_allocator != nullptr) { - auto deallocStatus = m_allocator->deallocate(reinterpret_cast<std::byte*>(m_data), m_capacity); - if (status == FudStatus::Success) { - status = deallocStatus; - } + m_allocator->deallocate(reinterpret_cast<std::byte*>(m_data), m_capacity); } m_allocator = nullptr; |