summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorDominick Allen <djallen@librehumanitas.org>2024-11-03 09:28:13 -0600
committerDominick Allen <djallen@librehumanitas.org>2024-11-03 09:28:13 -0600
commitc3fe2de828576900021d27a52114ebdb0a4cb6f0 (patch)
tree34d15165765e15894e2bedbc065081ee1d27ec06 /source
parente8422002f84dc4313894a5b3136c44a9005081fd (diff)
Factor out growth of String and make it scale by 1.5x.
Diffstat (limited to 'source')
-rw-r--r--source/fud_string.cpp71
1 files changed, 56 insertions, 15 deletions
diff --git a/source/fud_string.cpp b/source/fud_string.cpp
index 4dddedb..33e41c3 100644
--- a/source/fud_string.cpp
+++ b/source/fud_string.cpp
@@ -327,6 +327,42 @@ FudStatus String::nullTerminate()
return FudStatus::StringInvalid;
}
+FudStatus String::grow()
+{
+ auto cap = capacity();
+ if (cap >= maxStringLength) {
+ return FudStatus::Full;
+ }
+ size_t additional = cap / 2;
+ if (maxStringLength - additional < cap) {
+ additional = maxStringLength - cap;
+ }
+
+ FudStatus reserveStatus{};
+ while (additional > 0) {
+ reserveStatus = reserve(additional + cap);
+ if (reserveStatus == FudStatus::Success) {
+ break;
+ }
+ if (reserveStatus == FudStatus::AllocFailure) {
+ additional /= 2;
+ } else {
+ return reserveStatus;
+ }
+ }
+ if (reserveStatus != FudStatus::Success) {
+ return reserveStatus;
+ }
+
+ auto newCapacity = cap < maxStringLength / 2 ? cap * 2 : maxStringLength - 1U;
+ const auto resizeStatus = resize(newCapacity);
+ if (resizeStatus != FudStatus::Success) {
+ return resizeStatus;
+ }
+ fudAssert(isLarge());
+ fudAssert(m_repr.large.capacity == newCapacity);
+}
+
FudStatus String::reserve(size_t newCapacity)
{
if (!valid()) {
@@ -391,15 +427,12 @@ FudStatus String::pushBack(utf8 letter)
return FudStatus::StringInvalid;
}
- if (remainingLength() < 1) {
- auto cap = capacity() + 1U;
- auto newCapacity = cap < maxStringLength / 2 ? cap * 2 : maxStringLength - 1U;
- const auto resizeStatus = resize(newCapacity);
- if (resizeStatus != FudStatus::Success) {
- return resizeStatus;
+ if (remainingCapacity() < 1) {
+ auto growStatus = grow();
+ if (growStatus != FudStatus::Success) {
+ return growStatus;
}
fudAssert(isLarge());
- fudAssert(m_repr.large.capacity == newCapacity);
}
if (isLarge()) {
@@ -431,7 +464,15 @@ FudStatus String::pushBack(const FudUtf8& letter)
}
auto letterSize = letter.size();
- if (remainingLength() < letterSize) {
+ if (remainingCapacity() < letterSize) {
+ auto growStatus = grow();
+ if (growStatus != FudStatus::Success) {
+ return growStatus;
+ }
+ fudAssert(isLarge());
+ }
+
+ if (remainingCapacity() < letterSize) {
auto cap = capacity() + 1U;
auto newCapacity = cap < maxStringLength / 2 ? cap * 2 : maxStringLength - 1U;
if ((newCapacity - cap) < (letterSize + 1)) {
@@ -445,7 +486,7 @@ FudStatus String::pushBack(const FudUtf8& letter)
fudAssert(m_repr.large.capacity == newCapacity);
}
- auto copyStatus = copyMem(dataMut() + length(), remainingLength(), letterData, letterSize);
+ auto copyStatus = copyMem(dataMut() + length(), remainingCapacity(), letterData, letterSize);
if (copyStatus != FudStatus::Success) {
return copyStatus;
@@ -506,7 +547,7 @@ FudStatus String::append(StringView source)
}
auto* destPtr = dataMut() + length();
- auto status = copyMem(destPtr, remainingLength(), source.data(), source.length());
+ auto status = copyMem(destPtr, remainingCapacity(), source.data(), source.length());
fudAssert(status == FudStatus::Success);
addToLength(source.length());
@@ -551,13 +592,13 @@ DrainResult String::drain(StringView source)
return result;
}
- if (remainingLength() > 0) {
+ if (remainingCapacity() > 0) {
StringView firstPart{source};
- if (source.length() > remainingLength()) {
- firstPart.m_length = remainingLength();
+ if (source.length() > remainingCapacity()) {
+ firstPart.m_length = remainingCapacity();
}
auto* destPtr = dataMut() + length();
- auto status = copyMem(destPtr, remainingLength(), firstPart.m_data, firstPart.m_length);
+ auto status = copyMem(destPtr, remainingCapacity(), firstPart.m_data, firstPart.m_length);
fudAssert(status == FudStatus::Success);
addToLength(firstPart.m_length);
result.bytesDrained += firstPart.m_length;
@@ -592,7 +633,7 @@ DrainResult String::drain(StringView source)
}
auto* destPtr = dataMut() + length();
- result.status = copyMem(destPtr, remainingLength(), source.data(), source.length());
+ result.status = copyMem(destPtr, remainingCapacity(), source.data(), source.length());
fudAssert(result.status == FudStatus::Success);
result.bytesDrained += source.length();