summaryrefslogtreecommitdiff
path: root/include/fud_string.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/fud_string.hpp')
-rw-r--r--include/fud_string.hpp79
1 files changed, 73 insertions, 6 deletions
diff --git a/include/fud_string.hpp b/include/fud_string.hpp
index 1939c7d..6880cb7 100644
--- a/include/fud_string.hpp
+++ b/include/fud_string.hpp
@@ -18,6 +18,8 @@
#ifndef FUD_STRING_HPP
#define FUD_STRING_HPP
+#include "fud_assert.hpp"
+#include "fud_result.hpp"
#include "fud_status.hpp"
#include "fud_string_view.hpp"
#include "fud_utf8.hpp"
@@ -32,13 +34,77 @@ namespace fud {
constexpr size_t SSO_BUF_LENGTH = 15;
constexpr size_t SSO_BUF_SIZE = SSO_BUF_LENGTH + 1;
+using StringResult = Result<String, FudStatus>;
+
class String {
public:
- String() = default;
- explicit String(const utf8* cString);
- explicit String(const char* cString);
+ static StringResult makeFromCString(const char* cString);
+
+ static StringResult makeFromUtf8(const utf8* utf8String);
+
+ template <typename... Strings>
+ static StringResult makeFromCString(Strings... cStrings)
+ {
+ size_t totalLength = 0;
+ Array<size_t, sizeof...(cStrings)> lengths{};
+ Array<const char*, sizeof...(cStrings)> strPointers{};
+ size_t index = 0;
+ for (const auto* cStringItem: {cStrings...}) {
+ // for (size_t index = 0; index < strPointers.size(); ++index) {
+ // const auto* cString = strPointers[index];
+ const char* cString = nullptr;
+ if constexpr (std::is_same_v<decltype(cStringItem), const char*>) {
+ cString = cStringItem;
+ } else if constexpr (std::is_same_v<decltype(cStringItem), const utf8*>) {
+ cString = reinterpret_cast<const char*>(cStringItem);
+ } else {
+ static_assert(!std::is_same_v<decltype(cStringItem), const char*>);
+ }
+ strPointers[index] = cString;
+
+ auto lengthResult = cStringLength(cString);
+ if (lengthResult < 0 || lengthResult >= SSIZE_MAX) {
+ return StringResult::error(FudStatus::InvalidInput);
+ }
+ auto stringLength = static_cast<size_t>(lengthResult);
+ if (SIZE_MAX - totalLength < stringLength) {
+ return StringResult::error(FudStatus::Failure);
+ }
+ totalLength += stringLength;
+ lengths[index] = stringLength;
+ index++;
+ }
+
+ String output{};
+ auto* data = output.m_buffer.data();
+ output.m_length = totalLength;
+ 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;
+ }
+
+ size_t cumulativeLength = 0;
+ for (size_t idx = 0; idx < strPointers.size(); ++idx) {
+ const auto* cString = strPointers[idx];
+ auto copyStatus = copyMem(data, output.m_capacity - cumulativeLength, cString, lengths[idx]);
+ fudAssert(copyStatus == FudStatus::Success);
+ cumulativeLength += lengths[idx];
+ }
+
+ auto terminateStatus = output.nullTerminate();
+ fudAssert(terminateStatus == FudStatus::Success);
+
+ return StringResult::okay(std::move(output));
+ }
+
+ String() noexcept = default;
String(const String& rhs);
String(String&& rhs) noexcept;
+
~String();
String& operator=(const String& rhs);
@@ -109,7 +175,8 @@ class String {
return m_capacity - 1U - m_length;
}
- [[nodiscard]] inline StringView asView() const {
+ [[nodiscard]] inline StringView asView() const
+ {
return StringView(*this);
}
@@ -127,9 +194,9 @@ class String {
FudStatus append(StringView source);
- [[nodiscard]] String catenate(const String& rhs) const;
+ [[nodiscard]] StringResult catenate(const String& rhs) const;
- [[nodiscard]] String catenate(const char* rhs) const;
+ [[nodiscard]] StringResult catenate(const char* rhs) const;
[[nodiscard]] bool compare(const String& rhs) const;