Fix locale test data for GLIBC 2.27 and newer.

GLIBC 2.27 changed the locale data for fr_FR and ru_RU. In particular
they change the decimal and thousands separators used. This patch
makes the locale tests tolerate the updated locales.

llvm-svn: 329143
This commit is contained in:
Eric Fiselier 2018-04-04 04:00:14 +00:00
parent 7d3aba6687
commit fcc1e6d978
6 changed files with 101 additions and 38 deletions

View File

@ -4240,6 +4240,7 @@ static bool checked_string_to_char_convert(char& dest,
// FIXME: Work around specific multibyte sequences that we can reasonable
// translate into a different single byte.
switch (wout) {
case L'\u202F': // narrow non-breaking space
case L'\u00A0': // non-breaking space
dest = ' ';
return true;

View File

@ -25,6 +25,7 @@
#include "test_iterators.h"
#include "platform_support.h" // locale name macros
#include "test_macros.h"
typedef std::money_get<char, input_iterator<const char*> > Fn;
@ -46,6 +47,30 @@ public:
: Fw(refs) {}
};
// GLIBC 2.27 and newer use U2027 (narrow non-breaking space) as a thousands sep.
// this function converts the spaces in string inputs to that character if need
// be.
static std::wstring convert_thousands_sep(std::wstring const& in) {
#if !defined(TEST_HAS_GLIBC) || !TEST_GLIBC_PREREQ(2,27)
return in;
#else
std::wstring out;
unsigned I = 0;
bool seen_decimal = false;
for (; I < in.size(); ++I) {
if (seen_decimal || in[I] != L' ') {
seen_decimal |= in[I] == L',';
out.push_back(in[I]);
continue;
}
assert(in[I] == L' ');
out.push_back(L'\u202F');
}
return out;
#endif
}
int main()
{
std::ios ios(0);
@ -417,7 +442,7 @@ int main()
assert(ex == -1);
}
{ // positive
std::wstring v = L"1 234 567,89 ";
std::wstring v = convert_thousands_sep(L"1 234 567,89 ");
typedef input_iterator<const wchar_t*> I;
long double ex;
std::ios_base::iostate err = std::ios_base::goodbit;
@ -428,7 +453,7 @@ int main()
assert(ex == 123456789);
}
{ // negative
std::wstring v = L"-1 234 567,89";
std::wstring v = convert_thousands_sep(L"-1 234 567,89");
typedef input_iterator<const wchar_t*> I;
long double ex;
std::ios_base::iostate err = std::ios_base::goodbit;
@ -497,7 +522,7 @@ int main()
assert(ex == -1);
}
{ // positive, showbase
std::wstring v = L"1 234 567,89 \u20ac"; // EURO SIGN
std::wstring v = convert_thousands_sep(L"1 234 567,89 \u20ac"); // EURO SIGN
typedef input_iterator<const wchar_t*> I;
long double ex;
std::ios_base::iostate err = std::ios_base::goodbit;
@ -508,7 +533,7 @@ int main()
assert(ex == 123456789);
}
{ // positive, showbase
std::wstring v = L"1 234 567,89 \u20ac"; // EURO SIGN
std::wstring v = convert_thousands_sep(L"1 234 567,89 \u20ac"); // EURO SIGN
showbase(ios);
typedef input_iterator<const wchar_t*> I;
long double ex;
@ -521,7 +546,7 @@ int main()
noshowbase(ios);
}
{ // negative, showbase
std::wstring v = L"-1 234 567,89 \u20ac"; // EURO SIGN
std::wstring v = convert_thousands_sep(L"-1 234 567,89 \u20ac"); // EURO SIGN
showbase(ios);
typedef input_iterator<const wchar_t*> I;
long double ex;
@ -534,7 +559,7 @@ int main()
noshowbase(ios);
}
{ // negative, showbase
std::wstring v = L"1 234 567,89 EUR -";
std::wstring v = convert_thousands_sep(L"1 234 567,89 EUR -");
showbase(ios);
typedef input_iterator<const wchar_t*> I;
long double ex;
@ -546,7 +571,7 @@ int main()
noshowbase(ios);
}
{ // negative, showbase
std::wstring v = L"1 234 567,89 EUR -";
std::wstring v = convert_thousands_sep(L"1 234 567,89 EUR -");
typedef input_iterator<const wchar_t*> I;
long double ex;
std::ios_base::iostate err = std::ios_base::goodbit;
@ -583,7 +608,7 @@ int main()
assert(ex == -1);
}
{ // positive
std::wstring v = L"1 234 567,89 ";
std::wstring v = convert_thousands_sep(L"1 234 567,89 ");
typedef input_iterator<const wchar_t*> I;
long double ex;
std::ios_base::iostate err = std::ios_base::goodbit;
@ -594,7 +619,7 @@ int main()
assert(ex == 123456789);
}
{ // negative
std::wstring v = L"-1 234 567,89";
std::wstring v = convert_thousands_sep(L"-1 234 567,89");
typedef input_iterator<const wchar_t*> I;
long double ex;
std::ios_base::iostate err = std::ios_base::goodbit;
@ -663,7 +688,7 @@ int main()
assert(ex == -1);
}
{ // positive, showbase
std::wstring v = L"1 234 567,89 EUR";
std::wstring v = convert_thousands_sep(L"1 234 567,89 EUR");
typedef input_iterator<const wchar_t*> I;
long double ex;
std::ios_base::iostate err = std::ios_base::goodbit;
@ -674,7 +699,7 @@ int main()
assert(ex == 123456789);
}
{ // positive, showbase
std::wstring v = L"1 234 567,89 EUR";
std::wstring v = convert_thousands_sep(L"1 234 567,89 EUR");
showbase(ios);
typedef input_iterator<const wchar_t*> I;
long double ex;
@ -687,7 +712,7 @@ int main()
noshowbase(ios);
}
{ // negative, showbase
std::wstring v = L"-1 234 567,89 EUR";
std::wstring v = convert_thousands_sep(L"-1 234 567,89 EUR");
showbase(ios);
typedef input_iterator<const wchar_t*> I;
long double ex;
@ -700,7 +725,7 @@ int main()
noshowbase(ios);
}
{ // negative, showbase
std::wstring v = L"1 234 567,89 Eu-";
std::wstring v = convert_thousands_sep(L"1 234 567,89 Eu-");
showbase(ios);
typedef input_iterator<const wchar_t*> I;
long double ex;
@ -712,7 +737,7 @@ int main()
noshowbase(ios);
}
{ // negative, showbase
std::wstring v = L"1 234 567,89 Eu-";
std::wstring v = convert_thousands_sep(L"1 234 567,89 Eu-");
typedef input_iterator<const wchar_t*> I;
long double ex;
std::ios_base::iostate err = std::ios_base::goodbit;

View File

@ -25,6 +25,7 @@
#include "test_iterators.h"
#include "platform_support.h" // locale name macros
#include "test_macros.h"
typedef std::money_put<char, output_iterator<char*> > Fn;
@ -46,6 +47,32 @@ public:
: Fw(refs) {}
};
// GLIBC 2.27 and newer use U2027 (narrow non-breaking space) as a thousands sep.
// this function converts the spaces in string inputs to that character if need
// be.
static std::wstring convert_thousands_sep(std::wstring const& in) {
#if !defined(TEST_HAS_GLIBC) || !TEST_GLIBC_PREREQ(2,27)
return in;
#else
std::wstring out;
unsigned I = 0;
bool seen_num_start = false;
bool seen_decimal = false;
for (; I < in.size(); ++I) {
seen_decimal |= in[I] == L',';
seen_num_start |= in[I] == '-' || std::iswdigit(in[I]);
if (seen_decimal || !seen_num_start || in[I] != L' ') {
out.push_back(in[I]);
continue;
}
assert(in[I] == L' ');
out.push_back(L'\u202F');
}
return out;
#endif
}
int main()
{
std::ios ios(0);
@ -301,7 +328,7 @@ int main()
output_iterator<wchar_t*> iter = f.put(output_iterator<wchar_t*>(str),
false, ios, '*', v);
std::wstring ex(str, iter.base());
assert(ex == L"1 234 567,89");
assert(ex == convert_thousands_sep(L"1 234 567,89"));
}
{ // negative
long double v = -123456789;
@ -309,7 +336,7 @@ int main()
output_iterator<wchar_t*> iter = f.put(output_iterator<wchar_t*>(str),
false, ios, '*', v);
std::wstring ex(str, iter.base());
assert(ex == L"-1 234 567,89");
assert(ex == convert_thousands_sep(L"-1 234 567,89"));
}
{ // zero, showbase
long double v = 0;
@ -336,7 +363,7 @@ int main()
output_iterator<wchar_t*> iter = f.put(output_iterator<wchar_t*>(str),
false, ios, '*', v);
std::wstring ex(str, iter.base());
assert(ex == L"1 234 567,89 \u20ac");
assert(ex == convert_thousands_sep(L"1 234 567,89 \u20ac"));
}
{ // negative, showbase
long double v = -123456789;
@ -345,7 +372,7 @@ int main()
output_iterator<wchar_t*> iter = f.put(output_iterator<wchar_t*>(str),
false, ios, '*', v);
std::wstring ex(str, iter.base());
assert(ex == L"-1 234 567,89 \u20ac");
assert(ex == convert_thousands_sep(L"-1 234 567,89 \u20ac"));
}
{ // negative, showbase, left
long double v = -123456789;
@ -356,7 +383,7 @@ int main()
output_iterator<wchar_t*> iter = f.put(output_iterator<wchar_t*>(str),
false, ios, ' ', v);
std::wstring ex(str, iter.base());
assert(ex == L"-1 234 567,89 \u20ac ");
assert(ex == convert_thousands_sep(L"-1 234 567,89 \u20ac "));
assert(ios.width() == 0);
}
{ // negative, showbase, internal
@ -368,7 +395,7 @@ int main()
output_iterator<wchar_t*> iter = f.put(output_iterator<wchar_t*>(str),
false, ios, ' ', v);
std::wstring ex(str, iter.base());
assert(ex == L"-1 234 567,89 \u20ac");
assert(ex == convert_thousands_sep(L"-1 234 567,89 \u20ac"));
assert(ios.width() == 0);
}
{ // negative, showbase, right
@ -380,7 +407,7 @@ int main()
output_iterator<wchar_t*> iter = f.put(output_iterator<wchar_t*>(str),
false, ios, ' ', v);
std::wstring ex(str, iter.base());
assert(ex == L" -1 234 567,89 \u20ac");
assert(ex == convert_thousands_sep(L" -1 234 567,89 \u20ac"));
assert(ios.width() == 0);
}
@ -409,7 +436,7 @@ int main()
output_iterator<wchar_t*> iter = f.put(output_iterator<wchar_t*>(str),
true, ios, '*', v);
std::wstring ex(str, iter.base());
assert(ex == L"1 234 567,89");
assert(ex == convert_thousands_sep(L"1 234 567,89"));
}
{ // negative
long double v = -123456789;
@ -417,7 +444,7 @@ int main()
output_iterator<wchar_t*> iter = f.put(output_iterator<wchar_t*>(str),
true, ios, '*', v);
std::wstring ex(str, iter.base());
assert(ex == L"-1 234 567,89");
assert(ex == convert_thousands_sep(L"-1 234 567,89"));
}
{ // zero, showbase
long double v = 0;
@ -444,7 +471,7 @@ int main()
output_iterator<wchar_t*> iter = f.put(output_iterator<wchar_t*>(str),
true, ios, '*', v);
std::wstring ex(str, iter.base());
assert(ex == L"1 234 567,89 EUR");
assert(ex == convert_thousands_sep(L"1 234 567,89 EUR"));
}
{ // negative, showbase
long double v = -123456789;
@ -453,7 +480,7 @@ int main()
output_iterator<wchar_t*> iter = f.put(output_iterator<wchar_t*>(str),
true, ios, '*', v);
std::wstring ex(str, iter.base());
assert(ex == L"-1 234 567,89 EUR");
assert(ex == convert_thousands_sep(L"-1 234 567,89 EUR"));
}
{ // negative, showbase, left
long double v = -123456789;
@ -464,7 +491,7 @@ int main()
output_iterator<wchar_t*> iter = f.put(output_iterator<wchar_t*>(str),
true, ios, ' ', v);
std::wstring ex(str, iter.base());
assert(ex == L"-1 234 567,89 EUR ");
assert(ex == convert_thousands_sep(L"-1 234 567,89 EUR "));
assert(ios.width() == 0);
}
{ // negative, showbase, internal
@ -476,7 +503,7 @@ int main()
output_iterator<wchar_t*> iter = f.put(output_iterator<wchar_t*>(str),
true, ios, ' ', v);
std::wstring ex(str, iter.base());
assert(ex == L"-1 234 567,89 EUR");
assert(ex == convert_thousands_sep(L"-1 234 567,89 EUR"));
assert(ios.width() == 0);
}
{ // negative, showbase, right
@ -488,7 +515,7 @@ int main()
output_iterator<wchar_t*> iter = f.put(output_iterator<wchar_t*>(str),
true, ios, ' ', v);
std::wstring ex(str, iter.base());
assert(ex == L" -1 234 567,89 EUR");
assert(ex == convert_thousands_sep(L" -1 234 567,89 EUR"));
assert(ios.width() == 0);
}
}

