This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] PR 8761 and 7076, take 4


This revision fixes most of the nits and all the testsuite regressions.  Sorry
for the delay - I've been busy with my day job and other stuff.

I've removed _Format_cache.operator=() and repopulate the cache with the new
locale.  It could be added back if copyfmt performance is an issue.

I've placed the format cache constructor in an auto_ptr.  This protects
against leaking the cache.  The next call, to _Format_cache::_M_init(), calls
has_facet<T> under the covers.  This function has an exception specification
of throw(), but doesn't seem to have code that will actually throw an
exception.  Other than this, the function appears safe to me.

I'm not incredibly exception-savvy, so if this isn't acceptable, can someone
offer me a bit more idea of what should I do here?

I still have _Format_cache_base, since when you access the cache, you have an
ios_base, not a basic_ios<T, Traits>.  So I think this is easier to work
with (one less template parameter to make sure is around when casting).  Also,
it maintains access down the road.

I haven't added dummy virtual functions since I'm nervous about conjuring up
dummy interfaces for the future without a clue as to how they might be used,
esp., what parameters and return values to give.  We could do:
      virtual void _M_dummy1(string s = "");
      virtual int _M_dummy2();
Nathan, is this what you had in mind?



2003-01-23 Jerry Quinn  <jlquinn@optonline.net>

	* config/linker-map.gnu (_Format_cache::_Format_cache()): Export.
	* 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_cache): Declare.
	* include/bits/basic_ios.tcc (basic_ios::copyfmt): Rebuild format cache.
	(basic_ios::imbue): Force format cache to be built.
	(basic_ios::_M_init): Create and initialize format cache.
	(basic_ios::_M_cache): Define.
	* include/bits/ios_base.h (_Format_cache_base): Declare.
	(ios_base): Document reserved storage.
	(ios_base::_M_format_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_streambuf_write<_CharT, _OutIter>): New function.
	(__num_put_streambuf_write<_CharT>): New function specialization.
	(num_put::_M_insert): Remove explicit loop over iterator.  Use
	__num_put_streambuf_write.
	(_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_streambuf_write as friend function.
	* src/ios.cc: Clear _M_format_cache 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/linker-map.gnu libstdc++-v3/config/linker-map.gnu
--- libstdc++.orig/config/linker-map.gnu	Mon Jan  6 22:54:06 2003
+++ libstdc++-v3/config/linker-map.gnu	Fri Jan 24 00:14:13 2003
@@ -1,6 +1,6 @@
 ## Linker script for GNU ld 2.11.94+ only.
 ##
-## Copyright (C) 2002 Free Software Foundation, Inc.
+## Copyright (C) 2002, 2003 Free Software Foundation, Inc.
 ##
 ## This file is part of the libstdc++ version 3 distribution.
 ##
@@ -256,6 +256,13 @@
   _ZNSt24__default_alloc_templateILb1ELi0EE12_S_force_newE;
 
 } GLIBCPP_3.2.1;
+
+GLIBCPP_3.2.3 {
+
+  #std::_Format_cache<char>::_Format_cache[in-charge]()
+  _ZNSt13_Format_cacheIcEC1Ev;
+
+} GLIBCPP_3.2.2;
 
 # Symbols in the support library (libsupc++) have their own tag.
 CXXABI_1.2 {
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 22:54:25 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,15 @@
 
       void
       _M_cache_facets(const locale& __loc);
+
+      _Format_cache<_CharT>&
+      _M_cache()
+      { return *(_Format_cache<_CharT>*)_M_format_cache; }
+
+      const _Format_cache<_CharT>&
+      _M_cache() const
+      { return *(_Format_cache<_CharT>*)_M_format_cache; }
+
     };
 } // 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	Thu Jan 23 08:28:05 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
@@ -99,6 +99,9 @@
       this->exceptions(__rhs.exceptions());
       
       _M_call_callbacks(copyfmt_event);
+
+      _M_cache()._M_populate(*this);
+
       return *this;
     }
 
@@ -122,6 +125,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 +136,8 @@
       locale __old(this->getloc());
       ios_base::imbue(__loc);
       _M_cache_facets(__loc);
+      // Force the cache to be rebuilt.
+      _M_cache()._M_populate(*this);
       if (this->rdbuf() != 0)
 	this->rdbuf()->pubimbue(__loc);
       return __old;
@@ -142,6 +150,14 @@
       // NB: This may be called more than once on the same object.
       ios_base::_M_init();
       _M_cache_facets(_M_ios_locale);
+      if (!_M_format_cache)
+	{
+	  auto_ptr<_Format_cache<_CharT> > __fc(new _Format_cache<_CharT>());
+	  // This will call has_facet, which has a throw() declaration, but I
+	  // don't see how it could actually throw an exception.
+	  __fc->_M_init(*this);
+	  this->_M_format_cache = __fc.release();
+	}
       _M_tie = 0;
 
       // NB: The 27.4.4.1 Postconditions Table specifies requirements
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	Fri Jan 24 00:15:36 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,7 @@
     _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 +430,9 @@
     // Members for locale and locale caching.
     locale 		_M_ios_locale;
 
+    // Access to the format cache.  Cast this to _Format_cache<_CharT>*
+    _Format_cache_base*	_M_format_cache;
+
     void 
     _M_init();
 
@@ -632,6 +638,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 basic_ios::_M_init() has happened.
+    _Format_cache_base& _M_cache() { return *_M_format_cache; }
 
     // 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	Thu Jan 23 18:22:27 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,152 @@
     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() {}
+  };
+
+  // _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&);
+
+      void 
+      _M_populate (ios_base&);
+    };
+
+  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	Thu Jan 23 08:37:52 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 = (_Format_cache<_CharT>&) __io._M_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 = (_Format_cache<_CharT>&)__io._M_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,31 @@
       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_streambuf_write (ostreambuf_iterator<_CharT> __s, const _CharT* __ws,
+		      int __len)
+    {
+      __s._M_sbuf->sputn(__ws, __len);
+      return __s;
+    }
+
+  // This is the unspecialized form of the template
+  template<typename _CharT, typename _OutIter>
+    inline
+    _OutIter
+    __num_put_streambuf_write(_OutIter __s, const _CharT* __ws, int __len)
+    {
+      for (int __j = 0; __j < __len; __j++, ++__s)
+	*__s = __ws[__j];
+      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 +945,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_streambuf_write(__s, __ws, __len);
     }
 
   template<typename _CharT, typename _OutIter>
@@ -1965,22 +2053,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 +2061,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 +2139,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 +2163,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 +2182,62 @@
       while (__first != __last);
       return __s;
     }
+
+  template<typename _CharT>
+    inline
+    _Format_cache<_CharT>::_Format_cache()
+    : _M_use_grouping(false)
+    { }
+
+  // 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_streambuf_write<_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 22:50:49 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_format_cache(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_format_cache;
+    _M_format_cache = 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]