Commit 69971cd8 by Benjamin Kosnik Committed by Benjamin Kosnik

Implement std::money_put.


2001-09-09  Benjamin Kosnik  <bkoz@redhat.com>

	Implement std::money_put.
	* include/bits/locale_facets.h
	(moneypunct::_M_initialize_moneypunct): Split up specializations
	to account for _Intl.  More grody hacking to get around the
	ill-considered use of const bool as a template parameter.
	* config/locale/moneypunct_members_gnu.cc: And here.
	* config/locale/moneypunct_members_generic.cc: And here.
	* testsuite/22_locale/moneypunct_members_char.cc: Add tests.
	* testsuite/22_locale/moneypunct.cc: Add tests.
	* testsuite/22_locale/money_put_members_wchar_t.cc: New file.
	* testsuite/22_locale/moneypunct_members_wchar_t.cc: New file.

	* src/locale.cc (money_base::_S_construct_pattern): Move into
	gnu-specific file.
	* config/locale/moneypunct_members_gnu.cc: Add here.
	* config/locale/moneypunct_members_generic.cc: Add generic version
	here.

	* include/bits/locale_facets.tcc (money_put::do_put): Move member
	function definitions here.
	* include/bits/locale_facets.h (money_put): Implement.
	* src/locale-inst.cc: Add use_facet instantiations for moneypunct.
	Correct money_get, money_put instantiations.
	* src/locale.cc (money_base::_S_construct_pattern): Handle case
	where __posn == 0.
	* testsuite/22_locale/money_put_members_char.cc: Add tests.

