Core/StringExt: Add overloads of EndsWith

This commit is contained in:
Lynix 2022-03-19 14:19:52 +01:00
parent b97f1a4c41
commit cf5e4b72e1
3 changed files with 107 additions and 2 deletions

View File

@ -21,6 +21,9 @@ namespace Nz
NAZARA_CORE_API std::size_t ComputeCharacterCount(const std::string_view& str);
inline bool EndsWith(const std::string_view& str, const std::string_view& s);
NAZARA_CORE_API bool EndsWith(const std::string_view& lhs, const std::string_view& rhs, CaseIndependent);
NAZARA_CORE_API bool EndsWith(const std::string_view& lhs, const std::string_view& rhs, UnicodeAware);
NAZARA_CORE_API bool EndsWith(const std::string_view& lhs, const std::string_view& rhs, CaseIndependent, UnicodeAware);
NAZARA_CORE_API std::string FromUtf16String(const std::u16string_view& u16str);
NAZARA_CORE_API std::string FromUtf32String(const std::u32string_view& u32str);

View File

@ -96,6 +96,67 @@ namespace Nz
{
return utf8::distance(str.data(), str.data() + str.size());
}
bool EndsWith(const std::string_view& lhs, const std::string_view& rhs, CaseIndependent)
{
NAZARA_USE_ANONYMOUS_NAMESPACE
if (rhs.size() > lhs.size())
return false;
return std::equal(lhs.end() - rhs.size(), lhs.end(), rhs.begin(), rhs.end(), [](char c1, char c2)
{
return ToLower(c1) == ToLower(c2);
});
}
bool EndsWith(const std::string_view& lhs, const std::string_view& rhs, UnicodeAware)
{
if (lhs.empty())
return lhs == rhs;
else if (rhs.empty())
return true;
utf8::iterator<const char*> it(lhs.data() + lhs.size() - rhs.size(), lhs.data() + lhs.size() - rhs.size(), lhs.data() + lhs.size());
utf8::iterator<const char*> it2(rhs.data(), rhs.data(), rhs.data() + rhs.size());
do
{
if (it2.base() >= rhs.data() + rhs.size())
return true;
if (*it != *it2)
return false;
++it2;
}
while (*it++);
return true;
}
bool EndsWith(const std::string_view& lhs, const std::string_view& rhs, CaseIndependent, UnicodeAware)
{
if (lhs.empty())
return lhs == rhs;
else if (rhs.empty())
return true;
utf8::iterator<const char*> it(lhs.data() + lhs.size() - rhs.size(), lhs.data() + lhs.size() - rhs.size(), lhs.data() + lhs.size());
utf8::iterator<const char*> it2(rhs.data(), rhs.data(), rhs.data() + rhs.size());
do
{
if (it2.base() >= rhs.data() + rhs.size())
return true;
if (Unicode::GetLowercase(*it) != Unicode::GetLowercase(*it2))
return false;
++it2;
}
while (*it++);
return true;
}
std::string FromUtf16String(const std::u16string_view& u16str)
{
@ -271,8 +332,10 @@ namespace Nz
bool StartsWith(const std::string_view& lhs, const std::string_view& rhs, UnicodeAware)
{
if (lhs.empty() || rhs.empty())
if (lhs.empty())
return lhs == rhs;
else if (rhs.empty())
return true;
utf8::iterator<const char*> it(lhs.data(), lhs.data(), lhs.data() + lhs.size());
utf8::iterator<const char*> it2(rhs.data(), rhs.data(), rhs.data() + rhs.size());
@ -293,8 +356,10 @@ namespace Nz
bool StartsWith(const std::string_view& lhs, const std::string_view& rhs, CaseIndependent, UnicodeAware)
{
if (lhs.empty() || rhs.empty())
if (lhs.empty())
return lhs == rhs;
else if (rhs.empty())
return true;
utf8::iterator<const char*> it(lhs.data(), lhs.data(), lhs.data() + lhs.size());
utf8::iterator<const char*> it2(rhs.data(), rhs.data(), rhs.data() + rhs.size());

View File

@ -7,11 +7,32 @@ SCENARIO("String", "[CORE][STRING]")
WHEN("Checking if string ends with")
{
CHECK(Nz::EndsWith("", ""));
CHECK(Nz::EndsWith("Nazara Engine", ""));
CHECK(Nz::EndsWith("Nazara Engine", "Engine"));
CHECK_FALSE(Nz::EndsWith("Nazara Engine", "engine"));
CHECK_FALSE(Nz::EndsWith("Nazara Engine", " ngine"));
CHECK_FALSE(Nz::EndsWith("Nazara Engine", "NazaraEngine"));
CHECK_FALSE(Nz::EndsWith("Nazara Engine", "Nazara"));
CHECK_FALSE(Nz::EndsWith("Nazara Engine", "Sir Nazara van Engine"));
CHECK(Nz::EndsWith("", "", Nz::CaseIndependent{}));
CHECK(Nz::EndsWith("Nazara Engine", "", Nz::CaseIndependent{}));
CHECK(Nz::EndsWith("Nazara Engine", "Engine", Nz::CaseIndependent{}));
CHECK(Nz::EndsWith("Nazara Engine", "engine", Nz::CaseIndependent{}));
CHECK(Nz::EndsWith("Nazara engine", "EnGiNe", Nz::CaseIndependent{}));
CHECK_FALSE(Nz::EndsWith("Nazara Engine", " ngine", Nz::CaseIndependent{}));
CHECK_FALSE(Nz::EndsWith("Nazara Engine", "NazaraEngine", Nz::CaseIndependent{}));
CHECK_FALSE(Nz::EndsWith("Nazara Engine", "Nazara", Nz::CaseIndependent{}));
CHECK_FALSE(Nz::EndsWith("Nazara Engine", "Sir Nazara van Engine", Nz::CaseIndependent{}));
CHECK(Nz::EndsWith(u8"L'\u00CEle de R\u00E9", u8"", Nz::UnicodeAware{}));
CHECK(Nz::EndsWith(u8"L'\u00CEle de R\u00E9", u8"R\u00E9", Nz::UnicodeAware{}));
CHECK_FALSE(Nz::EndsWith(u8"L'\u00CEle de R\u00E9", u8"Long long j\u00F4hnson", Nz::UnicodeAware{}));
CHECK(Nz::EndsWith(u8"L'\u00CEle de R\u00E9", u8"", Nz::CaseIndependent{}, Nz::UnicodeAware{}));
CHECK(Nz::EndsWith(u8"L'\u00CEle de R\u00E9", u8"R\u00C9", Nz::CaseIndependent{}, Nz::UnicodeAware{}));
CHECK_FALSE(Nz::EndsWith(u8"L'\u00CEle de R\u00E9", u8"Long long j\u00F4hnson", Nz::CaseIndependent{}, Nz::UnicodeAware{}));
}
WHEN("Converting string back and forth")
@ -90,9 +111,25 @@ SCENARIO("String", "[CORE][STRING]")
WHEN("Checking if string starts with")
{
CHECK(Nz::StartsWith("Nazara Engine", ""));
CHECK(Nz::StartsWith("Nazara Engine", "Nazara"));
CHECK_FALSE(Nz::StartsWith("Nazara Engine", "Navara"));
CHECK_FALSE(Nz::StartsWith("Nazara Engine", "NaZaRa"));
CHECK_FALSE(Nz::StartsWith("Nazara Engine", "Long long johnson"));
CHECK(Nz::StartsWith("NAZARA Engine", "", Nz::CaseIndependent{}));
CHECK(Nz::StartsWith("NAZARA Engine", "Nazara", Nz::CaseIndependent{}));
CHECK(Nz::StartsWith("NAZARA Engine", "NaZaRa", Nz::CaseIndependent{}));
CHECK_FALSE(Nz::StartsWith("NAZARA Engine", "NavaRa", Nz::CaseIndependent{}));
CHECK_FALSE(Nz::StartsWith("NAZARA Engine", "Long long johnson", Nz::CaseIndependent{}));
CHECK(Nz::StartsWith(u8"L'\u00CEle de R\u00E9", u8"", Nz::UnicodeAware{}));
CHECK(Nz::StartsWith(u8"L'\u00CEle de R\u00E9", u8"L'\u00CEle", Nz::UnicodeAware{}));
CHECK_FALSE(Nz::StartsWith(u8"L'\u00CEle de R\u00E9", u8"Long long j\u00F4hnson", Nz::UnicodeAware{}));
CHECK(Nz::StartsWith(u8"L'\u00CEle de R\u00E9", u8"", Nz::CaseIndependent{}, Nz::UnicodeAware{}));
CHECK(Nz::StartsWith(u8"L'\u00CEle de R\u00E9", u8"l'\u00EEle", Nz::CaseIndependent{}, Nz::UnicodeAware{}));
CHECK_FALSE(Nz::StartsWith(u8"L'\u00CEle de R\u00E9", u8"Long long j\u00F4hnson", Nz::CaseIndependent{}, Nz::UnicodeAware{}));
}
WHEN("Converting between lower and upper")