This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

money_get should heed frac_digits


In the standard, the definition of moneypunct says that you can't have a
value for frac_digits and ignore it:

   $22.2.6.3.3/8
   The number of digits required after the decimal point (if any) is exactly
   the value returned by frac_digits().

The libstdc++ implementation of money_get<...>::do_get doesn't enforce this,
which lets people use as many digits as they want.

The attached testcase, tfrac.cpp, shows the places where we shouldn't be
accepting what's being fed into money_get.

In tfrac-diffs.txt, I've presented one approach to correct this.  There is one
curious issue in the fix, though---the name "__sep_pos" is no longer correct.
It's being used both to note the thousands separator and, now, how far we've
gone past the decimal-point that came.

Another approach, aside from renaming it, is actually using a new variable to
count how far we've come since the decimal-point, and thus keeping them
separated.

I'll let you guys decide if you want to do anything about the naming of it,
and will provide a revised patch if there's a style you want to go with.

B

-- 
Brendan Kehoe                                               brendan@zen.org

http://www.zen.org/~brendan/

Attachment: tfrac-diffs.txt
Description: Text document

// $22.2.6.3.3/8
// The number of digits required after the decimal point (if any) is exactly
// the value returned by frac_digits().


#include <locale>
#include <sstream>

class dublin : public std::moneypunct<wchar_t> {
public:
  int do_frac_digits() const { return 3; }
};

int main()
{
  std::wistringstream liffey;
  std::wstring coins;

  std::locale eire(std::locale::classic(), new dublin);
  liffey.imbue(eire);

  const std::money_get<wchar_t>& greed
    = std::use_facet<std::money_get<wchar_t> >(liffey.getloc());

  typedef std::istreambuf_iterator<wchar_t> iterator_type;
  iterator_type is(liffey);
  iterator_type end;

  std::ios_base::iostate err01 = std::ios_base::goodbit;

  int fails = 0;

  // Feed it 1 digit too many, which should fail.
  liffey.str(L"12.3456");
  greed.get(is, end, false, liffey, err01, coins);
  if (! (err01 & std::ios_base::failbit ))
    fails |= 0x01;

  err01 = std::ios_base::goodbit;

  // Feed it exactly what it wants, which should succeed.
  liffey.str(L"12.345");
  greed.get(is, end, false, liffey, err01, coins);
  if ( err01 & std::ios_base::failbit )
    fails |= 0x02;

  err01 = std::ios_base::goodbit;

  // Feed it 1 digit too few, which should fail.
  liffey.str(L"12.34");
  greed.get(is, end, false, liffey, err01, coins);
  if (! ( err01 & std::ios_base::failbit ))
    fails |= 0x04;

  err01 = std::ios_base::goodbit;

  // Feed it only a decimal-point, which should fail.
  liffey.str(L"12.");
  greed.get(is, end, false, liffey, err01, coins);
  if (! (err01 & std::ios_base::failbit ))
    fails |= 0x08;

  err01 = std::ios_base::goodbit;

  // Feed it no decimal-point at all, which should succeed.
  liffey.str(L"12");
  greed.get(is, end, false, liffey, err01, coins);
  if ( err01 & std::ios_base::failbit )
    fails |= 0x10;

  return fails;
}

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