lib/icu/Compare: add Windows implementation
Using CompareStringEx() and FindNLSStringEx(). Implements a missing piece for https://github.com/MusicPlayerDaemon/MPD/issues/820
This commit is contained in:
parent
f3fd2eb618
commit
8f00dbea45
@ -22,6 +22,11 @@
|
|||||||
#include "util/StringAPI.hxx"
|
#include "util/StringAPI.hxx"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "Win32.hxx"
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef HAVE_ICU_CASE_FOLD
|
#ifdef HAVE_ICU_CASE_FOLD
|
||||||
@ -29,6 +34,17 @@
|
|||||||
IcuCompare::IcuCompare(const char *_needle) noexcept
|
IcuCompare::IcuCompare(const char *_needle) noexcept
|
||||||
:needle(IcuCaseFold(_needle)) {}
|
:needle(IcuCaseFold(_needle)) {}
|
||||||
|
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
|
||||||
|
IcuCompare::IcuCompare(const char *_needle) noexcept
|
||||||
|
:needle(nullptr)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
needle = MultiByteToWideChar(CP_UTF8, _needle);
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
IcuCompare::IcuCompare(const char *_needle) noexcept
|
IcuCompare::IcuCompare(const char *_needle) noexcept
|
||||||
@ -41,6 +57,22 @@ IcuCompare::operator==(const char *haystack) const noexcept
|
|||||||
{
|
{
|
||||||
#ifdef HAVE_ICU_CASE_FOLD
|
#ifdef HAVE_ICU_CASE_FOLD
|
||||||
return StringIsEqual(IcuCaseFold(haystack).c_str(), needle.c_str());
|
return StringIsEqual(IcuCaseFold(haystack).c_str(), needle.c_str());
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
if (needle.IsNull())
|
||||||
|
/* the MultiByteToWideChar() call in the constructor
|
||||||
|
has failed, so let's always fail the comparison */
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto w_haystack = MultiByteToWideChar(CP_UTF8, haystack);
|
||||||
|
return CompareStringEx(LOCALE_NAME_INVARIANT,
|
||||||
|
NORM_IGNORECASE,
|
||||||
|
w_haystack.c_str(), -1,
|
||||||
|
needle.c_str(), -1,
|
||||||
|
nullptr, nullptr, 0) == CSTR_EQUAL;
|
||||||
|
} catch (...) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
return strcasecmp(haystack, needle.c_str());
|
return strcasecmp(haystack, needle.c_str());
|
||||||
#endif
|
#endif
|
||||||
@ -52,6 +84,24 @@ IcuCompare::IsIn(const char *haystack) const noexcept
|
|||||||
#ifdef HAVE_ICU_CASE_FOLD
|
#ifdef HAVE_ICU_CASE_FOLD
|
||||||
return StringFind(IcuCaseFold(haystack).c_str(),
|
return StringFind(IcuCaseFold(haystack).c_str(),
|
||||||
needle.c_str()) != nullptr;
|
needle.c_str()) != nullptr;
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
if (needle.IsNull())
|
||||||
|
/* the MultiByteToWideChar() call in the constructor
|
||||||
|
has failed, so let's always fail the comparison */
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto w_haystack = MultiByteToWideChar(CP_UTF8, haystack);
|
||||||
|
return FindNLSStringEx(LOCALE_NAME_INVARIANT,
|
||||||
|
FIND_FROMSTART|NORM_IGNORECASE,
|
||||||
|
w_haystack.c_str(), -1,
|
||||||
|
needle.c_str(), -1,
|
||||||
|
nullptr,
|
||||||
|
nullptr, nullptr, 0) >= 0;
|
||||||
|
} catch (...) {
|
||||||
|
/* MultiByteToWideChar() has failed */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#elif defined(HAVE_STRCASESTR)
|
#elif defined(HAVE_STRCASESTR)
|
||||||
return strcasestr(haystack, needle.c_str()) != nullptr;
|
return strcasestr(haystack, needle.c_str()) != nullptr;
|
||||||
#else
|
#else
|
||||||
|
@ -23,13 +23,23 @@
|
|||||||
#include "util/Compiler.h"
|
#include "util/Compiler.h"
|
||||||
#include "util/AllocatedString.hxx"
|
#include "util/AllocatedString.hxx"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <wchar.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class can compare one string ("needle") with lots of other
|
* This class can compare one string ("needle") with lots of other
|
||||||
* strings ("haystacks") efficiently, ignoring case. With some
|
* strings ("haystacks") efficiently, ignoring case. With some
|
||||||
* configurations, it can prepare a case-folded version of the needle.
|
* configurations, it can prepare a case-folded version of the needle.
|
||||||
*/
|
*/
|
||||||
class IcuCompare {
|
class IcuCompare {
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* Windows API functions work with wchar_t strings, so let's
|
||||||
|
cache the MultiByteToWideChar() result for performance */
|
||||||
|
AllocatedString<wchar_t> needle;
|
||||||
|
#else
|
||||||
AllocatedString<> needle;
|
AllocatedString<> needle;
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IcuCompare():needle(nullptr) {}
|
IcuCompare():needle(nullptr) {}
|
||||||
|
Loading…
Reference in New Issue
Block a user