View File

@ -21,7 +21,6 @@
#include <locale>
#include <limits>
#include <cassert>
#include <iostream> // FIXME: for debugging purposes only
#include "test_macros.h"
#include "platform_support.h" // locale name macros
@ -111,7 +110,8 @@ int main()
assert(f.decimal_point() == L',');
}
// GLIBC 2.23 uses '.' as the decimal point while other C libraries use ','
#ifndef TEST_HAS_GLIBC
// GLIBC 2.27 corrects this.
#if !defined(TEST_HAS_GLIBC) || TEST_GLIBC_PREREQ(2, 27)
const char sep = ',';
const wchar_t wsep = L',';
#else
@ -120,11 +120,6 @@ int main()
#endif
{
Fnf f(LOCALE_ru_RU_UTF_8, 1);
if (f.decimal_point() != sep) {
std::cout << "f.decimal_point() = '" << f.decimal_point() << "'\n";
std::cout << "sep = '" << sep << "'\n";
std::cout << std::endl;
}
assert(f.decimal_point() == sep);
}
{

View File

@ -92,7 +92,6 @@ int main()
Fwt f(LOCALE_en_US_UTF_8, 1);
assert(f.thousands_sep() == L',');
}
{
Fnf f(LOCALE_fr_FR_UTF_8, 1);
assert(f.thousands_sep() == ' ');
@ -101,13 +100,19 @@ int main()
Fnt f(LOCALE_fr_FR_UTF_8, 1);
assert(f.thousands_sep() == ' ');
}
// The below tests work around GLIBC's use of U202F as mon_thousands_sep.
#if defined(TEST_HAS_GLIBC) && TEST_GLIBC_PREREQ(2, 27)
const wchar_t fr_sep = L'\u202F';
#else
const wchar_t fr_sep = L' ';
#endif
{
Fwf f(LOCALE_fr_FR_UTF_8, 1);
assert(f.thousands_sep() == L' ');
assert(f.thousands_sep() == fr_sep);
}
{
Fwt f(LOCALE_fr_FR_UTF_8, 1);
assert(f.thousands_sep() == L' ');
assert(f.thousands_sep() == fr_sep);
}
// The below tests work around GLIBC's use of U00A0 as mon_thousands_sep
// and U002E as mon_decimal_point.
@ -116,6 +121,11 @@ int main()
#ifndef TEST_HAS_GLIBC
const char sep = ' ';
const wchar_t wsep = L' ';
#elif TEST_GLIBC_PREREQ(2, 27)
// FIXME libc++ specifically works around \u00A0 by translating it into
// a regular space.
const char sep = ' ';
const wchar_t wsep = L'\u202F';
#else
// FIXME libc++ specifically works around \u00A0 by translating it into
// a regular space.

View File

@ -56,7 +56,12 @@ int main()
std::locale l(LOCALE_fr_FR_UTF_8);
#if defined(TEST_HAS_GLIBC)
const char sep = ' ';
// The below tests work around GLIBC's use of U202F as LC_NUMERIC thousands_sep.
# if TEST_GLIBC_PREREQ(2, 27)
const wchar_t wsep = L'\u202f';
# else
const wchar_t wsep = L' ';
# endif
#else
const char sep = ',';
const wchar_t wsep = L',';