diff options
Diffstat (limited to 'src/lib/icu')
-rw-r--r-- | src/lib/icu/Collate.cxx | 151 | ||||
-rw-r--r-- | src/lib/icu/Collate.hxx | 5 | ||||
-rw-r--r-- | src/lib/icu/Converter.cxx | 163 | ||||
-rw-r--r-- | src/lib/icu/Converter.hxx | 97 | ||||
-rw-r--r-- | src/lib/icu/Error.cxx | 2 | ||||
-rw-r--r-- | src/lib/icu/Error.hxx | 2 | ||||
-rw-r--r-- | src/lib/icu/Init.cxx | 2 | ||||
-rw-r--r-- | src/lib/icu/Init.hxx | 2 | ||||
-rw-r--r-- | src/lib/icu/Util.cxx | 74 | ||||
-rw-r--r-- | src/lib/icu/Util.hxx | 45 | ||||
-rw-r--r-- | src/lib/icu/Win32.cxx | 60 | ||||
-rw-r--r-- | src/lib/icu/Win32.hxx | 38 |
12 files changed, 566 insertions, 75 deletions
diff --git a/src/lib/icu/Collate.cxx b/src/lib/icu/Collate.cxx index 17b536b37..dc8598a7a 100644 --- a/src/lib/icu/Collate.cxx +++ b/src/lib/icu/Collate.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -19,8 +19,10 @@ #include "config.h" #include "Collate.hxx" +#include "util/AllocatedString.hxx" #ifdef HAVE_ICU +#include "Util.hxx" #include "Error.hxx" #include "util/WritableBuffer.hxx" #include "util/ConstBuffer.hxx" @@ -29,13 +31,17 @@ #include <unicode/ucol.h> #include <unicode/ustring.h> -#elif defined(HAVE_GLIB) -#include <glib.h> #else #include <algorithm> #include <ctype.h> #endif +#ifdef WIN32 +#include "Win32.hxx" +#include "util/AllocatedString.hxx" +#include <windows.h> +#endif + #include <assert.h> #include <string.h> #include <strings.h> @@ -71,50 +77,6 @@ IcuCollateFinish() ucol_close(collator); } -static WritableBuffer<UChar> -UCharFromUTF8(const char *src) -{ - assert(src != nullptr); - - const size_t src_length = strlen(src); - const size_t dest_capacity = src_length; - UChar *dest = new UChar[dest_capacity]; - - UErrorCode error_code = U_ZERO_ERROR; - int32_t dest_length; - u_strFromUTF8(dest, dest_capacity, &dest_length, - src, src_length, - &error_code); - if (U_FAILURE(error_code)) { - delete[] dest; - return nullptr; - } - - return { dest, size_t(dest_length) }; -} - -static WritableBuffer<char> -UCharToUTF8(ConstBuffer<UChar> src) -{ - assert(!src.IsNull()); - - /* worst-case estimate */ - size_t dest_capacity = 4 * src.size; - - char *dest = new char[dest_capacity]; - - UErrorCode error_code = U_ZERO_ERROR; - int32_t dest_length; - u_strToUTF8(dest, dest_capacity, &dest_length, src.data, src.size, - &error_code); - if (U_FAILURE(error_code)) { - delete[] dest; - return nullptr; - } - - return { dest, size_t(dest_length) }; -} - #endif gcc_pure @@ -150,14 +112,32 @@ IcuCollate(const char *a, const char *b) return result; #endif -#elif defined(HAVE_GLIB) - return g_utf8_collate(a, b); +#elif defined(WIN32) + const auto wa = MultiByteToWideChar(CP_UTF8, a); + const auto wb = MultiByteToWideChar(CP_UTF8, b); + if (wa.IsNull()) + return wb.IsNull() ? 0 : -1; + else if (wb.IsNull()) + return 1; + + auto result = CompareStringEx(LOCALE_NAME_INVARIANT, + LINGUISTIC_IGNORECASE, + wa.c_str(), -1, + wb.c_str(), -1, + nullptr, nullptr, 0); + if (result != 0) + /* "To maintain the C runtime convention of comparing + strings, the value 2 can be subtracted from a + nonzero return value." */ + result -= 2; + + return result; #else - return strcasecmp(a, b); + return strcoll(a, b); #endif } -std::string +AllocatedString<> IcuCaseFold(const char *src) { #ifdef HAVE_ICU @@ -169,37 +149,70 @@ IcuCaseFold(const char *src) const auto u = UCharFromUTF8(src); if (u.IsNull()) - return std::string(src); + return AllocatedString<>::Duplicate(src); size_t folded_capacity = u.size * 2u; UChar *folded = new UChar[folded_capacity]; UErrorCode error_code = U_ZERO_ERROR; size_t folded_length = u_strFoldCase(folded, folded_capacity, - u.data, u.size, - U_FOLD_CASE_DEFAULT, - &error_code); + u.data, u.size, + U_FOLD_CASE_DEFAULT, + &error_code); delete[] u.data; if (folded_length == 0 || error_code != U_ZERO_ERROR) { delete[] folded; - return std::string(src); + return AllocatedString<>::Duplicate(src); } - auto result2 = UCharToUTF8({folded, folded_length}); + auto result = UCharToUTF8({folded, folded_length}); delete[] folded; - if (result2.IsNull()) - return std::string(src); - - std::string result(result2.data, result2.size); - delete[] result2.data; -#elif defined(HAVE_GLIB) - char *tmp = g_utf8_casefold(src, -1); - std::string result(tmp); - g_free(tmp); + return result; + +#elif defined(WIN32) + const auto u = MultiByteToWideChar(CP_UTF8, src); + if (u.IsNull()) + return AllocatedString<>::Duplicate(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); + + auto buffer = new wchar_t[size]; + if (LCMapStringEx(LOCALE_NAME_INVARIANT, + LCMAP_SORTKEY|LINGUISTIC_IGNORECASE, + u.c_str(), -1, buffer, size, + nullptr, nullptr, 0) <= 0) { + delete[] buffer; + return AllocatedString<>::Duplicate(src); + } + + auto result = WideCharToMultiByte(CP_UTF8, buffer); + delete[] buffer; + if (result.IsNull()) + return AllocatedString<>::Duplicate(src); + + return result; + #else - std::string result(src); - std::transform(result.begin(), result.end(), result.begin(), tolower); + size_t size = strlen(src) + 1; + auto buffer = new char[size]; + size_t nbytes = strxfrm(buffer, src, size); + if (nbytes >= size) { + /* buffer too small - reallocate and try again */ + delete[] buffer; + size = nbytes + 1; + buffer = new char[size]; + nbytes = strxfrm(buffer, src, size); + } + + assert(nbytes < size); + assert(buffer[nbytes] == 0); + + return AllocatedString<>::Donate(buffer); #endif - return result; } diff --git a/src/lib/icu/Collate.hxx b/src/lib/icu/Collate.hxx index 8ae8de46a..0ad3b24ff 100644 --- a/src/lib/icu/Collate.hxx +++ b/src/lib/icu/Collate.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -26,6 +26,7 @@ #include <string> class Error; +template<typename T> class AllocatedString; bool IcuCollateInit(Error &error); @@ -38,7 +39,7 @@ int IcuCollate(const char *a, const char *b); gcc_pure gcc_nonnull_all -std::string +AllocatedString<char> IcuCaseFold(const char *src); #endif diff --git a/src/lib/icu/Converter.cxx b/src/lib/icu/Converter.cxx new file mode 100644 index 000000000..61c0cbdd5 --- /dev/null +++ b/src/lib/icu/Converter.cxx @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2003-2015 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 "Converter.hxx" +#include "Error.hxx" +#include "util/Error.hxx" +#include "util/Macros.hxx" +#include "util/AllocatedString.hxx" +#include "util/WritableBuffer.hxx" +#include "util/ConstBuffer.hxx" + +#include <string.h> + +#ifdef HAVE_ICU +#include "Util.hxx" +#include <unicode/ucnv.h> +#elif defined(HAVE_ICONV) +#include "util/Domain.hxx" +static constexpr Domain iconv_domain("iconv"); +#endif + +#ifdef HAVE_ICU + +IcuConverter::~IcuConverter() +{ + ucnv_close(converter); +} + +#endif + +#ifdef HAVE_ICU_CONVERTER + +IcuConverter * +IcuConverter::Create(const char *charset, Error &error) +{ +#ifdef HAVE_ICU + UErrorCode code = U_ZERO_ERROR; + UConverter *converter = ucnv_open(charset, &code); + if (converter == nullptr) { + error.Format(icu_domain, int(code), + "Failed to initialize charset '%s': %s", + charset, u_errorName(code)); + return nullptr; + } + + return new IcuConverter(converter); +#elif defined(HAVE_ICONV) + iconv_t to = iconv_open("utf-8", charset); + iconv_t from = iconv_open(charset, "utf-8"); + if (to == (iconv_t)-1 || from == (iconv_t)-1) { + error.FormatErrno("Failed to initialize charset '%s'", + charset); + if (to != (iconv_t)-1) + iconv_close(to); + if (from != (iconv_t)-1) + iconv_close(from); + return nullptr; + } + + return new IcuConverter(to, from); +#endif +} + +#ifdef HAVE_ICU +#elif defined(HAVE_ICONV) + +static AllocatedString<char> +DoConvert(iconv_t conv, const char *src) +{ + // TODO: dynamic buffer? + char buffer[4096]; + char *in = const_cast<char *>(src); + char *out = buffer; + size_t in_left = strlen(src); + size_t out_left = sizeof(buffer); + + size_t n = iconv(conv, &in, &in_left, &out, &out_left); + + if (n == static_cast<size_t>(-1) || in_left > 0) + return nullptr; + + return AllocatedString<>::Duplicate(buffer, sizeof(buffer) - out_left); +} + +#endif + +AllocatedString<char> +IcuConverter::ToUTF8(const char *s) const +{ +#ifdef HAVE_ICU + const ScopeLock protect(mutex); + + ucnv_resetToUnicode(converter); + + // TODO: dynamic buffer? + UChar buffer[4096], *target = buffer; + const char *source = s; + + UErrorCode code = U_ZERO_ERROR; + + ucnv_toUnicode(converter, &target, buffer + ARRAY_SIZE(buffer), + &source, source + strlen(source), + nullptr, true, &code); + if (code != U_ZERO_ERROR) + return nullptr; + + const size_t target_length = target - buffer; + return UCharToUTF8({buffer, target_length}); +#elif defined(HAVE_ICONV) + return DoConvert(to_utf8, s); +#endif +} + +AllocatedString<char> +IcuConverter::FromUTF8(const char *s) const +{ +#ifdef HAVE_ICU + const ScopeLock protect(mutex); + + const auto u = UCharFromUTF8(s); + if (u.IsNull()) + return nullptr; + + ucnv_resetFromUnicode(converter); + + // TODO: dynamic buffer? + char buffer[4096], *target = buffer; + const UChar *source = u.data; + UErrorCode code = U_ZERO_ERROR; + + ucnv_fromUnicode(converter, &target, buffer + ARRAY_SIZE(buffer), + &source, u.end(), + nullptr, true, &code); + delete[] u.data; + + if (code != U_ZERO_ERROR) + return nullptr; + + return AllocatedString<>::Duplicate(buffer, target); + +#elif defined(HAVE_ICONV) + return DoConvert(from_utf8, s); +#endif +} + +#endif diff --git a/src/lib/icu/Converter.hxx b/src/lib/icu/Converter.hxx new file mode 100644 index 000000000..edb092d8f --- /dev/null +++ b/src/lib/icu/Converter.hxx @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2003-2015 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_CONVERTER_HXX +#define MPD_ICU_CONVERTER_HXX + +#include "check.h" +#include "Compiler.h" + +#ifdef HAVE_ICU +#include "thread/Mutex.hxx" +#define HAVE_ICU_CONVERTER +#elif defined(HAVE_ICONV) +#include <iconv.h> +#define HAVE_ICU_CONVERTER +#endif + +#ifdef HAVE_ICU_CONVERTER + +class Error; + +#ifdef HAVE_ICU +struct UConverter; +#endif + +template<typename T> class AllocatedString; + +/** + * This class can convert strings with a certain character set to and + * from UTF-8. + */ +class IcuConverter { +#ifdef HAVE_ICU + /** + * ICU's UConverter class is not thread-safe. This mutex + * serializes simultaneous calls. + */ + mutable Mutex mutex; + + UConverter *const converter; + + IcuConverter(UConverter *_converter):converter(_converter) {} +#elif defined(HAVE_ICONV) + const iconv_t to_utf8, from_utf8; + + IcuConverter(iconv_t _to, iconv_t _from) + :to_utf8(_to), from_utf8(_from) {} +#endif + +public: +#ifdef HAVE_ICU + ~IcuConverter(); +#elif defined(HAVE_ICONV) + ~IcuConverter() { + iconv_close(to_utf8); + iconv_close(from_utf8); + } +#endif + + static IcuConverter *Create(const char *charset, Error &error); + + /** + * Convert the string to UTF-8. + * + * Returns AllocatedString::Null() on error. + */ + gcc_pure gcc_nonnull_all + AllocatedString<char> ToUTF8(const char *s) const; + + /** + * Convert the string from UTF-8. + * + * Returns AllocatedString::Null() on error. + */ + gcc_pure gcc_nonnull_all + AllocatedString<char> FromUTF8(const char *s) const; +}; + +#endif + +#endif diff --git a/src/lib/icu/Error.cxx b/src/lib/icu/Error.cxx index 1fef078ac..f49ede352 100644 --- a/src/lib/icu/Error.cxx +++ b/src/lib/icu/Error.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff --git a/src/lib/icu/Error.hxx b/src/lib/icu/Error.hxx index e96667f57..37cdb12fe 100644 --- a/src/lib/icu/Error.hxx +++ b/src/lib/icu/Error.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff --git a/src/lib/icu/Init.cxx b/src/lib/icu/Init.cxx index 1d0ad0777..6b70d60ee 100644 --- a/src/lib/icu/Init.cxx +++ b/src/lib/icu/Init.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff --git a/src/lib/icu/Init.hxx b/src/lib/icu/Init.hxx index 9f585e2bd..402e7b957 100644 --- a/src/lib/icu/Init.hxx +++ b/src/lib/icu/Init.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2014 The Music Player Daemon Project + * Copyright (C) 2003-2015 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify diff --git a/src/lib/icu/Util.cxx b/src/lib/icu/Util.cxx new file mode 100644 index 000000000..92f1de5aa --- /dev/null +++ b/src/lib/icu/Util.cxx @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2003-2015 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 "Util.hxx" +#include "util/AllocatedString.hxx" +#include "util/WritableBuffer.hxx" +#include "util/ConstBuffer.hxx" + +#include <unicode/ustring.h> + +#include <assert.h> +#include <string.h> + +WritableBuffer<UChar> +UCharFromUTF8(const char *src) +{ + assert(src != nullptr); + + const size_t src_length = strlen(src); + const size_t dest_capacity = src_length; + UChar *dest = new UChar[dest_capacity]; + + UErrorCode error_code = U_ZERO_ERROR; + int32_t dest_length; + u_strFromUTF8(dest, dest_capacity, &dest_length, + src, src_length, + &error_code); + if (U_FAILURE(error_code)) { + delete[] dest; + return nullptr; + } + + return { dest, size_t(dest_length) }; +} + +AllocatedString<> +UCharToUTF8(ConstBuffer<UChar> src) +{ + assert(!src.IsNull()); + + /* worst-case estimate */ + size_t dest_capacity = 4 * src.size; + + char *dest = new char[dest_capacity + 1]; + + UErrorCode error_code = U_ZERO_ERROR; + int32_t dest_length; + u_strToUTF8(dest, dest_capacity, &dest_length, src.data, src.size, + &error_code); + if (U_FAILURE(error_code)) { + delete[] dest; + return nullptr; + } + + dest[dest_length] = 0; + return AllocatedString<>::Donate(dest); +} diff --git a/src/lib/icu/Util.hxx b/src/lib/icu/Util.hxx new file mode 100644 index 000000000..f2d99d0e6 --- /dev/null +++ b/src/lib/icu/Util.hxx @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2003-2015 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_UTIL_HXX +#define MPD_ICU_UTIL_HXX + +#include "check.h" + +#include <unicode/utypes.h> + +template<typename T> struct WritableBuffer; +template<typename T> struct ConstBuffer; +template<typename T> class AllocatedString; + +/** + * Wrapper for u_strFromUTF8(). The returned pointer must be freed + * with delete[]. + */ +WritableBuffer<UChar> +UCharFromUTF8(const char *src); + +/** + * Wrapper for u_strToUTF8(). The returned pointer must be freed with + * delete[]. + */ +AllocatedString<char> +UCharToUTF8(ConstBuffer<UChar> src); + +#endif diff --git a/src/lib/icu/Win32.cxx b/src/lib/icu/Win32.cxx new file mode 100644 index 000000000..6f190c924 --- /dev/null +++ b/src/lib/icu/Win32.cxx @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2003-2015 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 "Win32.hxx" +#include "util/AllocatedString.hxx" + +#include <windows.h> + +AllocatedString<char> +WideCharToMultiByte(unsigned code_page, const wchar_t *src) +{ + int length = WideCharToMultiByte(code_page, 0, src, -1, nullptr, 0, + nullptr, nullptr); + if (length <= 0) + return nullptr; + + char *buffer = new char[length]; + length = WideCharToMultiByte(code_page, 0, src, -1, buffer, length, + nullptr, nullptr); + if (length <= 0) { + delete[] buffer; + return nullptr; + } + + return AllocatedString<char>::Donate(buffer); +} + +AllocatedString<wchar_t> +MultiByteToWideChar(unsigned code_page, const char *src) +{ + int length = MultiByteToWideChar(code_page, 0, src, -1, nullptr, 0); + if (length <= 0) + return nullptr; + + wchar_t *buffer = new wchar_t[length]; + length = MultiByteToWideChar(code_page, 0, src, -1, buffer, length); + if (length <= 0) { + delete[] buffer; + return nullptr; + } + + return AllocatedString<wchar_t>::Donate(buffer); +} diff --git a/src/lib/icu/Win32.hxx b/src/lib/icu/Win32.hxx new file mode 100644 index 000000000..253fe169a --- /dev/null +++ b/src/lib/icu/Win32.hxx @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2003-2015 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_WIN32_HXX +#define MPD_ICU_WIN32_HXX + +#include "check.h" +#include "Compiler.h" + +#include <wchar.h> + +template<typename T> class AllocatedString; + +gcc_pure gcc_nonnull_all +AllocatedString<char> +WideCharToMultiByte(unsigned code_page, const wchar_t *src); + +gcc_pure gcc_nonnull_all +AllocatedString<wchar_t> +MultiByteToWideChar(unsigned code_page, const char *src); + +#endif |