From be024d4ad79b681b59566f8051b603b4082d676e Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 20 Sep 2017 23:05:31 +0200 Subject: [PATCH 1/8] lib/icu/Collate: remove unnecessary assert() --- src/lib/icu/Collate.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/icu/Collate.cxx b/src/lib/icu/Collate.cxx index abb4b709c..9238e74b0 100644 --- a/src/lib/icu/Collate.cxx +++ b/src/lib/icu/Collate.cxx @@ -146,7 +146,6 @@ AllocatedString<> IcuCaseFold(const char *src) try { #ifdef HAVE_ICU - assert(collator != nullptr); #if !CLANG_CHECK_VERSION(3,6) /* disabled on clang due to -Wtautological-pointer-compare */ assert(src != nullptr); From 5620f16330879769352c295781723e17b15da5c4 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 20 Sep 2017 23:11:58 +0200 Subject: [PATCH 2/8] lib/icu/Collate: move IcuCaseFold() to CaseFold.cxx --- Makefile.am | 1 + src/SongFilter.cxx | 2 +- src/lib/icu/CaseFold.cxx | 111 +++++++++++++++++++++++++++++++++++++++ src/lib/icu/CaseFold.hxx | 32 +++++++++++ src/lib/icu/Collate.cxx | 68 ------------------------ src/lib/icu/Collate.hxx | 6 --- 6 files changed, 145 insertions(+), 75 deletions(-) create mode 100644 src/lib/icu/CaseFold.cxx create mode 100644 src/lib/icu/CaseFold.hxx diff --git a/Makefile.am b/Makefile.am index 544fddeb6..fa121a8fa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -518,6 +518,7 @@ libevent_a_SOURCES = \ # UTF-8 library libicu_a_SOURCES = \ + src/lib/icu/CaseFold.cxx src/lib/icu/CaseFold.hxx \ src/lib/icu/Collate.cxx src/lib/icu/Collate.hxx \ src/lib/icu/Converter.cxx src/lib/icu/Converter.hxx diff --git a/src/SongFilter.cxx b/src/SongFilter.cxx index ed556ede0..c761550aa 100644 --- a/src/SongFilter.cxx +++ b/src/SongFilter.cxx @@ -27,7 +27,7 @@ #include "util/ASCII.hxx" #include "util/TimeParser.hxx" #include "util/UriUtil.hxx" -#include "lib/icu/Collate.hxx" +#include "lib/icu/CaseFold.hxx" #include diff --git a/src/lib/icu/CaseFold.cxx b/src/lib/icu/CaseFold.cxx new file mode 100644 index 000000000..ed4552d1c --- /dev/null +++ b/src/lib/icu/CaseFold.cxx @@ -0,0 +1,111 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "CaseFold.hxx" +#include "util/AllocatedString.hxx" + +#ifdef HAVE_ICU +#include "Util.hxx" +#include "util/AllocatedArray.hxx" +#include "util/ConstBuffer.hxx" + +#include +#include +#else +#include +#include +#endif + +#ifdef WIN32 +#include "Win32.hxx" +#include +#endif + +#include +#include + +#include +#include + +AllocatedString<> +IcuCaseFold(const char *src) +try { +#ifdef HAVE_ICU +#if !CLANG_CHECK_VERSION(3,6) + /* disabled on clang due to -Wtautological-pointer-compare */ + assert(src != nullptr); +#endif + + const auto u = UCharFromUTF8(src); + if (u.IsNull()) + return AllocatedString<>::Duplicate(src); + + AllocatedArray folded(u.size() * 2u); + + UErrorCode error_code = U_ZERO_ERROR; + size_t folded_length = u_strFoldCase(folded.begin(), folded.size(), + u.begin(), u.size(), + U_FOLD_CASE_DEFAULT, + &error_code); + if (folded_length == 0 || error_code != U_ZERO_ERROR) + return AllocatedString<>::Duplicate(src); + + 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 buffer(new wchar_t[size]); + if (LCMapStringEx(LOCALE_NAME_INVARIANT, + LCMAP_SORTKEY|LINGUISTIC_IGNORECASE, + u.c_str(), -1, buffer.get(), size, + nullptr, nullptr, 0) <= 0) + return AllocatedString<>::Duplicate(src); + + return WideCharToMultiByte(CP_UTF8, buffer.get()); + +#else + size_t size = strlen(src) + 1; + std::unique_ptr buffer(new char[size]); + size_t nbytes = strxfrm(buffer.get(), src, size); + if (nbytes >= size) { + /* buffer too small - reallocate and try again */ + buffer.reset(); + size = nbytes + 1; + buffer.reset(new char[size]); + nbytes = strxfrm(buffer.get(), src, size); + } + + assert(nbytes < size); + assert(buffer[nbytes] == 0); + + return AllocatedString<>::Donate(buffer.release()); +#endif +} catch (const std::runtime_error &) { + return AllocatedString<>::Duplicate(src); +} diff --git a/src/lib/icu/CaseFold.hxx b/src/lib/icu/CaseFold.hxx new file mode 100644 index 000000000..7d13a6e2a --- /dev/null +++ b/src/lib/icu/CaseFold.hxx @@ -0,0 +1,32 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_ICU_CASE_FOLD_HXX +#define MPD_ICU_CASE_FOLD_HXX + +#include "check.h" +#include "Compiler.h" + +template class AllocatedString; + +gcc_nonnull_all +AllocatedString +IcuCaseFold(const char *src); + +#endif diff --git a/src/lib/icu/Collate.cxx b/src/lib/icu/Collate.cxx index 9238e74b0..f16cba597 100644 --- a/src/lib/icu/Collate.cxx +++ b/src/lib/icu/Collate.cxx @@ -23,8 +23,6 @@ #ifdef HAVE_ICU #include "Util.hxx" -#include "util/AllocatedArray.hxx" -#include "util/ConstBuffer.hxx" #include "util/RuntimeError.hxx" #include @@ -141,69 +139,3 @@ IcuCollate(const char *a, const char *b) noexcept return strcoll(a, b); #endif } - -AllocatedString<> -IcuCaseFold(const char *src) -try { -#ifdef HAVE_ICU -#if !CLANG_CHECK_VERSION(3,6) - /* disabled on clang due to -Wtautological-pointer-compare */ - assert(src != nullptr); -#endif - - const auto u = UCharFromUTF8(src); - if (u.IsNull()) - return AllocatedString<>::Duplicate(src); - - AllocatedArray folded(u.size() * 2u); - - UErrorCode error_code = U_ZERO_ERROR; - size_t folded_length = u_strFoldCase(folded.begin(), folded.size(), - u.begin(), u.size(), - U_FOLD_CASE_DEFAULT, - &error_code); - if (folded_length == 0 || error_code != U_ZERO_ERROR) - return AllocatedString<>::Duplicate(src); - - 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 buffer(new wchar_t[size]); - if (LCMapStringEx(LOCALE_NAME_INVARIANT, - LCMAP_SORTKEY|LINGUISTIC_IGNORECASE, - u.c_str(), -1, buffer.get(), size, - nullptr, nullptr, 0) <= 0) - return AllocatedString<>::Duplicate(src); - - return WideCharToMultiByte(CP_UTF8, buffer.get()); - -#else - size_t size = strlen(src) + 1; - std::unique_ptr buffer(new char[size]); - size_t nbytes = strxfrm(buffer.get(), src, size); - if (nbytes >= size) { - /* buffer too small - reallocate and try again */ - buffer.reset(); - size = nbytes + 1; - buffer.reset(new char[size]); - nbytes = strxfrm(buffer.get(), src, size); - } - - assert(nbytes < size); - assert(buffer[nbytes] == 0); - - return AllocatedString<>::Donate(buffer.release()); -#endif -} catch (const std::runtime_error &) { - return AllocatedString<>::Duplicate(src); -} diff --git a/src/lib/icu/Collate.hxx b/src/lib/icu/Collate.hxx index d6cfcb764..d22fa6870 100644 --- a/src/lib/icu/Collate.hxx +++ b/src/lib/icu/Collate.hxx @@ -23,8 +23,6 @@ #include "check.h" #include "Compiler.h" -template class AllocatedString; - /** * Throws #std::runtime_error on error. */ @@ -38,8 +36,4 @@ gcc_pure gcc_nonnull_all int IcuCollate(const char *a, const char *b) noexcept; -gcc_nonnull_all -AllocatedString -IcuCaseFold(const char *src); - #endif From 59b49b7881fd2bc159b201174f5dd86864db17e3 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 20 Sep 2017 23:32:47 +0200 Subject: [PATCH 3/8] db/Selection: add missing config.h --- src/db/Selection.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/db/Selection.cxx b/src/db/Selection.cxx index bab9c9de8..c25bf99f1 100644 --- a/src/db/Selection.cxx +++ b/src/db/Selection.cxx @@ -17,6 +17,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "config.h" #include "Selection.hxx" #include "SongFilter.hxx" From 42914e822751c3ac91949622fa2dd4897e461bc0 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 20 Sep 2017 23:23:05 +0200 Subject: [PATCH 4/8] lib/icu/CaseFold: add "noexcept" --- src/lib/icu/CaseFold.cxx | 2 +- src/lib/icu/CaseFold.hxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/icu/CaseFold.cxx b/src/lib/icu/CaseFold.cxx index ed4552d1c..d34b1737b 100644 --- a/src/lib/icu/CaseFold.cxx +++ b/src/lib/icu/CaseFold.cxx @@ -45,7 +45,7 @@ #include AllocatedString<> -IcuCaseFold(const char *src) +IcuCaseFold(const char *src) noexcept try { #ifdef HAVE_ICU #if !CLANG_CHECK_VERSION(3,6) diff --git a/src/lib/icu/CaseFold.hxx b/src/lib/icu/CaseFold.hxx index 7d13a6e2a..bb5d5e76e 100644 --- a/src/lib/icu/CaseFold.hxx +++ b/src/lib/icu/CaseFold.hxx @@ -27,6 +27,6 @@ template class AllocatedString; gcc_nonnull_all AllocatedString -IcuCaseFold(const char *src); +IcuCaseFold(const char *src) noexcept; #endif From d0497dba926c7e258937ecb1952eb8d182292a06 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 20 Sep 2017 23:21:57 +0200 Subject: [PATCH 5/8] lib/icu/Compare: OO wrapper for IcuCaseFold() --- Makefile.am | 1 + src/lib/icu/Compare.cxx | 41 ++++++++++++++++++++++++++++++ src/lib/icu/Compare.hxx | 55 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 src/lib/icu/Compare.cxx create mode 100644 src/lib/icu/Compare.hxx diff --git a/Makefile.am b/Makefile.am index fa121a8fa..f909647d8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -519,6 +519,7 @@ libevent_a_SOURCES = \ libicu_a_SOURCES = \ src/lib/icu/CaseFold.cxx src/lib/icu/CaseFold.hxx \ + src/lib/icu/Compare.cxx src/lib/icu/Compare.hxx \ src/lib/icu/Collate.cxx src/lib/icu/Collate.hxx \ src/lib/icu/Converter.cxx src/lib/icu/Converter.hxx diff --git a/src/lib/icu/Compare.cxx b/src/lib/icu/Compare.cxx new file mode 100644 index 000000000..dc571a316 --- /dev/null +++ b/src/lib/icu/Compare.cxx @@ -0,0 +1,41 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "Compare.hxx" +#include "CaseFold.hxx" +#include "util/StringAPI.hxx" + +#include + +IcuCompare::IcuCompare(const char *_needle) noexcept + :needle(IcuCaseFold(_needle)) {} + +bool +IcuCompare::operator==(const char *haystack) const noexcept +{ + return StringIsEqual(IcuCaseFold(haystack).c_str(), needle.c_str()); +} + +bool +IcuCompare::IsIn(const char *haystack) const noexcept +{ + return StringFind(IcuCaseFold(haystack).c_str(), + needle.c_str()) != nullptr; +} diff --git a/src/lib/icu/Compare.hxx b/src/lib/icu/Compare.hxx new file mode 100644 index 000000000..9ee2e6848 --- /dev/null +++ b/src/lib/icu/Compare.hxx @@ -0,0 +1,55 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_ICU_COMPARE_HXX +#define MPD_ICU_COMPARE_HXX + +#include "check.h" +#include "Compiler.h" +#include "util/AllocatedString.hxx" + +/** + * 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 { + AllocatedString<> needle; + +public: + IcuCompare():needle(nullptr) {} + + explicit IcuCompare(const char *needle) noexcept; + + IcuCompare(IcuCompare &&) = default; + IcuCompare &operator=(IcuCompare &&) = default; + + gcc_pure + operator bool() const noexcept { + return !needle.IsNull(); + } + + gcc_pure + bool operator==(const char *haystack) const noexcept; + + gcc_pure + bool IsIn(const char *haystack) const noexcept; +}; + +#endif From 66646d927637b7b370fa81a098d3c35de7a47748 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 20 Sep 2017 23:26:38 +0200 Subject: [PATCH 6/8] SongFilter: use class IcuCompare --- src/SongFilter.cxx | 17 ++++------------- src/SongFilter.hxx | 8 ++++++-- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/SongFilter.cxx b/src/SongFilter.cxx index c761550aa..4c3e746b1 100644 --- a/src/SongFilter.cxx +++ b/src/SongFilter.cxx @@ -57,17 +57,10 @@ locate_parse_type(const char *str) noexcept return tag_name_parse_i(str); } -static AllocatedString<> -ImportString(const char *p, bool fold_case) -{ - return fold_case - ? IcuCaseFold(p) - : AllocatedString<>::Duplicate(p); -} - SongFilter::Item::Item(unsigned _tag, const char *_value, bool _fold_case) - :tag(_tag), fold_case(_fold_case), - value(ImportString(_value, _fold_case)) + :tag(_tag), + value(AllocatedString<>::Duplicate(_value)), + fold_case(_fold_case ? IcuCompare(value.c_str()) : IcuCompare()) { } @@ -87,9 +80,7 @@ SongFilter::Item::StringMatch(const char *s) const noexcept assert(tag != LOCATE_TAG_MODIFIED_SINCE); if (fold_case) { - const auto folded = IcuCaseFold(s); - assert(!folded.IsNull()); - return StringFind(folded.c_str(), value.c_str()) != nullptr; + return fold_case.IsIn(s); } else { return StringIsEqual(s, value.c_str()); } diff --git a/src/SongFilter.hxx b/src/SongFilter.hxx index a0bb25d41..ec8317879 100644 --- a/src/SongFilter.hxx +++ b/src/SongFilter.hxx @@ -20,6 +20,7 @@ #ifndef MPD_SONG_FILTER_HXX #define MPD_SONG_FILTER_HXX +#include "lib/icu/Compare.hxx" #include "util/AllocatedString.hxx" #include "Compiler.h" @@ -48,10 +49,13 @@ public: class Item { uint8_t tag; - bool fold_case; - AllocatedString<> value; + /** + * This value is only set if case folding is enabled. + */ + IcuCompare fold_case; + /** * For #LOCATE_TAG_MODIFIED_SINCE */ From 1295a1272a1d787986c99bd133261fe45c763efc Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 20 Sep 2017 23:43:06 +0200 Subject: [PATCH 7/8] lib/icu/Compare: add fallback using strcasecmp() and strcasestr() Our IcuCaseFold() fallback using strxfrm() is not actually case insensitive. This commit fixes the problem by switching to strcasecmp(). That function is not guaranteed to support UTF-8, but it's the best we can do in this sparse situation. Closes #111 --- NEWS | 1 + configure.ac | 1 + src/lib/icu/CaseFold.hxx | 4 ++++ src/lib/icu/Compare.cxx | 25 +++++++++++++++++++++++++ 4 files changed, 31 insertions(+) diff --git a/NEWS b/NEWS index 4857d2cda..ae617cdce 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,7 @@ ver 0.20.11 (not yet released) - curl: support Content-Type application/xml * decoder - ffmpeg: more reliable song duration +* fix case insensitive search without libicu ver 0.20.10 (2017/08/24) * decoder diff --git a/configure.ac b/configure.ac index 11d869e2b..ad8b6462a 100644 --- a/configure.ac +++ b/configure.ac @@ -241,6 +241,7 @@ AC_CHECK_FUNCS(getpwnam_r getpwuid_r) AC_CHECK_FUNCS(initgroups) AC_CHECK_FUNCS(fnmatch) AC_CHECK_FUNCS(strndup) +AC_CHECK_FUNCS(strcasestr) if test x$host_is_linux = xyes; then MPD_OPTIONAL_FUNC(eventfd, eventfd, USE_EVENTFD) diff --git a/src/lib/icu/CaseFold.hxx b/src/lib/icu/CaseFold.hxx index bb5d5e76e..5b9fa6064 100644 --- a/src/lib/icu/CaseFold.hxx +++ b/src/lib/icu/CaseFold.hxx @@ -23,6 +23,10 @@ #include "check.h" #include "Compiler.h" +#if defined(HAVE_ICU) || defined(_WIN32) +#define HAVE_ICU_CASE_FOLD +#endif + template class AllocatedString; gcc_nonnull_all diff --git a/src/lib/icu/Compare.cxx b/src/lib/icu/Compare.cxx index dc571a316..21b3230bb 100644 --- a/src/lib/icu/Compare.cxx +++ b/src/lib/icu/Compare.cxx @@ -24,18 +24,43 @@ #include +#ifdef HAVE_ICU_CASE_FOLD + IcuCompare::IcuCompare(const char *_needle) noexcept :needle(IcuCaseFold(_needle)) {} +#else + +IcuCompare::IcuCompare(const char *_needle) noexcept + :needle(AllocatedString<>::Duplicate(_needle)) {} + +#endif + bool IcuCompare::operator==(const char *haystack) const noexcept { +#ifdef HAVE_ICU_CASE_FOLD return StringIsEqual(IcuCaseFold(haystack).c_str(), needle.c_str()); +#else + return strcasecmp(haystack, needle.c_str()); +#endif } bool IcuCompare::IsIn(const char *haystack) const noexcept { +#ifdef HAVE_ICU_CASE_FOLD return StringFind(IcuCaseFold(haystack).c_str(), needle.c_str()) != nullptr; +#elif defined(HAVE_STRCASESTR) + return strcasestr(haystack, needle.c_str()) != nullptr; +#else + /* poor man's strcasestr() */ + for (const size_t length = strlen(needle.c_str()); + *haystack != 0; ++haystack) + if (strncasecmp(haystack, needle.c_str(), length) == 0) + return true; + + return false; +#endif } From 828f5f83844b072f43417066c36d7d257d63db1a Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 20 Sep 2017 23:53:03 +0200 Subject: [PATCH 8/8] lib/icu/CaseFold: disable broken strxfrm() callback --- src/lib/icu/CaseFold.cxx | 21 ++++++--------------- src/lib/icu/CaseFold.hxx | 6 ++++-- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/lib/icu/CaseFold.cxx b/src/lib/icu/CaseFold.cxx index d34b1737b..ccdf998d5 100644 --- a/src/lib/icu/CaseFold.cxx +++ b/src/lib/icu/CaseFold.cxx @@ -19,6 +19,9 @@ #include "config.h" #include "CaseFold.hxx" + +#ifdef HAVE_ICU_CASE_FOLD + #include "util/AllocatedString.hxx" #ifdef HAVE_ICU @@ -90,22 +93,10 @@ try { return WideCharToMultiByte(CP_UTF8, buffer.get()); #else - size_t size = strlen(src) + 1; - std::unique_ptr buffer(new char[size]); - size_t nbytes = strxfrm(buffer.get(), src, size); - if (nbytes >= size) { - /* buffer too small - reallocate and try again */ - buffer.reset(); - size = nbytes + 1; - buffer.reset(new char[size]); - nbytes = strxfrm(buffer.get(), src, size); - } - - assert(nbytes < size); - assert(buffer[nbytes] == 0); - - return AllocatedString<>::Donate(buffer.release()); +#error not implemented #endif } catch (const std::runtime_error &) { return AllocatedString<>::Duplicate(src); } + +#endif /* HAVE_ICU_CASE_FOLD */ diff --git a/src/lib/icu/CaseFold.hxx b/src/lib/icu/CaseFold.hxx index 5b9fa6064..eaeaf5689 100644 --- a/src/lib/icu/CaseFold.hxx +++ b/src/lib/icu/CaseFold.hxx @@ -21,11 +21,11 @@ #define MPD_ICU_CASE_FOLD_HXX #include "check.h" -#include "Compiler.h" #if defined(HAVE_ICU) || defined(_WIN32) #define HAVE_ICU_CASE_FOLD -#endif + +#include "Compiler.h" template class AllocatedString; @@ -34,3 +34,5 @@ AllocatedString IcuCaseFold(const char *src) noexcept; #endif + +#endif