summaryrefslogtreecommitdiff
path: root/source/fud_string.cpp
diff options
context:
space:
mode:
authorDominick Allen <djallen@librehumanitas.org>2024-10-29 10:28:11 -0500
committerDominick Allen <djallen@librehumanitas.org>2024-10-29 10:28:11 -0500
commitf281050ddb3b9d658cff67a254eedc3b79de5c5d (patch)
tree62c8673ca990a1df6169d08435924a69cc0b24b2 /source/fud_string.cpp
parent24cd7c8896b2091114e89ffda06b5c63eb2827c7 (diff)
Reduce string size, adopt clang-style SSO.
Diffstat (limited to 'source/fud_string.cpp')
-rw-r--r--source/fud_string.cpp364
1 files changed, 228 insertions, 136 deletions
diff --git a/source/fud_string.cpp b/source/fud_string.cpp
index 994689e..4943dac 100644
--- a/source/fud_string.cpp
+++ b/source/fud_string.cpp
@@ -39,22 +39,44 @@ StringResult String::makeFromCString(const char* cString, Allocator* allocator)
}
auto lenResult = cStringLength(cString);
- if (lenResult < 0 || lenResult >= SSIZE_MAX) {
+ if (lenResult < 0 || lenResult >= std::numeric_limits<ssize_t>::max()) {
return StringResult::error(FudStatus::ArgumentInvalid);
}
+ auto length = static_cast<size_t>(lenResult);
+ if constexpr (static_cast<size_t>(std::numeric_limits<ssize_t>::max()) > maxStringLength) {
+ if (length > maxStringLength) {
+ return StringResult::error(FudStatus::ArgumentInvalid);
+ }
+ }
+
String output{};
output.m_allocator = allocator;
- output.m_length = static_cast<size_t>(lenResult);
-
- if (output.m_length >= output.m_capacity) {
- output.m_capacity = output.m_length + 1;
- output.m_data = static_cast<utf8*>(M_TakeOrReturn(output.allocator()->allocate(output.m_capacity)));
- fudAssert(output.m_data != nullptr);
+ utf8* data{nullptr};
+ size_t capacity = length + 1;
+ bool isLarge = capacity > SsoBufSize;
+ if (isLarge) {
+ output.m_repr.large.capacity = capacity & largeStringCapacitymask;
+ output.m_repr.large.length = length;
+ 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;
+ } 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>(length) & smallStringLengthMask;
+ data = output.m_repr.small.buffer.data();
}
- auto copyStatus = copyMem(output.dataMut(), output.m_capacity, cString, output.m_length);
+ fudAssert(data != nullptr);
+
+ auto copyStatus = copyMem(data, capacity, cString, length);
fudAssert(copyStatus == FudStatus::Success);
auto terminateStatus = output.nullTerminate();
@@ -70,16 +92,26 @@ StringResult String::from(const String& rhs)
}
String output{};
- output.m_length = rhs.m_length;
- output.m_capacity = rhs.m_capacity;
output.m_allocator = rhs.m_allocator;
-
+ utf8* data{nullptr};
+ size_t capacity{0};
+ size_t length{0};
if (rhs.isLarge()) {
- output.m_data = static_cast<utf8*>(M_TakeOrReturn(output.allocator()->allocate(output.m_capacity)));
- fudAssert(output.m_data != nullptr);
+ output.m_repr.large = rhs.m_repr.large;
+ output.m_repr.large.data = static_cast<utf8*>(
+ M_TakeOrReturn(output.allocator()->allocate(output.m_repr.large.capacity)));
+ data = output.m_repr.large.data;
+ capacity = output.m_repr.large.capacity;
+ length = output.m_repr.large.length;
+ } else {
+ output.m_repr.small = rhs.m_repr.small;
+ data = output.m_repr.small.buffer.data();
+ capacity = SsoBufSize;
+ length = output.m_repr.small.length;
}
+ fudAssert(data != nullptr);
- auto copyResult = copyMem(output.dataMut(), output.m_capacity, rhs.data(), output.m_length);
+ auto copyResult = copyMem(output.dataMut(), capacity, rhs.data(), length);
fudAssert(copyResult == FudStatus::Success);
auto nullTerminateStatus = output.nullTerminate();
@@ -98,18 +130,30 @@ StringResult String::from(StringView view, Allocator* allocator)
return StringResult::error(FudStatus::ArgumentInvalid);
}
- String output{};
- output.m_allocator = allocator;
-
- if (view.m_length >= output.capacity() + 1U) {
- output.m_capacity = view.m_length + 1;
-
- output.m_data = static_cast<utf8*>(M_TakeOrReturn(output.allocator()->allocate(output.m_capacity)));
- fudAssert(output.m_data != nullptr);
+ if (view.nullTerminated()) {
+ return StringResult::error(FudStatus::ArgumentInvalid);
}
- output.setLength(view.m_length);
- auto copyStatus = copyMem(output.dataMut(), output.m_capacity, view.m_data, output.m_length);
+ String output{};
+ output.m_allocator = allocator;
+ size_t capacity = view.length() + 1U;
+ bool isLarge = capacity > SsoBufSize;
+ utf8* data{nullptr};
+ if (isLarge) {
+ output.m_repr.large.capacity = capacity & largeStringCapacitymask;
+ output.m_repr.large.length = view.length();
+ output.m_repr.large.data = static_cast<utf8*>(M_TakeOrReturn(output.allocator()->allocate(capacity)));
+ output.m_repr.large.isLarge = 1;
+ data = output.m_repr.large.data;
+ } 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>(view.length()) & smallStringLengthMask;
+ data = output.m_repr.small.buffer.data();
+ }
+ fudAssert(data != nullptr);
+ auto copyStatus = copyMem(data, capacity, view.m_data, view.length());
fudAssert(copyStatus == FudStatus::Success);
auto terminateStatus = output.nullTerminate();
@@ -118,15 +162,10 @@ StringResult String::from(StringView view, Allocator* allocator)
return StringResult::okay(std::move(output));
}
-String::String(String&& rhs) noexcept : m_allocator{rhs.m_allocator}, m_length{rhs.m_length}, m_capacity{rhs.m_capacity}
+String::String(String&& rhs) noexcept : m_allocator{rhs.m_allocator}, m_repr{std::move(rhs.m_repr)}
{
- if (rhs.isLarge()) {
- m_data = rhs.m_data;
- rhs.m_data = nullptr;
- } else {
- m_buffer = rhs.m_buffer;
- auto terminateStatus = nullTerminate();
- fudAssert(terminateStatus == FudStatus::Success);
+ if (isLarge()) {
+ rhs.m_repr.large.data = nullptr;
}
}
@@ -147,15 +186,27 @@ FudStatus String::copy(const String& rhs)
cleanup();
- m_length = rhs.m_length;
- m_capacity = rhs.m_capacity;
m_allocator = rhs.m_allocator;
+ m_repr = rhs.m_repr;
+
+ utf8* data{nullptr};
+ size_t capacity{};
+ size_t length{};
if (isLarge()) {
- m_data = static_cast<utf8*>(M_TakeOrReturn(allocator()->allocate(m_capacity)));
+ m_repr.large.data = static_cast<utf8*>(M_TakeOrReturn(allocator()->allocate(m_repr.large.capacity)));
+ capacity = m_repr.large.capacity;
+ length = m_repr.large.length;
+ data = m_repr.large.data;
+ } else {
+ capacity = SsoBufSize;
+ length = m_repr.small.length;
+ data = m_repr.small.buffer.data();
}
- auto copyResult = copyMem(dataMut(), m_capacity, rhs.data(), m_length);
+ fudAssert(data != nullptr);
+
+ auto copyResult = copyMem(dataMut(), capacity, rhs.data(), length);
fudAssert(copyResult == FudStatus::Success);
auto nullTerminateStatus = nullTerminate();
fudAssert(nullTerminateStatus == FudStatus::Success);
@@ -171,15 +222,11 @@ String& String::operator=(String&& rhs) noexcept
cleanup();
- m_length = rhs.m_length;
- m_capacity = rhs.m_capacity;
m_allocator = rhs.m_allocator;
- if (rhs.isLarge()) {
- m_data = rhs.m_data;
- rhs.m_data = nullptr;
- } else {
- m_buffer = rhs.m_buffer;
- fudAssert(nullTerminate() == FudStatus::Success);
+ m_repr = std::move(rhs.m_repr);
+
+ if (isLarge()) {
+ rhs.m_repr.large.data = nullptr;
}
return *this;
}
@@ -187,10 +234,10 @@ String& String::operator=(String&& rhs) noexcept
void String::cleanup()
{
const auto* allocPtr = allocator();
- if (isLarge() && m_data != nullptr && allocPtr != nullptr) {
- auto deallocStatus = allocator()->deallocate(m_data, m_capacity);
+ if (isLarge() && m_repr.large.data != nullptr && allocPtr != nullptr) {
+ auto deallocStatus = allocator()->deallocate(m_repr.large.data, m_repr.large.capacity);
static_cast<void>(deallocStatus);
- m_data = nullptr;
+ m_repr.large.data = nullptr;
}
}
@@ -200,26 +247,27 @@ FudStatus String::resize(size_t newCapacity)
return FudStatus::StringInvalid;
}
- if (m_length >= newCapacity) {
+ if (length() >= newCapacity) {
return FudStatus::OperationInvalid;
}
if (!isLarge() && newCapacity <= SSO_BUF_SIZE) {
- m_capacity = SSO_BUF_SIZE;
return FudStatus::Success;
}
if (newCapacity <= SSO_BUF_SIZE) {
+ fudAssert(isLarge());
+
+ auto len = static_cast<uint8_t>(length());
BufType temp{BufType::constFill(0)};
- auto copyResult = copyMem(dataMut(), temp.size(), temp.data(), length());
+ auto copyResult = copyMem(dataMut(), temp.size(), temp.data(), len);
fudAssert(copyResult == FudStatus::Success);
- auto deallocStatus = allocator()->deallocate(m_data, m_capacity);
- m_capacity = SSO_BUF_SIZE;
- m_data = nullptr;
-
- copyMem(m_buffer, temp);
- dataMut()[m_length] = '\0';
+ auto deallocStatus = allocator()->deallocate(m_repr.large.data, m_repr.large.capacity);
+ m_repr.small.isLarge = 0;
+ m_repr.small.length = len & smallStringLengthMask;
+ copyMem(m_repr.small.buffer, temp);
+ m_repr.small.buffer[len] = '\0';
return deallocStatus != FudStatus::Success ? FudStatus::DeallocFailure : FudStatus::Success;
}
@@ -227,17 +275,21 @@ FudStatus String::resize(size_t newCapacity)
auto* newData = static_cast<utf8*>(M_TakeOrReturn(allocator()->allocate(newCapacity)));
fudAssert(newData != nullptr);
- auto copyResult = copyMem(newData, newCapacity, dataMut(), length());
+ auto copyResult = copyMem(newData, newCapacity, data(), length());
fudAssert(copyResult == FudStatus::Success);
auto deallocStatus = FudStatus::Success;
if (isLarge()) {
- deallocStatus = allocator()->deallocate(dataMut(), m_capacity);
+ deallocStatus = allocator()->deallocate(dataMut(), m_repr.large.capacity);
}
- m_capacity = newCapacity;
- m_data = newData;
- dataMut()[m_length] = '\0';
+ size_t len = length();
+
+ m_repr.large.isLarge = 1;
+ m_repr.large.capacity = newCapacity & largeStringCapacitymask;
+ m_repr.large.data = newData;
+ m_repr.large.length = len;
+ m_repr.large.data[m_repr.large.length] = '\0';
fudAssert(valid());
return deallocStatus != FudStatus::Success ? FudStatus::DeallocFailure : FudStatus::Success;
@@ -245,7 +297,7 @@ FudStatus String::resize(size_t newCapacity)
bool String::nullTerminated() const
{
- return data() != nullptr && m_length < m_capacity && data()[m_length] == '\0';
+ return data() != nullptr && length() <= capacity() && data()[length()] == '\0';
}
bool String::valid() const
@@ -265,8 +317,8 @@ bool String::utf8Valid() const
FudStatus String::nullTerminate()
{
- if (m_length < m_capacity) {
- dataMut()[m_length] = '\0';
+ if (length() <= capacity()) {
+ dataMut()[length()] = '\0';
return FudStatus::Success;
}
return FudStatus::StringInvalid;
@@ -278,7 +330,7 @@ FudStatus String::reserve(size_t newCapacity)
return FudStatus::StringInvalid;
}
- if (newCapacity < m_capacity) {
+ if (newCapacity < capacity()) {
return FudStatus::Success;
}
@@ -291,7 +343,7 @@ FudStatus String::reserve(size_t newCapacity)
return NullOpt;
}
- utf8 backChar = dataMut()[m_length - 1];
+ utf8 backChar = dataMut()[length() - 1];
if (Ascii::valid(backChar)) {
return backChar;
}
@@ -305,13 +357,23 @@ Option<utf8> String::pop()
return NullOpt;
}
- if (m_length < 1) {
- return NullOpt;
+ utf8 letter{};
+ if (isLarge()) {
+ if (m_repr.large.length < 1) {
+ return NullOpt;
+ }
+ m_repr.large.length--;
+ letter = m_repr.large.data[m_repr.large.length];
+ m_repr.large.data[m_repr.large.length] = '\0';
+ } else {
+ if (m_repr.small.length < 1) {
+ return NullOpt;
+ }
+ m_repr.small.length--;
+ letter = m_repr.small.buffer[m_repr.small.length];
+ m_repr.small.buffer[m_repr.small.length] = '\0';
}
- m_length--;
- auto letter = dataMut()[m_length];
- dataMut()[m_length] = '\0';
return letter;
}
@@ -327,17 +389,25 @@ FudStatus String::pushBack(utf8 letter)
}
if (remainingLength() < 1) {
- auto newCapacity = m_capacity < SIZE_MAX / 2 ? m_capacity * 2 : SIZE_MAX;
+ auto cap = capacity() + 1U;
+ auto newCapacity = cap < maxStringLength / 2 ? cap * 2 : maxStringLength - 1U;
const auto resizeStatus = resize(newCapacity);
if (resizeStatus != FudStatus::Success) {
return resizeStatus;
}
- fudAssert(m_capacity == newCapacity);
+ fudAssert(isLarge());
+ fudAssert(m_repr.large.capacity == newCapacity);
}
- dataMut()[m_length] = letter;
- m_length++;
- dataMut()[m_length] = '\0';
+ if (isLarge()) {
+ m_repr.large.data[m_repr.large.length] = letter;
+ m_repr.large.length++;
+ m_repr.large.data[m_repr.large.length] = '\0';
+ } else {
+ m_repr.small.buffer[m_repr.small.length] = letter;
+ m_repr.small.length++;
+ m_repr.small.buffer[m_repr.small.length] = '\0';
+ }
return FudStatus::Success;
}
@@ -359,25 +429,31 @@ FudStatus String::pushBack(const FudUtf8& letter)
auto letterSize = letter.size();
if (remainingLength() < letterSize) {
- auto newCapacity = m_capacity < SIZE_MAX / 2 ? m_capacity * 2 : SIZE_MAX;
- if ((newCapacity - m_capacity) < (letterSize + 1)) {
+ auto cap = capacity() + 1U;
+ auto newCapacity = cap < maxStringLength / 2 ? cap * 2 : maxStringLength - 1U;
+ if ((newCapacity - cap) < (letterSize + 1)) {
return FudStatus::OperationInvalid;
}
const auto resizeStatus = resize(newCapacity);
if (resizeStatus != FudStatus::Success) {
return resizeStatus;
}
- fudAssert(m_capacity == newCapacity);
+ fudAssert(isLarge());
+ fudAssert(m_repr.large.capacity == newCapacity);
}
- auto copyStatus = copyMem(m_data + m_length, remainingLength(), letterData, letterSize);
+ auto copyStatus = copyMem(dataMut() + length(), remainingLength(), letterData, letterSize);
if (copyStatus != FudStatus::Success) {
return copyStatus;
}
- m_length += letterSize;
- dataMut()[m_length] = '\0';
+ addToLength(letterSize);
+ if (isLarge()) {
+ m_repr.large.data[m_repr.large.length] = '\0';
+ } else {
+ m_repr.small.buffer[m_repr.small.length] = '\0';
+ }
return FudStatus::Success;
}
@@ -416,21 +492,26 @@ FudStatus String::append(StringView source)
if (newSize < newLength) { // cppcheck-suppress knownConditionTrueFalse
return FudStatus::OperationInvalid;
}
- if (newSize >= m_capacity) {
+ if (newSize > capacity()) {
auto newCapacity = newSize < SIZE_MAX / 2 ? newSize * 2 : SIZE_MAX;
const auto resizeStatus = resize(newCapacity);
if (resizeStatus != FudStatus::Success) {
return resizeStatus;
}
- fudAssert(m_capacity == newCapacity);
+ fudAssert(isLarge());
+ fudAssert(m_repr.large.capacity == newCapacity);
}
auto* destPtr = dataMut() + length();
auto status = copyMem(destPtr, remainingLength(), source.data(), source.length());
fudAssert(status == FudStatus::Success);
- m_length += source.length();
- status = nullTerminate();
+ addToLength(source.length());
+ if (isLarge()) {
+ m_repr.large.data[m_repr.large.length] = '\0';
+ } else {
+ m_repr.small.buffer[m_repr.small.length] = '\0';
+ }
return status;
}
@@ -475,7 +556,7 @@ DrainResult String::drain(StringView source)
auto* destPtr = dataMut() + length();
auto status = copyMem(destPtr, remainingLength(), firstPart.m_data, firstPart.m_length);
fudAssert(status == FudStatus::Success);
- m_length += firstPart.m_length;
+ addToLength(firstPart.m_length);
result.bytesWritten += firstPart.m_length;
status = nullTerminate();
source.advanceUnsafe(firstPart.m_length);
@@ -496,23 +577,24 @@ DrainResult String::drain(StringView source)
result.status = FudStatus::OperationInvalid;
return result;
}
- if (newSize >= m_capacity) {
+ if (newSize > capacity()) {
auto newCapacity = newSize < SIZE_MAX / 2 ? newSize * 2 : SIZE_MAX;
const auto resizeStatus = resize(newCapacity);
if (resizeStatus != FudStatus::Success) {
result.status = resizeStatus;
return result;
}
- fudAssert(m_capacity == newCapacity);
+ fudAssert(isLarge());
+ fudAssert(m_repr.large.capacity == newCapacity);
}
auto* destPtr = dataMut() + length();
- auto status = copyMem(destPtr, remainingLength(), source.data(), source.length());
- fudAssert(status == FudStatus::Success);
+ result.status = copyMem(destPtr, remainingLength(), source.data(), source.length());
+ fudAssert(result.status == FudStatus::Success);
result.bytesWritten += source.length();
- m_length = newLength;
- status = nullTerminate();
+ setLength(newLength);
+ result.status = nullTerminate();
return result;
}
@@ -524,45 +606,46 @@ StringResult String::catenate(const char* rhs) const
}
auto lenResult = cStringLength(rhs);
- if (lenResult < 0 || lenResult >= SSIZE_MAX) {
+ if (lenResult < 0 || lenResult >= static_cast<ssize_t>(maxStringLength)) {
return StringResult::error(FudStatus::ArgumentInvalid);
}
size_t rhsLength = static_cast<size_t>(lenResult);
- String output{};
-
- if (SIZE_MAX - m_length < rhsLength) {
+ if (maxStringLength - length() < rhsLength) {
return StringResult::error(FudStatus::Failure);
}
- output.m_allocator = m_allocator;
-
- output.m_length = m_length + rhsLength;
- if (output.m_length > output.m_capacity) {
- output.m_capacity = output.m_length + 1;
- }
-
- if (!output.isLarge()) {
- auto status = copyMem(output.m_buffer.data(), output.m_capacity, data(), length());
- fudAssert(status == FudStatus::Success);
-
- status = copyMem(output.m_buffer.data() + length(), output.m_capacity - length(), rhs, rhsLength);
- fudAssert(status == FudStatus::Success);
+ size_t outputLength = rhsLength + length();
- auto terminateStatus = output.nullTerminate();
- fudAssert(terminateStatus == FudStatus::Success);
-
- return StringResult::okay(std::move(output));
+ String output{};
+ output.m_allocator = m_allocator;
+ size_t outputCapacity = outputLength + 1;
+ utf8* outputData{nullptr};
+ if (outputCapacity > SsoBufSize) {
+ output.m_repr.large.capacity = outputCapacity & largeStringCapacitymask;
+ output.m_repr.large.length = outputLength;
+ 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;
+ outputData = output.m_repr.large.data;
+ } else {
+ outputCapacity = 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>(outputLength) & smallStringLengthMask;
+ outputData = output.m_repr.small.buffer.data();
}
- output.m_data = static_cast<utf8*>(M_TakeOrReturn(output.allocator()->allocate(output.m_capacity)));
- fudAssert(output.m_data != nullptr);
+ fudAssert(outputData != nullptr);
- auto status = copyMem(output.m_data, m_capacity, data(), length());
- fudAssert(status == FudStatus::Success);
+ auto copyStatus = copyMem(outputData, outputCapacity, data(), length());
+ fudAssert(copyStatus == FudStatus::Success);
- status = copyMem(output.m_data + length(), output.m_capacity - length(), rhs, rhsLength);
- fudAssert(status == FudStatus::Success);
+ copyStatus = copyMem(outputData + length(), outputCapacity - length(), rhs, rhsLength);
+ fudAssert(copyStatus == FudStatus::Success);
auto terminateStatus = output.nullTerminate();
fudAssert(terminateStatus == FudStatus::Success);
@@ -576,29 +659,37 @@ StringResult String::catenate(const String& rhs) const
return StringResult::error(FudStatus::ArgumentInvalid);
}
- if (SIZE_MAX - m_length < rhs.length()) {
+ if (maxStringLength - length() < rhs.length()) {
return StringResult::error(FudStatus::Failure);
}
String output{};
output.m_allocator = m_allocator;
- output.m_length = m_length + rhs.length();
- output.m_capacity = output.m_length + 1;
-
- if (output.m_capacity < SSO_BUF_SIZE) {
- output.m_capacity = SSO_BUF_SIZE;
- }
-
- if (output.isLarge()) {
- output.m_data = static_cast<utf8*>(M_TakeOrReturn(output.allocator()->allocate(output.m_capacity)));
- fudAssert(output.m_data != nullptr);
+ size_t outputLength = length() + rhs.length();
+ size_t outputCapacity = outputLength + 1;
+ utf8* outputData{nullptr};
+ if (outputCapacity > SsoBufSize) {
+ output.m_repr.large.capacity = outputCapacity & largeStringCapacitymask;
+ output.m_repr.large.length = outputLength;
+ 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;
+ outputData = output.m_repr.large.data;
+ } else {
+ outputCapacity = 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>(outputLength) & smallStringLengthMask;
+ outputData = output.m_repr.small.buffer.data();
}
- auto* destPtr = output.dataMut();
- auto status = copyMem(destPtr, m_capacity, data(), length());
+ auto status = copyMem(outputData, outputCapacity, data(), length());
fudAssert(status == FudStatus::Success);
- status = copyMem(destPtr + length(), output.m_capacity - length(), rhs.data(), rhs.length());
+ status = copyMem(outputData + length(), outputCapacity - length(), rhs.data(), rhs.length());
fudAssert(status == FudStatus::Success);
auto terminateStatus = output.nullTerminate();
@@ -629,13 +720,14 @@ bool String::compare(const String& rhs) const
return diffResult.getOkay() == 0;
}
-FudStatus String::clear() {
+FudStatus String::clear()
+{
if (!valid()) {
return FudStatus::StringInvalid;
}
dataMut()[0] = '\0';
- m_length = 0;
+ setLength(0);
return FudStatus::Success;
}