diff options
| author | Eric Fiselier <eric@efcs.ca> | 2016-12-11 00:20:59 +0000 |
|---|---|---|
| committer | Eric Fiselier <eric@efcs.ca> | 2016-12-11 00:20:59 +0000 |
| commit | 0d542d350dafd662fb5fe9c00b5a3e4f61ee442f (patch) | |
| tree | 3625e856fa7dbc0be25c83a48b6a53848c7423f2 /libcxx/test | |
| parent | 658bb0964a74d86ee71bb0fd53ba6684b7be3567 (diff) | |
| download | bcm5719-llvm-0d542d350dafd662fb5fe9c00b5a3e4f61ee442f.tar.gz bcm5719-llvm-0d542d350dafd662fb5fe9c00b5a3e4f61ee442f.zip | |
[libc++] Fix support for multibyte thousands_sep and decimal_point in moneypunct_byname and numpunct_byname.
Summary:
The underlying C locales provide the `thousands_sep` and `decimal_point` as strings, possible with more than one character. We currently don't handle this case even for `wchar_t`.
This patch properly converts the mbs -> wide character for `moneypunct_byname<wchar_t>`. For the `moneypunct_byname<char>` case we attempt to narrow the WC and if that fails we also attempt to translate it to some reasonable value. For example we translate U00A0 (non-breaking space) into U0020 (regular space). If none of these conversions succeed then we simply allow the base class to provide a fallback value.
Reviewers: mclow.lists, EricWF
Subscribers: vangyzen, george.burgess.iv, cfe-commits
Differential Revision: https://reviews.llvm.org/D24218
llvm-svn: 289347
Diffstat (limited to 'libcxx/test')
4 files changed, 49 insertions, 28 deletions
diff --git a/libcxx/test/std/localization/locale.categories/category.monetary/locale.moneypunct.byname/decimal_point.pass.cpp b/libcxx/test/std/localization/locale.categories/category.monetary/locale.moneypunct.byname/decimal_point.pass.cpp index 8270377f3ab..4051d451fcb 100644 --- a/libcxx/test/std/localization/locale.categories/category.monetary/locale.moneypunct.byname/decimal_point.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.monetary/locale.moneypunct.byname/decimal_point.pass.cpp @@ -12,9 +12,6 @@ // REQUIRES: locale.ru_RU.UTF-8 // REQUIRES: locale.zh_CN.UTF-8 -// Russia uses ',' for the decimal separator. GLIBC returns '.' -// XFAIL: linux - // <locale> // class moneypunct_byname<charT, International> @@ -25,6 +22,7 @@ #include <limits> #include <cassert> +#include "test_macros.h" #include "platform_support.h" // locale name macros class Fnf @@ -111,22 +109,29 @@ int main() Fwt f(LOCALE_fr_FR_UTF_8, 1); assert(f.decimal_point() == L','); } - +// GLIBC 2.23 uses '.' as the decimal point while other C libraries use ',' +#ifndef TEST_HAS_GLIBC + const char sep = ','; + const wchar_t wsep = L','; +#else + const char sep = '.'; + const wchar_t wsep = L'.'; +#endif { Fnf f(LOCALE_ru_RU_UTF_8, 1); - assert(f.decimal_point() == ','); + assert(f.decimal_point() == sep); } { Fnt f(LOCALE_ru_RU_UTF_8, 1); - assert(f.decimal_point() == ','); + assert(f.decimal_point() == sep); } { Fwf f(LOCALE_ru_RU_UTF_8, 1); - assert(f.decimal_point() == L','); + assert(f.decimal_point() == wsep); } { Fwt f(LOCALE_ru_RU_UTF_8, 1); - assert(f.decimal_point() == L','); + assert(f.decimal_point() == wsep); } { diff --git a/libcxx/test/std/localization/locale.categories/category.monetary/locale.moneypunct.byname/thousands_sep.pass.cpp b/libcxx/test/std/localization/locale.categories/category.monetary/locale.moneypunct.byname/thousands_sep.pass.cpp index a8782832de5..aa585a436e6 100644 --- a/libcxx/test/std/localization/locale.categories/category.monetary/locale.moneypunct.byname/thousands_sep.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.monetary/locale.moneypunct.byname/thousands_sep.pass.cpp @@ -18,16 +18,11 @@ // charT thousands_sep() const; -// Failure related to GLIBC's use of U00A0 as mon_thousands_sep -// and U002E as mon_decimal_point. -// TODO: U00A0 should be investigated. -// Possibly related to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=16006 -// XFAIL: linux-gnu - #include <locale> #include <limits> #include <cassert> +#include "test_macros.h" #include "platform_support.h" // locale name macros class Fnf @@ -114,22 +109,34 @@ int main() Fwt f(LOCALE_fr_FR_UTF_8, 1); assert(f.thousands_sep() == L' '); } - +// The below tests work around GLIBC's use of U00A0 as mon_thousands_sep +// and U002E as mon_decimal_point. +// TODO: Fix thousands_sep for 'char'. +// related to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=16006 +#ifndef TEST_HAS_GLIBC + const char sep = ' '; + const wchar_t wsep = L' '; +#else + // FIXME libc++ specifically works around \u00A0 by translating it into + // a regular space. + const char sep = ' '; + const wchar_t wsep = L'\u00A0'; +#endif { Fnf f(LOCALE_ru_RU_UTF_8, 1); - assert(f.thousands_sep() == ' '); + assert(f.thousands_sep() == sep); } { Fnt f(LOCALE_ru_RU_UTF_8, 1); - assert(f.thousands_sep() == ' '); + assert(f.thousands_sep() == sep); } { Fwf f(LOCALE_ru_RU_UTF_8, 1); - assert(f.thousands_sep() == L' '); + assert(f.thousands_sep() == wsep); } { Fwt f(LOCALE_ru_RU_UTF_8, 1); - assert(f.thousands_sep() == L' '); + assert(f.thousands_sep() == wsep); } { diff --git a/libcxx/test/std/localization/locale.categories/facet.numpunct/locale.numpunct.byname/grouping.pass.cpp b/libcxx/test/std/localization/locale.categories/facet.numpunct/locale.numpunct.byname/grouping.pass.cpp index d5112a9508b..f3df52a21b8 100644 --- a/libcxx/test/std/localization/locale.categories/facet.numpunct/locale.numpunct.byname/grouping.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/facet.numpunct/locale.numpunct.byname/grouping.pass.cpp @@ -16,12 +16,10 @@ // string grouping() const; -// TODO: investigation needed -// XFAIL: linux-gnu - #include <locale> #include <cassert> +#include "test_macros.h" #include "platform_support.h" // locale name macros int main() @@ -54,15 +52,20 @@ int main() } { std::locale l(LOCALE_fr_FR_UTF_8); +#if defined(TEST_HAS_GLIBC) + const char* const group = "\3"; +#else + const char* const group = "\x7f"; +#endif { typedef char C; const std::numpunct<C>& np = std::use_facet<std::numpunct<C> >(l); - assert(np.grouping() == "\x7F"); + assert(np.grouping() == group); } { typedef wchar_t C; const std::numpunct<C>& np = std::use_facet<std::numpunct<C> >(l); - assert(np.grouping() == "\x7F"); + assert(np.grouping() == group); } } } diff --git a/libcxx/test/std/localization/locale.categories/facet.numpunct/locale.numpunct.byname/thousands_sep.pass.cpp b/libcxx/test/std/localization/locale.categories/facet.numpunct/locale.numpunct.byname/thousands_sep.pass.cpp index b1bd03ff736..38cbcfda4f0 100644 --- a/libcxx/test/std/localization/locale.categories/facet.numpunct/locale.numpunct.byname/thousands_sep.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/facet.numpunct/locale.numpunct.byname/thousands_sep.pass.cpp @@ -16,12 +16,11 @@ // char_type thousands_sep() const; -// TODO: investigation needed -// XFAIL: linux-gnu #include <locale> #include <cassert> +#include "test_macros.h" #include "platform_support.h" // locale name macros int main() @@ -54,15 +53,22 @@ int main() } { std::locale l(LOCALE_fr_FR_UTF_8); +#if defined(TEST_HAS_GLIBC) + const char sep = ' '; + const wchar_t wsep = L' '; +#else + const char sep = ','; + const wchar_t wsep = L','; +#endif { typedef char C; const std::numpunct<C>& np = std::use_facet<std::numpunct<C> >(l); - assert(np.thousands_sep() == ','); + assert(np.thousands_sep() == sep); } { typedef wchar_t C; const std::numpunct<C>& np = std::use_facet<std::numpunct<C> >(l); - assert(np.thousands_sep() == L','); + assert(np.thousands_sep() == wsep); } } } |

