Fix moneypunct_byname algorithm to more accurately represent C locales in C++.
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@152501 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/locale b/include/locale
index f6d3860..bec27f6 100644
--- a/include/locale
+++ b/include/locale
@@ -3060,6 +3060,9 @@
string_type __sym;
string_type __psn;
string_type __nsn;
+ // Capture the spaces read into money_base::{space,none} so they
+ // can be compared to initial spaces in __sym.
+ string_type __spaces;
int __fd;
__money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp,
__sym, __psn, __nsn, __fd);
@@ -3073,7 +3076,7 @@
if (__p != 3)
{
if (__ct.is(ctype_base::space, *__b))
- ++__b;
+ __spaces.push_back(*__b++);
else
{
__err |= ios_base::failbit;
@@ -3085,7 +3088,7 @@
if (__p != 3)
{
while (__b != __e && __ct.is(ctype_base::space, *__b))
- ++__b;
+ __spaces.push_back(*__b++);
}
break;
case money_base::sign:
@@ -3144,9 +3147,31 @@
if (__sb || __more_needed)
{
ios_base::iostate __et = ios_base::goodbit;
- string_type* __k = __scan_keyword(__b, __e, &__sym, &__sym+1,
- __ct, __et);
- if (__sb && __k != &__sym)
+ typename string_type::const_iterator __sym_space_end = __sym.begin();
+ if (__p > 0 && (__pat.field[__p - 1] == money_base::none ||
+ __pat.field[__p - 1] == money_base::space)) {
+ // Match spaces we've already read against spaces at
+ // the beginning of __sym.
+ while (__sym_space_end != __sym.end() &&
+ __ct.is(ctype_base::space, *__sym_space_end))
+ ++__sym_space_end;
+ const size_t __num_spaces = __sym_space_end - __sym.begin();
+ if (__num_spaces > __spaces.size() ||
+ !equal(__spaces.end() - __num_spaces, __spaces.end(),
+ __sym.begin())) {
+ // No match. Put __sym_space_end back at the
+ // beginning of __sym, which will prevent a
+ // match in the next loop.
+ __sym_space_end = __sym.begin();
+ }
+ }
+ typename string_type::const_iterator __sym_curr_char = __sym_space_end;
+ while (__sym_curr_char != __sym.end() && __b != __e &&
+ *__b == *__sym_curr_char) {
+ ++__b;
+ ++__sym_curr_char;
+ }
+ if (__sb && __sym_curr_char != __sym.end())
{
__err |= ios_base::failbit;
return false;