OSDN Git Service

2001-09-13 Benjamin Kosnik <bkoz@redhat.com>
authorbkoz <bkoz@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 13 Sep 2001 23:21:25 +0000 (23:21 +0000)
committerbkoz <bkoz@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 13 Sep 2001 23:21:25 +0000 (23:21 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@45585 138bc75d-0d04-0410-961f-82ee72b054a4

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/locale_facets.h
libstdc++-v3/include/bits/locale_facets.tcc
libstdc++-v3/src/locale-inst.cc
libstdc++-v3/src/locale.cc
libstdc++-v3/testsuite/22_locale/money_get.cc [new file with mode: 0644]
libstdc++-v3/testsuite/22_locale/money_get_members_char.cc [new file with mode: 0644]

index f52b092..66a4b8e 100644 (file)
@@ -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,
index 1e64224..9b81336 100644 (file)
@@ -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
   {
index 5ed35d1..ccf227e 100644 (file)
@@ -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,
index 78464a6..df0a3af 100644 (file)
@@ -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
index 990e662..d69e7e6 100644 (file)
@@ -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 (file)
index 0000000..333af26
--- /dev/null
@@ -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 (file)
index 0000000..6b035e5
--- /dev/null
@@ -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;
+}