Merge tag 'v0.21.23'
release v0.21.23
This commit is contained in:
@@ -34,12 +34,6 @@
|
||||
#include <algorithm>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Win32.hxx"
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
#include <string.h>
|
||||
@@ -65,27 +59,6 @@ try {
|
||||
folded.SetSize(folded_length);
|
||||
return UCharToUTF8({folded.begin(), folded.size()});
|
||||
|
||||
#elif defined(_WIN32)
|
||||
const auto u = MultiByteToWideChar(CP_UTF8, src);
|
||||
|
||||
const int size = LCMapStringEx(LOCALE_NAME_INVARIANT,
|
||||
LCMAP_SORTKEY|LINGUISTIC_IGNORECASE,
|
||||
u.c_str(), -1, nullptr, 0,
|
||||
nullptr, nullptr, 0);
|
||||
if (size <= 0)
|
||||
return AllocatedString<>::Duplicate(src);
|
||||
|
||||
std::unique_ptr<wchar_t[]> buffer(new wchar_t[size]);
|
||||
int result = LCMapStringEx(LOCALE_NAME_INVARIANT,
|
||||
LCMAP_SORTKEY|LINGUISTIC_IGNORECASE,
|
||||
u.c_str(), -1, buffer.get(), size,
|
||||
nullptr, nullptr, 0);
|
||||
if (result <= 0)
|
||||
return AllocatedString<>::Duplicate(src);
|
||||
|
||||
return WideCharToMultiByte(CP_UTF8,
|
||||
{buffer.get(), size_t(result - 1)});
|
||||
|
||||
#else
|
||||
#error not implemented
|
||||
#endif
|
||||
|
@@ -22,7 +22,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined(HAVE_ICU) || defined(_WIN32)
|
||||
#ifdef HAVE_ICU
|
||||
#define HAVE_ICU_CASE_FOLD
|
||||
|
||||
#include <string_view>
|
||||
|
@@ -108,7 +108,7 @@ IcuCollate(std::string_view a, std::string_view b) noexcept
|
||||
}
|
||||
|
||||
auto result = CompareStringEx(LOCALE_NAME_INVARIANT,
|
||||
LINGUISTIC_IGNORECASE,
|
||||
NORM_IGNORECASE,
|
||||
wa.c_str(), -1,
|
||||
wb.c_str(), -1,
|
||||
nullptr, nullptr, 0);
|
||||
|
@@ -22,11 +22,27 @@
|
||||
#include "util/StringAPI.hxx"
|
||||
#include "config.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Win32.hxx"
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ICU_CASE_FOLD
|
||||
|
||||
IcuCompare::IcuCompare(std::string_view _needle) noexcept
|
||||
:needle(IcuCaseFold(_needle)) {}
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
IcuCompare::IcuCompare(std::string_view _needle) noexcept
|
||||
:needle(nullptr)
|
||||
{
|
||||
try {
|
||||
needle = MultiByteToWideChar(CP_UTF8, _needle);
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
IcuCompare::IcuCompare(std::string_view _needle) noexcept
|
||||
@@ -39,6 +55,22 @@ IcuCompare::operator==(const char *haystack) const noexcept
|
||||
{
|
||||
#ifdef HAVE_ICU_CASE_FOLD
|
||||
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
|
||||
return StringIsEqualIgnoreCase(haystack, needle.c_str());
|
||||
#endif
|
||||
@@ -50,6 +82,24 @@ IcuCompare::IsIn(const char *haystack) const noexcept
|
||||
#ifdef HAVE_ICU_CASE_FOLD
|
||||
return StringFind(IcuCaseFold(haystack).c_str(),
|
||||
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)
|
||||
return strcasestr(haystack, needle.c_str()) != nullptr;
|
||||
#else
|
||||
|
@@ -25,13 +25,23 @@
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <wchar.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This class can compare one string ("needle") with lots of other
|
||||
* strings ("haystacks") efficiently, ignoring case. With some
|
||||
* configurations, it can prepare a case-folded version of the needle.
|
||||
*/
|
||||
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;
|
||||
#endif
|
||||
|
||||
public:
|
||||
IcuCompare():needle(nullptr) {}
|
||||
@@ -40,12 +50,12 @@ public:
|
||||
|
||||
IcuCompare(const IcuCompare &src) noexcept
|
||||
:needle(src
|
||||
? AllocatedString<>::Duplicate(src.needle)
|
||||
? src.needle.Clone()
|
||||
: nullptr) {}
|
||||
|
||||
IcuCompare &operator=(const IcuCompare &src) noexcept {
|
||||
needle = src
|
||||
? AllocatedString<>::Duplicate(src.needle)
|
||||
? src.needle.Clone()
|
||||
: nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
Reference in New Issue
Block a user