diff options
-rw-r--r-- | libstdc++-v3/ChangeLog | 29 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/basic_ios.h | 12 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/basic_ios.tcc | 44 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/ios_base.h | 11 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/locale_facets.h | 87 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/locale_facets.tcc | 43 | ||||
-rw-r--r-- | libstdc++-v3/src/ios.cc | 4 | ||||
-rw-r--r-- | libstdc++-v3/src/locale-inst.cc | 2 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/27_io/ios_members.cc | 53 |
9 files changed, 224 insertions, 61 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 57896f52396..f3fb9fe96e4 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,32 @@ +2003-02-17 Benjamin Kosnik <bkoz@redhat.com> + + * include/bits/basic_ios.tcc (copyfmt): Copy locale data as well. + * testsuite/27_io/ios_members.cc (test03): New. + +2003-02-17 Jerry Quinn <jlquinn@optonline.net> + + * include/bits/basic_ios.h (basic_ios::_M_cache_locale): Declare. + (basic_ios::_M_cache_facets): Move into above. + * include/bits/basic_ios.tcc (basic_ios::copyfmt): Rebuild locale + cache. + (basic_ios::imbue): Force locale cache to be built. + (basic_ios::_M_init): Create and initialize locale cache. + * include/bits/ios_base.h (__locale_cache_base): Declare. + (ios_base::_M_locale_cache): New. + (ios_base::_M_cache): Define. + * include/bits/locale_facets.h: (__num_base): Fix comment. Add + _S_end. + (__locale_cache_base,__locale_cache<_CharT>): New classes. + (__locale_cache<char>, __locale_cache<wchar_t>): New specializations. + * include/bits/locale_facets.tcc (num_put::_M_convert_int): Use locale + cache literal string, grouping flag, thousands separator. + (__locale_cache<_CharT>::__locale_cache): New. + (__locale_cache<_CharT>::_M_init): New. + (__locale_cache<_CharT>::_M_populate): New. + * src/ios.cc: Clear _M_locale_cache in constructor. + * src/locale-inst.cc (__locale_cache<char>, __locale_cache<_char_t>): + New. + 2003-02-17 Paolo Carlini <pcarlini@unitus.it> * src/locale-inst.cc: Do not include <cassert>. diff --git a/libstdc++-v3/include/bits/basic_ios.h b/libstdc++-v3/include/bits/basic_ios.h index 29c1436cf27..7d0e47ef3af 100644 --- a/libstdc++-v3/include/bits/basic_ios.h +++ b/libstdc++-v3/include/bits/basic_ios.h @@ -1,6 +1,7 @@ // Iostreams base classes -*- C++ -*- -// Copyright (C) 1997, 1998, 1999, 2001, 2002 Free Software Foundation, Inc. +// Copyright (C) 1997, 1998, 1999, 2001, 2002, 2003 +// Free Software Foundation, Inc. // // 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 @@ -90,9 +91,9 @@ namespace std // Cached use_facet<ctype>, which is based on the current locale info. const __ctype_type* _M_fctype; - // From ostream. + // For ostream. const __numput_type* _M_fnumput; - // From istream. + // For istream. const __numget_type* _M_fnumget; public: @@ -239,7 +240,8 @@ namespace std * The parameter is passed by derived streams. */ explicit - basic_ios(basic_streambuf<_CharT, _Traits>* __sb) : ios_base() + basic_ios(basic_streambuf<_CharT, _Traits>* __sb) + : ios_base(), _M_fctype(0), _M_fnumput(0), _M_fnumget(0) { this->init(__sb); } /** @@ -438,7 +440,7 @@ namespace std } void - _M_cache_facets(const locale& __loc); + _M_cache_locale(const locale& __loc); }; } // namespace std diff --git a/libstdc++-v3/include/bits/basic_ios.tcc b/libstdc++-v3/include/bits/basic_ios.tcc index 876281ae303..8ac1c609322 100644 --- a/libstdc++-v3/include/bits/basic_ios.tcc +++ b/libstdc++-v3/include/bits/basic_ios.tcc @@ -60,12 +60,12 @@ namespace std basic_ios<_CharT, _Traits>& basic_ios<_CharT, _Traits>::copyfmt(const basic_ios& __rhs) { - // Per 27.1.1.1, do not call imbue, yet must trash all caches + // Per 27.1.1, do not call imbue, yet must trash all caches // associated with imbue() // Alloc any new word array first, so if it fails we have "rollback". _Words* __words = (__rhs._M_word_size <= _S_local_word_size) ? - _M_local_word : new _Words[__rhs._M_word_size]; + _M_local_word : new _Words[__rhs._M_word_size]; // Bump refs before doing callbacks, for safety. _Callback_list* __cb = __rhs._M_callbacks; @@ -79,7 +79,8 @@ namespace std } _M_dispose_callbacks(); - _M_callbacks = __cb; // NB: Don't want any added during above. + // NB: Don't want any added during above. + _M_callbacks = __cb; for (int __i = 0; __i < __rhs._M_word_size; ++__i) __words[__i] = __rhs._M_word[__i]; if (_M_word != _M_local_word) @@ -95,10 +96,14 @@ namespace std this->precision(__rhs.precision()); this->tie(__rhs.tie()); this->fill(__rhs.fill()); + _M_ios_locale = __rhs.getloc(); + _M_cache_locale(_M_ios_locale); + + _M_call_callbacks(copyfmt_event); + // The next is required to be the last assignment. this->exceptions(__rhs.exceptions()); - - _M_call_callbacks(copyfmt_event); + return *this; } @@ -129,7 +134,7 @@ namespace std { locale __old(this->getloc()); ios_base::imbue(__loc); - _M_cache_facets(__loc); + _M_cache_locale(__loc); if (this->rdbuf() != 0) this->rdbuf()->pubimbue(__loc); return __old; @@ -141,8 +146,14 @@ namespace std { // NB: This may be called more than once on the same object. ios_base::_M_init(); - _M_cache_facets(_M_ios_locale); - _M_tie = 0; + + // Cache locale data and specific facets used by iostreams. + if (!_M_locale_cache.get()) + { + typedef __locale_cache<_CharT> __cache_t; + this->_M_locale_cache = auto_ptr<__locale_cache_base>(static_cast<__locale_cache_base*>(new __cache_t)); + _M_cache_locale(_M_ios_locale); + } // NB: The 27.4.4.1 Postconditions Table specifies requirements // after basic_ios::init() has been called. As part of this, @@ -159,6 +170,7 @@ namespace std _M_fill = _CharT(); _M_fill_init = false; + _M_tie = 0; _M_exception = goodbit; _M_streambuf = __sb; _M_streambuf_state = __sb ? goodbit : badbit; @@ -166,21 +178,15 @@ namespace std template<typename _CharT, typename _Traits> void - basic_ios<_CharT, _Traits>::_M_cache_facets(const locale& __loc) + basic_ios<_CharT, _Traits>::_M_cache_locale(const locale& __loc) { - if (has_facet<__ctype_type>(__loc)) + if (__builtin_expect(has_facet<__ctype_type>(__loc), true)) _M_fctype = &use_facet<__ctype_type>(__loc); - else - _M_fctype = 0; - // Should be filled in by ostream and istream, respectively. - if (has_facet<__numput_type>(__loc)) + if (__builtin_expect(has_facet<__numput_type>(__loc), true)) _M_fnumput = &use_facet<__numput_type>(__loc); - else - _M_fnumput = 0; - if (has_facet<__numget_type>(__loc)) + if (__builtin_expect(has_facet<__numget_type>(__loc), true)) _M_fnumget = &use_facet<__numget_type>(__loc); - else - _M_fnumget = 0; + static_cast<__locale_cache<_CharT>&>(_M_cache())._M_init(__loc); } // Inhibit implicit instantiations for required instantiations, diff --git a/libstdc++-v3/include/bits/ios_base.h b/libstdc++-v3/include/bits/ios_base.h index a7d4bf614c4..26ee38df383 100644 --- a/libstdc++-v3/include/bits/ios_base.h +++ b/libstdc++-v3/include/bits/ios_base.h @@ -146,6 +146,8 @@ namespace std enum _Ios_Seekdir { _M_ios_seekdir_end = 1L << 16 }; + class __locale_cache_base; + // 27.4.2 Class ios_base /** * @brief The very top of the I/O class hierarchy. @@ -430,6 +432,10 @@ namespace std // Members for locale and locale caching. locale _M_ios_locale; + // Cache of locale and facet data. + // Cast this to __locale_cache<_CharT>* + auto_ptr<__locale_cache_base> _M_locale_cache; + void _M_init(); @@ -636,6 +642,11 @@ namespace std return __word._M_pword; } + // Access to the cache. Not safe to call until basic_ios::_M_init() has + // happened. + __locale_cache_base& + _M_cache() { return *_M_locale_cache; } + // Destructor /** * Destroys local storage and diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h index 1feb960c2cf..59154f4c35e 100644 --- a/libstdc++-v3/include/bits/locale_facets.h +++ b/libstdc++-v3/include/bits/locale_facets.h @@ -161,6 +161,7 @@ namespace std return __s; } + // 22.2.1.1 Template class ctype // Include host and configuration specific ctype enums for ctype_base. #include <bits/ctype_base.h> @@ -531,8 +532,8 @@ namespace std class __num_base { public: - // NB: Code depends on the order of _M_atoms_out elements. - // Below are the indices into _M_atoms_out. + // NB: Code depends on the order of _S_atoms_out elements. + // Below are the indices into _S_atoms_out. enum { _S_minus, @@ -543,14 +544,15 @@ namespace std _S_digits_end = _S_digits + 16, _S_udigits = _S_digits_end, _S_udigits_end = _S_udigits + 16, - _S_e = _S_digits + 14, // For scientific notation, 'e' - _S_E = _S_udigits + 14 // For scientific notation, 'E' + _S_e = _S_digits + 14, // For scientific notation, 'e' + _S_E = _S_udigits + 14, // For scientific notation, 'E' + _S_end = _S_udigits_end }; - // A list of valid numeric literals for output. - // This array contains the chars after having been passed through - // the current locale's ctype<_CharT>.widen(). - // For the standard "C" locale, this is + // A list of valid numeric literals for output. This array + // contains chars that will be passed through the current locale's + // ctype<_CharT>.widen() and then used to render numbers. + // For the standard "C" locale, this is // "-+xX0123456789abcdef0123456789ABCDEF". static const char* _S_atoms_out; @@ -1931,6 +1933,75 @@ namespace std inline _CharT tolower(_CharT __c, const locale& __loc) { return use_facet<ctype<_CharT> >(__loc).tolower(__c); } + + + // __locale_cache holds the information extracted from the + // numpunct<> and moneypunct<> facets in a form optimized for + // parsing and formatting. It is stored as an + // auto_ptr<__locale_cache_base> member of ios_base and directly + // accessed via a casting to the derived __locale_cache<_CharT> in + // parameterized facets. + // The intent twofold: to avoid the costs of creating a locale + // object and to avoid calling the virtual functions in a locale's + // facet to look up data. + class __locale_cache_base + { + public: + virtual + ~__locale_cache_base() { } + }; + + template<typename _CharT> + class __locale_cache : public __locale_cache_base + { + // Types: + typedef _CharT char_type; + typedef char_traits<_CharT> traits_type; + typedef basic_string<_CharT> string_type; + + public: + // Data Members: + + // A list of valid numeric literals: for the standard "C" + // locale, this is "-+xX0123456789abcdef0123456789ABCDEF". This + // array contains the chars after having been passed through the + // current locale's ctype<_CharT>.widen(). + _CharT _M_literals[__num_base::_S_end]; + + // The sign used to separate decimal values: for standard US + // locales, this would usually be: "." Abstracted from + // numpunct::decimal_point(). + _CharT _M_decimal_point; + + // The sign used to separate groups of digits into smaller + // strings that the eye can parse with less difficulty: for + // standard US locales, this would usually be: "," Abstracted + // from numpunct::thousands_sep(). + _CharT _M_thousands_sep; + + // However the US's "false" and "true" are translated. From + // numpunct::truename() and numpunct::falsename(), respectively. + string_type _M_truename; + string_type _M_falsename; + + // If we are checking groupings. This should be equivalent to + // numpunct::groupings().size() != 0 + bool _M_use_grouping; + + // If we are using numpunct's groupings, this is the current + // grouping string in effect (from numpunct::grouping()). + string _M_grouping; + + __locale_cache() : _M_use_grouping(false) + { }; + + __locale_cache& + operator=(const __locale_cache& __lc); + + // Make sure the cache is built before the first use. + void + _M_init(const locale&); + }; } // namespace std #endif diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index ffb97ea0c9c..857074f976f 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -768,20 +768,14 @@ namespace std _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, _ValueT __v) const { - // Buildup list of digits given the current ctype. - _CharT __lit[_S_udigits_end]; - const locale __loc = __io.getloc(); - if (__builtin_expect(has_facet< ctype<_CharT> >(__loc), true)) - { - const ctype<_CharT>& __ct = use_facet< ctype<_CharT> >(__loc); - __ct.widen(_S_atoms_out, _S_atoms_out + _S_udigits_end, __lit); - } + typedef __locale_cache<_CharT> __cache_type; + __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache()); + _CharT* __lit = __lc._M_literals; // Long enough to hold hex, dec, and octal representations. int __ilen = 4 * sizeof(_ValueT); _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __ilen)); - // [22.2.2.2.2] Stage 1, numeric conversion to character. // Result is returned right-justified in the buffer. int __len; @@ -790,15 +784,13 @@ namespace std // Add grouping, if necessary. _CharT* __cs2; - const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); - const string __grouping = __np.grouping(); - if (__grouping.size()) + if (__lc._M_use_grouping) { // Grouping can add (almost) as many separators as the // number of digits, but no more. __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len * 2)); - _M_group_int(__grouping, __np.thousands_sep(), __io, + _M_group_int(__lc._M_grouping, __lc._M_thousands_sep, __io, __cs2, __cs, __len); __cs = __cs2; } @@ -2216,6 +2208,31 @@ namespace std return __s; } + // Generic definition, locale cache initialization. + template<typename _CharT> + void + __locale_cache<_CharT>::_M_init(const locale& __loc) + { + if (__builtin_expect(has_facet<numpunct<_CharT> >(__loc), true)) + { + const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); + _M_falsename = __np.falsename(); + _M_truename = __np.truename(); + _M_thousands_sep = __np.thousands_sep(); + _M_decimal_point = __np.decimal_point(); + _M_grouping = __np.grouping(); + _M_use_grouping = _M_grouping.size() != 0 + && _M_grouping.data()[0] != 0; + } + if (__builtin_expect(has_facet<ctype<_CharT> >(__loc), true)) + { + const ctype<_CharT>& __ct = use_facet< ctype<_CharT> >(__loc); + __ct.widen(__num_base::_S_atoms_out, + __num_base::_S_atoms_out + __num_base::_S_end, + _M_literals); + } + } + // Inhibit implicit instantiations for required instantiations, // which are defined via explicit instantiations elsewhere. // NB: This syntax is a GNU extension. diff --git a/libstdc++-v3/src/ios.cc b/libstdc++-v3/src/ios.cc index 75fdee1e5c2..9de6d1309f9 100644 --- a/libstdc++-v3/src/ios.cc +++ b/libstdc++-v3/src/ios.cc @@ -1,6 +1,6 @@ // Iostreams base classes -*- C++ -*- -// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 +// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 // Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free @@ -302,7 +302,7 @@ namespace std return __old; } - ios_base::ios_base() : _M_callbacks(0), _M_word(0) + ios_base::ios_base() : _M_callbacks(0), _M_word(0), _M_locale_cache(0) { // Do nothing: basic_ios::init() does it. // NB: _M_callbacks and _M_word must be zero for non-initialized diff --git a/libstdc++-v3/src/locale-inst.cc b/libstdc++-v3/src/locale-inst.cc index 4dfc03b55c7..73b028df1be 100644 --- a/libstdc++-v3/src/locale-inst.cc +++ b/libstdc++-v3/src/locale-inst.cc @@ -45,6 +45,7 @@ namespace std template class moneypunct_byname<char, true>; template class money_get<char, istreambuf_iterator<char> >; template class money_put<char, ostreambuf_iterator<char> >; + template class __locale_cache<char>; #ifdef _GLIBCPP_USE_WCHAR_T template class moneypunct<wchar_t, false>; @@ -53,6 +54,7 @@ namespace std template class moneypunct_byname<wchar_t, true>; template class money_get<wchar_t, istreambuf_iterator<wchar_t> >; template class money_put<wchar_t, ostreambuf_iterator<wchar_t> >; + template class __locale_cache<wchar_t>; #endif // numpunct, numpunct_byname, num_get, and num_put diff --git a/libstdc++-v3/testsuite/27_io/ios_members.cc b/libstdc++-v3/testsuite/27_io/ios_members.cc index df00c6a4ce5..4c359801678 100644 --- a/libstdc++-v3/testsuite/27_io/ios_members.cc +++ b/libstdc++-v3/testsuite/27_io/ios_members.cc @@ -1,6 +1,6 @@ // 1999-09-20 bkoz -// Copyright (C) 1999 Free Software Foundation, Inc. +// Copyright (C) 1999, 2003 Free Software Foundation, Inc. // // 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 @@ -40,15 +40,15 @@ void test01() std::ios_base::fmtflags flag02, flag03; const std::ios_base::fmtflags flag01 = std::ios_base::skipws | std::ios_base::dec; - - const std::locale glocale = std::locale(); + + const std::locale c_loc = std::locale::classic(); std::ios ios_01(NULL); std::ios::char_type ct01; std::ios::char_type ct02('x');; // 27.4.2.3 locales - ios_01.imbue(glocale); + ios_01.imbue(c_loc); // char narrow(char_type c, char dfault) const; char c1 = ios_01.narrow(ct02, 0); @@ -57,10 +57,6 @@ void test01() // char_type widen(char c) const; ct01 = ios_01.widen('c'); VERIFY( ct01 == 'c' ); - -#ifdef DEBUG_ASSERT - assert(test); -#endif } // 27.4.4.3 basic_ios iostate flags function @@ -76,8 +72,6 @@ void test02() const iostate iostate01 = std::ios_base::badbit | std::ios_base::eofbit; const iostate iostate04 = std::ios_base::badbit; - const std::locale glocale = std::locale(); - std::ios ios_01(NULL); std::ios::char_type ct01; std::ios::char_type ct02('x');; @@ -135,14 +129,45 @@ void test02() catch(...) { VERIFY( false ); } +} + +// copyfmt and locales. +void test03() +{ + bool test = true; + + using namespace std; -#ifdef DEBUG_ASSERT - assert(test); -#endif + typedef std::ios_base::fmtflags fmtflags; + typedef std::ios_base::iostate iostate; + locale loc_c = locale::classic(); + locale loc_de("de_DE"); + std::ios ios_01(NULL); + std::ios ios_02(NULL); + ios_01.imbue(loc_c); + ios_02.imbue(loc_de); + ios_02.setstate(ios_base::badbit); + VERIFY( loc_c == ios_01.getloc() ); + VERIFY( loc_de == ios_02.getloc() ); + + iostate ios1 = ios_01.rdstate(); + iostate ios2 = ios_02.rdstate(); + streambuf* sb1 = ios_01.rdbuf(); + streambuf* sb2 = ios_02.rdbuf(); + ios_01.copyfmt(ios_02); + + VERIFY( loc_de == ios_01.getloc() ); + VERIFY( ios_01.getloc() == ios_02.getloc() ); + VERIFY( ios1 == ios_01.rdstate() ); + VERIFY( ios2 == ios_02.rdstate() ); + VERIFY( sb1 == ios_01.rdbuf() ); + VERIFY( sb2 == ios_02.rdbuf() ); } -int main() { +int main() +{ test01(); test02(); + test03(); return 0; } |