summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libstdc++-v3/ChangeLog29
-rw-r--r--libstdc++-v3/include/bits/basic_ios.h12
-rw-r--r--libstdc++-v3/include/bits/basic_ios.tcc44
-rw-r--r--libstdc++-v3/include/bits/ios_base.h11
-rw-r--r--libstdc++-v3/include/bits/locale_facets.h87
-rw-r--r--libstdc++-v3/include/bits/locale_facets.tcc43
-rw-r--r--libstdc++-v3/src/ios.cc4
-rw-r--r--libstdc++-v3/src/locale-inst.cc2
-rw-r--r--libstdc++-v3/testsuite/27_io/ios_members.cc53
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;
}