[multiple changes]

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.

From-SVN: r63025
This commit is contained in:
Benjamin Kosnik 2003-02-18 05:45:07 +00:00
parent 59ac5a1725
commit 6067bea410
9 changed files with 225 additions and 62 deletions

View File

@ -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>.

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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 );
}
#ifdef DEBUG_ASSERT
assert(test);
#endif
}
int main() {
// copyfmt and locales.
void test03()
{
bool test = true;
using namespace std;
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()
{
test01();
test02();
test03();
return 0;
}