This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix money_get::do_get for multi char sign


Hi,

this is for the last problem I'm aware of. 'Til now I failed to take into proper
account this remark from Nathan:

    ...
    If the symbol is the last thing in the format (really the
                                                   ^^^^^^^^^^
    last thing, no "rest of the sign" left to read) then if it's optional
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    you don't try to read it.
    ...

I have fixed the current code simply adding an additional || in the if at the
beginning of case symbol: *if* the sign is more than one char and the symbol is
optional (i.e., charbase is false) I try to read the symbol even if is the last
thing in the format (or but last with last field "none").

Regression checked i686-pc-linux-gnu.

Ciao, Paolo.

P.S. As suggested by Benjamin, in the next days I'm planning to cross check with
different "exotic" locales, and more generally, auditing the many facets for
problems similar to those we have fixed in money_get::do_get.

///////////

2002-02-06  Paolo Carlini  <pcarlini@unitus.it>

        * include/bits/locale_facets.tcc (money_get::do_get(string)):
        In case money_base::symbol deal properly with multi-char sign
        for patterns {X,Y,Z,symbol} and {X,Y,symbol,none}.
        * testsuite/22_locale/money_get_members_char.cc: Add test07.
        * testsuite/22_locale/money_get_members_wchar_t.cc: Add test07.

