diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-26 01:42:18 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-26 01:42:18 +1000 |
commit | 09d26d43b5262f480fd55eab9980eff06a71edbb (patch) | |
tree | 1e53765861cd966d204782aeefd15b1a67b3266f /source/core/StarStringView.cpp | |
parent | 13a74602bd4c46149da9949d448387a40b8ebd1c (diff) |
Add string view variant of Star::String and use it
it's 1:30 AM AGAIN !! !!!!!
This might have broken the inventory icons of custom hats a little, need to look into that
Diffstat (limited to 'source/core/StarStringView.cpp')
-rw-r--r-- | source/core/StarStringView.cpp | 429 |
1 files changed, 429 insertions, 0 deletions
diff --git a/source/core/StarStringView.cpp b/source/core/StarStringView.cpp new file mode 100644 index 0000000..1bea5e5 --- /dev/null +++ b/source/core/StarStringView.cpp @@ -0,0 +1,429 @@ +#include "StarStringView.hpp" + +namespace Star { +// To string +String::String(StringView s) : m_string(s.utf8()) {} +String::String(std::string_view s) : m_string(s) {} + +String& String::operator+=(StringView s) { + m_string += s.utf8(); + return *this; +} + +String& String::operator+=(std::string_view s) { + m_string += s; + return *this; +} + +StringView::StringView() {} +StringView::StringView(StringView const& s) : m_view(s.m_view) {} +StringView::StringView(StringView&& s) noexcept : m_view(move(s.m_view)) {}; +StringView::StringView(String const& s) : m_view(s.utf8()) {}; +StringView::StringView(char const* s) : m_view(s) {}; +StringView::StringView(char const* s, size_t n) : m_view(s, n) {}; + +StringView::StringView(std::string_view const& s) : m_view(s) {}; +StringView::StringView(std::string_view&& s) noexcept : m_view(move(s)) {}; +StringView::StringView(std::string const& s) : m_view(s) {} + +StringView::StringView(Char const* s) : m_view((char const*)s, sizeof(*s)) {} +StringView::StringView(Char const* s, size_t n) : m_view((char const*)s, n * sizeof(*s)) {}; + +std::string_view const& StringView::utf8() const { + return m_view; +} + +std::string_view StringView::takeUtf8() { + return take(m_view); +} + +ByteArray StringView::utf8Bytes() const { + return ByteArray(m_view.data(), m_view.size()); +} + +char const* StringView::utf8Ptr() const { + return m_view.data(); +} + +size_t StringView::utf8Size() const { + return m_view.size(); +} + +StringView::const_iterator StringView::begin() const { + return const_iterator(m_view.begin()); +} + +StringView::const_iterator StringView::end() const { + return const_iterator(m_view.end()); +} + +size_t StringView::size() const { + return utf8Length(m_view.data(), m_view.size()); +} + +size_t StringView::length() const { + return size(); +} + +bool StringView::empty() const { + return m_view.empty(); +} + +StringView::Char StringView::operator[](size_t index) const { + auto it = begin(); + for (size_t i = 0; i < index; ++i) + ++it; + return *it; +} + +StringView::Char StringView::at(size_t i) const { + if (i > size()) + throw OutOfRangeException(strf("Out of range in StringView::at(%s)", i)); + return operator[](i); +} + +bool StringView::endsWith(StringView end, CaseSensitivity cs) const { + auto endsize = end.size(); + if (endsize == 0) + return true; + + auto mysize = size(); + if (endsize > mysize) + return false; + + return compare(mysize - endsize, NPos, end, 0, NPos, cs) == 0; +} +bool StringView::endsWith(Char end, CaseSensitivity cs) const { + if (size() == 0) + return false; + + return String::charEqual(end, operator[](size() - 1), cs); +} + +bool StringView::beginsWith(StringView beg, CaseSensitivity cs) const { + auto begSize = beg.size(); + if (begSize == 0) + return true; + + auto mysize = size(); + if (begSize > mysize) + return false; + + return compare(0, begSize, beg, 0, NPos, cs) == 0; +} + +bool StringView::beginsWith(Char beg, CaseSensitivity cs) const { + if (size() == 0) + return false; + + return String::charEqual(beg, operator[](0), cs); +} + +void StringView::forEachSplitAnyView(StringView chars, SplitCallback callback) const { + if (chars.empty()) + return; + + size_t beg = 0; + while (true) { + size_t end = m_view.find_first_of(chars.m_view, beg); + if (end == NPos) { + callback(m_view.substr(beg), beg, end); + break; + } + callback(m_view.substr(beg, end - beg), beg, end - beg); + beg = end + 1; + } +} + +void StringView::forEachSplitView(StringView pattern, SplitCallback callback) const { + if (pattern.empty()) + return; + + size_t beg = 0; + while (true) { + size_t end = m_view.find(pattern.m_view, beg); + if (end == NPos) { + callback(m_view.substr(beg), beg, end); + break; + } + callback(m_view.substr(beg, end - beg), beg, end - beg); + beg = end + pattern.m_view.size(); + } +} + +bool StringView::hasChar(Char c) const { + for (Char ch : *this) + if (ch == c) + return true; + return false; +} + +bool StringView::hasCharOrWhitespace(Char c) const { + return empty() ? String::isSpace(c) : hasChar(c); +} + +size_t StringView::find(Char c, size_t pos, CaseSensitivity cs) const { + auto it = begin(); + for (size_t i = 0; i < pos; ++i) { + if (it == end()) + break; + ++it; + } + + while (it != end()) { + if (String::charEqual(c, *it, cs)) + return pos; + ++pos; + ++it; + } + + return NPos; +} + +size_t StringView::find(StringView str, size_t pos, CaseSensitivity cs) const { + if (str.empty()) + return 0; + + auto it = begin(); + for (size_t i = 0; i < pos; ++i) { + if (it == end()) + break; + ++it; + } + + const_iterator sit = str.begin(); + const_iterator mit = it; + while (it != end()) { + if (String::charEqual(*sit, *mit, cs)) { + do { + ++mit; + ++sit; + if (sit == str.end()) + return pos; + else if (mit == end()) + break; + } while (String::charEqual(*sit, *mit, cs)); + sit = str.begin(); + } + ++pos; + mit = ++it; + } + + return NPos; +} + +size_t StringView::findLast(Char c, CaseSensitivity cs) const { + auto it = begin(); + + size_t found = NPos; + size_t pos = 0; + while (it != end()) { + if (String::charEqual(c, *it, cs)) + found = pos; + ++pos; + ++it; + } + + return found; +} + +size_t StringView::findLast(StringView str, CaseSensitivity cs) const { + if (str.empty()) + return 0; + + size_t pos = 0; + auto it = begin(); + size_t result = NPos; + const_iterator sit = str.begin(); + const_iterator mit = it; + while (it != end()) { + if (String::charEqual(*sit, *mit, cs)) { + do { + ++mit; + ++sit; + if (sit == str.end()) { + result = pos; + break; + } + if (mit == end()) + break; + } while (String::charEqual(*sit, *mit, cs)); + sit = str.begin(); + } + ++pos; + mit = ++it; + } + + return result; +} + +size_t StringView::findFirstOf(StringView pattern, size_t beg) const { + auto it = begin(); + size_t i; + for (i = 0; i < beg; ++i) + ++it; + + while (it != end()) { + if (pattern.hasCharOrWhitespace(*it)) + return i; + ++it; + ++i; + } + return NPos; +} + +size_t StringView::findFirstNotOf(StringView pattern, size_t beg) const { + auto it = begin(); + size_t i; + for (i = 0; i < beg; ++i) + ++it; + + while (it != end()) { + if (!pattern.hasCharOrWhitespace(*it)) + return i; + ++it; + ++i; + } + return NPos; +} + +size_t StringView::findNextBoundary(size_t index, bool backwards) const { + starAssert(index <= size()); + if (!backwards && (index == size())) + return index; + if (backwards) { + if (index == 0) + return 0; + index--; + } + Char c = this->at(index); + while (!String::isSpace(c)) { + if (backwards && (index == 0)) + return 0; + index += backwards ? -1 : 1; + if (index == size()) + return size(); + c = this->at(index); + } + while (String::isSpace(c)) { + if (backwards && (index == 0)) + return 0; + index += backwards ? -1 : 1; + if (index == size()) + return size(); + c = this->at(index); + } + if (backwards && !(index == size())) + return index + 1; + return index; +} + +bool StringView::contains(StringView s, CaseSensitivity cs) const { + return find(s, 0, cs) != NPos; +} + +int StringView::compare(StringView s, CaseSensitivity cs) const { + if (cs == CaseSensitivity::CaseSensitive) + return m_view.compare(s.m_view); + else + return compare(0, NPos, s, 0, NPos, cs); +} + +bool StringView::equals(StringView s, CaseSensitivity cs) const { + return compare(s, cs) == 0; +} + +bool StringView::equalsIgnoreCase(StringView s) const { + return compare(s, CaseSensitivity::CaseInsensitive) == 0; +} + +StringView StringView::substr(size_t position, size_t n) const { + auto len = size(); + if (position > len) + throw OutOfRangeException(strf("out of range in StringView::substr(%s, %s)", position, n)); + + if (position == 0 && n >= len) + return *this; + + String ret; + ret.reserve(std::min(n, len - position)); + + auto it = begin(); + std::advance(it, position); + + for (size_t i = 0; i < n; ++i) { + if (it == end()) + break; + ret.append(*it); + ++it; + } + + return ret; +} + +int StringView::compare(size_t selfOffset, size_t selfLen, StringView other, + size_t otherOffset, size_t otherLen, CaseSensitivity cs) const { + auto selfIt = begin(); + auto otherIt = other.begin(); + + while (selfOffset > 0 && selfIt != end()) { + ++selfIt; + --selfOffset; + } + + while (otherOffset > 0 && otherIt != other.end()) { + ++otherIt; + --otherLen; + } + + while (true) { + if ((selfIt == end() || selfLen == 0) && (otherIt == other.end() || otherLen == 0)) + return 0; + else if (selfIt == end() || selfLen == 0) + return -1; + else if (otherIt == other.end() || otherLen == 0) + return 1; + + auto c1 = *selfIt; + auto c2 = *otherIt; + + if (cs == CaseSensitivity::CaseInsensitive) { + c1 = String::toLower(c1); + c2 = String::toLower(c2); + } + + if (c1 < c2) + return -1; + else if (c2 < c1) + return 1; + + ++selfIt; + ++otherIt; + --selfLen; + --otherLen; + } +} + +StringView& StringView::operator=(StringView s) { + m_view = s.m_view; + return *this; +} + +bool operator==(StringView s1, StringView s2) { + return s1.m_view == s2.m_view; +} + +bool operator!=(StringView s1, StringView s2) { + return s1.m_view != s2.m_view; +} + +bool operator<(StringView s1, StringView s2) { + return s1.m_view < s2.m_view; +} + +std::ostream& operator<<(std::ostream& os, StringView& s) { + os << s.utf8(); + return os; +} + +}
\ No newline at end of file |