diff options
author | Dominick Allen <djallen@librehumanitas.org> | 2024-10-29 21:02:25 -0500 |
---|---|---|
committer | Dominick Allen <djallen@librehumanitas.org> | 2024-10-29 21:02:25 -0500 |
commit | 8ce397e8c0a83e49e390de9deb73d588e4931ecf (patch) | |
tree | 31f4f4facf0cb75535aaec130d606c54fe97b2d8 /include/fud_string.hpp | |
parent | f281050ddb3b9d658cff67a254eedc3b79de5c5d (diff) |
Reworking of Result.
Diffstat (limited to 'include/fud_string.hpp')
-rw-r--r-- | include/fud_string.hpp | 64 |
1 files changed, 22 insertions, 42 deletions
diff --git a/include/fud_string.hpp b/include/fud_string.hpp index 0020c67..cdc6b91 100644 --- a/include/fud_string.hpp +++ b/include/fud_string.hpp @@ -21,6 +21,7 @@ #include "fud_allocator.hpp" #include "fud_assert.hpp" #include "fud_c_string.hpp" +#include "fud_drain.hpp" #include "fud_option.hpp" #include "fud_result.hpp" #include "fud_status.hpp" @@ -36,22 +37,7 @@ static_assert(CHAR_BIT == 8); namespace fud { -struct DrainResult { - size_t bytesWritten; - FudStatus status; -}; - -/* TODO: make SSO_BUF_LENGTH user configurable. */ - -/** \brief The maximum length of a string using the small string optimization - * buffer. */ -constexpr size_t SSO_BUF_LENGTH = 15; - -/** \brief The size of the small string optimization buffer, to include space - * for the null terminator. */ -constexpr size_t SSO_BUF_SIZE = SSO_BUF_LENGTH + 1; - -static constexpr size_t SsoBufSize = 23; +constexpr size_t SsoBufSize = 23; class String; @@ -163,26 +149,26 @@ class String { fudAssert(totalLength < maxStringLength); String output{}; - output.m_allocator = allocator; + output.m_allocator = reinterpret_cast<uintptr_t>(allocator); utf8* data{nullptr}; size_t capacity = totalLength + 1; bool isLarge = capacity > SsoBufSize; if (isLarge) { - output.m_repr.large.capacity = capacity & largeStringCapacitymask; + output.m_repr.large.capacity = capacity; output.m_repr.large.length = totalLength; auto dataResult = output.allocator()->allocate(output.m_repr.large.capacity); if (dataResult.isError()) { return StringResult::error(dataResult.getError()); } output.m_repr.large.data = static_cast<utf8*>(dataResult.getOkay()); - output.m_repr.large.isLarge = 1; data = output.m_repr.large.data; + output.setLarge(); } else { capacity = SsoBufSize; static_assert(SsoBufSize < std::numeric_limits<int8_t>::max()); - output.m_repr.small.isLarge = 0; output.m_repr.small.length = static_cast<uint8_t>(totalLength) & smallStringLengthMask; data = output.m_repr.small.buffer.data(); + output.setSmall(); } fudAssert(data != nullptr); @@ -317,18 +303,19 @@ class String { private: static constexpr size_t maxStringLength = (static_cast<size_t>(1) << 63) - 1; - static constexpr size_t largeStringCapacitymask = (static_cast<size_t>(1) << 63) - 1; static constexpr uint8_t maxSmallStringLength = SsoBufSize; - static constexpr uint8_t smallStringLengthMask = 0x7F; + static constexpr uint8_t smallStringLengthMask = 0xFF; + static constexpr auto isLargeMask = static_cast<uintptr_t>(0x01); + static constexpr auto allocatorMask = ~isLargeMask; [[nodiscard]] static bool allocatorValid(Allocator* allocator) { - return allocator != nullptr; + return (reinterpret_cast<uintptr_t>(allocator) & isLargeMask) == 0; } Allocator* allocator() const { - return m_allocator; + return reinterpret_cast<Allocator*>(m_allocator & allocatorMask); } [[nodiscard]] bool nullTerminated() const; @@ -350,19 +337,17 @@ class String { /** \brief The allocator used to get storage for characters when the string * is large. */ - Allocator* m_allocator{&globalFudAllocator}; + uintptr_t m_allocator{reinterpret_cast<uintptr_t>(&globalFudAllocator)}; using BufType = Array<utf8, SsoBufSize>; union { struct { - uint8_t isLarge : 1; - size_t capacity : 63; + size_t capacity; size_t length; utf8* data; } large; struct { - uint8_t isLarge : 1 = 0; - uint8_t length : 7 = 0; + uint8_t length = 0; BufType buffer{}; } small{}; } m_repr{}; @@ -370,22 +355,17 @@ class String { /** \brief Whether or not the string must use its allocator for storage. */ [[nodiscard]] bool isLarge() const { - struct { - uint8_t isLarge : 1; - uint8_t length : 7; - } determinant; - copyMem<1>(determinant, m_repr); - return determinant.isLarge; + return (m_allocator & isLargeMask) != 0; } - [[nodiscard]] size_t smallLength() const + void setLarge() { - struct { - uint8_t isLarge : 1; - uint8_t length : 7; - } determinant; - copyMem<1>(determinant, m_repr); - return determinant.isLarge; + m_allocator |= isLargeMask; + } + + void setSmall() + { + m_allocator &= allocatorMask; } void addToLength(size_t augend) |