diff --git a/Include/auROXTL/auStringUtils.hpp b/Include/auROXTL/auStringUtils.hpp index d5caa1e..40ff96a 100644 --- a/Include/auROXTL/auStringUtils.hpp +++ b/Include/auROXTL/auStringUtils.hpp @@ -19,7 +19,8 @@ AuCodepointsContains, AuCodepointsReplaceAll, AuCodepointsSplitString (views), AuCodepointsFindPreviousValidByteOffsetFromOffset, AuCodepointsFindPreviousValidByteOffsetFromByteOffset - AuCodepointsIsEqualIgnoreCase + AuCodepointsIsEqualIgnoreCase, AuCodepointsStartsWithEqualIgnoreCase, AuCodepointsEndsWithEqualIgnoreCase, + AuCodepointsReverseIterate, AuCodepointsReverseIterateSubStrPrefixView, AuCodepointsReverseIterateSubStrSuffixView For translating between locales (including utf8-32), defer to AuLocale (Aurora::Locale) in the Aurora Runtime. ***/ @@ -1307,6 +1308,168 @@ static CodepointOffset_t AuCodepointsFindCodepointOffset(const AuROString &in, return AuROString::npos; } +static bool AuCodepointsStartsWithEqualIgnoreCase(const AuROString &inA, + const AuROString &inB) +{ + if (inA.size() < inB.size()) + { + return false; + } + + if (inA.empty() || + inB.empty()) + { + return true; + } + + const char *pItr = inA.data(); + const char *pItr2 = inB.data(); + const char *pEnd = pItr + inB.length(); + + while (pItr < pEnd) + { + AuUInt32 c {}; + + if ((c = *pItr) <= 0x7FU) + { + if (AuToLower(c) != AuToLower(*pItr2)) + { + return false; + } + ++pItr2; + ++pItr; + } + else + { + AuUInt32 nby {}; + + if ((*pItr & 0xC0U) != 0xC0U) + { + return AuMemcmp(pItr, pItr2, pEnd - pItr) == 0; + } + + for (AuUInt8 b = *pItr; (b & 0x80U) != 0; b <<= 1, ++nby) + { + } + + if (nby > kAuCodepointUTF8MaxBytes) + { + return AuMemcmp(pItr, pItr2, pEnd - pItr) == 0; + } + + if (AuUInt(pEnd - pItr) < AuUInt(nby)) + { + return AuMemcmp(pItr, pItr2, pEnd - pItr) == 0; + } + + if (AuMemcmp(pItr, pItr2, nby) != 0) + { + return false; + } + + pItr += nby; + pItr2 += nby; + } + } + + return true; +} + +static bool AuCodepointsEndsWithEqualIgnoreCase(const AuROString &inA, + const AuROString &inB) +{ + if (inA.size() < inB.size()) + { + return false; + } + + if (inA.empty() || + inB.empty()) + { + return true; + } + + AuUInt uOffset { inA.Size() }; + AuUInt uOffset2 { inB.Size() }; + + while (uOffset && uOffset2) + { + AuUInt32 c {}; + + auto uLastValid = AuCodepointsFindPreviousValidByteOffsetFromByteOffset(inB, uOffset2); + if (uLastValid == AuROString::npos) + { + return false; + } + + auto nby = uOffset2 - uLastValid; + + if (AuSInt(uOffset) - AuSInt(nby) < 0) + { + return false; + } + + auto pItr = inA.data() + uOffset - nby; + auto pItr2 = inB.data() + uOffset2 - nby; + + if ((c = *pItr) <= 0x7FU) + { + if (AuToLower(c) != AuToLower(*pItr2)) + { + return false; + } + + uOffset -= 1; + uOffset2 -= 1; + } + else + { + if (AuMemcmp(pItr, pItr2, nby) != 0) + { + return false; + } + + uOffset -= nby; + uOffset2 -= nby; + } + } + + return true; +} + +static AuUInt AuCodepointsReverseIterate(const AuROString &string) +{ + auto uLastValid = AuCodepointsFindPreviousValidByteOffsetFromByteOffset(string, string.Size()); + if (uLastValid == AuROString::npos) + { + return AuROString::npos; + } + + return string.Size() - uLastValid; +} + +static AuROString AuCodepointsReverseIterateSubStrPrefixView(const AuROString &string) +{ + auto uOffset = AuCodepointsReverseIterate(string); + if (uOffset == AuROString::npos) + { + return AuROString {}; + } + + return string.RemoveSuffix(uOffset); +} + +static AuROString AuCodepointsReverseIterateSubStrSuffixView(const AuROString &string) +{ + auto uLastValid = AuCodepointsFindPreviousValidByteOffsetFromByteOffset(string, string.Size()); + if (uLastValid == AuROString::npos) + { + return AuROString {}; + } + + return string.RemovePrefix(uLastValid); +} + static bool AuCodepointsContains(const AuROString &value, const AuROString &subpattern, CodepointOffset_t uStartPosition = {}) { return AuCodepointsFindCodepointOffset(value, subpattern, uStartPosition) != AuROString::npos; diff --git a/Include/auROXTL/auUTF8StringView.hpp b/Include/auROXTL/auUTF8StringView.hpp index 8f14ebb..9ee9380 100644 --- a/Include/auROXTL/auUTF8StringView.hpp +++ b/Include/auROXTL/auUTF8StringView.hpp @@ -155,7 +155,31 @@ struct AuROString return AuROString { this->pPointer + pos1, count1 }; } - inline constexpr AuROString remove_suffix(size_type n) + inline constexpr void stl_remove_suffix(size_type n) + { + if (this->uLength < n) + { + *this = AuROString { }; + } + else + { + *this = AuROString { this->pPointer, this->uLength - n }; + } + } + + inline constexpr void stl_remove_prefix(size_type n) + { + if (this->uLength < n) + { + *this = AuROString { }; + } + else + { + *this = AuROString { this->pPointer + n, this->uLength - n }; + } + } + + inline constexpr AuROString remove_suffix(size_type n) const { if (this->uLength < n) { @@ -165,7 +189,7 @@ struct AuROString return AuROString { this->pPointer, this->uLength - n }; } - inline constexpr AuROString remove_prefix(size_type n) + inline constexpr AuROString remove_prefix(size_type n) const { if (this->uLength < n) { @@ -175,12 +199,12 @@ struct AuROString return AuROString { this->pPointer + n, this->uLength - n }; } - inline constexpr AuROString RemoveSuffix(size_type n) + inline constexpr AuROString RemoveSuffix(size_type n) const { return remove_suffix(n); } - inline constexpr AuROString RemovePrefix(size_type n) + inline constexpr AuROString RemovePrefix(size_type n) const { return remove_prefix(n); } @@ -520,6 +544,11 @@ struct AuROString return this->substr(pos1, count1); } + inline constexpr AuROString SubStr(size_type pos1, size_type count1 = npos) const noexcept + { + return this->substr(pos1, count1); + } + inline constexpr int Compare(basic_string_view v) const noexcept { return this->compare(v); @@ -1201,6 +1230,11 @@ struct AuRONString return this->substr(pos1, count1); } + inline constexpr AuROString SubStr(size_type pos1, size_type count1 = npos) const noexcept + { + return this->substr(pos1, count1); + } + inline constexpr int Compare(AuROString v) const noexcept { return this->compare(v);