summaryrefslogtreecommitdiff
path: root/include/fud_string.hpp
diff options
context:
space:
mode:
authorDominick Allen <djallen@librehumanitas.org>2024-10-29 21:02:25 -0500
committerDominick Allen <djallen@librehumanitas.org>2024-10-29 21:02:25 -0500
commit8ce397e8c0a83e49e390de9deb73d588e4931ecf (patch)
tree31f4f4facf0cb75535aaec130d606c54fe97b2d8 /include/fud_string.hpp
parentf281050ddb3b9d658cff67a254eedc3b79de5c5d (diff)
Reworking of Result.
Diffstat (limited to 'include/fud_string.hpp')
-rw-r--r--include/fud_string.hpp64
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)