diff options
Diffstat (limited to 'source/fud_string.cpp')
-rw-r--r-- | source/fud_string.cpp | 113 |
1 files changed, 80 insertions, 33 deletions
diff --git a/source/fud_string.cpp b/source/fud_string.cpp index 3a9aca0..82a9fe5 100644 --- a/source/fud_string.cpp +++ b/source/fud_string.cpp @@ -46,30 +46,37 @@ ssize_t cStringLength(const char* str, size_t maxLength) return size; } -// NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast) -String::String(const utf8* cString) : String(reinterpret_cast<const char*>(cString)) -{ -} -// NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast) - -String::String(const char* cString) +StringResult String::makeFromCString(const char* cString) { auto lenResult = cStringLength(cString); if (lenResult < 0 || lenResult >= SSIZE_MAX) { - m_length = 1; - m_capacity = 0; - } else if (static_cast<size_t>(lenResult) < SSO_BUF_SIZE) { - m_length = static_cast<size_t>(lenResult); - fudAssert(copyMem(m_buffer.data(), m_buffer.size(), cString, m_length) == FudStatus::Success); - fudAssert(nullTerminate() == FudStatus::Success); - } else { - m_length = static_cast<size_t>(lenResult); - m_capacity = m_length + 1; - m_data = static_cast<utf8*>(fudAlloc(m_capacity)); - fudAssert(m_data != nullptr); - fudAssert(copyMem(m_data, m_capacity, cString, m_length) == FudStatus::Success); - fudAssert(nullTerminate() == FudStatus::Success); + return StringResult::error(FudStatus::InvalidInput); + } + + String output{}; + auto* data = output.m_buffer.data(); + output.m_length = static_cast<size_t>(lenResult); + if (output.m_length >= output.m_capacity) { + output.m_capacity = output.m_length + 1; + data = static_cast<utf8*>(fudAlloc(output.m_capacity)); + if (data == nullptr) { + return StringResult::error(FudStatus::AllocFailure); + } + output.m_data = data; } + auto copyStatus = copyMem(data, output.m_capacity, cString, output.m_length); + fudAssert(copyStatus == FudStatus::Success); + auto terminateStatus = output.nullTerminate(); + fudAssert(terminateStatus == FudStatus::Success); + + return StringResult::okay(std::move(output)); +} + +StringResult String::makeFromUtf8(const utf8* utf8String) +{ + // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast) + return makeFromCString(reinterpret_cast<const char*>(utf8String)); + // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast) } String::String(const String& rhs) : m_length{rhs.m_length}, m_capacity{rhs.m_capacity} @@ -364,7 +371,7 @@ FudStatus String::append(StringView source) return FudStatus::OperationInvalid; } const size_t newSize = newLength + 1; // cppcheck-suppress knownConditionTrueFalse - if (newSize < newLength) { // cppcheck-suppress knownConditionTrueFalse + if (newSize < newLength) { // cppcheck-suppress knownConditionTrueFalse return FudStatus::OperationInvalid; } if (newSize >= m_capacity) { @@ -386,22 +393,60 @@ FudStatus String::append(StringView source) return status; } -String String::catenate(const char* rhs) const +StringResult String::catenate(const char* rhs) const { - String rhsString{rhs}; - return catenate(rhsString); -} + if (!valid()) { + return StringResult::error(FudStatus::InvalidInput); + } + + auto lenResult = cStringLength(rhs); + if (lenResult < 0 || lenResult >= SSIZE_MAX) { + return StringResult::error(FudStatus::InvalidInput); + } + size_t rhsLength = static_cast<size_t>(lenResult); -String String::catenate(const String& rhs) const -{ String output{}; - output.m_length = 1; - output.m_capacity = 0; + if (SIZE_MAX - m_length < rhsLength) + { + return StringResult::error(FudStatus::Failure); + } + + output.m_length = m_length + rhsLength; + auto* destPtr = output.m_buffer.data(); + if (output.m_length >= output.m_capacity) { + output.m_capacity = output.m_length + 1; + destPtr = static_cast<utf8*>(fudAlloc(output.m_capacity)); + if (destPtr == nullptr) { + return StringResult::error(FudStatus::AllocFailure); + } + output.m_data = destPtr; + } + + auto status = copyMem(destPtr, m_capacity, data(), length()); + fudAssert(status == FudStatus::Success); + + status = copyMem(destPtr + length(), output.m_capacity - length(), rhs, rhsLength); + fudAssert(status == FudStatus::Success); + + auto terminateStatus = output.nullTerminate(); + fudAssert(terminateStatus == FudStatus::Success); + + return StringResult::okay(std::move(output)); +} + +StringResult String::catenate(const String& rhs) const +{ if (!valid() || !rhs.valid()) { - return output; + return StringResult::error(FudStatus::InvalidInput); } + if (SIZE_MAX - m_length < rhs.length()) + { + return StringResult::error(FudStatus::Failure); + } + + String output{}; output.m_length = m_length + rhs.length(); output.m_capacity = output.m_length + 1; if (output.m_capacity < SSO_BUF_SIZE) { @@ -414,12 +459,14 @@ String String::catenate(const String& rhs) const auto* destPtr = output.data(); auto status = copyMem(destPtr, m_capacity, data(), length()); fudAssert(status == FudStatus::Success); + status = copyMem(destPtr + length(), output.m_capacity - length(), rhs.data(), rhs.length()); fudAssert(status == FudStatus::Success); - static_cast<void>(status); - fudAssert(output.nullTerminate() == FudStatus::Success); - return output; + auto terminateStatus = output.nullTerminate(); + fudAssert(terminateStatus == FudStatus::Success); + + return StringResult::okay(std::move(output)); } bool String::compare(const String& rhs) const |