This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[patch] PR 8761 and 7076, take 3
- From: Jerry Quinn <jlquinn at optonline dot net>
- To: libstdc++ at gcc dot gnu dot org
- Date: Tue, 21 Jan 2003 01:05:52 -0500
- Subject: [patch] PR 8761 and 7076, take 3
OK, here is the next rendition of my patch for speeding up integer I/O output
performance.
The cache is no longer hung off the pword list. ios_base now contains a
pointer to the cache, acted upon by the routines in basic_ios<>. The nigglets
are fixed.
I still get compile failures for 22_locale/num_put_members_char.cc,
22_locale/num_put_members_wchar_t.cc, and
26_numerics/complex_inserters_extractors.cc. All three have to do with
unexported symbols for the shared library case. Anyone know what's going on
there?
2003-01-21 Jerry Quinn <jlquinn@optonline.net>
* config/locale/generic/c_locale.h (__convert_from_v): Add
template declaration.
* config/locale/gnu/c_locale.h: Same.
* src/locale.cc (__convert_from_v<long>,
__convert_from_v<unsigned long>, __convert_from_v<long long>,
__convert_from_v<unsigned long long>): Add specialization
definitions.
* include/bits/basic_ios.h (_Format_cache::_M_get_cache): Declare.
* include/bits/basic_ios.tcc (basic_ios::copyfmt): Copy format cache.
(basic_ios::imbue): Force format cache to be built.
(basic_ios::_M_init): Create and initialize format cache.
(basic_ios::_M_get_cache): Define.
* include/bits/ios_base.h (_format_cache_base): Declare.
(ios_base): Document reserved storage.
(ios_base::_M_fc): New.
(ios_base::_M_get_cache): New.
* include/bits/locale_facets.h: Remove <ios>. Include
<bits/ios_base.h>.
(convert_to_v): Declare here.
(struct __pad): Same.
(__verify_grouping): Same.
(__add_grouping): Same.
(_Format_cache<_CharT>): New class.
(_Format_cache<char>, _Format_cache<wchar_t>): New specializations.
* include/bits/locale_facets.tcc (__num_put_abs, __num_put_unsigned):
New inline functions.
(__convert_from_int): New.
(num_put::_M_convert_int): Remove unused parameter names. Choose large
enough buffer for text. Use format cache literal string. Use
__convert_from_int. Use __num_put_abs. Use
__num_put_unsigned. Formatted text is now at the end of the buffer.
(num_put::_M_widen): Remove __loc. Remove __ctype. Remove __np. Use
_Format_cache. Move __basefield to within grouping block. Get
grouping and thousands_sep info from cache.
(__num_put_output<_CharT>): New function.
(num_put::_M_insert): Remove explicit loop over iterator. Use
__num_put_output.
(_Format_cache<_CharT>::_Format_cache): New.
(_Format_cache<_CharT>::_M_init): New.
(_Format_cache<_CharT>::_M_populate): New.
(_Format_cache<_CharT>::_S_callback): New.
(_Format_cache<_CharT>::_S_get): New.
(_Format_cache<char>::_Format_cache): New specialization.
(_Format_cache<wchar_t>::_Format_cache): New specialization.
* include/bits/streambuf_iterator.h: Include <streambuf>.
(ostreambuf_iterator): Add __num_put_output as friend function.
* src/ios.cc: Clear_M_fc in constructor and destructor
* src/locale-inst.cc (_Format_cache<char>, _Format_cache<_char_t>):
New.
(__convert_from_v<long long>, __convert_from_v<unsigned long long>):
Add ifdef.
(__convert_from_int<char,unsigned long>): New.
(__convert_from_int<char,unsigned long long>): New.
(__convert_from_int<wchar_t, unsigned long>): New.
(__convert_from_int<wchar_t, unsigned long long>): New.
* src/localenames.cc (_Format_cache<char>::_Format_cache,
_Format_cache<wchar_t>::_Format_cache): New.
diff -u -r libstdc++.orig/config/locale/generic/c_locale.h libstdc++-v3/config/locale/generic/c_locale.h
--- libstdc++.orig/config/locale/generic/c_locale.h Mon Jan 6 22:54:06 2003
+++ libstdc++-v3/config/locale/generic/c_locale.h Wed Jan 15 00:22:21 2003
@@ -1,6 +1,6 @@
// Wrapper for underlying C-language localization -*- C++ -*-
-// Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+// Copyright (C) 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
@@ -41,6 +41,16 @@
{
typedef int* __c_locale;
+ // Convert numeric value of type _Tv to string and return length of string.
+ // If snprintf is available use it, otherwise fall back to the unsafe sprintf
+ // which, in general, can be dangerous and should be avoided.
+ template<typename _Tv>
+ int
+ __convert_from_v(char* __out, const int __size, const char* __fmt,
+ _Tv __v, const __c_locale&, int __prec = -1);
+
+
+ // Generic definition.
template<typename _Tv>
int
__convert_from_v(char* __out, const int __size, const char* __fmt,
diff -u -r libstdc++.orig/config/locale/gnu/c_locale.h libstdc++-v3/config/locale/gnu/c_locale.h
--- libstdc++.orig/config/locale/gnu/c_locale.h Mon Jan 6 22:54:06 2003
+++ libstdc++-v3/config/locale/gnu/c_locale.h Wed Jan 15 00:21:41 2003
@@ -1,6 +1,6 @@
// Wrapper for underlying C-language localization -*- C++ -*-
-// Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+// Copyright (C) 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
@@ -53,6 +53,17 @@
{
typedef __locale_t __c_locale;
+ // Convert numeric value of type _Tv to string and return length of string.
+ // If snprintf is available use it, otherwise fall back to the unsafe sprintf
+ // which, in general, can be dangerous and should be avoided.
+ template<typename _Tv>
+ int
+ __convert_from_v(char* __out, const int __size, const char* __fmt,
+ _Tv __v, const __c_locale&, int __prec = -1);
+
+
+
+ // Generic definition.
template<typename _Tv>
int
__convert_from_v(char* __out, const int __size, const char* __fmt,
diff -u -r libstdc++.orig/include/bits/basic_ios.h libstdc++-v3/include/bits/basic_ios.h
--- libstdc++.orig/include/bits/basic_ios.h Mon Jan 6 22:54:07 2003
+++ libstdc++-v3/include/bits/basic_ios.h Tue Jan 21 00:57:15 2003
@@ -1,6 +1,6 @@
// 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
@@ -430,6 +430,12 @@
void
_M_cache_facets(const locale& __loc);
+
+ _Format_cache<_CharT>&
+ _M_get_cache();
+
+ const _Format_cache<_CharT>&
+ _M_get_cache() const;
};
} // namespace std
diff -u -r libstdc++.orig/include/bits/basic_ios.tcc libstdc++-v3/include/bits/basic_ios.tcc
--- libstdc++.orig/include/bits/basic_ios.tcc Mon Jan 6 22:54:07 2003
+++ libstdc++-v3/include/bits/basic_ios.tcc Tue Jan 21 00:37:30 2003
@@ -1,6 +1,6 @@
// basic_ios locale and locale-related member functions -*- C++ -*-
-// Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc.
+// Copyright (C) 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,6 +90,8 @@
_M_word = __words;
_M_word_size = __rhs._M_word_size;
+ _M_get_cache() = __rhs._M_get_cache();
+
this->flags(__rhs.flags());
this->width(__rhs.width());
this->precision(__rhs.precision());
@@ -122,6 +124,9 @@
return __ret;
}
+ // Forward decl makes the _S_get call below happy. Better way to do this?
+ template<typename _CharT> class _Format_cache;
+
// Locales:
template<typename _CharT, typename _Traits>
locale
@@ -130,6 +135,8 @@
locale __old(this->getloc());
ios_base::imbue(__loc);
_M_cache_facets(__loc);
+ // Force the cache to be rebuilt.
+ _M_get_cache()._M_populate(*this);
if (this->rdbuf() != 0)
this->rdbuf()->pubimbue(__loc);
return __old;
@@ -142,6 +149,12 @@
// NB: This may be called more than once on the same object.
ios_base::_M_init();
_M_cache_facets(_M_ios_locale);
+ if (!_M_fc)
+ {
+ _Format_cache<_CharT>* __fc = new _Format_cache<_CharT>();
+ __fc->_M_init(*this);
+ this->_M_fc = __fc;
+ }
_M_tie = 0;
// NB: The 27.4.4.1 Postconditions Table specifies requirements
@@ -182,6 +195,21 @@
else
_M_fnumget = 0;
}
+
+ template<typename _CharT, typename _Traits>
+ _Format_cache<_CharT>&
+ basic_ios<_CharT, _Traits>::_M_get_cache()
+ {
+ return *(_Format_cache<_CharT>*)_M_fc;
+ }
+
+ template<typename _CharT, typename _Traits>
+ const _Format_cache<_CharT>&
+ basic_ios<_CharT, _Traits>::_M_get_cache() const
+ {
+ return *(_Format_cache<_CharT>*)_M_fc;
+ }
+
// Inhibit implicit instantiations for required instantiations,
// which are defined via explicit instantiations elsewhere.
diff -u -r libstdc++.orig/include/bits/ios_base.h libstdc++-v3/include/bits/ios_base.h
--- libstdc++.orig/include/bits/ios_base.h Mon Jan 6 22:54:07 2003
+++ libstdc++-v3/include/bits/ios_base.h Tue Jan 21 00:11:09 2003
@@ -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
@@ -144,6 +144,8 @@
enum _Ios_Seekdir { _M_ios_seekdir_end = 1L << 16 };
+ class _format_cache_base;
+
// 27.4.2 Class ios_base
/**
* @brief The very top of the I/O class hierarchy.
@@ -414,6 +416,8 @@
_Words _M_word_zero;
// Guaranteed storage.
+ // The first 5 iword and pword slots are reserved for internal use.
+
static const int _S_local_word_size = 8;
_Words _M_local_word[_S_local_word_size];
@@ -427,6 +431,10 @@
// Members for locale and locale caching.
locale _M_ios_locale;
+
+ // Access to the format cache
+ _format_cache_base* _M_fc;
+
void
_M_init();
@@ -632,6 +640,12 @@
? _M_word[__ix] : _M_grow_words(__ix);
return __word._M_pword;
}
+
+ // Basic_ios stores the format cache, but sometimes, all we have is the
+ // ios_base. This provides access and casting. A little bit ugly as you
+ // must assign this to a _Format_cache<_CharT> for the cast to happen
+ // cleanly. Not safe to call until _M_init() has happened.
+ _format_cache_base& _M_get_cache() { return *(_format_cache_base*)_M_fc; }
// Destructor
/**
diff -u -r libstdc++.orig/include/bits/locale_facets.h libstdc++-v3/include/bits/locale_facets.h
--- libstdc++.orig/include/bits/locale_facets.h Mon Jan 6 22:54:07 2003
+++ libstdc++-v3/include/bits/locale_facets.h Tue Jan 21 00:11:57 2003
@@ -1,6 +1,6 @@
// Locale support -*- 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
@@ -44,7 +44,7 @@
#include <ctime> // For struct tm
#include <cwctype> // For wctype_t
-#include <ios> // For ios_base
+#include <bits/ios_base.h> // For ios_base
namespace std
{
@@ -55,9 +55,6 @@
# define _GLIBCPP_NUM_FACETS 14
#endif
- template<typename _CharT, typename _Traits>
- struct __pad;
-
// 22.2.1.1 Template class ctype
// Include host and configuration specific ctype enums for ctype_base.
#include <bits/ctype_base.h>
@@ -1805,6 +1802,158 @@
inline _CharT
tolower(_CharT __c, const locale& __loc)
{ return use_facet<ctype<_CharT> >(__loc).tolower(__c); }
+
+
+ // Convert string to numeric value of type _Tv and store results.
+ // NB: This is specialized for all required types, there is no
+ // generic definition.
+ template<typename _Tv>
+ void
+ __convert_to_v(const char* __in, _Tv& __out, ios_base::iostate& __err,
+ const __c_locale& __cloc, int __base = 10);
+
+ // NB: Of the two parameters, _CharT can be deduced from the
+ // function arguments. The other (_Traits) has to be explicitly specified.
+ template<typename _CharT, typename _Traits>
+ struct __pad
+ {
+ static void
+ _S_pad(ios_base& __io, _CharT __fill, _CharT* __news,
+ const _CharT* __olds, const streamsize __newlen,
+ const streamsize __oldlen, const bool __num);
+ };
+
+ // Used by both numeric and monetary facets.
+ // Check to make sure that the __grouping_tmp string constructed in
+ // money_get or num_get matches the canonical grouping for a given
+ // locale.
+ // __grouping_tmp is parsed L to R
+ // 1,222,444 == __grouping_tmp of "\1\3\3"
+ // __grouping is parsed R to L
+ // 1,222,444 == __grouping of "\3" == "\3\3\3"
+ template<typename _CharT>
+ bool
+ __verify_grouping(const basic_string<_CharT>& __grouping,
+ basic_string<_CharT>& __grouping_tmp);
+
+ // Used by both numeric and monetary facets.
+ // 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 __gbeg != __gend.
+ template<typename _CharT>
+ _CharT*
+ __add_grouping(_CharT* __s, _CharT __sep,
+ const char* __gbeg, const char* __gend,
+ const _CharT* __first, const _CharT* __last);
+
+
+
+ // Pseudo pointer machinery for transparent casting from void* to
+ // _Format_cache<_CharT>
+ template<typename _CharT>
+ class _Format_cache;
+
+ class _format_cache_base
+ {
+ public:
+ virtual
+ ~_format_cache_base() {}
+
+ template<typename _CharT>
+ operator _Format_cache<_CharT>*() { return (_Format_cache<_CharT>*)this; }
+ };
+
+ // _Format_cache holds the information extracted from the numpunct<> and
+ // moneypunct<> facets in a form optimized for parsing and formatting. It
+ // is stored as a member of basic_ios and accessed via a void* pointer in
+ // the ios_base object passed to the _get and _put facets.
+
+ // Its intent is to avoid the cost of creating a locale object and
+ // calling the virtual functions in locale facets.
+ template<typename _CharT>
+ class _Format_cache : public _format_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().
+ //
+
+ // NB: code depends on the order of definitions of the names
+ // these are indices into _M_numeric_literals, below.
+ // This string is formatted for putting, not getting. (output, not input)
+ enum
+ {
+ _S_minus,
+ _S_plus,
+ _S_x,
+ _S_X,
+ _S_digits,
+ _S_digits_end = _S_digits + 16,
+ _S_udigits = _S_digits_end,
+ _S_udigits_end = _S_udigits + 16,
+ _S_ee = _S_digits + 14, // For scientific notation, 'e'
+ _S_Ee = _S_udigits + 14 // For scientific notation, 'E'
+ };
+
+ _CharT _M_literals[_S_udigits_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;
+
+ _Format_cache();
+
+ _Format_cache& operator=(const _Format_cache& __fc);
+
+
+ // Make sure the cache is built before the first use.
+ void _M_init(ios_base&);
+
+ private:
+ void
+ _M_populate (ios_base&);
+
+ friend class basic_ios<_CharT>;
+ };
+
+ template<>
+ _Format_cache<char>::_Format_cache();
+#ifdef _GLIBCPP_USE_WCHAR_T
+ template<>
+ _Format_cache<wchar_t>::_Format_cache();
+#endif
} // namespace std
#endif
diff -u -r libstdc++.orig/include/bits/locale_facets.tcc libstdc++-v3/include/bits/locale_facets.tcc
--- libstdc++.orig/include/bits/locale_facets.tcc Mon Jan 6 22:54:07 2003
+++ libstdc++-v3/include/bits/locale_facets.tcc Tue Jan 21 00:47:28 2003
@@ -1,6 +1,6 @@
// Locale support -*- 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
@@ -686,39 +686,105 @@
return _M_widen_float(__s, __io, __fill, __cs, __len);
}
+ // num_put::_M_convert_int is only ever specialized with long, unsigned
+ // long, long long, and unsigned long long. These adapters permit calling
+ // into unsigned long and unsigned long long functions.
+ inline unsigned long __num_put_abs(long __v) { return -(unsigned long)__v; }
+ inline unsigned long __num_put_abs(unsigned long __v) { return __v; }
+ inline unsigned long __num_put_unsigned(long __v) { return (unsigned long)__v; }
+ inline unsigned long __num_put_unsigned(unsigned long __v) { return __v; }
+#ifdef _GLIBCPP_USE_LONG_LONG
+ inline unsigned long long __num_put_abs(long long __v) { return -(unsigned long long)__v; }
+ inline unsigned long long __num_put_abs(unsigned long long __v) { return __v; }
+ inline unsigned long long __num_put_unsigned(long long __v) { return -(unsigned long long)__v; }
+ inline unsigned long long __num_put_unsigned(unsigned long long __v) { return __v; }
+#endif
+
+ // Only called with unsigned long and unsigned long long
+ template<typename _CharT, typename _ValueT>
+ int
+ __convert_from_int(_CharT* __out, const int __size, _ValueT __v,
+ const _CharT* __lit, ios_base::fmtflags __flags,
+ bool __neg)
+ {
+ _CharT* __bufptr = __out + __size - 1;
+ _CharT* __bufend = __out + __size;
+ ios_base::fmtflags __bf = __flags & ios_base::basefield;
+
+ if (__builtin_expect(__bf == ios_base::oct, false))
+ {
+ // Octal
+ bool __showbase = ((__flags & ios_base::showbase) && __v); // Don't write base if already 0
+ do {
+ *__bufptr-- = __lit[(__v & 0x7) + _Format_cache<_CharT>::_S_digits];
+ __v >>=3;
+ } while (__v != 0);
+ if (__showbase)
+ *__bufptr-- = __lit[_Format_cache<_CharT>::_S_digits];
+ }
+ else if (__builtin_expect(__bf == ios_base::hex, false))
+ {
+ // Hex
+ int __case_offset = (__flags & ios_base::uppercase)
+ ? _Format_cache<_CharT>::_S_udigits
+ : _Format_cache<_CharT>::_S_digits;
+ do {
+ *__bufptr-- = __lit[(__v & 0xf) + __case_offset];
+ __v >>=4;
+ } while (__v != 0);
+ if (__flags & ios_base::showbase)
+ {
+ // 'x' or 'X'
+ *__bufptr-- = __lit[_Format_cache<_CharT>::_S_x +
+ (int)(!!(__flags & ios_base::uppercase))];
+ // '0'
+ *__bufptr-- = __lit[_Format_cache<_CharT>::_S_digits];
+ }
+ }
+ else
+ {
+ // Decimal
+ do {
+ *__bufptr-- = __lit[(__v % 10) + _Format_cache<_CharT>::_S_digits];
+ __v /= 10;
+ } while (__v != 0);
+ if (__neg)
+ *__bufptr-- = __lit[_Format_cache<_CharT>::_S_minus];
+ else if (__flags & ios_base::showpos)
+ *__bufptr-- = __lit[_Format_cache<_CharT>::_S_plus];
+ }
+ int __ret = __bufend - __bufptr - 1;
+ return __ret;
+ }
+
template<typename _CharT, typename _OutIter>
template<typename _ValueT>
_OutIter
num_put<_CharT, _OutIter>::
- _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
- char __modl, _ValueT __v) const
+ _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char,
+ char, _ValueT __v) const
{
// [22.2.2.2.2] Stage 1, numeric conversion to character.
- // Long enough for the max format spec.
- char __fbuf[16];
- _S_format_int(__io, __fbuf, __mod, __modl);
-#ifdef _GLIBCPP_USE_C99
- // First try a buffer perhaps big enough.
- int __cs_size = 64;
- char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
- int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
- _S_c_locale);
- // If the buffer was not large enough, try again with the correct size.
- if (__len >= __cs_size)
- {
- __cs_size = __len + 1;
- __cs = static_cast<char*>(__builtin_alloca(__cs_size));
- __len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
- _S_c_locale);
- }
-#else
- // Leave room for "+/-," "0x," and commas. This size is
- // arbitrary, but should be largely sufficient.
- char __cs[128];
- int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
-#endif
- return _M_widen_int(__s, __io, __fill, __cs, __len);
+ // Long enough to hold hex, dec, and octal representations.
+ int __cs_size = 4 * sizeof(_ValueT);
+ _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
+ * __cs_size));
+ _Format_cache<_CharT>* __fc = __io._M_get_cache();
+ _CharT* __lit = __fc->_M_literals;
+
+ int __len;
+ // Choose the adaptor required to convert the value for calling into
+ // an unsigned long (long) rendering function. Result is returned
+ // right-justified in the buffer.
+ if (__v < 0)
+ __len = __convert_from_int(&__cs[0], __cs_size, __num_put_abs(__v),
+ __lit, __io.flags(), true);
+ else
+ __len = __convert_from_int(&__cs[0], __cs_size, __num_put_unsigned(__v),
+ __lit, __io.flags(), false);
+
+ return _M_widen_int(__s, __io, __fill, (char*)(__cs + __cs_size - __len), __len);
}
template<typename _CharT, typename _OutIter>
@@ -784,22 +850,21 @@
{
// [22.2.2.2.2] Stage 2, convert to char_type, using correct
// numpunct.decimal_point() values for '.' and adding grouping.
- const locale __loc = __io.getloc();
- const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
- _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
- * __len));
+
+ _CharT* __ws = (_CharT*)__cs;
// Grouping can add (almost) as many separators as the number of
// digits, but no more.
_CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
* __len * 2));
- __ctype.widen(__cs, __cs + __len, __ws);
+
+ _Format_cache<_CharT>* __fc = __io._M_get_cache();
+
// Add grouping, if necessary.
- const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
- const string __grouping = __np.grouping();
- const ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
- if (__grouping.size())
+ if (__fc->_M_use_grouping)
{
+ const ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
+
// By itself __add_grouping cannot deal correctly with __ws when
// ios::showbase is set and ios_base::oct || ios_base::hex.
// Therefore we take care "by hand" of the initial 0, 0x or 0X.
@@ -819,9 +884,9 @@
*(__ws2 + 1) = *(__ws + 1);
}
_CharT* __p;
- __p = __add_grouping(__ws2 + __off, __np.thousands_sep(),
- __grouping.c_str(),
- __grouping.c_str() + __grouping.size(),
+ __p = __add_grouping(__ws2 + __off, __fc->_M_thousands_sep,
+ __fc->_M_grouping.c_str(),
+ __fc->_M_grouping.c_str() + __fc->_M_grouping.size(),
__ws + __off, __ws + __len);
__len = __p - __ws2;
// Switch strings.
@@ -830,6 +895,20 @@
return _M_insert(__s, __io, __fill, __ws, __len);
}
+
+ // This template permits specializing the stage 4 output code in _M_insert
+ // on ostreambuf_iterator. For the streambufs, sputn is significantly more
+ // efficient than incrementing iterators.
+ template<typename _CharT>
+ inline
+ ostreambuf_iterator<_CharT>
+ __num_put_output (ostreambuf_iterator<_CharT> __s, const _CharT* __ws,
+ int __len)
+ {
+ __s._M_sbuf->sputn(__ws, __len);
+ return __s;
+ }
+
// For use by integer and floating-point types after they have been
// converted into a char_type string.
template<typename _CharT, typename _OutIter>
@@ -855,9 +934,7 @@
// [22.2.2.2.2] Stage 4.
// Write resulting, fully-formatted string to output iterator.
- for (int __j = 0; __j < __len; ++__j, ++__s)
- *__s = __ws[__j];
- return __s;
+ return __num_put_output(__s, __ws, __len);
}
template<typename _CharT, typename _OutIter>
@@ -1965,22 +2042,6 @@
return static_cast<long>(__val);
}
- // Convert string to numeric value of type _Tv and store results.
- // NB: This is specialized for all required types, there is no
- // generic definition.
- template<typename _Tv>
- void
- __convert_to_v(const char* __in, _Tv& __out, ios_base::iostate& __err,
- const __c_locale& __cloc, int __base = 10);
-
- // Convert numeric value of type _Tv to string and return length of string.
- // If snprintf is available use it, otherwise fall back to the unsafe sprintf
- // which, in general, can be dangerous and should be avoided.
- template<typename _Tv>
- int
- __convert_from_v(char* __out, const int __size, const char* __fmt,
- _Tv __v, const __c_locale&, int __prec = -1);
-
// Construct correctly padded string, as per 22.2.2.2.2
// Assumes
// __newlen > __oldlen
@@ -1989,18 +2050,6 @@
// internal-adjusted objects are padded according to the rules below
// concerning 0[xX] and +-, otherwise, exactly as right-adjusted
// ones are.
-
- // NB: Of the two parameters, _CharT can be deduced from the
- // function arguments. The other (_Traits) has to be explicitly specified.
- template<typename _CharT, typename _Traits>
- struct __pad
- {
- static void
- _S_pad(ios_base& __io, _CharT __fill, _CharT* __news,
- const _CharT* __olds, const streamsize __newlen,
- const streamsize __oldlen, const bool __num);
- };
-
template<typename _CharT, typename _Traits>
void
__pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill,
@@ -2079,14 +2128,6 @@
__newlen - __beglen - __mod);
}
- // Used by both numeric and monetary facets.
- // Check to make sure that the __grouping_tmp string constructed in
- // money_get or num_get matches the canonical grouping for a given
- // locale.
- // __grouping_tmp is parsed L to R
- // 1,222,444 == __grouping_tmp of "/1/3/3"
- // __grouping is parsed R to L
- // 1,222,444 == __grouping of "/3" == "/3/3/3"
template<typename _CharT>
bool
__verify_grouping(const basic_string<_CharT>& __grouping,
@@ -2111,11 +2152,6 @@
return __test;
}
- // Used by both numeric and monetary facets.
- // 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 __gbeg != __gend.
template<typename _CharT>
_CharT*
__add_grouping(_CharT* __s, _CharT __sep,
@@ -2135,6 +2171,76 @@
while (__first != __last);
return __s;
}
+
+ template<typename _CharT>
+ inline
+ _Format_cache<_CharT>::_Format_cache()
+ : _M_use_grouping(false)
+ { }
+
+ template<typename _CharT>
+ _Format_cache<_CharT>&
+ _Format_cache<_CharT>::operator=(const _Format_cache<_CharT>& __fc)
+ {
+ copy<const _CharT*,_CharT*>(&__fc._M_literals[0], &__fc._M_literals[0] + _S_udigits_end, &_M_literals[0]);
+ _M_decimal_point = __fc._M_decimal_point;
+ _M_thousands_sep = __fc._M_thousands_sep;
+ _M_truename = __fc._M_truename;
+ _M_falsename = __fc._M_falsename;
+ _M_use_grouping = __fc._M_use_grouping;
+ _M_grouping = __fc._M_grouping;
+ return *this;
+ }
+
+ // Cache initialization
+ template<typename _CharT>
+ inline
+ void
+ _Format_cache<_CharT>::_M_init(ios_base& __io)
+ { _M_populate(__io); }
+
+ // char and wchar_t specializations start out valid, so no need to call
+ // _M_populate
+ template<>
+ inline
+ void
+ _Format_cache<char>::_M_init(ios_base&)
+ { }
+#ifdef _GLIBCPP_USE_WCHAR_T
+ template<>
+ inline
+ void
+ _Format_cache<wchar_t>::_M_init(ios_base&)
+ { }
+#endif
+
+
+ template<typename _CharT>
+ void
+ _Format_cache<_CharT>::_M_populate(ios_base& __io)
+ {
+ static const char _S_numeric_literals[] = "-+xX0123456789abcdef0123456789ABCDEF";
+ static const int _S_literal_count = sizeof(_S_numeric_literals) - 1;
+
+ locale __loc = __io.getloc();
+ if (__builtin_expect(has_facet<numpunct<_CharT> >(__loc), true))
+ {
+ numpunct<_CharT> const& __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))
+ {
+ ctype<_CharT> const& __ct = use_facet< ctype<_CharT> >(__loc);
+ __ct.widen(_S_numeric_literals,
+ _S_numeric_literals + _S_literal_count, _M_literals);
+ }
+ }
+
// Inhibit implicit instantiations for required instantiations,
// which are defined via explicit instantiations elsewhere.
diff -u -r libstdc++.orig/include/bits/streambuf_iterator.h libstdc++-v3/include/bits/streambuf_iterator.h
--- libstdc++.orig/include/bits/streambuf_iterator.h Mon Jan 6 22:54:07 2003
+++ libstdc++-v3/include/bits/streambuf_iterator.h Sun Jan 19 13:39:46 2003
@@ -1,6 +1,6 @@
// Streambuf iterators
-// 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
@@ -40,6 +40,8 @@
#pragma GCC system_header
+#include <streambuf>
+
namespace std
{
// 24.5.3 Template class istreambuf_iterator
@@ -191,6 +193,10 @@
bool
failed() const throw()
{ return _M_failed; }
+
+ friend ostreambuf_iterator<_CharT>
+ __num_put_output<_CharT>(ostreambuf_iterator<_CharT> __s,
+ const _CharT* __ws, int __len);
};
template<typename _CharT, typename _Traits>
diff -u -r libstdc++.orig/src/ios.cc libstdc++-v3/src/ios.cc
--- libstdc++.orig/src/ios.cc Mon Jan 6 22:54:07 2003
+++ libstdc++-v3/src/ios.cc Tue Jan 21 00:53:17 2003
@@ -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
@@ -301,7 +301,7 @@
return __old;
}
- ios_base::ios_base() : _M_callbacks(0), _M_word(0)
+ ios_base::ios_base() : _M_callbacks(0), _M_word(0), _M_fc(0)
{
// Do nothing: basic_ios::init() does it.
// NB: _M_callbacks and _M_word must be zero for non-initialized
@@ -318,6 +318,8 @@
delete [] _M_word;
_M_word = 0;
}
+ delete _M_fc;
+ _M_fc = 0;
}
void
diff -u -r libstdc++.orig/src/locale-inst.cc libstdc++-v3/src/locale-inst.cc
--- libstdc++.orig/src/locale-inst.cc Mon Jan 6 22:54:07 2003
+++ libstdc++-v3/src/locale-inst.cc Tue Jan 21 00:54:39 2003
@@ -1,6 +1,6 @@
// Locale support -*- C++ -*-
-// Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+// Copyright (C) 1999, 2000, 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
@@ -46,6 +46,7 @@
template class moneypunct_byname<char, true>;
template class money_get<char, istreambuf_iterator<char> >;
template class money_put<char, ostreambuf_iterator<char> >;
+ template class _Format_cache<char>;
#ifdef _GLIBCPP_USE_WCHAR_T
template class moneypunct<wchar_t, false>;
@@ -54,6 +55,7 @@
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 _Format_cache<wchar_t>;
#endif
// numpunct, numpunct_byname, num_get, and num_put
@@ -451,6 +453,7 @@
__convert_from_v(char*, const int, const char*, unsigned long,
const __c_locale&, int);
+#ifdef _GLIBCPP_USE_LONG_LONG
template
int
__convert_from_v(char*, const int, const char*, long long,
@@ -460,4 +463,35 @@
int
__convert_from_v(char*, const int, const char*, unsigned long long,
const __c_locale&, int);
+#endif
+
+ template
+ int
+ __convert_from_int(char* __out, const int __size, unsigned long __v,
+ const char* __lit, ios_base::fmtflags __flags,
+ bool __neg);
+
+#ifdef _GLIBCPP_USE_WCHAR_T
+ template
+ int
+ __convert_from_int(wchar_t* __out, const int __size, unsigned long __v,
+ const wchar_t* __lit, ios_base::fmtflags __flags,
+ bool __neg);
+#endif
+
+#ifdef _GLIBCPP_USE_LONG_LONG
+ template
+ int
+ __convert_from_int(char* __out, const int __size, unsigned long long __v,
+ const char* __lit, ios_base::fmtflags __flags,
+ bool __neg);
+
+#ifdef _GLIBCPP_USE_WCHAR_T
+ template
+ int
+ __convert_from_int(wchar_t* __out, const int __size, unsigned long long __v,
+ const wchar_t* __lit, ios_base::fmtflags __flags,
+ bool __neg);
+#endif
+#endif
} // namespace std
diff -u -r libstdc++.orig/src/localename.cc libstdc++-v3/src/localename.cc
--- libstdc++.orig/src/localename.cc Mon Jan 6 22:54:07 2003
+++ libstdc++-v3/src/localename.cc Tue Jan 21 00:55:05 2003
@@ -1,4 +1,4 @@
-// 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
@@ -350,4 +350,28 @@
}
}
}
+
+ template<>
+ _Format_cache<char>::_Format_cache()
+ : _M_decimal_point('.'), _M_thousands_sep(','),
+ _M_truename("true"), _M_falsename("false"), _M_use_grouping(false)
+ {
+ static const char _S_numeric_literals[] = "-+xX0123456789abcdef0123456789ABCDEF";
+ static const int _S_literal_count = sizeof(_S_numeric_literals) - 1;
+
+ copy(_S_numeric_literals, _S_numeric_literals + _S_literal_count, _M_literals);
+ }
+
+#ifdef _GLIBCPP_USE_WCHAR_T
+ template<>
+ _Format_cache<wchar_t>::_Format_cache()
+ : _M_decimal_point(L'.'), _M_thousands_sep(L','),
+ _M_truename(L"true"), _M_falsename(L"false"), _M_use_grouping(false)
+ {
+ static const wchar_t _S_numeric_literals[] = L"-+xX0123456789abcdef0123456789ABCDEF";
+ static const int _S_literal_count = (sizeof(_S_numeric_literals) - 1) / sizeof(wchar_t);
+
+ copy(_S_numeric_literals, _S_numeric_literals + _S_literal_count, _M_literals);
+ }
+#endif
} // namespace std