aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorBenjamin Kosnik <bkoz@redhat.com>2001-09-13 23:21:25 +0000
committerBenjamin Kosnik <bkoz@gcc.gnu.org>2001-09-13 23:21:25 +0000
commitfb67885447f8021e35a6cc51c2286cfe065ae599 (patch)
tree71f51fbe376cd500205783c3af35a35cc79c431f /libstdc++-v3
parent6a3d403114ac013e8a5e9a8f9496b6d8fd6a8f99 (diff)
downloadgcc-fb67885447f8021e35a6cc51c2286cfe065ae599.zip
gcc-fb67885447f8021e35a6cc51c2286cfe065ae599.tar.gz
gcc-fb67885447f8021e35a6cc51c2286cfe065ae599.tar.bz2
Implement std::money_get.
2001-09-13 Benjamin Kosnik <bkoz@redhat.com> Implement std::money_get. * include/bits/locale_facets.tcc (money_get::do_get): Implement. * include/bits/locale_facets.h (money_get): Correct signatures. * testsuite/22_locale/money_get.cc: New file. * testsuite/22_locale/money_get_members_char.cc: New file. * include/bits/locale_facets.tcc (__verify_grouping): New function. Consolidate num_get and money_get group checking into one function. (money_get): Use it. * src/locale.cc (num_get::_M_extract): Use it. * src/locale-inst.cc: Add instantiation. From-SVN: r45585
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog15
-rw-r--r--libstdc++-v3/include/bits/locale_facets.h162
-rw-r--r--libstdc++-v3/include/bits/locale_facets.tcc327
-rw-r--r--libstdc++-v3/src/locale-inst.cc8
-rw-r--r--libstdc++-v3/src/locale.cc23
-rw-r--r--libstdc++-v3/testsuite/22_locale/money_get.cc53
-rw-r--r--libstdc++-v3/testsuite/22_locale/money_get_members_char.cc279
7 files changed, 720 insertions, 147 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index f52b092..66a4b8e 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,18 @@
+2001-09-13 Benjamin Kosnik <bkoz@redhat.com>
+
+ Implement std::money_get.
+ * include/bits/locale_facets.tcc (money_get::do_get): Implement.
+ * include/bits/locale_facets.h (money_get): Correct signatures.
+ * testsuite/22_locale/money_get.cc: New file.
+ * testsuite/22_locale/money_get_members_char.cc: New file.
+
+ * include/bits/locale_facets.tcc (__verify_grouping): New
+ function. Consolidate num_get and money_get group checking into
+ one function.
+ (money_get): Use it.
+ * src/locale.cc (num_get::_M_extract): Use it.
+ * src/locale-inst.cc: Add instantiation.
+
2001-09-12 Gabriel Dos Reis <gdr@merlin.codesourcery.com>
* include/bits/std_limits.h (numeric_limits<float>::radix,
diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h
index 1e64224..9b81336 100644
--- a/libstdc++-v3/include/bits/locale_facets.h
+++ b/libstdc++-v3/include/bits/locale_facets.h
@@ -1212,88 +1212,6 @@ namespace std
};
- template<typename _CharT, typename _InIter>
- class money_get : public locale::facet
- {
- public:
- typedef _CharT char_type;
- typedef _InIter iter_type;
- typedef basic_string<_CharT> string_type;
-
- static locale::id id;
-
- explicit
- money_get(size_t __refs = 0) : locale::facet(__refs) { }
-
- iter_type
- get(iter_type __s, iter_type __end, bool __intl,
- ios_base& __f, ios_base::iostate& __err, long double& __units) const
- { return do_get(__s, __end, __intl, __f, __err, __units); }
-
- iter_type
- get(iter_type __s, iter_type __end, bool __intl, ios_base& __f,
- ios_base::iostate& __err, string_type& __digits) const
- { return do_get(__s, __end, __intl, __f, __err, __digits); }
-
- protected:
- virtual
- ~money_get() { }
-
- virtual iter_type
- do_get(iter_type __s, iter_type /*__end*/, bool /*__intl*/,
- ios_base& /*__io*/, ios_base::iostate& /*__err*/,
- long double& /*__units*/) const
- { return __s; }
-
- virtual iter_type
- do_get(iter_type __s, iter_type /*__end*/, bool /*__intl*/,
- ios_base& /*__io*/, ios_base::iostate& /*__err*/,
- string_type& /*__digits*/) const
- { return __s; }
- };
-
- template<typename _CharT, typename _InIter>
- locale::id money_get<_CharT, _InIter>::id;
-
- template<typename _CharT, typename _OutIter>
- class money_put : public locale::facet
- {
- public:
- typedef _CharT char_type;
- typedef _OutIter iter_type;
- typedef basic_string<_CharT> string_type;
-
- static locale::id id;
-
- explicit
- money_put(size_t __refs = 0) : locale::facet(__refs) { }
-
- iter_type
- put(iter_type __s, bool __intl, ios_base& __f,
- char_type __fill, long double __units) const
- { return this->do_put(__s, __intl, __f, __fill, __units); }
-
- iter_type
- put(iter_type __s, bool __intl, ios_base& __f,
- char_type __fill, const string_type& __digits) const
- { return this->do_put(__s, __intl, __f, __fill, __digits); }
-
- protected:
- virtual
- ~money_put() { }
-
- virtual iter_type
- do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
- long double __units) const;
-
- virtual iter_type
- do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
- const string_type& __digits) const;
- };
-
- template<typename _CharT, typename _OutIter>
- locale::id money_put<_CharT, _OutIter>::id;
-
struct money_base
{
enum part { none, space, symbol, sign, value };
@@ -1477,6 +1395,86 @@ namespace std
template<typename _CharT, bool _Intl>
const bool moneypunct_byname<_CharT, _Intl>::intl;
+ template<typename _CharT, typename _InIter>
+ class money_get : public locale::facet
+ {
+ public:
+ typedef _CharT char_type;
+ typedef _InIter iter_type;
+ typedef basic_string<_CharT> string_type;
+
+ static locale::id id;
+
+ explicit
+ money_get(size_t __refs = 0) : locale::facet(__refs) { }
+
+ iter_type
+ get(iter_type __s, iter_type __end, bool __intl,
+ ios_base& __f, ios_base::iostate& __err, long double& __units) const
+ { return this->do_get(__s, __end, __intl, __f, __err, __units); }
+
+ iter_type
+ get(iter_type __s, iter_type __end, bool __intl, ios_base& __f,
+ ios_base::iostate& __err, string_type& __digits) const
+ { return this->do_get(__s, __end, __intl, __f, __err, __digits); }
+
+ protected:
+ virtual
+ ~money_get() { }
+
+ virtual iter_type
+ do_get(iter_type __s, iter_type __end, bool __intl,
+ ios_base& __io, ios_base::iostate& __err,
+ long double& __units) const;
+
+ virtual iter_type
+ do_get(iter_type __s, iter_type __end, bool __intl,
+ ios_base& __io, ios_base::iostate& __err,
+ string_type& __digits) const;
+ };
+
+ template<typename _CharT, typename _InIter>
+ locale::id money_get<_CharT, _InIter>::id;
+
+ template<typename _CharT, typename _OutIter>
+ class money_put : public locale::facet
+ {
+ public:
+ typedef _CharT char_type;
+ typedef _OutIter iter_type;
+ typedef basic_string<_CharT> string_type;
+
+ static locale::id id;
+
+ explicit
+ money_put(size_t __refs = 0) : locale::facet(__refs) { }
+
+ iter_type
+ put(iter_type __s, bool __intl, ios_base& __f,
+ char_type __fill, long double __units) const
+ { return this->do_put(__s, __intl, __f, __fill, __units); }
+
+ iter_type
+ put(iter_type __s, bool __intl, ios_base& __f,
+ char_type __fill, const string_type& __digits) const
+ { return this->do_put(__s, __intl, __f, __fill, __digits); }
+
+ protected:
+ virtual
+ ~money_put() { }
+
+ virtual iter_type
+ do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
+ long double __units) const;
+
+ virtual iter_type
+ do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
+ const string_type& __digits) const;
+ };
+
+ template<typename _CharT, typename _OutIter>
+ locale::id money_put<_CharT, _OutIter>::id;
+
struct messages_base
{
diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc
index 5ed35d1..ccf227e 100644
--- a/libstdc++-v3/include/bits/locale_facets.tcc
+++ b/libstdc++-v3/include/bits/locale_facets.tcc
@@ -227,19 +227,227 @@ namespace std
return __ncp;
}
+ template<typename _CharT, typename _InIter>
+ money_get<_CharT, _InIter>::iter_type
+ money_get<_CharT, _InIter>::do_get(iter_type __s, iter_type __end,
+ bool __intl, ios_base& __io,
+ ios_base::iostate& __err,
+ long double& __units) const
+ {
+ string_type __str;
+ this->do_get(__s, __end, __intl, __io, __err, __str);
+
+ const int __n = numeric_limits<long double>::digits10;
+ char* __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __n));
+ const locale __loc = __io.getloc();
+ const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+ const _CharT* __wcs = __str.c_str();
+ __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs);
+
+ char* __sanity;
+ errno = 0;
+ long double __ld = strtold(__cs, &__sanity);
+ if (!(__err & ios_base::failbit)
+ && __sanity != __cs && *__sanity == '\0' && errno == 0)
+ __units = __ld;
+ return __s;
+ }
+
+ template<typename _CharT, typename _InIter>
+ money_get<_CharT, _InIter>::iter_type
+ money_get<_CharT, _InIter>::do_get(iter_type __s, iter_type __end,
+ bool __intl, ios_base& __io,
+ ios_base::iostate& __err,
+ string_type& __units) const
+ {
+ // These contortions are quite unfortunate.
+ typedef moneypunct<_CharT, true> __money_true;
+ typedef moneypunct<_CharT, false> __money_false;
+ typedef money_base::part part;
+ typedef typename string_type::size_type size_type;
+
+ const locale __loc = __io.getloc();
+ const __money_true& __mpt = use_facet<__money_true>(__loc);
+ const __money_false& __mpf = use_facet<__money_false>(__loc);
+ const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+
+ const money_base::pattern __p = __intl ? __mpt.neg_format()
+ : __mpf.neg_format();
+
+ const string_type __pos_sign =__intl ? __mpt.positive_sign()
+ : __mpf.positive_sign();
+ const string_type __neg_sign =__intl ? __mpt.negative_sign()
+ : __mpf.negative_sign();
+ const char_type __d = __intl ? __mpt.decimal_point()
+ : __mpf.decimal_point();
+ const char_type __sep = __intl ? __mpt.thousands_sep()
+ : __mpf.thousands_sep();
+
+ const string __grouping = __intl ? __mpt.grouping()
+ : __mpf.grouping();
+
+ // Set to deduced positive or negative sign, depending.
+ string_type __sign;
+ // String of grouping info from thousands_sep plucked from __units.
+ string __grouping_tmp;
+ // Marker for thousands_sep position.
+ int __sep_pos = 0;
+ // If input iterator is in a valid state.
+ bool __testvalid = true;
+ // Flag marking when a decimal point is found.
+ bool __testdecfound = false;
+
+ char_type __c = *__s;
+ char_type __eof = static_cast<char_type>(char_traits<char_type>::eof());
+ for (int __i = 0; __s != __end && __i < 4 && __testvalid; ++__i)
+ {
+ part __which = static_cast<part>(__p.field[__i]);
+ switch (__which)
+ {
+ case money_base::symbol:
+ if (__io.flags() & ios_base::showbase)
+ {
+ // Symbol is required.
+ const string_type __symbol = __intl ? __mpt.curr_symbol()
+ : __mpf.curr_symbol();
+ size_type __len = __symbol.size();
+ size_type __i = 0;
+ while (__s != __end
+ && __i < __len && __symbol[__i] == __c)
+ {
+ __c = *(++__s);
+ ++__i;
+ }
+ if (__i != __len)
+ __testvalid = false;
+ }
+ break;
+ case money_base::sign:
+ // Sign might not exist, or be more than one character long.
+ if (__pos_sign.size() && __neg_sign.size())
+ {
+ // Sign is mandatory.
+ if (__c == __pos_sign[0])
+ {
+ __sign = __pos_sign;
+ __c = *(++__s);
+ }
+ else if (__c == __neg_sign[0])
+ {
+ __sign = __neg_sign;
+ __c = *(++__s);
+ }
+ else
+ __testvalid = false;
+ }
+ else if (__pos_sign.size() && __c == __pos_sign[0])
+ {
+ __sign = __pos_sign;
+ __c = *(++__s);
+ }
+ else if (__neg_sign.size() && __c == __neg_sign[0])
+ {
+ __sign = __neg_sign;
+ __c = *(++__s);
+ }
+ break;
+ case money_base::value:
+ // Extract digits, remove and stash away the
+ // grouping of found thousands separators.
+ while (__s != __end
+ && (__ctype.is(ctype_base::digit, __c)
+ || (__c == __d && !__testdecfound)
+ || __c == __sep))
+ {
+ if (__c == __d)
+ {
+ __grouping_tmp += static_cast<char>(__sep_pos);
+ __sep_pos = 0;
+ __testdecfound = true;
+ }
+ else if (__c == __sep)
+ {
+ if (__grouping.size())
+ {
+ // Mark position for later analysis.
+ __grouping_tmp += static_cast<char>(__sep_pos);
+ __sep_pos = 0;
+ }
+ else
+ {
+ __testvalid = false;
+ break;
+ }
+ }
+ else
+ {
+ __units += __c;
+ ++__sep_pos;
+ }
+ __c = *(++__s);
+ }
+ break;
+ case money_base::space:
+ case money_base::none:
+ // Only if not at the end of the pattern.
+ if (__i != 3)
+ while (__s != __end && __ctype.is(ctype_base::space, __c))
+ __c = *(++__s);
+ break;
+ }
+ }
+
+ // Need to get the rest of the sign characters, if they exist.
+ if (__sign.size() > 1)
+ {
+ size_type __len = __sign.size();
+ size_type __i = 1;
+ for (; __c != __eof && __i < __len; ++__i)
+ while (__s != __end && __c != __sign[__i])
+ __c = *(++__s);
+
+ if (__i != __len)
+ __testvalid = false;
+ }
+
+ // Strip leading zeros.
+ while (__units[0] == __ctype.widen('0'))
+ __units.erase(__units.begin());
+
+ if (__sign == __neg_sign)
+ __units.insert(__units.begin(), __ctype.widen('-'));
+
+ // Test for grouping fidelity.
+ if (__grouping.size() && __grouping_tmp.size())
+ {
+ if (!__verify_grouping(__grouping, __grouping_tmp))
+ __testvalid = false;
+ }
+
+ // Iff no more characters are available.
+ if (__c == __eof)
+ __err |= ios_base::eofbit;
+
+ // Iff valid sequence is not recognized.
+ if (!__testvalid || !__units.size())
+ __err |= ios_base::failbit;
+
+ return __s;
+ }
+
template<typename _CharT, typename _OutIter>
money_put<_CharT, _OutIter>::iter_type
money_put<_CharT, _OutIter>::do_put(iter_type __s, bool __intl,
ios_base& __io, char_type __fill,
long double __units) const
{
- locale __loc = __io.getloc();
- const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
+ const locale __loc = __io.getloc();
+ const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
const int __n = numeric_limits<long double>::digits10;
char* __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __n));
_CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
int __len = sprintf(__cs, "%.01Lf", __units);
- __ct.widen(__cs, __cs + __len, __ws);
+ __ctype.widen(__cs, __cs + __len, __ws);
string_type __digits(__ws);
return this->do_put(__s, __intl, __io, __fill, __digits);
}
@@ -250,17 +458,18 @@ namespace std
ios_base& __io, char_type __fill,
const string_type& __digits) const
{
- typedef typename string_type::size_type size_type;
+ typedef typename string_type::size_type size_type;
+ typedef money_base::part part;
- locale __loc = __io.getloc();
- size_type __width = static_cast<size_type>(__io.width());
+ const locale __loc = __io.getloc();
+ const size_type __width = static_cast<size_type>(__io.width());
// These contortions are quite unfortunate.
typedef moneypunct<_CharT, true> __money_true;
typedef moneypunct<_CharT, false> __money_false;
const __money_true& __mpt = use_facet<__money_true>(__loc);
const __money_false& __mpf = use_facet<__money_false>(__loc);
- const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
+ const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
// Determine if negative or positive formats are to be used, and
// discard leading negative_sign if it is present.
@@ -268,7 +477,7 @@ namespace std
const char_type* __end = __beg + __digits.size();
money_base::pattern __p;
string_type __sign;
- if (*__beg != __ct.widen('-'))
+ if (*__beg != __ctype.widen('-'))
{
__p = __intl ? __mpt.pos_format() : __mpf.pos_format();
__sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign();
@@ -281,7 +490,7 @@ namespace std
}
// Look for valid numbers in the current ctype facet within input digits.
- __end = __ct.scan_not(ctype_base::digit, __beg, __end);
+ __end = __ctype.scan_not(ctype_base::digit, __beg, __end);
if (__beg != __end)
{
// Assume valid input, and attempt to format.
@@ -289,15 +498,16 @@ namespace std
// final_value = grouped units + (decimal point) + (digits)
string_type __res;
string_type __value;
- string_type __symbol = __intl
- ? __mpt.curr_symbol() : __mpf.curr_symbol();
+ const string_type __symbol = __intl ? __mpt.curr_symbol()
+ : __mpf.curr_symbol();
// Deal with decimal point, decimal digits.
- int __frac = __intl ? __mpt.frac_digits() : __mpf.frac_digits();
+ const int __frac = __intl ? __mpt.frac_digits()
+ : __mpf.frac_digits();
if (__frac > 0)
{
- char_type __d = __intl
- ? __mpt.decimal_point() : __mpf.decimal_point();
+ const char_type __d = __intl ? __mpt.decimal_point()
+ : __mpf.decimal_point();
if (__end - __beg >= __frac)
{
__value = string_type(__end - __frac, __end);
@@ -309,7 +519,7 @@ namespace std
// Have to pad zeros in the decimal position.
__value = string_type(__beg, __end);
int __paddec = __frac - (__end - __beg);
- char_type __zero = __ct.widen('0');
+ char_type __zero = __ctype.widen('0');
__value.insert(__value.begin(), __paddec, __zero);
__value.insert(__value.begin(), __d);
__beg = __end;
@@ -320,11 +530,12 @@ namespace std
// grouping rules.
if (__beg != __end)
{
- string __grouping = __intl ? __mpt.grouping() : __mpf.grouping();
+ const string __grouping = __intl ? __mpt.grouping()
+ : __mpf.grouping();
if (__grouping.size())
{
- char_type __sep = __intl ? __mpt.thousands_sep()
- : __mpf.thousands_sep();
+ const char_type __sep = __intl ? __mpt.thousands_sep()
+ : __mpf.thousands_sep();
const char* __gbeg = __grouping.data();
const char* __gend = __gbeg + __grouping.size();
const int __n = numeric_limits<long double>::digits10 * 2;
@@ -346,7 +557,6 @@ namespace std
// Fit formatted digits into the required pattern.
for (int __i = 0; __i < 4; ++__i)
{
- typedef money_base::part part;
part __which = static_cast<part>(__p.field[__i]);
switch (__which)
{
@@ -371,7 +581,7 @@ namespace std
if (__testipad)
__res += string_type(__width - __len, __fill);
else
- __res += __ct.widen(' ');
+ __res += __ctype.widen(' ');
break;
case money_base::none:
if (__testipad)
@@ -888,11 +1098,11 @@ namespace std
}
// __pad is specialized for ostreambuf_iterator, random access iterator.
- template <typename _CharT, typename _OutIter>
+ template<typename _CharT, typename _OutIter>
inline _OutIter
__pad(_OutIter __s, _CharT __fill, int __padding);
- template <typename _CharT, typename _RaIter>
+ template<typename _CharT, typename _RaIter>
_RaIter
__pad(_RaIter __s, _CharT __fill, int __padding,
random_access_iterator_tag)
@@ -901,7 +1111,7 @@ namespace std
return __s + __padding;
}
- template <typename _CharT, typename _OutIter, typename _Tag>
+ template<typename _CharT, typename _OutIter, typename _Tag>
_OutIter
__pad(_OutIter __s, _CharT __fill, int __padding, _Tag)
{
@@ -909,7 +1119,7 @@ namespace std
return __s;
}
- template <typename _CharT, typename _OutIter>
+ template<typename _CharT, typename _OutIter>
inline _OutIter
__pad(_OutIter __s, _CharT __fill, int __padding)
{
@@ -917,7 +1127,7 @@ namespace std
typename iterator_traits<_OutIter>::iterator_category());
}
- template <typename _CharT, typename _OutIter>
+ template<typename _CharT, typename _OutIter>
_OutIter
__pad_numeric(_OutIter __s, ios_base::fmtflags /*__flags*/,
_CharT /*__fill*/, int /*__width*/,
@@ -929,7 +1139,7 @@ namespace std
}
// Partial specialization for ostreambuf_iterator.
- template <typename _CharT>
+ template<typename _CharT>
ostreambuf_iterator<_CharT>
__pad_numeric(ostreambuf_iterator<_CharT> __s, ios_base::fmtflags __flags,
_CharT __fill, int __width, _CharT const* __first,
@@ -966,7 +1176,7 @@ namespace std
return __s3;
}
- template <typename _CharT, typename _OutIter>
+ template<typename _CharT, typename _OutIter>
_OutIter
num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
@@ -998,11 +1208,42 @@ namespace std
return __s;
}
- // __group_digits inserts "group separator" characters into an array
- // of characters. It's recursive, one iteration per group. It moves
- // the characters in the buffer this way: "xxxx12345" -> "12,345xxx".
- // Call this only with __gbeg != __gend.
- template <typename _CharT>
+ // Check to make sure that the __grouping_tmp string constructed in
+ // money_get or num_get matches the canonical grouping for a given
+ // locale.
+ // __grouping_tmp is parsed L to R
+ // 1,222,444 == __grouping_tmp of "/1/3/3"
+ // __grouping is parsed R to L
+ // 1,222,444 == __grouping of "/3" == "/3/3/3"
+ template<typename _CharT>
+ bool
+ __verify_grouping(const basic_string<_CharT>& __grouping,
+ basic_string<_CharT>& __grouping_tmp)
+ {
+ int __i = 0;
+ int __j = 0;
+ const int __len = __grouping.size();
+ const int __n = __grouping_tmp.size();
+ bool __test = true;
+
+ // Parsed number groupings have to match the
+ // numpunct::grouping string exactly, starting at the
+ // right-most point of the parsed sequence of elements ...
+ while (__test && __i < __n - 1)
+ for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i)
+ __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1];
+ // ... but the last parsed grouping can be <= numpunct
+ // grouping.
+ __j == __len ? __j = 0 : __j;
+ __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1];
+ return __test;
+ }
+
+ // Inserts "group separator" characters into an array of characters.
+ // It's recursive, one iteration per group. It moves the characters
+ // in the buffer this way: "xxxx12345" -> "12,345xxx". Call this
+ // only with __gbeg != __gend.
+ template<typename _CharT>
_CharT*
__group_digits(_CharT* __s, _CharT __sep,
const char* __gbeg, const char* __gend,
@@ -1024,7 +1265,7 @@ namespace std
return __s;
}
- template <typename _CharT, typename _OutIter, typename _ValueT>
+ template<typename _CharT, typename _OutIter, typename _ValueT>
_OutIter
__output_integer(_OutIter __s, ios_base& __io, _CharT __fill, bool __neg,
_ValueT __v)
@@ -1097,7 +1338,7 @@ namespace std
__digits, __p, __digits_end);
}
- template <typename _CharT, typename _OutIter>
+ template<typename _CharT, typename _OutIter>
_OutIter
num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
@@ -1112,7 +1353,7 @@ namespace std
return __output_integer(__s, __io, __fill, __neg, __uv);
}
- template <typename _CharT, typename _OutIter>
+ template<typename _CharT, typename _OutIter>
_OutIter
num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __io, char_type __fill,
@@ -1120,7 +1361,7 @@ namespace std
{ return __output_integer(__s, __io, __fill, false, __v); }
#ifdef _GLIBCPP_USE_LONG_LONG
- template <typename _CharT, typename _OutIter>
+ template<typename _CharT, typename _OutIter>
_OutIter
num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
@@ -1135,7 +1376,7 @@ namespace std
return __output_integer(__s, __b, __fill, __neg, __uv);
}
- template <typename _CharT, typename _OutIter>
+ template<typename _CharT, typename _OutIter>
_OutIter
num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __io, char_type __fill,
@@ -1162,7 +1403,7 @@ namespace std
size_t __padding = __io.width() > streamsize(__slen) ?
__io.width() -__slen : 0;
locale __loc = __io.getloc();
- ctype<_CharT> const& __ct = use_facet<ctype<_CharT> >(__loc);
+ ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
ios_base::fmtflags __adjfield = __io.flags() & ios_base::adjustfield;
const char* const __eptr = __sptr + __slen;
// [22.2.2.2.2.19] Table 61
@@ -1171,7 +1412,7 @@ namespace std
// [22.2.2.2.2.14]; widen()
if (__sptr < __eptr && (*__sptr == '+' || *__sptr == '-'))
{
- __s = __ct.widen(*__sptr);
+ __s = __ctype.widen(*__sptr);
++__s;
++__sptr;
}
@@ -1193,7 +1434,7 @@ namespace std
__s = __fmt->_M_decimal_point;
// [22.2.2.2.2.14]; widen()
else
- __s = __ct.widen(*__sptr);
+ __s = __ctype.widen(*__sptr);
}
// [22.2.2.2.2.19] Table 61
if (__padding)
@@ -1206,7 +1447,7 @@ namespace std
__build_float_format(ios_base& __io, char* __fptr, char __modifier,
streamsize __prec);
- template <typename _CharT, typename _OutIter>
+ template<typename _CharT, typename _OutIter>
_OutIter
num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
@@ -1229,7 +1470,7 @@ namespace std
return __output_float(__s, __io, __fill, __sbuf, __slen);
}
- template <typename _CharT, typename _OutIter>
+ template<typename _CharT, typename _OutIter>
_OutIter
num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __io, char_type __fill,
@@ -1254,7 +1495,7 @@ namespace std
return __output_float(__s, __io, __fill, __sbuf, __slen);
}
- template <typename _CharT, typename _OutIter>
+ template<typename _CharT, typename _OutIter>
_OutIter
num_put<_CharT, _OutIter>::
do_put(iter_type __s, ios_base& __io, char_type __fill,
diff --git a/libstdc++-v3/src/locale-inst.cc b/libstdc++-v3/src/locale-inst.cc
index 78464a6..df0a3af 100644
--- a/libstdc++-v3/src/locale-inst.cc
+++ b/libstdc++-v3/src/locale-inst.cc
@@ -264,6 +264,10 @@ namespace std
__group_digits<char>(char*, char, char const*, char const*,
char const*, char const*);
+ template
+ bool
+ __verify_grouping<char>(const basic_string<char>&, basic_string<char>&);
+
template
ostreambuf_iter
__output_integer<char, ostreambuf_iter, unsigned long>
@@ -298,6 +302,10 @@ namespace std
wchar_t*
__group_digits<wchar_t>(wchar_t*, wchar_t, char const*, char const*,
wchar_t const*, wchar_t const*);
+ template
+ bool
+ __verify_grouping<wchar_t>(const basic_string<wchar_t>&,
+ basic_string<wchar_t>&);
template
wostreambuf_iter
diff --git a/libstdc++-v3/src/locale.cc b/libstdc++-v3/src/locale.cc
index 990e6624..d69e7e6 100644
--- a/libstdc++-v3/src/locale.cc
+++ b/libstdc++-v3/src/locale.cc
@@ -646,28 +646,7 @@ namespace std
// Add the ending grouping
__grp += static_cast<char>(__sep_pos);
- // __grp is parsed L to R
- // 1,222,444 == __grp of "/1/3/3"
- // __fmt->_M_grouping is parsed R to L
- // 1,222,444 == __fmt->_M_grouping of "/3" == "/3/3/3"
- int __i = 0;
- int __j = 0;
- const int __len = __fmt->_M_grouping.size();
- int __n = __grp.size();
- bool __test = true;
-
- // Parsed number groupings have to match the
- // numpunct::grouping string exactly, starting at the
- // right-most point of the parsed sequence of elements ...
- while (__test && __i < __n - 1)
- for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i)
- __test &= __fmt->_M_grouping[__j] == __grp[__n - __i - 1];
- // ... but the last parsed grouping can be <= numpunct
- // grouping.
- __j == __len ? __j = 0 : __j;
- __test &= __fmt->_M_grouping[__j] >= __grp[__n - __i - 1];
-
- if (!__test)
+ if (!__verify_grouping(__fmt->_M_grouping, __grp))
{
__err |= ios_base::failbit;
__xtrc[__pos] = '\0';
diff --git a/libstdc++-v3/testsuite/22_locale/money_get.cc b/libstdc++-v3/testsuite/22_locale/money_get.cc
new file mode 100644
index 0000000..333af26
--- /dev/null
+++ b/libstdc++-v3/testsuite/22_locale/money_get.cc
@@ -0,0 +1,53 @@
+// 2001-09-12 Benjamin Kosnik <bkoz@redhat.com>
+
+// Copyright (C) 2001 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library. This library 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, or (at your option)
+// any later version.
+
+// This library 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 library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 22.2.6.1 Template class money_get
+
+#include <locale>
+
+void test01()
+{
+ // Check for required base class.
+ typedef std::money_get<char> test_type;
+ typedef std::locale::facet base_type;
+ const test_type& obj = std::use_facet<test_type>(std::locale());
+ const base_type* base = &obj;
+
+ // Check for required typedefs
+ typedef test_type::char_type char_type;
+ typedef test_type::string_type string_type;
+ typedef test_type::iter_type iter_type;
+}
+
+// Should be able to instantiate this for other types besides char, wchar_t
+class gnu_money_get: public std::money_get<unsigned char>
+{ };
+
+void test02()
+{
+ gnu_money_get facet01;
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/22_locale/money_get_members_char.cc b/libstdc++-v3/testsuite/22_locale/money_get_members_char.cc
new file mode 100644
index 0000000..6b035e5
--- /dev/null
+++ b/libstdc++-v3/testsuite/22_locale/money_get_members_char.cc
@@ -0,0 +1,279 @@
+// 2001-09-12 Benjamin Kosnik <bkoz@redhat.com>
+
+// Copyright (C) 2001 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library. This library 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, or (at your option)
+// any later version.
+
+// This library 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 library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 22.2.6.1.1 money_get members
+
+#include <locale>
+#include <sstream>
+#include <testsuite_hooks.h>
+
+// XXX This test is not working for non-glibc locale models.
+// { dg-do run { xfail *-*-* } }
+
+// test string version
+void test01()
+{
+ using namespace std;
+ typedef money_base::part part;
+ typedef money_base::pattern pattern;
+ typedef istreambuf_iterator<char> iterator_type;
+
+ bool test = true;
+ string str;
+
+ // basic construction
+ locale loc_c = locale::classic();
+ str = loc_c.name();
+
+ locale loc_hk("en_HK");
+ str = loc_hk.name();
+ VERIFY( loc_c != loc_hk );
+
+ locale loc_fr("fr_FR@euro");
+ str = loc_fr.name();
+ VERIFY( loc_c != loc_fr );
+
+ locale loc_de("de_DE");
+ str = loc_de.name();
+ VERIFY( loc_c != loc_de );
+
+ VERIFY( loc_hk != loc_fr );
+ VERIFY( loc_hk != loc_de );
+ VERIFY( loc_de != loc_fr );
+
+ // cache the moneypunct facets
+ typedef moneypunct<char, true> __money_true;
+ typedef moneypunct<char, false> __money_false;
+ const __money_true& monpunct_c_t = use_facet<__money_true>(loc_c);
+ const __money_true& monpunct_de_t = use_facet<__money_true>(loc_de);
+ const __money_false& monpunct_c_f = use_facet<__money_false>(loc_c);
+ const __money_false& monpunct_de_f = use_facet<__money_false>(loc_de);
+ const __money_true& monpunct_hk_t = use_facet<__money_true>(loc_hk);
+ const __money_false& monpunct_hk_f = use_facet<__money_false>(loc_hk);
+
+ // sanity check the data is correct.
+ const string empty;
+
+ // total EPA budget FY 2002
+ const string digits1("720000000000");
+
+ // est. cost, national missle "defense", expressed as a loss in USD 2001
+ const string digits2("-10000000000000");
+
+ // not valid input
+ const string digits3("-A");
+
+ // input less than frac_digits
+ const string digits4("-1");
+
+ iterator_type end;
+ istringstream iss;
+ iss.imbue(loc_de);
+ // cache the money_get facet
+ const money_get<char>& mon_get = use_facet<money_get<char> >(iss.getloc());
+
+
+ iss.str("7.200.000.000,00 ");
+ iterator_type is_it01(iss);
+ string result1;
+ ios_base::iostate err01 = ios_base::goodbit;
+ mon_get.get(is_it01, end, true, iss, err01, result1);
+ VERIFY( result1 == digits1 );
+ VERIFY( err01 == ios_base::eofbit );
+
+ iss.str("7.200.000.000,00 ");
+ iterator_type is_it02(iss);
+ string result2;
+ ios_base::iostate err02 = ios_base::goodbit;
+ mon_get.get(is_it02, end, true, iss, err02, result2);
+ VERIFY( result2 == digits1 );
+ VERIFY( err02 == ios_base::eofbit );
+
+ iss.str("7.200.000.000,00 a");
+ iterator_type is_it03(iss);
+ string result3;
+ ios_base::iostate err03 = ios_base::goodbit;
+ mon_get.get(is_it03, end, true, iss, err03, result3);
+ VERIFY( result3 == digits1 );
+ VERIFY( err03 == ios_base::goodbit );
+
+ iss.str("");
+ iterator_type is_it04(iss);
+ string result4;
+ ios_base::iostate err04 = ios_base::goodbit;
+ mon_get.get(is_it04, end, true, iss, err04, result4);
+ VERIFY( result4 == empty );
+ VERIFY( err04 == ios_base::failbit | ios_base::eofbit );
+
+ iss.str("working for enlightenment and peace in a mad world");
+ iterator_type is_it05(iss);
+ string result5;
+ ios_base::iostate err05 = ios_base::goodbit;
+ mon_get.get(is_it05, end, true, iss, err05, result5);
+ VERIFY( result5 == empty );
+ VERIFY( err05 == ios_base::failbit );
+
+ // now try with showbase, to get currency symbol in format
+ iss.setf(ios_base::showbase);
+
+ iss.str("7.200.000.000,00 DEM ");
+ iterator_type is_it06(iss);
+ string result6;
+ ios_base::iostate err06 = ios_base::goodbit;
+ mon_get.get(is_it06, end, true, iss, err06, result6);
+ VERIFY( result6 == digits1 );
+ VERIFY( err06 == ios_base::eofbit );
+
+ iss.str("7.200.000.000,00 DEM "); // Extra space.
+ iterator_type is_it07(iss);
+ string result7;
+ ios_base::iostate err07 = ios_base::goodbit;
+ mon_get.get(is_it07, end, true, iss, err07, result7);
+ VERIFY( result7 == digits1 );
+ VERIFY( err07 == ios_base::goodbit );
+
+ iss.str("7.200.000.000,00 DM");
+ iterator_type is_it08(iss);
+ string result8;
+ ios_base::iostate err08 = ios_base::goodbit;
+ mon_get.get(is_it08, end, false, iss, err08, result8);
+ VERIFY( result8 == digits1 );
+ VERIFY( err08 == ios_base::eofbit );
+
+ iss.imbue(loc_hk);
+ iss.str("HK$7,200,000,000.00");
+ iterator_type is_it09(iss);
+ string result9;
+ ios_base::iostate err09 = ios_base::goodbit;
+ mon_get.get(is_it09, end, false, iss, err09, result9);
+ VERIFY( result9 == digits1 );
+ VERIFY( err09 == ios_base::eofbit );
+
+ iss.str("(HKD 100,000,000,000.00)");
+ iterator_type is_it10(iss);
+ string result10;
+ ios_base::iostate err10 = ios_base::goodbit;
+ mon_get.get(is_it10, end, true, iss, err10, result10);
+ VERIFY( result10 == digits2 );
+ VERIFY( err10 == ios_base::goodbit );
+
+ iss.str("(HKD .01)");
+ iterator_type is_it11(iss);
+ string result11;
+ ios_base::iostate err11 = ios_base::goodbit;
+ mon_get.get(is_it11, end, true, iss, err11, result11);
+ VERIFY( result11 == digits4 );
+ VERIFY( err11 == ios_base::goodbit );
+}
+
+// test double/string versions
+void test02()
+{
+ using namespace std;
+ typedef money_base::part part;
+ typedef money_base::pattern pattern;
+ typedef istreambuf_iterator<char> iterator_type;
+
+ bool test = true;
+ string str;
+
+ // basic construction
+ locale loc_c = locale::classic();
+ str = loc_c.name();
+
+ locale loc_hk("en_HK");
+ str = loc_hk.name();
+ VERIFY( loc_c != loc_hk );
+
+ locale loc_fr("fr_FR@euro");
+ str = loc_fr.name();
+ VERIFY( loc_c != loc_fr );
+
+ locale loc_de("de_DE");
+ str = loc_de.name();
+ VERIFY( loc_c != loc_de );
+
+ VERIFY( loc_hk != loc_fr );
+ VERIFY( loc_hk != loc_de );
+ VERIFY( loc_de != loc_fr );
+
+ // cache the moneypunct facets
+ typedef moneypunct<char, true> __money_true;
+ typedef moneypunct<char, false> __money_false;
+ const __money_true& monpunct_c_t = use_facet<__money_true>(loc_c);
+ const __money_true& monpunct_de_t = use_facet<__money_true>(loc_de);
+ const __money_false& monpunct_c_f = use_facet<__money_false>(loc_c);
+ const __money_false& monpunct_de_f = use_facet<__money_false>(loc_de);
+ const __money_true& monpunct_hk_t = use_facet<__money_true>(loc_hk);
+ const __money_false& monpunct_hk_f = use_facet<__money_false>(loc_hk);
+
+ // sanity check the data is correct.
+ const string empty;
+
+ // total EPA budget FY 2002
+ const long double digits1 = 720000000000;
+
+ // est. cost, national missle "defense", expressed as a liss in USD 2001
+ const long double digits2 = -10000000000000;
+
+ // input less than frac_digits
+ const long double digits4 = -1;
+
+ iterator_type end;
+ istringstream iss;
+ iss.imbue(loc_de);
+ // cache the money_get facet
+ const money_get<char>& mon_get = use_facet<money_get<char> >(iss.getloc());
+
+ iss.str("7.200.000.000,00 ");
+ iterator_type is_it01(iss);
+ long double result1;
+ ios_base::iostate err01 = ios_base::goodbit;
+ mon_get.get(is_it01, end, true, iss, err01, result1);
+ VERIFY( result1 == digits1 );
+ VERIFY( err01 == ios_base::eofbit );
+
+ iss.str("7.200.000.000,00 ");
+ iterator_type is_it02(iss);
+ long double result2;
+ ios_base::iostate err02 = ios_base::goodbit;
+ mon_get.get(is_it02, end, false, iss, err02, result2);
+ VERIFY( result2 == digits1 );
+ VERIFY( err02 == ios_base::eofbit );
+
+ // now try with showbase, to get currency symbol in format
+ iss.setf(ios_base::showbase);
+
+ iss.imbue(loc_hk);
+ iss.str("(HKD .01)");
+ iterator_type is_it03(iss);
+ long double result3;
+ ios_base::iostate err03 = ios_base::goodbit;
+ mon_get.get(is_it03, end, true, iss, err03, result3);
+ VERIFY( result3 == digits4 );
+ VERIFY( err03 == ios_base::goodbit );
+}
+
+int main()
+{
+ test01();
+ test02();
+ return 0;
+}