From e1a0572dd809ae3defa258fd154e6d52d6058c57 Mon Sep 17 00:00:00 2001 From: bkoz Date: Mon, 10 Sep 2001 01:00:27 +0000 Subject: [PATCH] 2001-09-09 Benjamin Kosnik 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@45496 138bc75d-0d04-0410-961f-82ee72b054a4 --- libstdc++-v3/ChangeLog | 29 ++ .../config/locale/moneypunct_members_generic.cc | 42 ++- .../config/locale/moneypunct_members_gnu.cc | 357 +++++++++++++++++---- libstdc++-v3/include/bits/locale_facets.h | 51 +-- libstdc++-v3/include/bits/locale_facets.tcc | 265 ++++++++++++--- libstdc++-v3/include/bits/std_iosfwd.h | 7 +- libstdc++-v3/src/locale-inst.cc | 20 +- libstdc++-v3/src/locale.cc | 176 ---------- libstdc++-v3/src/localename.cc | 4 +- .../testsuite/22_locale/money_put_members_char.cc | 224 ++++++++++++- .../22_locale/money_put_members_wchar_t.cc | 275 ++++++++++++++++ libstdc++-v3/testsuite/22_locale/moneypunct.cc | 29 +- .../testsuite/22_locale/moneypunct_members_char.cc | 62 ++-- .../22_locale/moneypunct_members_wchar_t.cc | 127 ++++++++ 14 files changed, 1297 insertions(+), 371 deletions(-) create mode 100644 libstdc++-v3/testsuite/22_locale/money_put_members_wchar_t.cc create mode 100644 libstdc++-v3/testsuite/22_locale/moneypunct_members_wchar_t.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index f3bcd3b..c220b26 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,32 @@ +2001-09-09 Benjamin Kosnik + + 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 * testsuite_flags.in: No longer need to search testsuite builddir. diff --git a/libstdc++-v3/config/locale/moneypunct_members_generic.cc b/libstdc++-v3/config/locale/moneypunct_members_generic.cc index 8c06871..dd92443 100644 --- a/libstdc++-v3/config/locale/moneypunct_members_generic.cc +++ b/libstdc++-v3/config/locale/moneypunct_members_generic.cc @@ -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::_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::_M_initialize_moneypunct(__c_locale) + moneypunct::_M_initialize_moneypunct(__c_locale) { // "C" locale _M_decimal_point = '.'; @@ -56,7 +78,23 @@ namespace std #ifdef _GLIBCPP_USE_WCHAR_T template<> void - moneypunct::_M_initialize_moneypunct(__c_locale) + moneypunct::_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::_M_initialize_moneypunct(__c_locale) { // "C" locale _M_decimal_point = L'.'; diff --git a/libstdc++-v3/config/locale/moneypunct_members_gnu.cc b/libstdc++-v3/config/locale/moneypunct_members_gnu.cc index d31c84a..83d647e 100644 --- a/libstdc++-v3/config/locale/moneypunct_members_gnu.cc +++ b/libstdc++-v3/config/locale/moneypunct_members_gnu.cc @@ -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::_M_initialize_moneypunct(__c_locale __cloc) + moneypunct::_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::_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::_M_initialize_moneypunct(__c_locale __cloc) + moneypunct::_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(__nl_langinfo_l(__POSITIVE_SIGN, __cloc)); _M_negative_sign = reinterpret_cast(__nl_langinfo_l(__NEGATIVE_SIGN, __cloc)); - if (intl) - { - _M_curr_symbol = reinterpret_cast(__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(__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(__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::_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(__nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc)); + _M_thousands_sep = reinterpret_cast(__nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC,__cloc)); + _M_grouping = __nl_langinfo_l(GROUPING, __cloc); + _M_positive_sign = reinterpret_cast(__nl_langinfo_l(__POSITIVE_SIGN, __cloc)); + _M_negative_sign = reinterpret_cast(__nl_langinfo_l(__NEGATIVE_SIGN, __cloc)); + + // _Intl == false. + _M_curr_symbol = reinterpret_cast(__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 diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h index ffef999..1e64224 100644 --- a/libstdc++-v3/include/bits/locale_facets.h +++ b/libstdc++-v3/include/bits/locale_facets.h @@ -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 @@ -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 @@ -1427,21 +1425,28 @@ namespace std template const bool moneypunct<_CharT, _Intl>::intl; + // NB: Cannot be made generic. template 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::_M_initialize_moneypunct(__c_locale __cloc); template<> void - moneypunct::_M_initialize_moneypunct(__c_locale __cloc); + moneypunct::_M_initialize_moneypunct(__c_locale __cloc); #ifdef _GLIBCPP_USE_WCHAR_T template<> void - moneypunct::_M_initialize_moneypunct(__c_locale __cloc); + moneypunct::_M_initialize_moneypunct(__c_locale __cloc); + + template<> + void + moneypunct::_M_initialize_moneypunct(__c_locale __cloc); #endif template @@ -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 inline bool isspace(_CharT __c, const locale& __loc) @@ -1694,8 +1699,4 @@ namespace std { return use_facet >(__loc).tolower(__c); } } // namespace std -#endif /* _CPP_BITS_LOCFACETS_H */ - -// Local Variables: -// mode:c++ -// End: +#endif diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index 088f0c5..5ed35d1 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -227,6 +227,184 @@ namespace std return __ncp; } + template + 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 >(__loc); + const int __n = numeric_limits::digits10; + char* __cs = static_cast(__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 + 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(__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 >(__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::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(__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 _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 _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(*__front) != __table[0]) - *--__front = __table[0]; - __sign_end = __front; + && static_cast(*__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 @@ -1276,16 +1457,4 @@ namespace std } } // namespace std -#endif // _CPP_BITS_LOCFACETS_TCC - - - - - - - - - - - - +#endif diff --git a/libstdc++-v3/include/bits/std_iosfwd.h b/libstdc++-v3/include/bits/std_iosfwd.h index 9d2dbc2..8a9b702 100644 --- a/libstdc++-v3/include/bits/std_iosfwd.h +++ b/libstdc++-v3/include/bits/std_iosfwd.h @@ -128,9 +128,4 @@ namespace std #endif } // namespace std -#endif // _CPP_IOSFWD - - - - - +#endif diff --git a/libstdc++-v3/src/locale-inst.cc b/libstdc++-v3/src/locale-inst.cc index 0b9cf75..78464a6 100644 --- a/libstdc++-v3/src/locale-inst.cc +++ b/libstdc++-v3/src/locale-inst.cc @@ -54,10 +54,8 @@ namespace std template class moneypunct; template class moneypunct_byname; template class moneypunct_byname; - template class money_get; - template class money_put; template class money_get; - template class money_put; + template class money_put; template class _Format_cache; #ifdef _GLIBCPP_USE_WCHAR_T @@ -65,10 +63,8 @@ namespace std template class moneypunct; template class moneypunct_byname; template class moneypunct_byname; - template class money_get; - template class money_put; template class money_get; - template class money_put; + template class money_put; template class _Format_cache; #endif @@ -149,6 +145,12 @@ namespace std template const collate& use_facet >(const locale&); + template + const moneypunct& + use_facet >(const locale&); + template + const moneypunct& + use_facet >(const locale&); #ifdef _GLIBCPP_USE_WCHAR_T template const num_put& @@ -165,6 +167,12 @@ namespace std template const collate& use_facet >(const locale&); + template + const moneypunct& + use_facet >(const locale&); + template + const moneypunct& + use_facet >(const locale&); #endif // has_facet diff --git a/libstdc++-v3/src/locale.cc b/libstdc++-v3/src/locale.cc index 1ab74a3..990e662 100644 --- a/libstdc++-v3/src/locale.cc +++ b/libstdc++-v3/src/locale.cc @@ -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(); } diff --git a/libstdc++-v3/src/localename.cc b/libstdc++-v3/src/localename.cc index 3a2b9cf..f921c2f 100644 --- a/libstdc++-v3/src/localename.cc +++ b/libstdc++-v3/src/localename.cc @@ -96,7 +96,7 @@ namespace std _M_init_facet(new std::ctype); _M_init_facet(new codecvt); _M_init_facet(new moneypunct(__cloc)); - _M_init_facet(new moneypunct(__cloc)); + _M_init_facet(new moneypunct(__cloc)); _M_init_facet(new money_get); _M_init_facet(new money_put); _M_init_facet(new numpunct(__cloc)); @@ -111,7 +111,7 @@ namespace std _M_init_facet(new std::ctype); _M_init_facet(new codecvt); _M_init_facet(new moneypunct(__cloc)); - _M_init_facet(new moneypunct(__cloc)); + _M_init_facet(new moneypunct(__cloc)); _M_init_facet(new money_get); _M_init_facet(new money_put); _M_init_facet(new numpunct(__cloc)); diff --git a/libstdc++-v3/testsuite/22_locale/money_put_members_char.cc b/libstdc++-v3/testsuite/22_locale/money_put_members_char.cc index be82297..5495afe 100644 --- a/libstdc++-v3/testsuite/22_locale/money_put_members_char.cc +++ b/libstdc++-v3/testsuite/22_locale/money_put_members_char.cc @@ -21,16 +21,19 @@ // 22.2.6.2.1 money_put members #include +#include #include // 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 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& monp_c = use_facet >(loc_c); - const money_put& monp_us = use_facet >(loc_us); - const money_put& monp_fr = use_facet >(loc_fr); - const money_put& monp_de = use_facet >(loc_de); + // cache the moneypunct facets + typedef moneypunct __money_true; + typedef moneypunct __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& mon_put = use_facet >(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 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 __money_true; + typedef moneypunct __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& mon_put = use_facet >(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; } diff --git a/libstdc++-v3/testsuite/22_locale/money_put_members_wchar_t.cc b/libstdc++-v3/testsuite/22_locale/money_put_members_wchar_t.cc new file mode 100644 index 0000000..e3399f3 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/money_put_members_wchar_t.cc @@ -0,0 +1,275 @@ +// 2001-09-09 Benjamin Kosnik + +// 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 +#include +#include + +// 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 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 __money_true; + typedef moneypunct __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& mon_put = use_facet >(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 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 __money_true; + typedef moneypunct __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& mon_put = use_facet >(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; +} diff --git a/libstdc++-v3/testsuite/22_locale/moneypunct.cc b/libstdc++-v3/testsuite/22_locale/moneypunct.cc index 256369a..4bba75a 100644 --- a/libstdc++-v3/testsuite/22_locale/moneypunct.cc +++ b/libstdc++-v3/testsuite/22_locale/moneypunct.cc @@ -21,11 +21,25 @@ // 22.2.6.3 Template class moneypunct #include +#include void test01() { // Check for required base class. - typedef std::moneypunct test_type; + typedef std::moneypunct test_type; + typedef std::locale::facet base_type; + const test_type& obj = std::use_facet(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 test_type; typedef std::locale::facet base_type; const test_type& obj = std::use_facet(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 +class gnu_moneypunct_t: public std::moneypunct { }; -void test02() +class gnu_moneypunct_f: public std::moneypunct +{ }; + +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; } diff --git a/libstdc++-v3/testsuite/22_locale/moneypunct_members_char.cc b/libstdc++-v3/testsuite/22_locale/moneypunct_members_char.cc index 1ddd426..cfc9164 100644 --- a/libstdc++-v3/testsuite/22_locale/moneypunct_members_char.cc +++ b/libstdc++-v3/testsuite/22_locale/moneypunct_members_char.cc @@ -56,31 +56,47 @@ void test01() VERIFY( loc_de != loc_fr ); // cache the moneypunct facets - const moneypunct& monp_c = use_facet >(loc_c); - const moneypunct& monp_us = use_facet >(loc_us); - const moneypunct& monp_fr = use_facet >(loc_fr); - const moneypunct& monp_de = use_facet >(loc_de); + typedef moneypunct __money_true; + typedef moneypunct __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 ); diff --git a/libstdc++-v3/testsuite/22_locale/moneypunct_members_wchar_t.cc b/libstdc++-v3/testsuite/22_locale/moneypunct_members_wchar_t.cc new file mode 100644 index 0000000..01b8d28 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/moneypunct_members_wchar_t.cc @@ -0,0 +1,127 @@ +// 2001-09-09 Benjamin Kosnik + +// 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 +#include + +// 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 __money_true; + typedef moneypunct __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(pos1.field[0]) != static_cast(pos2.field[0])); + VERIFY(static_cast(pos1.field[1]) != static_cast(pos2.field[1])); + VERIFY(static_cast(pos1.field[2]) != static_cast(pos2.field[2])); + VERIFY(static_cast(pos1.field[3]) != static_cast(pos2.field[3])); + + VERIFY(static_cast(neg1.field[0]) != static_cast(neg2.field[0])); + VERIFY(static_cast(neg1.field[1]) != static_cast(neg2.field[1])); + VERIFY(static_cast(neg1.field[2]) != static_cast(neg2.field[2])); + VERIFY(static_cast(neg1.field[3]) != static_cast(neg2.field[3])); +} +#endif + +int main() +{ +#ifdef _GLIBCPP_USE_WCHAR_T + test01(); +#endif + return 0; +} -- 2.7.4