diff options
author | Dominick Allen <djallen@librehumanitas.org> | 2024-11-03 09:28:13 -0600 |
---|---|---|
committer | Dominick Allen <djallen@librehumanitas.org> | 2024-11-03 09:28:13 -0600 |
commit | c3fe2de828576900021d27a52114ebdb0a4cb6f0 (patch) | |
tree | 34d15165765e15894e2bedbc065081ee1d27ec06 /source | |
parent | e8422002f84dc4313894a5b3136c44a9005081fd (diff) |
Factor out growth of String and make it scale by 1.5x.
Diffstat (limited to 'source')
-rw-r--r-- | source/fud_string.cpp | 71 |
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(); |