diff options
author | Max Kellermann <max@musicpd.org> | 2017-09-20 23:11:58 +0200 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2017-09-20 23:11:58 +0200 |
commit | 5620f16330879769352c295781723e17b15da5c4 (patch) | |
tree | 8c84d754889d862b337382fbf60905b67af7deee /src/lib/icu | |
parent | be024d4ad79b681b59566f8051b603b4082d676e (diff) |
lib/icu/Collate: move IcuCaseFold() to CaseFold.cxx
Diffstat (limited to 'src/lib/icu')
-rw-r--r-- | src/lib/icu/CaseFold.cxx | 111 | ||||
-rw-r--r-- | src/lib/icu/CaseFold.hxx | 32 | ||||
-rw-r--r-- | src/lib/icu/Collate.cxx | 68 | ||||
-rw-r--r-- | src/lib/icu/Collate.hxx | 6 |
4 files changed, 143 insertions, 74 deletions
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 <unicode/ucol.h> +#include <unicode/ustring.h> +#else +#include <algorithm> +#include <ctype.h> +#endif + +#ifdef WIN32 +#include "Win32.hxx" +#include <windows.h> +#endif + +#include <memory> +#include <stdexcept> + +#include <assert.h> +#include <string.h> + +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<UChar> 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<wchar_t[]> 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<char[]> 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<typename T> class AllocatedString; + +gcc_nonnull_all +AllocatedString<char> +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 <unicode/ucol.h> @@ -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<UChar> 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<wchar_t[]> 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<char[]> 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<typename T> 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<char> -IcuCaseFold(const char *src); - #endif |