diff -prN libstdc++-v3-orig/include/bits/locale_facets.tcc
libstdc++-v3/include/bits/locale_facets.tcc
*** libstdc++-v3-orig/include/bits/locale_facets.tcc Mon Feb  4 22:25:13 2002
--- libstdc++-v3/include/bits/locale_facets.tcc Tue Feb  5 12:49:47 2002
*************** namespace std
*** 941,948 ****
     switch (__which)
    {
    case money_base::symbol:
!     if (__io.flags() & ios_base::showbase || __i < 2 ||
!         __i == 2 && static_cast<part>(__p.field[3]) != money_base::none)
        {
          // According to 22.2.6.1.2.2, symbol is required if
          // (__io.flags() & ios_base::showbase), otherwise is optional
--- 941,950 ----
     switch (__which)
    {
    case money_base::symbol:
!     if (__io.flags() & ios_base::showbase
!         || __i < 2
!         || (__i == 2 && static_cast<part>(__p.field[3]) != money_base::none)
!         || __sign.size() > 1)
        {
          // According to 22.2.6.1.2.2, symbol is required if
          // (__io.flags() & ios_base::showbase), otherwise is optional
diff -prN libstdc++-v3-orig/testsuite/22_locale/money_get_members_char.cc
libstdc++-v3/testsuite/22_locale/money_get_members_char.cc
*** libstdc++-v3-orig/testsuite/22_locale/money_get_members_char.cc Mon Feb  4
22:16:01 2002
--- libstdc++-v3/testsuite/22_locale/money_get_members_char.cc Wed Feb  6
01:20:16 2002
*************** void test06()
*** 419,424 ****
--- 419,523 ----
    VERIFY( val == buffer3 );
  }

+ class My_money_io_a : public std::moneypunct<char,false>
+ {
+ public:
+   explicit My_money_io_a(size_t r = 0): std::moneypunct<char,false>(r) { }
+   char_type do_decimal_point() const { return '.'; }
+   char_type do_thousands_sep() const { return ','; }
+   std::string do_grouping() const { return "\004"; }
+
+   std::string do_curr_symbol() const { return "$"; }
+   std::string do_positive_sign() const { return "()"; }
+
+   int do_frac_digits() const { return 2; }
+
+   pattern do_pos_format() const
+   {
+     static pattern pat = { { sign, value, space, symbol } };
+     return pat;
+   }
+ };
+
+ class My_money_io_b : public std::moneypunct<char,false>
+ {
+ public:
+   explicit My_money_io_b(size_t r = 0): std::moneypunct<char,false>(r) { }
+   char_type do_decimal_point() const { return '.'; }
+   char_type do_thousands_sep() const { return ','; }
+   std::string do_grouping() const { return "\004"; }
+
+   std::string do_curr_symbol() const { return "$"; }
+   std::string do_positive_sign() const { return "()"; }
+
+   int do_frac_digits() const { return 2; }
+
+   pattern do_pos_format() const
+   {
+     static pattern pat = { { sign, value, symbol, none } };
+     return pat;
+   }
+ };
+
+ // This one exercises patterns of the type { X, Y, Z, symbol } and
+ // { X, Y, symbol, none } for a two character long sign. Therefore
+ // the optional symbol (showbase is false by default) must be consumed
+ // if present, since "rest of the sign" is left to read.
+ void test07()
+ {
+   using namespace std;
+   typedef istreambuf_iterator<char> InIt;
+
+   bool intl = false;
+   ios_base::iostate err;
+
+   locale loc_a(locale::classic(), new My_money_io_a);
+
+   string buffer_a("(1234.56 $)");
+   string buffer_a_ns("(1234.56 )");
+
+   InIt iend_a, iend_a_ns;
+   string val_a, val_a_ns;
+
+   const money_get<char,InIt>& mg_a  =
+     use_facet<money_get<char, InIt> >(loc_a);
+
+   istringstream fmt_a(buffer_a);
+   fmt_a.imbue(loc_a);
+   InIt ibeg_a(fmt_a);
+   mg_a.get(ibeg_a,iend_a,intl,fmt_a,err,val_a);
+   VERIFY( val_a == "123456" );
+
+   istringstream fmt_a_ns(buffer_a_ns);
+   fmt_a_ns.imbue(loc_a);
+   InIt ibeg_a_ns(fmt_a_ns);
+   mg_a.get(ibeg_a_ns,iend_a_ns,intl,fmt_a_ns,err,val_a_ns);
+   VERIFY( val_a_ns == "123456" );
+
+   locale loc_b(locale::classic(), new My_money_io_b);
+
+   string buffer_b("(1234.56$)");
+   string buffer_b_ns("(1234.56)");
+
+   InIt iend_b, iend_b_ns;
+   string val_b, val_b_ns;
+
+   const money_get<char,InIt>& mg_b  =
+     use_facet<money_get<char, InIt> >(loc_b);
+
+   istringstream fmt_b(buffer_b);
+   fmt_b.imbue(loc_b);
+   InIt ibeg_b(fmt_b);
+   mg_b.get(ibeg_b,iend_b,intl,fmt_b,err,val_b);
+   VERIFY( val_b == "123456" );
+
+   istringstream fmt_b_ns(buffer_b_ns);
+   fmt_b_ns.imbue(loc_b);
+   InIt ibeg_b_ns(fmt_b_ns);
+   mg_b.get(ibeg_b_ns,iend_b_ns,intl,fmt_b_ns,err,val_b_ns);
+   VERIFY( val_b_ns == "123456" );
+ }
+
  int main()
  {
    test01();
*************** int main()
*** 427,431 ****
--- 526,531 ----
    test04();
    test05();
    test06();
+   test07();
    return 0;
  }
diff -prN libstdc++-v3-orig/testsuite/22_locale/money_get_members_wchar_t.cc
libstdc++-v3/testsuite/22_locale/money_get_members_wchar_t.cc
*** libstdc++-v3-orig/testsuite/22_locale/money_get_members_wchar_t.cc Mon Feb
4 22:16:33 2002
--- libstdc++-v3/testsuite/22_locale/money_get_members_wchar_t.cc Wed Feb  6
01:20:38 2002
*************** void test06()
*** 420,425 ****
--- 420,524 ----
    mg.get(ibeg3,iend3,false,fmt3,err,val);
    VERIFY( val == buffer3 );
  }
+
+ class My_money_io_a : public std::moneypunct<wchar_t,false>
+ {
+ public:
+   explicit My_money_io_a(size_t r = 0): std::moneypunct<wchar_t,false>(r) { }
+   char_type do_decimal_point() const { return L'.'; }
+   char_type do_thousands_sep() const { return L','; }
+   std::string do_grouping() const { return "\004"; }
+
+   std::wstring do_curr_symbol() const { return L"$"; }
+   std::wstring do_positive_sign() const { return L"()"; }
+
+   int do_frac_digits() const { return 2; }
+
+   pattern do_pos_format() const
+   {
+     static pattern pat = { { sign, value, space, symbol } };
+     return pat;
+   }
+ };
+
+ class My_money_io_b : public std::moneypunct<wchar_t,false>
+ {
+ public:
+   explicit My_money_io_b(size_t r = 0): std::moneypunct<wchar_t,false>(r) { }
+   char_type do_decimal_point() const { return L'.'; }
+   char_type do_thousands_sep() const { return L','; }
+   std::string do_grouping() const { return "\004"; }
+
+   std::wstring do_curr_symbol() const { return L"$"; }
+   std::wstring do_positive_sign() const { return L"()"; }
+
+   int do_frac_digits() const { return 2; }
+
+   pattern do_pos_format() const
+   {
+     static pattern pat = { { sign, value, symbol, none } };
+     return pat;
+   }
+ };
+
+ // This one exercises patterns of the type { X, Y, Z, symbol } and
+ // { X, Y, symbol, none } for a two character long sign. Therefore
+ // the optional symbol (showbase is false by default) must be consumed
+ // if present, since "rest of the sign" is left to read.
+ void test07()
+ {
+   using namespace std;
+   typedef istreambuf_iterator<wchar_t> InIt;
+
+   bool intl = false;
+   ios_base::iostate err;
+
+   locale loc_a(locale::classic(), new My_money_io_a);
+
+   wstring buffer_a(L"(1234.56 $)");
+   wstring buffer_a_ns(L"(1234.56 )");
+
+   InIt iend_a, iend_a_ns;
+   wstring val_a, val_a_ns;
+
+   const money_get<wchar_t,InIt>& mg_a  =
+     use_facet<money_get<wchar_t, InIt> >(loc_a);
+
+   wistringstream fmt_a(buffer_a);
+   fmt_a.imbue(loc_a);
+   InIt ibeg_a(fmt_a);
+   mg_a.get(ibeg_a,iend_a,intl,fmt_a,err,val_a);
+   VERIFY( val_a == L"123456" );
+
+   wistringstream fmt_a_ns(buffer_a_ns);
+   fmt_a_ns.imbue(loc_a);
+   InIt ibeg_a_ns(fmt_a_ns);
+   mg_a.get(ibeg_a_ns,iend_a_ns,intl,fmt_a_ns,err,val_a_ns);
+   VERIFY( val_a_ns == L"123456" );
+
+   locale loc_b(locale::classic(), new My_money_io_b);
+
+   wstring buffer_b(L"(1234.56$)");
+   wstring buffer_b_ns(L"(1234.56)");
+
+   InIt iend_b, iend_b_ns;
+   wstring val_b, val_b_ns;
+
+   const money_get<wchar_t,InIt>& mg_b  =
+     use_facet<money_get<wchar_t, InIt> >(loc_b);
+
+   wistringstream fmt_b(buffer_b);
+   fmt_b.imbue(loc_b);
+   InIt ibeg_b(fmt_b);
+   mg_b.get(ibeg_b,iend_b,intl,fmt_b,err,val_b);
+   VERIFY( val_b == L"123456" );
+
+   wistringstream fmt_b_ns(buffer_b_ns);
+   fmt_b_ns.imbue(loc_b);
+   InIt ibeg_b_ns(fmt_b_ns);
+   mg_b.get(ibeg_b_ns,iend_b_ns,intl,fmt_b_ns,err,val_b_ns);
+   VERIFY( val_b_ns == L"123456" );
+ }
  #endif

  int main()
*************** int main()
*** 431,436 ****
--- 530,536 ----
    test04();
    test05();
    test06();
+   test07();
  #endif
    return 0;
  }




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]