Skip to content

Commit

Permalink
More string comparisons
Browse files Browse the repository at this point in the history
  • Loading branch information
SupSuper committed Nov 7, 2018
1 parent 9e170e0 commit 47143be
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 4 deletions.
65 changes: 61 additions & 4 deletions src/Engine/Unicode.cpp
Expand Up @@ -27,6 +27,7 @@
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shlwapi.h>
#else
#include <cassert>
#endif
Expand Down Expand Up @@ -249,13 +250,49 @@ bool naturalCompare(const std::string &a, const std::string &b)
else
#endif
{
// sorry unix users you get ASCII sort
std::string::const_iterator i, j;
for (i = a.begin(), j = b.begin(); i != a.end() && j != b.end() && std::tolower(*i, utf8) == std::tolower(*j, utf8); ++i, ++j);
return (i != a.end() && j != b.end() && std::tolower(*i, utf8) < tolower(*j, utf8));
// fallback to lexographical sort
return caseCompare(a, b);
}
}

/**
* Compares two UTF-8 strings ignoring case.
* @param a String A.
* @param b String B.
* @return String A comes before String B.
*/
bool caseCompare(const std::string &a, const std::string &b)
{
#ifdef _WIN32
std::wstring wa = convMbToWc(a, CP_UTF8);
std::wstring wb = convMbToWc(b, CP_UTF8);
return (StrCmpIW(wa.c_str(), wb.c_str()) < 0);
#else
return (std::use_facet< std::collate<char> >(utf8).compare(&a[0], &a[a.size()], &b[0], &b[b.size()]) < 0);
#endif
}

/**
* Searches for a substring in another string ignoring case.
* @param haystack String to search.
* @param needle String to find.
* @return True if the needle is in the haystack.
*/
bool caseFind(const std::string &haystack, const std::string &needle)
{
#ifdef _WIN32
std::wstring wa = convMbToWc(haystack, CP_UTF8);
std::wstring wb = convMbToWc(needle, CP_UTF8);
return (StrStrIW(wa.c_str(), wb.c_str()) != NULL);
#else
std::wstring wa = convMbToWc(haystack, 0);
std::wstring wb = convMbToWc(needle, 0);
std::use_facet< std::ctype<wchar_t> >(utf8).toupper(&wa[0], &wb[wb.size()]);
std::use_facet< std::ctype<wchar_t> >(utf8).toupper(&wb[0], &wb[wb.size()]);
return (wa.find(wb) != std::wstring::npos);
#endif
}

/**
* Uppercases a UTF-8 string, modified in place.
* Used for case-insensitive comparisons.
Expand All @@ -276,6 +313,26 @@ void upperCase(std::string &s)
#endif
}

/**
* Lowercases a UTF-8 string, modified in place.
* Used for case-insensitive comparisons.
* @param s Source string.
*/
void lowerCase(std::string &s)
{
if (s.empty())
return;
#ifdef _WIN32
std::wstring ws = convMbToWc(s, CP_UTF8);
CharLowerW(&ws[0]);
s = convWcToMb(ws, CP_UTF8);
#else
std::wstring ws = convMbToWc(s, 0);
std::use_facet< std::ctype<wchar_t> >(utf8).tolower(&ws[0], &ws[ws.size()]);
s = convWcToMb(ws, 0);
#endif
}

/**
* Replaces every instance of a substring.
* @param str The string to modify.
Expand Down
6 changes: 6 additions & 0 deletions src/Engine/Unicode.h
Expand Up @@ -68,8 +68,14 @@ namespace Unicode

/// Compares two strings by natural order.
bool naturalCompare(const std::string &a, const std::string &b);
/// Compares two strings case-insensitive.
bool caseCompare(const std::string &a, const std::string &b);
/// Find a string in another case-insensitive.
bool caseFind(const std::string &haystack, const std::string &needle);
/// Uppercases a string in place.
void upperCase(std::string &s);
/// Lowercases a string in place.
void upperCase(std::string &s);
/// Replaces a substring.
void replace(std::string &str, const std::string &find, const std::string &replace);
/// Formats an integer value as number with separators.
Expand Down

0 comments on commit 47143be

Please sign in to comment.