From-SVN: r45496
parent 1650fcad
2001-09-09 Benjamin Kosnik <bkoz@redhat.com>
Implement std::money_put.
* include/bits/locale_facets.h
(moneypunct::_M_initialize_moneypunct): Split up specializations
to account for _Intl. More grody hacking to get around the
ill-considered use of const bool as a template parameter.
* config/locale/moneypunct_members_gnu.cc: And here.
* config/locale/moneypunct_members_generic.cc: And here.
* testsuite/22_locale/moneypunct_members_char.cc: Add tests.
* testsuite/22_locale/moneypunct.cc: Add tests.
* testsuite/22_locale/money_put_members_wchar_t.cc: New file.
* testsuite/22_locale/moneypunct_members_wchar_t.cc: New file.
* src/locale.cc (money_base::_S_construct_pattern): Move into
gnu-specific file.
* config/locale/moneypunct_members_gnu.cc: Add here.
* config/locale/moneypunct_members_generic.cc: Add generic version
here.
* include/bits/locale_facets.tcc (money_put::do_put): Move member
function definitions here.
* include/bits/locale_facets.h (money_put): Implement.
* src/locale-inst.cc: Add use_facet instantiations for moneypunct.
Correct money_get, money_put instantiations.
* src/locale.cc (money_base::_S_construct_pattern): Handle case
where __posn == 0.
* testsuite/22_locale/money_put_members_char.cc: Add tests.
2001-09-05 Phil Edwards <pme@sources.redhat.com>
* testsuite_flags.in: No longer need to search testsuite builddir.
......
......@@ -37,9 +37,31 @@
namespace std
{
// Construct and return valid pattern consisting of some combination of:
// space none symbol sign value
money_base::pattern
money_base::_S_construct_pattern(char __preceeds, char __space, char __posn)
{ return _S_default_pattern; }
template<>
void
moneypunct<char, true>::_M_initialize_moneypunct(__c_locale)
{
// "C" locale
_M_decimal_point = '.';
_M_thousands_sep = ',';
_M_grouping = "";
_M_curr_symbol = string_type();
_M_positive_sign = string_type();
_M_negative_sign = string_type();
_M_frac_digits = 0;
_M_pos_format = money_base::_S_default_pattern;
_M_neg_format = money_base::_S_default_pattern;
}
template<>
void
moneypunct<char>::_M_initialize_moneypunct(__c_locale)
moneypunct<char, false>::_M_initialize_moneypunct(__c_locale)
{
// "C" locale
_M_decimal_point = '.';
......@@ -56,7 +78,23 @@ namespace std
#ifdef _GLIBCPP_USE_WCHAR_T
template<>
void
moneypunct<wchar_t>::_M_initialize_moneypunct(__c_locale)
moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale)
{
// "C" locale
_M_decimal_point = L'.';
_M_thousands_sep = L',';
_M_grouping = "";
_M_curr_symbol = string_type();
_M_positive_sign = string_type();
_M_negative_sign = string_type();
_M_frac_digits = 0;
_M_pos_format = money_base::_S_default_pattern;
_M_neg_format = money_base::_S_default_pattern;
}
template<>
void
moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale)
{
// "C" locale
_M_decimal_point = L'.';
......
......@@ -37,9 +37,186 @@
namespace std
{
// Construct and return valid pattern consisting of some combination of:
// space none symbol sign value
money_base::pattern
money_base::_S_construct_pattern(char __preceeds, char __space, char __posn)
{
pattern __ret;
// This insanely complicated routine attempts to construct a valid
// pattern for use with monyepunct. A couple of invariants:
// if (__preceeds) symbol -> value
// else value -> symbol
// if (__space) space
// else none
// none == never first
// space never first or last
// Any elegant implementations of this are welcome.
switch (__posn)
{
case 0:
case 1:
// 1 The sign precedes the value and symbol.
if (__space)
{
// Pattern starts with sign.
if (__preceeds)
{
__ret.field[1] = symbol;
__ret.field[2] = space;
__ret.field[3] = value;
}
else
{
__ret.field[1] = value;
__ret.field[2] = space;
__ret.field[3] = symbol;
}
__ret.field[0] = sign;
}
else
{
// Pattern starts with sign and ends with none.
if (__preceeds)
{
__ret.field[1] = symbol;
__ret.field[2] = value;
}
else
{
__ret.field[1] = value;
__ret.field[2] = symbol;
}
__ret.field[0] = sign;
__ret.field[3] = none;
}
break;
case 2:
// 2 The sign follows the value and symbol.
if (__space)
{
// Pattern either ends with sign.
if (__preceeds)
{
__ret.field[0] = symbol;
__ret.field[1] = space;
__ret.field[2] = value;
}
else
{
__ret.field[0] = value;
__ret.field[1] = space;
__ret.field[2] = symbol;
}
__ret.field[3] = sign;
}
else
{
// Pattern ends with sign then none.
if (__preceeds)
{
__ret.field[0] = symbol;
__ret.field[1] = value;
}
else
{
__ret.field[0] = value;
__ret.field[1] = symbol;
}
__ret.field[2] = sign;
__ret.field[3] = none;
}
break;
case 3:
// 3 The sign immediately precedes the symbol.
if (__space)
{
// Have space.
if (__preceeds)
{
__ret.field[0] = sign;
__ret.field[1] = symbol;
__ret.field[2] = space;
__ret.field[3] = value;
}
else
{
__ret.field[0] = value;
__ret.field[1] = space;
__ret.field[2] = sign;
__ret.field[3] = symbol;
}
}
else
{
// Have none.
if (__preceeds)
{
__ret.field[0] = sign;
__ret.field[1] = symbol;
__ret.field[2] = value;
}
else
{
__ret.field[0] = value;
__ret.field[1] = sign;
__ret.field[2] = symbol;
}
__ret.field[3] = none;
}
break;
case 4:
// 4 The sign immediately follows the symbol.
if (__space)
{
// Have space.
if (__preceeds)
{
__ret.field[0] = symbol;
__ret.field[1] = sign;
__ret.field[2] = space;
__ret.field[3] = value;
}
else
{
__ret.field[0] = value;
__ret.field[1] = space;
__ret.field[2] = symbol;
__ret.field[3] = sign;
}
}
else
{
// Have none.
if (__preceeds)
{
__ret.field[0] = symbol;
__ret.field[1] = sign;
__ret.field[2] = value;
}
else
{
__ret.field[0] = value;
__ret.field[1] = symbol;
__ret.field[2] = sign;
}
__ret.field[3] = none;
}
break;
default:
;
}
return __ret;
}
template<>
void
moneypunct<char>::_M_initialize_moneypunct(__c_locale __cloc)
moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc)
{
if (!__cloc)
{
......@@ -62,45 +239,69 @@ namespace std
_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
if (intl)
{
_M_curr_symbol = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, __cloc));
char __ppreceeds = *(__nl_langinfo_l(__INT_P_CS_PRECEDES,
__cloc));
char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
_M_pos_format = _S_construct_pattern(__ppreceeds, __pspace,
__pposn);
char __npreceeds = *(__nl_langinfo_l(__INT_N_CS_PRECEDES,
__cloc));
char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
_M_neg_format = _S_construct_pattern(__npreceeds, __nspace,
__nposn);
}
else
{
_M_curr_symbol = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
char __ppreceeds = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
_M_pos_format = _S_construct_pattern(__ppreceeds, __pspace,
__pposn);
char __npreceeds = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
_M_neg_format = _S_construct_pattern(__npreceeds, __nspace,
__nposn);
}
// _Intl == true
_M_curr_symbol = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, __cloc));
char __ppreceeds = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
_M_pos_format = _S_construct_pattern(__ppreceeds, __pspace, __pposn);
char __npreceeds = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
if (!__nposn)
_M_negative_sign = "()";
_M_neg_format = _S_construct_pattern(__npreceeds, __nspace, __nposn);
}
}
template<>
void
moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc)
{
if (!__cloc)
{
// "C" locale
_M_decimal_point = '.';
_M_thousands_sep = ',';
_M_grouping = "";
_M_curr_symbol = string_type();
_M_positive_sign = string_type();
_M_negative_sign = string_type();
_M_frac_digits = 0;
_M_pos_format = money_base::_S_default_pattern;
_M_neg_format = money_base::_S_default_pattern;
}
else
{
// Named locale.
_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT, __cloc));
_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, __cloc));
_M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc);
_M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc);
_M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
// _Intl == false
_M_curr_symbol = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
char __ppreceeds = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
_M_pos_format = _S_construct_pattern(__ppreceeds, __pspace, __pposn);
char __npreceeds = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
if (!__nposn)
_M_negative_sign = "()";
_M_neg_format = _S_construct_pattern(__npreceeds, __nspace, __nposn);
}
}
#ifdef _GLIBCPP_USE_WCHAR_T
template<>
void
moneypunct<wchar_t>::_M_initialize_moneypunct(__c_locale __cloc)
moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc)
{
if (!__cloc)
{
......@@ -123,38 +324,62 @@ namespace std
_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
_M_positive_sign = reinterpret_cast<wchar_t*>(__nl_langinfo_l(__POSITIVE_SIGN, __cloc));
_M_negative_sign = reinterpret_cast<wchar_t*>(__nl_langinfo_l(__NEGATIVE_SIGN, __cloc));
if (intl)
{
_M_curr_symbol = reinterpret_cast<wchar_t*>(__nl_langinfo_l(__INT_CURR_SYMBOL, __cloc));
_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, __cloc));
char __ppreceeds = *(__nl_langinfo_l(__INT_P_CS_PRECEDES,
__cloc));
char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
_M_pos_format = _S_construct_pattern(__ppreceeds, __pspace,
__pposn);
char __npreceeds = *(__nl_langinfo_l(__INT_N_CS_PRECEDES,
__cloc));
char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
_M_neg_format = _S_construct_pattern(__npreceeds, __nspace,
__nposn);
}
else
{
_M_curr_symbol = reinterpret_cast<wchar_t*>(__nl_langinfo_l(__CURRENCY_SYMBOL, __cloc));
_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
char __ppreceeds = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
_M_pos_format = _S_construct_pattern(__ppreceeds, __pspace,
__pposn);
char __npreceeds = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
_M_neg_format = _S_construct_pattern(__npreceeds, __nspace,
__nposn);
}
// _Intl == true.
_M_curr_symbol = reinterpret_cast<wchar_t*>(__nl_langinfo_l(__INT_CURR_SYMBOL, __cloc));
_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, __cloc));
char __ppreceeds = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc));
char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc));
_M_pos_format = _S_construct_pattern(__ppreceeds, __pspace, __pposn);
char __npreceeds = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc));
char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc));
char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
if (!__nposn)
_M_negative_sign = L"()";
_M_neg_format = _S_construct_pattern(__npreceeds, __nspace, __nposn);
}
}
template<>
void
moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc)
{
if (!__cloc)
{
// "C" locale
_M_decimal_point = L'.';
_M_thousands_sep = L',';
_M_grouping = "";
_M_curr_symbol = string_type();
_M_positive_sign = string_type();
_M_negative_sign = string_type();
_M_frac_digits = 0;
_M_pos_format = money_base::_S_default_pattern;
_M_neg_format = money_base::_S_default_pattern;
}
else
{
// Named locale.
_M_decimal_point = reinterpret_cast<wchar_t>(__nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc));
_M_thousands_sep = reinterpret_cast<wchar_t>(__nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC,__cloc));
_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
_M_positive_sign = reinterpret_cast<wchar_t*>(__nl_langinfo_l(__POSITIVE_SIGN, __cloc));
_M_negative_sign = reinterpret_cast<wchar_t*>(__nl_langinfo_l(__NEGATIVE_SIGN, __cloc));
// _Intl == false.
_M_curr_symbol = reinterpret_cast<wchar_t*>(__nl_langinfo_l(__CURRENCY_SYMBOL, __cloc));
_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
char __ppreceeds = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc));
char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc));
_M_pos_format = _S_construct_pattern(__ppreceeds, __pspace, __pposn);
char __npreceeds = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc));
char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc));
char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
if (!__nposn)
_M_negative_sign = L"()";
_M_neg_format = _S_construct_pattern(__npreceeds, __nspace, __nposn);
}
}
#endif
......
......@@ -1271,26 +1271,24 @@ namespace std
iter_type
put(iter_type __s, bool __intl, ios_base& __f,
char_type __fill, long double __units) const
{ return do_put(__s, __intl, __f, __fill, __units); }
{ 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 do_put(__s, __intl, __f, __fill, __digits); }
{ return this->do_put(__s, __intl, __f, __fill, __digits); }
protected:
virtual
~money_put() { }
virtual iter_type
do_put(iter_type __s, bool, ios_base& /*__io*/, char_type /*__fill*/,
long double /*__units*/) const
{ return __s; }
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, ios_base& /*__io*/, char_type /*__fill*/,
const string_type& /*__digits*/) const
{ return __s; }
do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
const string_type& __digits) const;
};
template<typename _CharT, typename _OutIter>
......@@ -1417,8 +1415,8 @@ namespace std
{ return _M_neg_format; }
// For use at construction time only.
void
_M_initialize_moneypunct(__c_locale __cloc = NULL);
void
_M_initialize_moneypunct(__c_locale __cloc = NULL);
};
template<typename _CharT, bool _Intl>
......@@ -1427,21 +1425,28 @@ namespace std
template<typename _CharT, bool _Intl>
const bool moneypunct<_CharT, _Intl>::intl;
// NB: Cannot be made generic.
template<typename _CharT, bool _Intl>
void
moneypunct<_CharT, _Intl>::_M_initialize_moneypunct(__c_locale /*__cloc*/)
{
// NB: Cannot be made generic.
}
moneypunct<_CharT, _Intl>::_M_initialize_moneypunct(__c_locale)
{ }
template<>
void
moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc);
template<>
void
moneypunct<char>::_M_initialize_moneypunct(__c_locale __cloc);
moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc);
#ifdef _GLIBCPP_USE_WCHAR_T
template<>
void
moneypunct<wchar_t>::_M_initialize_moneypunct(__c_locale __cloc);
moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc);
template<>
void
moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc);
#endif
template<typename _CharT, bool _Intl>
......@@ -1625,10 +1630,10 @@ namespace std
};
// Subclause convenience interfaces, inlines
// NB: these are inline
// because, when used in a loop, some compilers can hoist the body
// out of the loop; then it's just as fast as the C is*() function.
// Subclause convenience interfaces, inlines.
// NB: These are inline because, when used in a loop, some compilers
// can hoist the body out of the loop; then it's just as fast as the
// C is*() function.
template<typename _CharT>
inline bool
isspace(_CharT __c, const locale& __loc)
......@@ -1694,8 +1699,4 @@ namespace std
{ return use_facet<ctype<_CharT> >(__loc).tolower(__c); }
} // namespace std
#endif /* _CPP_BITS_LOCFACETS_H */
// Local Variables:
// mode:c++
// End:
#endif
......@@ -227,6 +227,184 @@ namespace std
return __ncp;
}
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 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);
string_type __digits(__ws);
return this->do_put(__s, __intl, __io, __fill, __digits);
}
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,
const string_type& __digits) const
{
typedef typename string_type::size_type size_type;
locale __loc = __io.getloc();
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);
// Determine if negative or positive formats are to be used, and
// discard leading negative_sign if it is present.
const char_type* __beg = __digits.data();
const char_type* __end = __beg + __digits.size();
money_base::pattern __p;
string_type __sign;
if (*__beg != __ct.widen('-'))
{
__p = __intl ? __mpt.pos_format() : __mpf.pos_format();
__sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign();
}
else
{
__p = __intl ? __mpt.neg_format() : __mpf.neg_format();
__sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign();
++__beg;
}
// Look for valid numbers in the current ctype facet within input digits.
__end = __ct.scan_not(ctype_base::digit, __beg, __end);
if (__beg != __end)
{
// Assume valid input, and attempt to format.
// Break down input numbers into base components, as follows:
// final_value = grouped units + (decimal point) + (digits)
string_type __res;
string_type __value;
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();
if (__frac > 0)
{
char_type __d = __intl
? __mpt.decimal_point() : __mpf.decimal_point();
if (__end - __beg >= __frac)
{
__value = string_type(__end - __frac, __end);
__value.insert(__value.begin(), __d);
__end -= __frac;
}
else
{
// Have to pad zeros in the decimal position.
__value = string_type(__beg, __end);
int __paddec = __frac - (__end - __beg);
char_type __zero = __ct.widen('0');
__value.insert(__value.begin(), __paddec, __zero);
__value.insert(__value.begin(), __d);
__beg = __end;
}
}
// Add thousands separators to non-decimal digits, per
// grouping rules.
if (__beg != __end)
{
string __grouping = __intl ? __mpt.grouping() : __mpf.grouping();
if (__grouping.size())
{
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;
_CharT* __s = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
_CharT* __s_end = __group_digits(__s, __sep, __gbeg,
__gend, __beg, __end);
__value.insert(0, __s, __s_end - __s);
}
else
__value.insert(0, string_type(__beg, __end));
}
// Calculate length of resulting string.
ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield;
size_type __len = __value.size() + __sign.size();
__len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0;
bool __testipad = __f == ios_base::internal && __len < __width;
// 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)
{
case money_base::symbol:
if (__io.flags() & ios_base::showbase)
__res += __symbol;
break;
case money_base::sign:
// Sign might not exist, or be more than one
// charater long. In that case, add in the rest
// below.
if (__sign.size())
__res += __sign[0];
break;
case money_base::value:
__res += __value;
break;
case money_base::space:
// At least one space is required, but if internal
// formatting is required, an arbitrary number of
// fill spaces will be necessary.
if (__testipad)
__res += string_type(__width - __len, __fill);
else
__res += __ct.widen(' ');
break;
case money_base::none:
if (__testipad)
__res += string_type(__width - __len, __fill);
break;
}
}
// Special case of multi-part sign parts.
if (__sign.size() > 1)
__res += string_type(__sign.begin() + 1, __sign.end());
// Pad, if still necessary.
__len = __res.size();
if (__width > __len)
{
if (__f == ios_base::left)
// After.
__res.append(__width - __len, __fill);
else
// Before.
__res.insert(0, string_type(__width - __len, __fill));
__len = __width;
}
// Write resulting, fully-formatted string to output iterator.
for (size_type __i = 0; __i < __len; ++__i)
__s = __res[__i];
}
__io.width(0);
return __s;
}
// This member function takes an (w)istreambuf_iterator object and
// parses it into a generic char array suitable for parsing with
// strto[l,ll,f,d]. The thought was to encapsulate the conversion
......@@ -823,20 +1001,20 @@ namespace std
// __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 __grouping != __grend.
// Call this only with __gbeg != __gend.
template <typename _CharT>
_CharT*
__group_digits(_CharT* __s, _CharT __grsep, char const* __grouping,
char const* __grend, _CharT const* __first,
_CharT const* __last)
__group_digits(_CharT* __s, _CharT __sep,
const char* __gbeg, const char* __gend,
const _CharT* __first, const _CharT* __last)
{
if (__last - __first > *__grouping)
if (__last - __first > *__gbeg)
{
__s = __group_digits(__s, __grsep,
(__grouping + 1 == __grend ? __grouping : __grouping + 1),
__grend, __first, __last - *__grouping);
__first = __last - *__grouping;
*__s++ = __grsep;
__s = __group_digits(__s, __sep,
(__gbeg + 1 == __gend ? __gbeg : __gbeg + 1),
__gend, __first, __last - *__gbeg);
__first = __last - *__gbeg;
*__s++ = __sep;
}
do
{
......@@ -849,71 +1027,74 @@ namespace std
template <typename _CharT, typename _OutIter, typename _ValueT>
_OutIter
__output_integer(_OutIter __s, ios_base& __io, _CharT __fill, bool __neg,
_ValueT __v)
_ValueT __v)
{
// Leave room for "+/-," "0x," and commas.
const long _M_room = numeric_limits<_ValueT>::digits10 * 2 + 4;
_CharT __digits[_M_room];
_CharT* __front = __digits + _M_room;
// Leave room for "+/-," "0x," and commas. This size is
// arbitrary, but should work.
const int __n = numeric_limits<_ValueT>::digits10 * 2 + 4;
_CharT* __digits = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
_CharT* __digits_end = __digits + __n;
ios_base::fmtflags __flags = __io.flags();
const _Format_cache<_CharT>* __fmt = _Format_cache<_CharT>::_S_get(__io);
char const* __table = __fmt->_S_literals + __fmt->_S_digits;
ios_base::fmtflags __basefield = (__flags & __io.basefield);
_CharT* __sign_end = __front;
_CharT* __sign_end = __digits_end;
if (__basefield == ios_base::hex)
{
if (__flags & ios_base::uppercase)
__table += 16; // use ABCDEF
do
*--__front = __table[__v & 15];
*--__digits_end = __table[__v & 15];
while ((__v >>= 4) != 0);
__sign_end = __front;
__sign_end = __digits_end;
if (__flags & ios_base::showbase)
{
*--__front = __fmt->_S_literals[__fmt->_S_x +
*--__digits_end = __fmt->_S_literals[__fmt->_S_x +
((__flags & ios_base::uppercase) ? 1 : 0)];
*--__front = __table[0];
*--__digits_end = __table[0];
}
}
else if (__basefield == ios_base::oct)
{
do
*--__front = __table[__v & 7];
*--__digits_end = __table[__v & 7];
while ((__v >>= 3) != 0);
if (__flags & ios_base::showbase
&& static_cast<char>(*__front) != __table[0])
*--__front = __table[0];
__sign_end = __front;
&& static_cast<char>(*__digits_end) != __table[0])
*--__digits_end = __table[0];
__sign_end = __digits_end;
}
else
{
// NB: This is _lots_ faster than using ldiv.
do
*--__front = __table[__v % 10];
*--__digits_end = __table[__v % 10];
while ((__v /= 10) != 0);
__sign_end = __front;
__sign_end = __digits_end;
// NB: ios_base:hex || ios_base::oct assumed to be unsigned.
if (__neg || (__flags & ios_base::showpos))
*--__front = __fmt->_S_literals[__fmt->_S_plus - __neg];
*--__digits_end = __fmt->_S_literals[__fmt->_S_plus - __neg];
}
// XXX should specialize!
if (!__fmt->_M_use_grouping && !__io.width())
return copy(__front, __digits + _M_room, __s);
return copy(__digits_end, __digits + __n, __s);
if (!__fmt->_M_use_grouping)
return __pad_numeric(__s, __flags, __fill, __io.width(0),
__front, __sign_end, __digits + _M_room);
__digits_end, __sign_end, __digits + __n);
_CharT* __p = __digits;
while (__front < __sign_end)
*__p++ = *__front++;
const char* __gr = __fmt->_M_grouping.data();
__front = __group_digits(__p, __fmt->_M_thousands_sep, __gr,
__gr + __fmt->_M_grouping.size(), __sign_end, __digits + _M_room);
while (__digits_end < __sign_end)
*__p++ = *__digits_end++;
const char* __gbeg = __fmt->_M_grouping.data();
const char* __gend = __gbeg + __fmt->_M_grouping.size();
__digits_end = __group_digits(__p, __fmt->_M_thousands_sep,
__gbeg, __gend,
__sign_end, __digits + __n);
return __pad_numeric(__s, __flags, __fill, __io.width(0),
__digits, __p, __front);
__digits, __p, __digits_end);
}
template <typename _CharT, typename _OutIter>
......@@ -1276,16 +1457,4 @@ namespace std
}
} // namespace std
#endif // _CPP_BITS_LOCFACETS_TCC
#endif
......@@ -128,9 +128,4 @@ namespace std
#endif
} // namespace std
#endif // _CPP_IOSFWD
#endif
......@@ -54,10 +54,8 @@ namespace std
template class moneypunct<char, true>;
template class moneypunct_byname<char, false>;
template class moneypunct_byname<char, true>;
template class money_get<char, obuf_iterator>;
template class money_put<char, obuf_iterator>;
template class money_get<char, ibuf_iterator>;
template class money_put<char, ibuf_iterator>;
template class money_put<char, obuf_iterator>;
template class _Format_cache<char>;
#ifdef _GLIBCPP_USE_WCHAR_T
......@@ -65,10 +63,8 @@ namespace std
template class moneypunct<wchar_t, true>;
template class moneypunct_byname<wchar_t, false>;
template class moneypunct_byname<wchar_t, true>;
template class money_get<wchar_t, wobuf_iterator>;
template class money_put<wchar_t, wobuf_iterator>;
template class money_get<wchar_t, wibuf_iterator>;
template class money_put<wchar_t, wibuf_iterator>;
template class money_put<wchar_t, wobuf_iterator>;
template class _Format_cache<wchar_t>;
#endif
......@@ -149,6 +145,12 @@ namespace std
template
const collate<char>&
use_facet<collate<char> >(const locale&);
template
const moneypunct<char, true>&
use_facet<moneypunct<char, true> >(const locale&);
template
const moneypunct<char, false>&
use_facet<moneypunct<char, false> >(const locale&);
#ifdef _GLIBCPP_USE_WCHAR_T
template
const num_put<wchar_t, wobuf_iterator>&
......@@ -165,6 +167,12 @@ namespace std
template
const collate<wchar_t>&
use_facet<collate<wchar_t> >(const locale&);
template
const moneypunct<wchar_t, true>&
use_facet<moneypunct<wchar_t, true> >(const locale&);
template
const moneypunct<wchar_t, false>&
use_facet<moneypunct<wchar_t, false> >(const locale&);
#endif
// has_facet
......
......@@ -162,182 +162,6 @@ namespace std
0
};
// Construct and return valid pattern consisting of some combination of:
// space none symbol sign value
money_base::pattern
money_base::_S_construct_pattern(char __preceeds, char __space, char __posn)
{
pattern __ret;
// This insanely complicated routine attempts to construct a valid
// pattern for use with monyepunct. A couple of invariants:
// if (__preceeds) symbol -> value
// else value -> symbol
// if (__space) space
// else none
// none == never first
// space never first or last
// Any elegant implementations of this are welcome.
switch (__posn)
{
case 1:
// 1 The sign precedes the value and symbol.
if (__space)
{
// Pattern starts with sign.
if (__preceeds)
{
__ret.field[1] = symbol;
__ret.field[2] = space;
__ret.field[3] = value;
}
else
{
__ret.field[1] = value;
__ret.field[2] = space;
__ret.field[3] = symbol;
}
__ret.field[0] = sign;
}
else
{
// Pattern starts with sign and ends with none.
if (__preceeds)
{
__ret.field[1] = symbol;
__ret.field[2] = value;
}
else
{
__ret.field[1] = value;
__ret.field[2] = symbol;
}
__ret.field[0] = sign;
__ret.field[3] = none;
}
break;
case 2:
// 2 The sign follows the value and symbol.
if (__space)
{
// Pattern either ends with sign.
if (__preceeds)
{
__ret.field[0] = symbol;
__ret.field[1] = space;
__ret.field[2] = value;
}
else
{
__ret.field[0] = value;
__ret.field[1] = space;
__ret.field[2] = symbol;
}
__ret.field[3] = sign;
}
else
{
// Pattern ends with sign then none.
if (__preceeds)
{
__ret.field[0] = symbol;
__ret.field[1] = value;
}
else
{
__ret.field[0] = value;
__ret.field[1] = symbol;
}
__ret.field[2] = sign;
__ret.field[3] = none;
}
break;
case 3:
// 3 The sign immediately precedes the symbol.
if (__space)
{
// Have space.
if (__preceeds)
{
__ret.field[0] = sign;
__ret.field[1] = symbol;
__ret.field[2] = space;
__ret.field[3] = value;
}
else
{
__ret.field[0] = value;
__ret.field[1] = space;
__ret.field[2] = sign;
__ret.field[3] = symbol;
}
}
else
{
// Have none.
if (__preceeds)
{
__ret.field[0] = sign;
__ret.field[1] = symbol;
__ret.field[2] = value;
}
else
{
__ret.field[0] = value;
__ret.field[1] = sign;
__ret.field[2] = symbol;
}
__ret.field[3] = none;
}
break;
case 4:
// 4 The sign immediately follows the symbol.
if (__space)
{
// Have space.
if (__preceeds)
{
__ret.field[0] = symbol;
__ret.field[1] = sign;
__ret.field[2] = space;
__ret.field[3] = value;
}
else
{
__ret.field[0] = value;
__ret.field[1] = space;
__ret.field[2] = symbol;
__ret.field[3] = sign;
}
}
else
{
// Have none.
if (__preceeds)
{
__ret.field[0] = symbol;
__ret.field[1] = sign;
__ret.field[2] = value;
}
else
{
__ret.field[0] = value;
__ret.field[1] = symbol;
__ret.field[2] = sign;
}
__ret.field[3] = none;
}
break;
default:
;
}
return __ret;
}
locale::~locale() throw()
{ _M_impl->_M_remove_reference(); }
......
......@@ -96,7 +96,7 @@ namespace std
_M_init_facet(new std::ctype<char>);
_M_init_facet(new codecvt<char, char, mbstate_t>);
_M_init_facet(new moneypunct<char, false>(__cloc));
_M_init_facet(new moneypunct<char,true>(__cloc));
_M_init_facet(new moneypunct<char, true>(__cloc));
_M_init_facet(new money_get<char>);
_M_init_facet(new money_put<char>);
_M_init_facet(new numpunct<char>(__cloc));
......@@ -111,7 +111,7 @@ namespace std
_M_init_facet(new std::ctype<wchar_t>);
_M_init_facet(new codecvt<wchar_t, char, mbstate_t>);
_M_init_facet(new moneypunct<wchar_t, false>(__cloc));
_M_init_facet(new moneypunct<wchar_t,true>(__cloc));
_M_init_facet(new moneypunct<wchar_t, true>(__cloc));
_M_init_facet(new money_get<wchar_t>);
_M_init_facet(new money_put<wchar_t>);
_M_init_facet(new numpunct<wchar_t>(__cloc));
......
......@@ -21,16 +21,19 @@
// 22.2.6.2.1 money_put 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 ostreambuf_iterator<char> iterator_type;
bool test = true;
string str;
......@@ -39,11 +42,11 @@ void test01()
locale loc_c = locale::classic();
str = loc_c.name();
locale loc_us("en_US");
str = loc_us.name();
VERIFY( loc_c != loc_us );
locale loc_hk("en_HK");
str = loc_hk.name();
VERIFY( loc_c != loc_hk );
locale loc_fr("fr_FR");
locale loc_fr("fr_FR@euro");
str = loc_fr.name();
VERIFY( loc_c != loc_fr );
......@@ -51,23 +54,218 @@ void test01()
str = loc_de.name();
VERIFY( loc_c != loc_de );
VERIFY( loc_us != loc_fr );
VERIFY( loc_us != loc_de );
VERIFY( loc_hk != loc_fr );
VERIFY( loc_hk != loc_de );
VERIFY( loc_de != loc_fr );
// cache the money_put facets
const money_put<char>& monp_c = use_facet<money_put<char> >(loc_c);
const money_put<char>& monp_us = use_facet<money_put<char> >(loc_us);
const money_put<char>& monp_fr = use_facet<money_put<char> >(loc_fr);
const money_put<char>& monp_de = use_facet<money_put<char> >(loc_de);
// 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.
// VERIFY( dp1 != dp2 );
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");
ostringstream oss;
oss.imbue(loc_de);
// cache the money_put facet
const money_put<char>& mon_put = use_facet<money_put<char> >(oss.getloc());
iterator_type os_it01 = mon_put.put(oss.rdbuf(), true, oss, '*', digits1);
string result1 = oss.str();
VERIFY( result1 == "7.200.000.000,00 ");
oss.str(empty);
iterator_type os_it02 = mon_put.put(oss.rdbuf(), false, oss, '*', digits1);
string result2 = oss.str();
VERIFY( result2 == "7.200.000.000,00 ");
// intl and non-intl versions should be the same.
VERIFY( result1 == result2 );
// now try with showbase, to get currency symbol in format
oss.setf(ios_base::showbase);
oss.str(empty);
iterator_type os_it03 = mon_put.put(oss.rdbuf(), true, oss, '*', digits1);
string result3 = oss.str();
VERIFY( result3 == "7.200.000.000,00 DEM ");
oss.str(empty);
iterator_type os_it04 = mon_put.put(oss.rdbuf(), false, oss, '*', digits1);
string result4 = oss.str();
VERIFY( result4 == "7.200.000.000,00 DM");
// intl and non-intl versions should be different.
VERIFY( result3 != result4 );
VERIFY( result3 != result1 );
VERIFY( result4 != result2 );
// test sign of more than one digit, say hong kong.
oss.imbue(loc_hk);
oss.str(empty);
iterator_type os_it05 = mon_put.put(oss.rdbuf(), false, oss, '*', digits1);
string result5 = oss.str();
VERIFY( result5 == "HK$7,200,000,000.00");
oss.str(empty);
iterator_type os_it06 = mon_put.put(oss.rdbuf(), true, oss, '*', digits2);
string result6 = oss.str();
VERIFY( result6 == "(HKD 100,000,000,000.00)");
// test one-digit formats without zero padding
oss.imbue(loc_c);
oss.str(empty);
iterator_type os_it07 = mon_put.put(oss.rdbuf(), true, oss, '*', digits4);
string result7 = oss.str();
VERIFY( result7 == "1");
// test one-digit formats with zero padding, zero frac widths
oss.imbue(loc_hk);
oss.str(empty);
iterator_type os_it08 = mon_put.put(oss.rdbuf(), true, oss, '*', digits4);
string result8 = oss.str();
VERIFY( result8 == "(HKD .01)");
oss.unsetf(ios_base::showbase);
// test bunk input
oss.str(empty);
iterator_type os_it09 = mon_put.put(oss.rdbuf(), true, oss, '*', digits3);
string result9 = oss.str();
VERIFY( result9 == "");
// test io.width() > length
// test various fill strategies
oss.imbue(loc_de);
oss.str(empty);
oss.width(20);
iterator_type os_it10 = mon_put.put(oss.rdbuf(), true, oss, '*', digits4);
string result10 = oss.str();
VERIFY( result10 == "***************-,01 ");
oss.str(empty);
oss.width(20);
oss.setf(ios_base::internal);
iterator_type os_it11 = mon_put.put(oss.rdbuf(), true, oss, '*', digits4);
string result11 = oss.str();
VERIFY( result11 == "-,01****************");
}
// test double/string versions
void test02()
{
using namespace std;
typedef money_base::part part;
typedef money_base::pattern pattern;
typedef ostreambuf_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 loss in USD 2001
const long double digits2 = -10000000000000;
// input less than frac_digits
const long double digits4 = -1;
ostringstream oss;
oss.imbue(loc_de);
// cache the money_put facet
const money_put<char>& mon_put = use_facet<money_put<char> >(oss.getloc());
iterator_type os_it01 = mon_put.put(oss.rdbuf(), true, oss, '*', digits1);
string result1 = oss.str();
VERIFY( result1 == "7.200.000.000,00 ");
oss.str(empty);
iterator_type os_it02 = mon_put.put(oss.rdbuf(), false, oss, '*', digits1);
string result2 = oss.str();
VERIFY( result2 == "7.200.000.000,00 ");
// intl and non-intl versions should be the same.
VERIFY( result1 == result2 );
// now try with showbase, to get currency symbol in format
oss.setf(ios_base::showbase);
oss.str(empty);
iterator_type os_it03 = mon_put.put(oss.rdbuf(), true, oss, '*', digits1);
string result3 = oss.str();
VERIFY( result3 == "7.200.000.000,00 DEM ");
oss.str(empty);
iterator_type os_it04 = mon_put.put(oss.rdbuf(), false, oss, '*', digits1);
string result4 = oss.str();
VERIFY( result4 == "7.200.000.000,00 DM");
// intl and non-intl versions should be different.
VERIFY( result3 != result4 );
VERIFY( result3 != result1 );
VERIFY( result4 != result2 );
}
int main()
{
test01();
test02();
return 0;
}
// 2001-09-09 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.2.1 money_put members
#include <locale>
#include <sstream>
#include <testsuite_hooks.h>
// XXX This test is not working for non-glibc locale models.
// { dg-do run { xfail *-*-* } }
#ifdef _GLIBCPP_USE_WCHAR_T
// test string version
void test01()
{
using namespace std;
typedef money_base::part part;
typedef money_base::pattern pattern;
typedef ostreambuf_iterator<wchar_t> 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<wchar_t, true> __money_true;
typedef moneypunct<wchar_t, 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 wstring empty;
// total EPA budget FY 2002
const wstring digits1(L"720000000000");
// est. cost, national missle "defense", expressed as a loss in USD 2001
const wstring digits2(L"-10000000000000");
// not valid input
const wstring digits3(L"-A");
// input less than frac_digits
const wstring digits4(L"-1");
wostringstream oss;
oss.imbue(loc_de);
// cache the money_put facet
const money_put<wchar_t>& mon_put = use_facet<money_put<wchar_t> >(oss.getloc());
iterator_type os_it01 = mon_put.put(oss.rdbuf(), true, oss, '*', digits1);
wstring result1 = oss.str();
VERIFY( result1 == L"7.200.000.000,00 ");
oss.str(empty);
iterator_type os_it02 = mon_put.put(oss.rdbuf(), false, oss, '*', digits1);
wstring result2 = oss.str();
VERIFY( result2 == L"7.200.000.000,00 ");
// intl and non-intl versions should be the same.
VERIFY( result1 == result2 );
// now try with showbase, to get currency symbol in format
oss.setf(ios_base::showbase);
oss.str(empty);
iterator_type os_it03 = mon_put.put(oss.rdbuf(), true, oss, '*', digits1);
wstring result3 = oss.str();
VERIFY( result3 == L"7.200.000.000,00 DEM ");
oss.str(empty);
iterator_type os_it04 = mon_put.put(oss.rdbuf(), false, oss, '*', digits1);
wstring result4 = oss.str();
VERIFY( result4 == L"7.200.000.000,00 DM");
// intl and non-intl versions should be different.
VERIFY( result3 != result4 );
VERIFY( result3 != result1 );
VERIFY( result4 != result2 );
// test sign of more than one digit, say hong kong.
oss.imbue(loc_hk);
oss.str(empty);
iterator_type os_it05 = mon_put.put(oss.rdbuf(), false, oss, '*', digits1);
wstring result5 = oss.str();
VERIFY( result5 == L"HK$7,200,000,000.00");
oss.str(empty);
iterator_type os_it06 = mon_put.put(oss.rdbuf(), true, oss, '*', digits2);
wstring result6 = oss.str();
VERIFY( result6 == L"(HKD 100,000,000,000.00)");
// test one-digit formats without zero padding
oss.imbue(loc_c);
oss.str(empty);
iterator_type os_it07 = mon_put.put(oss.rdbuf(), true, oss, '*', digits4);
wstring result7 = oss.str();
VERIFY( result7 == L"1");
// test one-digit formats with zero padding, zero frac widths
oss.imbue(loc_hk);
oss.str(empty);
iterator_type os_it08 = mon_put.put(oss.rdbuf(), true, oss, '*', digits4);
wstring result8 = oss.str();
VERIFY( result8 == L"(HKD .01)");
oss.unsetf(ios_base::showbase);
// test bunk input
oss.str(empty);
iterator_type os_it09 = mon_put.put(oss.rdbuf(), true, oss, '*', digits3);
wstring result9 = oss.str();
VERIFY( result9 == L"");
// test io.width() > length
// test various fill strategies
oss.imbue(loc_de);
oss.str(empty);
oss.width(20);
iterator_type os_it10 = mon_put.put(oss.rdbuf(), true, oss, '*', digits4);
wstring result10 = oss.str();
VERIFY( result10 == L"***************-,01 ");
oss.str(empty);
oss.width(20);
oss.setf(ios_base::internal);
iterator_type os_it11 = mon_put.put(oss.rdbuf(), true, oss, '*', digits4);
wstring result11 = oss.str();
VERIFY( result11 == L"-,01****************");
}
// test double/wstring versions
void test02()
{
using namespace std;
typedef money_base::part part;
typedef money_base::pattern pattern;
typedef ostreambuf_iterator<wchar_t> 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<wchar_t, true> __money_true;
typedef moneypunct<wchar_t, 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 wstring empty;
// total EPA budget FY 2002
const long double digits1 = 720000000000;
// est. cost, national missle "defense", expressed as a loss in USD 2001
const long double digits2 = -10000000000000;
// input less than frac_digits
const long double digits4 = -1;
wostringstream oss;
oss.imbue(loc_de);
// cache the money_put facet
const money_put<wchar_t>& mon_put = use_facet<money_put<wchar_t> >(oss.getloc());
iterator_type os_it01 = mon_put.put(oss.rdbuf(), true, oss, '*', digits1);
wstring result1 = oss.str();
VERIFY( result1 == L"7.200.000.000,00 ");
oss.str(empty);
iterator_type os_it02 = mon_put.put(oss.rdbuf(), false, oss, '*', digits1);
wstring result2 = oss.str();
VERIFY( result2 == L"7.200.000.000,00 ");
// intl and non-intl versions should be the same.
VERIFY( result1 == result2 );
// now try with showbase, to get currency symbol in format
oss.setf(ios_base::showbase);
oss.str(empty);
iterator_type os_it03 = mon_put.put(oss.rdbuf(), true, oss, '*', digits1);
wstring result3 = oss.str();
VERIFY( result3 == L"7.200.000.000,00 DEM ");
oss.str(empty);
iterator_type os_it04 = mon_put.put(oss.rdbuf(), false, oss, '*', digits1);
wstring result4 = oss.str();
VERIFY( result4 == L"7.200.000.000,00 DM");
// intl and non-intl versions should be different.
VERIFY( result3 != result4 );
VERIFY( result3 != result1 );
VERIFY( result4 != result2 );
}
#endif
int main()
{
#ifdef _GLIBCPP_USE_WCHAR_T
test01();
test02();
#endif
return 0;
}
......@@ -21,11 +21,25 @@
// 22.2.6.3 Template class moneypunct
#include <locale>
#include <testsuite_hooks.h>
void test01()
{
// Check for required base class.
typedef std::moneypunct<char> test_type;
typedef std::moneypunct<char, true> 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;
}
void test02()
{
// Check for required base class.
typedef std::moneypunct<char, false> test_type;
typedef std::locale::facet base_type;
const test_type& obj = std::use_facet<test_type>(std::locale());
const base_type* base = &obj;
......@@ -36,17 +50,24 @@ void test01()
}
// Should be able to instantiate this for other types besides char, wchar_t
class gnu_moneypunct: public std::moneypunct<unsigned char>
class gnu_moneypunct_t: public std::moneypunct<unsigned char, true>
{ };
void test02()
class gnu_moneypunct_f: public std::moneypunct<unsigned char, false>
{ };
void test03()
{
gnu_moneypunct facet01;
gnu_moneypunct_t facet01;
gnu_moneypunct_f facet02;
VERIFY (facet01.intl == true);
VERIFY (facet02.intl == false);
}
int main()
{
test01();
test02();
test03();
return 0;
}
......@@ -56,31 +56,47 @@ void test01()
VERIFY( loc_de != loc_fr );
// cache the moneypunct facets
const moneypunct<char>& monp_c = use_facet<moneypunct<char> >(loc_c);
const moneypunct<char>& monp_us = use_facet<moneypunct<char> >(loc_us);
const moneypunct<char>& monp_fr = use_facet<moneypunct<char> >(loc_fr);
const moneypunct<char>& monp_de = use_facet<moneypunct<char> >(loc_de);
typedef moneypunct<char, true> __money_true;
typedef moneypunct<char, false> __money_false;
const __money_true& monp_c_t = use_facet<__money_true>(loc_c);
const __money_true& monp_us_t = use_facet<__money_true>(loc_us);
const __money_true& monp_fr_t = use_facet<__money_true>(loc_fr);
const __money_true& monp_de_t = use_facet<__money_true>(loc_de);
const __money_false& monp_c_f = use_facet<__money_false>(loc_c);
const __money_false& monp_us_f = use_facet<__money_false>(loc_us);
const __money_false& monp_fr_f = use_facet<__money_false>(loc_fr);
const __money_false& monp_de_f = use_facet<__money_false>(loc_de);
// quick sanity check for data.
char q1 = monp_c_t.decimal_point();
char q2 = monp_c_t.thousands_sep();
char q3 = monp_c_f.decimal_point();
char q4 = monp_c_f.thousands_sep();
VERIFY( q1 != char() );
VERIFY( q2 != char() );
VERIFY( q3 != char() );
VERIFY( q4 != char() );
// sanity check the data is correct.
char dp1 = monp_c.decimal_point();
char th1 = monp_c.thousands_sep();
string g1 = monp_c.grouping();
string cs1 = monp_c.curr_symbol();
string ps1 = monp_c.positive_sign();
string ns1 = monp_c.negative_sign();
int fd1 = monp_c.frac_digits();
pattern pos1 = monp_c.pos_format();
pattern neg1 = monp_c.neg_format();
char dp2 = monp_de.decimal_point();
char th2 = monp_de.thousands_sep();
string g2 = monp_de.grouping();
string cs2 = monp_de.curr_symbol();
string ps2 = monp_de.positive_sign();
string ns2 = monp_de.negative_sign();
int fd2 = monp_de.frac_digits();
pattern pos2 = monp_de.pos_format();
pattern neg2 = monp_de.neg_format();
char dp1 = monp_c_t.decimal_point();
char th1 = monp_c_t.thousands_sep();
string g1 = monp_c_t.grouping();
string cs1 = monp_c_t.curr_symbol();
string ps1 = monp_c_t.positive_sign();
string ns1 = monp_c_t.negative_sign();
int fd1 = monp_c_t.frac_digits();
pattern pos1 = monp_c_t.pos_format();
pattern neg1 = monp_c_t.neg_format();
char dp2 = monp_de_t.decimal_point();
char th2 = monp_de_t.thousands_sep();
string g2 = monp_de_t.grouping();
string cs2 = monp_de_t.curr_symbol();
string ps2 = monp_de_t.positive_sign();
string ns2 = monp_de_t.negative_sign();
int fd2 = monp_de_t.frac_digits();
pattern pos2 = monp_de_t.pos_format();
pattern neg2 = monp_de_t.neg_format();
VERIFY( dp1 != dp2 );
VERIFY( th1 != th2 );
......
// 2001-09-09 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.3.1 moneypunct members
#include <locale>
#include <testsuite_hooks.h>
// XXX This test is not working for non-glibc locale models.
// { dg-do run { xfail *-*-* } }
#ifdef _GLIBCPP_USE_WCHAR_T
void test01()
{
using namespace std;
typedef money_base::part part;
typedef money_base::pattern pattern;
bool test = true;
string str;
// basic construction
locale loc_c = locale::classic();
str = loc_c.name();
locale loc_us("en_US");
str = loc_us.name();
VERIFY( loc_c != loc_us );
locale loc_fr("fr_FR");
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_us != loc_fr );
VERIFY( loc_us != loc_de );
VERIFY( loc_de != loc_fr );
// cache the moneypunct facets
typedef moneypunct<wchar_t, true> __money_true;
typedef moneypunct<wchar_t, false> __money_false;
const __money_true& monp_c_t = use_facet<__money_true>(loc_c);
const __money_true& monp_us_t = use_facet<__money_true>(loc_us);
const __money_true& monp_fr_t = use_facet<__money_true>(loc_fr);
const __money_true& monp_de_t = use_facet<__money_true>(loc_de);
const __money_false& monp_c_f = use_facet<__money_false>(loc_c);
const __money_false& monp_us_f = use_facet<__money_false>(loc_us);
const __money_false& monp_fr_f = use_facet<__money_false>(loc_fr);
const __money_false& monp_de_f = use_facet<__money_false>(loc_de);
// quick sanity check for data.
wchar_t q1 = monp_c_t.decimal_point();
wchar_t q2 = monp_c_t.thousands_sep();
wchar_t q3 = monp_c_f.decimal_point();
wchar_t q4 = monp_c_f.thousands_sep();
VERIFY( q1 != wchar_t() );
VERIFY( q2 != wchar_t() );
VERIFY( q3 != wchar_t() );
VERIFY( q4 != wchar_t() );
// sanity check the data is correct.
wchar_t dp1 = monp_c_t.decimal_point();
wchar_t th1 = monp_c_t.thousands_sep();
string g1 = monp_c_t.grouping();
wstring cs1 = monp_c_t.curr_symbol();
wstring ps1 = monp_c_t.positive_sign();
wstring ns1 = monp_c_t.negative_sign();
int fd1 = monp_c_t.frac_digits();
pattern pos1 = monp_c_t.pos_format();
pattern neg1 = monp_c_t.neg_format();
wchar_t dp2 = monp_de_t.decimal_point();
wchar_t th2 = monp_de_t.thousands_sep();
string g2 = monp_de_t.grouping();
wstring cs2 = monp_de_t.curr_symbol();
wstring ps2 = monp_de_t.positive_sign();
wstring ns2 = monp_de_t.negative_sign();
int fd2 = monp_de_t.frac_digits();
pattern pos2 = monp_de_t.pos_format();
pattern neg2 = monp_de_t.neg_format();
VERIFY( dp1 != dp2 );
VERIFY( th1 != th2 );
VERIFY( g1 != g2 );
VERIFY( cs1 != cs2 );
// VERIFY( ps1 != ps2 );
VERIFY( ns1 != ns2 );
VERIFY( fd1 != fd2 );
VERIFY(static_cast<part>(pos1.field[0]) != static_cast<part>(pos2.field[0]));
VERIFY(static_cast<part>(pos1.field[1]) != static_cast<part>(pos2.field[1]));
VERIFY(static_cast<part>(pos1.field[2]) != static_cast<part>(pos2.field[2]));
VERIFY(static_cast<part>(pos1.field[3]) != static_cast<part>(pos2.field[3]));
VERIFY(static_cast<part>(neg1.field[0]) != static_cast<part>(neg2.field[0]));
VERIFY(static_cast<part>(neg1.field[1]) != static_cast<part>(neg2.field[1]));
VERIFY(static_cast<part>(neg1.field[2]) != static_cast<part>(neg2.field[2]));
VERIFY(static_cast<part>(neg1.field[3]) != static_cast<part>(neg2.field[3]));
}
#endif
int main()
{
#ifdef _GLIBCPP_USE_WCHAR_T
test01();
#endif
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment