aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libstdc++-v3/ChangeLog46
-rw-r--r--libstdc++-v3/config/linker-map.gnu3
-rw-r--r--libstdc++-v3/config/locale/generic/numeric_members.cc62
-rw-r--r--libstdc++-v3/config/locale/gnu/numeric_members.cc90
-rw-r--r--libstdc++-v3/include/bits/basic_ios.tcc8
-rw-r--r--libstdc++-v3/include/bits/ios_base.h54
-rw-r--r--libstdc++-v3/include/bits/locale_classes.h227
-rw-r--r--libstdc++-v3/include/bits/locale_facets.h190
-rw-r--r--libstdc++-v3/include/bits/locale_facets.tcc61
-rw-r--r--libstdc++-v3/src/globals.cc15
-rw-r--r--libstdc++-v3/src/ios.cc4
-rw-r--r--libstdc++-v3/src/locale-inst.cc4
-rw-r--r--libstdc++-v3/src/locale.cc53
-rw-r--r--libstdc++-v3/src/localename.cc114
-rw-r--r--libstdc++-v3/testsuite/27_io/ios_base/cons/assign_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/27_io/ios_base/cons/copy_neg.cc2
16 files changed, 620 insertions, 315 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 9e2c2c1..4572136 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,49 @@
+2003-06-26 Benjamin Kosnik <bkoz@redhat.com>
+
+ * include/bits/ios_base.h (ios_base::_M_getloc): Return reference
+ to the imbued locale.
+ * include/bits/locale_facets.tcc (num_put::_M_convert_int): Use
+ _M_getloc.
+ (num_put::_M_convert_float): Use.
+
+2003-06-26 Benjamin Kosnik <bkoz@redhat.com>
+ Jerry Quinn <jlquinn@optonline.net>
+
+ * config/linker-map.gnu: Add __numpunct_cache.
+ * config/locale/gnu/numeric_members.cc
+ (numpunct::_M_initialize_numpunct): Account for _M_data, fill in
+ all elements for "C" locale.
+ (numpunct::~numpunct): Delete _M_data.
+ * config/locale/generic/numeric_members.cc: Same.
+ * include/bits/basic_ios.tcc
+ (basic_ios::init): Remove __locale_cache bits.
+ (basic_ios::_M_cache_locale): Same.
+ * include/bits/ios_base.h: Same. Tweaks.
+ * include/bits/locale_classes.h: Tweaks. Reorder classes.
+ (__use_cache): Make friends with _Impl, locale.
+ (_Impl::_M_caches): Add.
+ (_Impl::_M_install_cache): Add.
+ * include/bits/locale_facets.h (__numpunct_cache): New.
+ (numpunct): Encapsulate data members in __numpunct_cache member,
+ _M_data. Adjust virtuals.
+ (numpunct::numpunct): New ctor for the same.
+ (__locale_cache_base): Remove.
+ (__locale_cache): Remove.
+ * include/bits/locale_facets.tcc (__use_cache): New function,
+ specializations.
+ (num_put::_M_convert_int, _M_convert_float, do_put): Use it.
+ * src/globals.cc: Add cache_vec, numpunct_cache_c, numpunct_cache_w.
+ * src/ios.cc (ios_base::ios_base): Remove __locale_cache.
+ * src/locale-inst.cc: Same. Add __numpunct_cache.
+ * src/locale.cc: Tweak inlines.
+ (__use_cache): Define specializations.
+ * src/localename.cc: Use global bits.
+ (_Impl::~Impl): Deal with __numpunct_cache destruction.
+ (_Impl::_Impl): Same. Pre-cache standard numpunct facets.
+ (_Impl::_M_init_facet): Take into account __numpunct_cache.
+ * testsuite/27_io/ios_base/cons/assign_neg.cc: Update line numbers.
+ * testsuite/27_io/ios_base/cons/copy_neg.cc: Same.
+
2003-06-26 Nathan C. Myers <ncm-nospam@cantrip.org>
Paolo Carlini <pcarlini@unitus.it>
diff --git a/libstdc++-v3/config/linker-map.gnu b/libstdc++-v3/config/linker-map.gnu
index 77d69fc..21bdfd3 100644
--- a/libstdc++-v3/config/linker-map.gnu
+++ b/libstdc++-v3/config/linker-map.gnu
@@ -55,7 +55,8 @@ GLIBCPP_3.4 {
std::__num_base::_S_format_float*;
std::__num_base::_S_format_int*;
std::__num_base::_S_atoms_in;
- std::__num_base::_S_atoms_out
+ std::__num_base::_S_atoms_out;
+ std::__numpunct_cache*;
};
# Names not in an 'extern' block are mangled names.
diff --git a/libstdc++-v3/config/locale/generic/numeric_members.cc b/libstdc++-v3/config/locale/generic/numeric_members.cc
index f942e04..320f0ff 100644
--- a/libstdc++-v3/config/locale/generic/numeric_members.cc
+++ b/libstdc++-v3/config/locale/generic/numeric_members.cc
@@ -1,6 +1,6 @@
// std::numpunct implementation details, generic version -*- 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
@@ -42,16 +42,30 @@ namespace std
numpunct<char>::_M_initialize_numpunct(__c_locale)
{
// "C" locale
- _M_decimal_point = '.';
- _M_thousands_sep = ',';
- _M_grouping = "";
- _M_truename = "true";
- _M_falsename = "false";
+ if (!_M_data)
+ _M_data = new __numpunct_cache<char>;
+
+ _M_data->_M_grouping = "";
+ _M_data->_M_use_grouping = false;
+
+ _M_data->_M_decimal_point = '.';
+ _M_data->_M_thousands_sep = ',';
+
+ for (size_t i = 0; i < __num_base::_S_oend; ++i)
+ _M_data->_M_atoms_out[i] = __num_base::_S_atoms_out[i];
+ _M_data->_M_atoms_out[__num_base::_S_oend] = wchar_t();
+
+ for (size_t i = 0; i < __num_base::_S_iend; ++i)
+ _M_data->_M_atoms_in[i] = __num_base::_S_atoms_in[i];
+ _M_data->_M_atoms_in[__num_base::_S_iend] = wchar_t();
+
+ _M_data->_M_truename = "true";
+ _M_data->_M_falsename = "false";
}
template<>
numpunct<char>::~numpunct()
- { }
+ { delete _M_data; }
#ifdef _GLIBCPP_USE_WCHAR_T
template<>
@@ -59,15 +73,37 @@ namespace std
numpunct<wchar_t>::_M_initialize_numpunct(__c_locale)
{
// "C" locale
- _M_decimal_point = L'.';
- _M_thousands_sep = L',';
- _M_grouping = "";
- _M_truename = L"true";
- _M_falsename = L"false";
+ if (!_M_data)
+ _M_data = new __numpunct_cache<wchar_t>;
+
+ _M_data->_M_grouping = "";
+ _M_data->_M_use_grouping = false;
+
+ _M_data->_M_decimal_point = L'.';
+ _M_data->_M_thousands_sep = L',';
+
+ // Use ctype::widen code without the facet...
+ unsigned char uc;
+ for (size_t i = 0; i < __num_base::_S_oend; ++i)
+ {
+ uc = static_cast<unsigned char>(__num_base::_S_atoms_out[i]);
+ _M_data->_M_atoms_out[i] = btowc(uc);
+ }
+ _M_data->_M_atoms_out[__num_base::_S_oend] = wchar_t();
+
+ for (size_t i = 0; i < __num_base::_S_iend; ++i)
+ {
+ uc = static_cast<unsigned char>(__num_base::_S_atoms_in[i]);
+ _M_data->_M_atoms_in[i] = btowc(uc);
+ }
+ _M_data->_M_atoms_in[__num_base::_S_iend] = wchar_t();
+
+ _M_data->_M_truename = L"true";
+ _M_data->_M_falsename = L"false";
}
template<>
numpunct<wchar_t>::~numpunct()
- { }
+ { delete _M_data; }
#endif
}
diff --git a/libstdc++-v3/config/locale/gnu/numeric_members.cc b/libstdc++-v3/config/locale/gnu/numeric_members.cc
index 5b666eb..dd8c76b 100644
--- a/libstdc++-v3/config/locale/gnu/numeric_members.cc
+++ b/libstdc++-v3/config/locale/gnu/numeric_members.cc
@@ -1,6 +1,6 @@
// std::numpunct implementation details, GNU version -*- 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
@@ -42,70 +42,112 @@ namespace std
void
numpunct<char>::_M_initialize_numpunct(__c_locale __cloc)
{
+ if (!_M_data)
+ _M_data = new __numpunct_cache<char>;
+
if (!__cloc)
{
// "C" locale
- _M_decimal_point = '.';
- _M_thousands_sep = ',';
- _M_grouping = "";
+ _M_data->_M_grouping = "";
+ _M_data->_M_use_grouping = false;
+
+ _M_data->_M_decimal_point = '.';
+ _M_data->_M_thousands_sep = ',';
+
+ for (size_t i = 0; i < __num_base::_S_oend; ++i)
+ _M_data->_M_atoms_out[i] = __num_base::_S_atoms_out[i];
+ _M_data->_M_atoms_out[__num_base::_S_oend] = wchar_t();
+
+ for (size_t i = 0; i < __num_base::_S_iend; ++i)
+ _M_data->_M_atoms_in[i] = __num_base::_S_atoms_in[i];
+ _M_data->_M_atoms_in[__num_base::_S_iend] = wchar_t();
}
else
{
// Named locale.
- _M_decimal_point = *(__nl_langinfo_l(RADIXCHAR, __cloc));
- _M_thousands_sep = *(__nl_langinfo_l(THOUSEP, __cloc));
- // Check for NUL, which implies no grouping.
- if (_M_thousands_sep == '\0')
- _M_grouping = "";
+ _M_data->_M_decimal_point = *(__nl_langinfo_l(RADIXCHAR, __cloc));
+ _M_data->_M_thousands_sep = *(__nl_langinfo_l(THOUSEP, __cloc));
+
+ // Check for NULL, which implies no grouping.
+ if (_M_data->_M_thousands_sep == '\0')
+ _M_data->_M_grouping = "";
else
- _M_grouping = __nl_langinfo_l(GROUPING, __cloc);
+ _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
}
// NB: There is no way to extact this info from posix locales.
// _M_truename = __nl_langinfo_l(YESSTR, __cloc);
- _M_truename = "true";
+ _M_data->_M_truename = "true";
// _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
- _M_falsename = "false";
+ _M_data->_M_falsename = "false";
}
template<>
numpunct<char>::~numpunct()
- { }
+ { delete _M_data; }
#ifdef _GLIBCPP_USE_WCHAR_T
template<>
void
numpunct<wchar_t>::_M_initialize_numpunct(__c_locale __cloc)
{
+ if (!_M_data)
+ _M_data = new __numpunct_cache<wchar_t>;
+
if (!__cloc)
{
// "C" locale
- _M_decimal_point = L'.';
- _M_thousands_sep = L',';
- _M_grouping = "";
+ _M_data->_M_grouping = "";
+ _M_data->_M_use_grouping = false;
+
+ _M_data->_M_decimal_point = L'.';
+ _M_data->_M_thousands_sep = L',';
+
+#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
+ __c_locale __old = __uselocale(_S_c_locale);
+#endif
+ // Use ctype::widen code without the facet...
+ unsigned char uc;
+ for (size_t i = 0; i < __num_base::_S_oend; ++i)
+ {
+ uc = static_cast<unsigned char>(__num_base::_S_atoms_out[i]);
+ _M_data->_M_atoms_out[i] = btowc(uc);
+ }
+ _M_data->_M_atoms_out[__num_base::_S_oend] = wchar_t();
+
+ for (size_t i = 0; i < __num_base::_S_iend; ++i)
+ {
+ uc = static_cast<unsigned char>(__num_base::_S_atoms_in[i]);
+ _M_data->_M_atoms_in[i] = btowc(uc);
+ }
+ _M_data->_M_atoms_in[__num_base::_S_iend] = wchar_t();
+#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
+ __uselocale(__old);
+#endif
}
else
{
// Named locale.
union __s_and_w { const char *__s; unsigned int __w; } __u;
__u.__s = __nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc);
- _M_decimal_point = static_cast<wchar_t>(__u.__w);
+ _M_data->_M_decimal_point = static_cast<wchar_t>(__u.__w);
__u.__s = __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc);
- _M_thousands_sep = static_cast<wchar_t>(__u.__w);
- if (_M_thousands_sep == L'\0')
- _M_grouping = "";
+ _M_data->_M_thousands_sep = static_cast<wchar_t>(__u.__w);
+
+ if (_M_data->_M_thousands_sep == L'\0')
+ _M_data->_M_grouping = "";
else
- _M_grouping = __nl_langinfo_l(GROUPING, __cloc);
+ _M_data->_M_grouping = __nl_langinfo_l(GROUPING, __cloc);
}
// NB: There is no way to extact this info from posix locales.
// _M_truename = __nl_langinfo_l(YESSTR, __cloc);
- _M_truename = L"true";
+ _M_data->_M_truename = L"true";
// _M_falsename = __nl_langinfo_l(NOSTR, __cloc);
- _M_falsename = L"false";
+ _M_data->_M_falsename = L"false";
}
template<>
numpunct<wchar_t>::~numpunct()
- { }
+ { delete _M_data; }
#endif
}
diff --git a/libstdc++-v3/include/bits/basic_ios.tcc b/libstdc++-v3/include/bits/basic_ios.tcc
index cf2701e..54f34b5 100644
--- a/libstdc++-v3/include/bits/basic_ios.tcc
+++ b/libstdc++-v3/include/bits/basic_ios.tcc
@@ -138,12 +138,7 @@ namespace std
ios_base::_M_init();
// 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);
- }
+ _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,
@@ -176,7 +171,6 @@ namespace std
_M_num_put = &use_facet<__numput_type>(__loc);
if (__builtin_expect(has_facet<__numget_type>(__loc), true))
_M_num_get = &use_facet<__numget_type>(__loc);
- 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 37a02a4..ef2f57a 100644
--- a/libstdc++-v3/include/bits/ios_base.h
+++ b/libstdc++-v3/include/bits/ios_base.h
@@ -146,8 +146,6 @@ namespace std
enum _Ios_Seekdir { _S_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.
@@ -212,47 +210,65 @@ namespace std
* - floatfield
*/
typedef _Ios_Fmtflags fmtflags;
+
/// Insert/extract @c bool in alphabetic rather than numeric format.
static const fmtflags boolalpha = fmtflags(__ios_flags::_S_boolalpha);
+
/// Converts integer input or generates integer output in decimal base.
static const fmtflags dec = fmtflags(__ios_flags::_S_dec);
+
/// Generate floating-point output in fixed-point notation.
static const fmtflags fixed = fmtflags(__ios_flags::_S_fixed);
+
/// Converts integer input or generates integer output in hexadecimal base.
static const fmtflags hex = fmtflags(__ios_flags::_S_hex);
+
/// Adds fill characters at a designated internal point in certain
/// generated output, or identical to @c right if no such point is
/// designated.
static const fmtflags internal = fmtflags(__ios_flags::_S_internal);
+
/// Adds fill characters on the right (final positions) of certain
/// generated output. (I.e., the thing you print is flush left.)
static const fmtflags left = fmtflags(__ios_flags::_S_left);
+
/// Converts integer input or generates integer output in octal base.
static const fmtflags oct = fmtflags(__ios_flags::_S_oct);
+
/// Adds fill characters on the left (initial positions) of certain
/// generated output. (I.e., the thing you print is flush right.)
static const fmtflags right = fmtflags(__ios_flags::_S_right);
+
/// Generates floating-point output in scientific notation.
static const fmtflags scientific = fmtflags(__ios_flags::_S_scientific);
+
/// Generates a prefix indicating the numeric base of generated integer
/// output.
static const fmtflags showbase = fmtflags(__ios_flags::_S_showbase);
+
/// Generates a decimal-point character unconditionally in generated
/// floating-point output.
static const fmtflags showpoint = fmtflags(__ios_flags::_S_showpoint);
+
/// Generates a + sign in non-negative generated numeric output.
static const fmtflags showpos = fmtflags(__ios_flags::_S_showpos);
+
/// Skips leading white space before certain input operations.
static const fmtflags skipws = fmtflags(__ios_flags::_S_skipws);
+
/// Flushes output after each output operation.
static const fmtflags unitbuf = fmtflags(__ios_flags::_S_unitbuf);
+
/// Replaces certain lowercase letters with their uppercase equivalents
/// in generated output.
static const fmtflags uppercase = fmtflags(__ios_flags::_S_uppercase);
+
/// A mask of left|right|internal. Useful for the 2-arg form of @c setf.
static const fmtflags adjustfield = fmtflags(__ios_flags::_S_adjustfield);
+
/// A mask of dec|oct|hex. Useful for the 2-arg form of @c setf.
static const fmtflags basefield = fmtflags(__ios_flags::_S_basefield);
+
/// A mask of scientific|fixed. Useful for the 2-arg form of @c setf.
static const fmtflags floatfield = fmtflags(__ios_flags::_S_floatfield);
@@ -269,15 +285,19 @@ namespace std
* - goodbit
*/
typedef _Ios_Iostate iostate;
+
/// Indicates a loss of integrity in an input or output sequence (such
/// as an irrecoverable read error from a file).
static const iostate badbit = iostate(__ios_flags::_S_badbit);
+
/// Indicates that an input operation reached the end of an input sequence.
static const iostate eofbit = iostate(__ios_flags::_S_eofbit);
+
/// Indicates that an input operation failed to read the expected
/// characters, or that an output operation failed to generate the
/// desired characters.
static const iostate failbit = iostate(__ios_flags::_S_failbit);
+
/// Indicates all is well.
static const iostate goodbit = iostate(0);
@@ -296,19 +316,25 @@ namespace std
* - trunc
*/
typedef _Ios_Openmode openmode;
+
/// Seek to end before each write.
static const openmode app = openmode(__ios_flags::_S_app);
+
/// Open and seek to end immediately after opening.
static const openmode ate = openmode(__ios_flags::_S_ate);
+
/// Perform input and output in binary mode (as opposed to text mode).
/// This is probably not what you think it is; see
/// http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#3 and
/// http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#7 for more.
static const openmode binary = openmode(__ios_flags::_S_bin);
+
/// Open for input. Default for @c ifstream and fstream.
static const openmode in = openmode(__ios_flags::_S_in);
+
/// Open for output. Default for @c ofstream and fstream.
static const openmode out = openmode(__ios_flags::_S_out);
+
/// Open for input. Default for @c ofstream.
static const openmode trunc = openmode(__ios_flags::_S_trunc);
@@ -323,10 +349,13 @@ namespace std
* - end, equivalent to @c SEEK_END in the C standard library.
*/
typedef _Ios_Seekdir seekdir;
+
/// Request a seek relative to the beginning of the stream.
static const seekdir beg = seekdir(0);
+
/// Request a seek relative to the current position within the sequence.
static const seekdir cur = seekdir(SEEK_CUR);
+
/// Request a seek relative to the current end of the sequence.
static const seekdir end = seekdir(SEEK_END);
@@ -432,10 +461,6 @@ 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();
@@ -604,7 +629,7 @@ namespace std
/**
* @brief Locale access
- * @return The locale currently in effect.
+ * @return A copy of the current locale.
*
* If @c imbue(loc) has previously been called, then this function
* returns @c loc. Otherwise, it returns a copy of @c std::locale(),
@@ -613,6 +638,16 @@ namespace std
inline locale
getloc() const { return _M_ios_locale; }
+ /**
+ * @brief Locale access
+ * @return A reference to the current locale.
+ *
+ * Like getloc above, but returns a reference instead of
+ * generating a copy.
+ */
+ inline const locale&
+ _M_getloc() const { return _M_ios_locale; }
+
// [27.4.2.5] ios_base storage functions
/**
* @doctodo
@@ -642,11 +677,6 @@ 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_classes.h b/libstdc++-v3/include/bits/locale_classes.h
index e7210f8..cfc1149 100644
--- a/libstdc++-v3/include/bits/locale_classes.h
+++ b/libstdc++-v3/include/bits/locale_classes.h
@@ -71,7 +71,11 @@ namespace std
template<typename _Facet>
friend const _Facet&
use_facet(const locale&);
-
+
+ template<typename _Cache>
+ friend const _Cache&
+ __use_cache(const locale& __loc);
+
// Category values:
// NB: Order must match _S_facet_categories definition in locale.cc
static const category none = 0;
@@ -141,6 +145,12 @@ namespace std
// Current global locale
static _Impl* _S_global;
+ // Names of underlying locale categories.
+ // NB: locale::global() has to know how to modify all the
+ // underlying categories, not just the ones required by the C++
+ // standard.
+ static const char** _S_categories;
+
// Number of standard categories. For C++, these categories are
// collate, ctype, monetary, numeric, time, and messages. These
// directly correspond to ISO C99 macros LC_COLLATE, LC_CTYPE,
@@ -153,12 +163,6 @@ namespace std
// and LC_IDENTIFICATION.
static const size_t _S_categories_size = 6 + _GLIBCPP_NUM_CATEGORIES;
- // Names of underlying locale categories.
- // NB: locale::global() has to know how to modify all the
- // underlying categories, not just the ones required by the C++
- // standard.
- static const char** _S_categories;
-
explicit
locale(_Impl*) throw();
@@ -177,7 +181,107 @@ namespace std
};
- // Implementation object for locale
+ // 22.1.1.1.2 Class locale::facet
+ class locale::facet
+ {
+ private:
+ friend class locale;
+ friend class locale::_Impl;
+
+ mutable _Atomic_word _M_references;
+
+ protected:
+ // Contains data from the underlying "C" library for the classic locale.
+ static __c_locale _S_c_locale;
+
+ // String literal for the name of the classic locale.
+ static char _S_c_name[2];
+
+ explicit
+ facet(size_t __refs = 0) throw() : _M_references(__refs ? 1 : 0)
+ { }
+
+ virtual
+ ~facet();
+
+ static void
+ _S_create_c_locale(__c_locale& __cloc, const char* __s,
+ __c_locale __old = 0);
+
+ static __c_locale
+ _S_clone_c_locale(__c_locale& __cloc);
+
+ static void
+ _S_destroy_c_locale(__c_locale& __cloc);
+
+ private:
+ inline void
+ _M_add_reference() const throw()
+ { __atomic_add(&_M_references, 1); }
+
+ inline void
+ _M_remove_reference() const throw()
+ {
+ if (__exchange_and_add(&_M_references, -1) == 1)
+ {
+ try
+ { delete this; }
+ catch (...)
+ { }
+ }
+ }
+
+ facet(const facet&); // Not defined.
+
+ void
+ operator=(const facet&); // Not defined.
+ };
+
+
+ // 22.1.1.1.3 Class locale::id
+ class locale::id
+ {
+ private:
+ friend class locale;
+ friend class locale::_Impl;
+
+ template<typename _Facet>
+ friend const _Facet&
+ use_facet(const locale&);
+
+ template<typename _Facet>
+ friend bool
+ has_facet(const locale&) throw ();
+
+ // NB: There is no accessor for _M_index because it may be used
+ // before the constructor is run; the effect of calling a member
+ // function (even an inline) would be undefined.
+ mutable size_t _M_index;
+
+ // Last id number assigned.
+ static _Atomic_word _S_highwater;
+
+ void
+ operator=(const id&); // Not defined.
+
+ id(const id&); // Not defined.
+
+ public:
+ // NB: This class is always a static data member, and thus can be
+ // counted on to be zero-initialized.
+ id() { }
+
+ inline size_t
+ _M_id() const
+ {
+ if (!_M_index)
+ _M_index = 1 + __exchange_and_add(&_S_highwater, 1);
+ return _M_index - 1;
+ }
+ };
+
+
+ // Implementation object for locale.
class locale::_Impl
{
public:
@@ -186,18 +290,23 @@ namespace std
friend class locale::facet;
template<typename _Facet>
+ friend bool
+ has_facet(const locale&) throw();
+
+ template<typename _Facet>
friend const _Facet&
use_facet(const locale&);
- template<typename _Facet>
- friend bool
- has_facet(const locale&) throw();
+ template<typename _Cache>
+ friend const _Cache&
+ __use_cache(const locale& __loc);
private:
// Data Members.
_Atomic_word _M_references;
const facet** _M_facets;
size_t _M_facets_size;
+ const facet** _M_caches;
char** _M_names;
static const locale::id* const _S_id_ctype[];
static const locale::id* const _S_id_numeric[];
@@ -258,7 +367,14 @@ namespace std
template<typename _Facet>
inline void
_M_init_facet(_Facet* __facet)
- { _M_install_facet(&_Facet::id, __facet); }
+ { _M_install_facet(&_Facet::id, __facet); }
+
+ void
+ _M_install_cache(const facet* __cache, size_t __index)
+ {
+ __cache->_M_add_reference();
+ _M_caches[__index] = __cache;
+ }
};
template<typename _Facet>
@@ -274,93 +390,6 @@ namespace std
_M_impl->_M_names[__i] = __new;
}
}
-
-
- // 22.1.1.1.2 Class locale::facet
- class locale::facet
- {
- private:
- friend class locale;
- friend class locale::_Impl;
-
- mutable _Atomic_word _M_references;
-
- protected:
- // Contains data from the underlying "C" library for the classic locale.
- static __c_locale _S_c_locale;
-
- // String literal for the name of the classic locale.
- static char _S_c_name[2];
-
- explicit
- facet(size_t __refs = 0) throw();
-
- virtual
- ~facet();
-
- static void
- _S_create_c_locale(__c_locale& __cloc, const char* __s,
- __c_locale __old = 0);
-
- static __c_locale
- _S_clone_c_locale(__c_locale& __cloc);
-
- static void
- _S_destroy_c_locale(__c_locale& __cloc);
-
- private:
- void
- _M_add_reference() const throw();
-
- void
- _M_remove_reference() const throw();
-
- facet(const facet&); // Not defined.
-
- void
- operator=(const facet&); // Not defined.
- };
-
-
- // 22.1.1.1.3 Class locale::id
- class locale::id
- {
- private:
- friend class locale;
- friend class locale::_Impl;
- template<typename _Facet>
- friend const _Facet&
- use_facet(const locale&);
- template<typename _Facet>
- friend bool
- has_facet(const locale&) throw ();
-
- // NB: There is no accessor for _M_index because it may be used
- // before the constructor is run; the effect of calling a member
- // function (even an inline) would be undefined.
- mutable size_t _M_index;
-
- // Last id number assigned.
- static _Atomic_word _S_highwater;
-
- void
- operator=(const id&); // Not defined.
-
- id(const id&); // Not defined.
-
- public:
- // NB: This class is always a static data member, and thus can be
- // counted on to be zero-initialized.
- id();
-
- inline size_t
- _M_id() const
- {
- if (!_M_index)
- _M_index = 1 + __exchange_and_add(&_S_highwater, 1);
- return _M_index - 1;
- }
- };
} // namespace std
#endif
diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h
index a0060e8..72141f19 100644
--- a/libstdc++-v3/include/bits/locale_facets.h
+++ b/libstdc++-v3/include/bits/locale_facets.h
@@ -574,6 +574,96 @@ namespace std
_S_format_float(const ios_base& __io, char* __fptr, char __mod);
};
+ template<typename _CharT>
+ struct __numpunct_cache : public locale::facet
+ {
+ // Types:
+ typedef _CharT char_type;
+
+ const char* _M_grouping;
+ bool _M_use_grouping;
+ const char_type* _M_truename;
+ const char_type* _M_falsename;
+ char_type _M_decimal_point;
+ char_type _M_thousands_sep;
+
+ // A list of valid numeric literals for output: in 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_atoms_out[__num_base::_S_oend + 1];
+
+ // A list of valid numeric literals for output: in the standard
+ // "C" locale, this is "0123456789eEabcdfABCDF"
+ // This array contains the chars after having been passed
+ // through the current locale's ctype<_CharT>.widen().
+ _CharT _M_atoms_in[__num_base::_S_iend + 1];
+
+ bool _M_allocated;
+
+ __numpunct_cache(size_t __refs = 0) : locale::facet(__refs),
+ _M_grouping(NULL), _M_use_grouping(false), _M_truename(NULL),
+ _M_falsename(NULL), _M_decimal_point(char_type()),
+ _M_thousands_sep(char_type()), _M_allocated(false)
+ { }
+
+ ~__numpunct_cache();
+
+ void
+ _M_cache(const locale& __loc);
+ };
+
+ template<typename _CharT>
+ void
+ __numpunct_cache<_CharT>::_M_cache(const locale& __loc)
+ {
+ const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
+ string __grouping = __np.grouping();
+ char* __group = new char[__grouping.length() + 1];
+ __grouping.copy(__group, __grouping.length());
+ __group[__grouping.length()] = _CharT();
+ _M_grouping = __group;
+
+ _M_use_grouping = __grouping.length() != 0 && __grouping.data()[0] != 0;
+
+ typedef basic_string<_CharT> __string_type;
+
+ __string_type __true = __np.truename();
+ _CharT* __truename = new _CharT[__true.length() + 1];
+ __true.copy(__truename, __true.length());
+ __truename[__true.length()] = _CharT();
+ _M_truename = __truename;
+
+ __string_type __false = __np.falsename();
+ _CharT* __falsename = new _CharT[__false.length() + 1];
+ __false.copy(__falsename, __false.length());
+ __falsename[__false.length()] = _CharT();
+ _M_falsename = __falsename;
+
+ _M_decimal_point = __np.decimal_point();
+ _M_thousands_sep = __np.thousands_sep();
+
+ const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
+ __ct.widen(__num_base::_S_atoms_out,
+ __num_base::_S_atoms_out + __num_base::_S_oend, _M_atoms_out);
+ _M_atoms_out[__num_base::_S_oend] = _CharT();
+ __ct.widen(__num_base::_S_atoms_in,
+ __num_base::_S_atoms_in + __num_base::_S_iend, _M_atoms_in);
+ _M_atoms_in[__num_base::_S_iend] = _CharT();
+
+ _M_allocated = true;
+ }
+
+ template<typename _CharT>
+ __numpunct_cache<_CharT>::~__numpunct_cache()
+ {
+ if (_M_allocated)
+ {
+ delete [] _M_grouping;
+ delete [] _M_truename;
+ delete [] _M_falsename;
+ }
+ }
template<typename _CharT>
class numpunct : public locale::facet
@@ -582,23 +672,26 @@ namespace std
// Types:
typedef _CharT char_type;
typedef basic_string<_CharT> string_type;
+ typedef __numpunct_cache<_CharT> __cache_type;
+
+ protected:
+ __cache_type* _M_data;
+ public:
static locale::id id;
- private:
- char_type _M_decimal_point;
- char_type _M_thousands_sep;
- const char* _M_grouping;
- const char_type* _M_truename;
- const char_type* _M_falsename;
+ explicit
+ numpunct(size_t __refs = 0) : facet(__refs), _M_data(NULL)
+ { _M_initialize_numpunct(); }
- public:
explicit
- numpunct(size_t __refs = 0) : locale::facet(__refs)
+ numpunct(__cache_type* __cache, size_t __refs = 0)
+ : facet(__refs), _M_data(__cache)
{ _M_initialize_numpunct(); }
explicit
- numpunct(__c_locale __cloc, size_t __refs = 0) : locale::facet(__refs)
+ numpunct(__c_locale __cloc, size_t __refs = 0)
+ : locale::facet(__refs), _M_data(NULL)
{ _M_initialize_numpunct(__cloc); }
char_type
@@ -627,23 +720,23 @@ namespace std
virtual char_type
do_decimal_point() const
- { return _M_decimal_point; }
+ { return _M_data->_M_decimal_point; }
virtual char_type
do_thousands_sep() const
- { return _M_thousands_sep; }
+ { return _M_data->_M_thousands_sep; }
virtual string
do_grouping() const
- { return _M_grouping; }
+ { return _M_data->_M_grouping; }
virtual string_type
do_truename() const
- { return _M_truename; }
+ { return _M_data->_M_truename; }
virtual string_type
do_falsename() const
- { return _M_falsename; }
+ { return _M_data->_M_falsename; }
// For use at construction time only.
void
@@ -1928,75 +2021,6 @@ 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_oend];
-
- // 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 6240182..5081591 100644
--- a/libstdc++-v3/include/bits/locale_facets.tcc
+++ b/libstdc++-v3/include/bits/locale_facets.tcc
@@ -86,6 +86,21 @@ namespace std
return static_cast<const _Facet&>(*__facets[__i]);
}
+ // Routine to access a cache for the facet. If the cache didn't
+ // exist before, it gets constructed on the fly.
+ template<typename _Facet>
+ const _Facet&
+ __use_cache(const locale& __loc);
+
+ template<>
+ const __numpunct_cache<char>&
+ __use_cache(const locale& __loc);
+
+#ifdef _GLIBCPP_USE_WCHAR_T
+ template<>
+ const __numpunct_cache<wchar_t>&
+ __use_cache(const locale& __loc);
+#endif
// Stage 1: Determine a conversion specifier.
template<typename _CharT, typename _InIter>
@@ -768,11 +783,12 @@ namespace std
_M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill,
_ValueT __v) const
{
- typedef __locale_cache<_CharT> __cache_type;
- __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache());
- _CharT* __lit = __lc._M_literals;
+ typedef typename numpunct<_CharT>::__cache_type __cache_type;
+ const locale& __loc = __io._M_getloc();
+ const __cache_type& __lc = __use_cache<__cache_type>(__loc);
+ const _CharT* __lit = __lc._M_atoms_out;
- // Long enough to hold hex, dec, and octal representations.
+ // Long enough to hold hex, dec, and octal representations.
int __ilen = 4 * sizeof(_ValueT);
_CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
* __ilen));
@@ -872,8 +888,9 @@ namespace std
else if (__prec < static_cast<streamsize>(0))
__prec = static_cast<streamsize>(6);
- typedef __locale_cache<_CharT> __cache_type;
- __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache());
+ typedef typename numpunct<_CharT>::__cache_type __cache_type;
+ const locale& __loc = __io._M_getloc();
+ const __cache_type& __lc = __use_cache<__cache_type>(__loc);
// [22.2.2.2.2] Stage 1, numeric conversion to character.
int __len;
@@ -918,7 +935,6 @@ namespace std
// [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)
@@ -974,8 +990,10 @@ namespace std
}
else
{
- typedef __locale_cache<_CharT> __cache_type;
- __cache_type& __lc = static_cast<__cache_type&>(__io._M_cache());
+ typedef typename numpunct<_CharT>::__cache_type __cache_type;
+ const locale& __loc = __io._M_getloc();
+ const __cache_type& __lc = __use_cache<__cache_type>(__loc);
+
typedef basic_string<_CharT> __string_type;
__string_type __name;
if (__v)
@@ -2273,31 +2291,6 @@ 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_oend,
- _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/globals.cc b/libstdc++-v3/src/globals.cc
index a0220f1..6793a9b 100644
--- a/libstdc++-v3/src/globals.cc
+++ b/libstdc++-v3/src/globals.cc
@@ -127,6 +127,10 @@ namespace __gnu_cxx
__attribute__ ((aligned(__alignof__(locale::facet*))));
fake_facet_vec facet_vec[_GLIBCPP_NUM_FACETS];
+ typedef char fake_cache_vec[sizeof(locale::facet*)]
+ __attribute__ ((aligned(__alignof__(locale::facet*))));
+ fake_cache_vec cache_vec[_GLIBCPP_NUM_FACETS];
+
typedef char fake_ctype_c[sizeof(std::ctype<char>)]
__attribute__ ((aligned(__alignof__(std::ctype<char>))));
fake_ctype_c ctype_c;
@@ -235,6 +239,17 @@ namespace __gnu_cxx
fake_messages_w messages_w;
#endif
+ // Storage for C locale caches
+ typedef char fake_locale_cache_c[sizeof(std::__numpunct_cache<char>)]
+ __attribute__ ((aligned(__alignof__(std::__numpunct_cache<char>))));
+ fake_locale_cache_c numpunct_cache_c;
+
+#ifdef _GLIBCPP_USE_WCHAR_T
+ typedef char fake_locale_cache_w[sizeof(std::__numpunct_cache<wchar_t>)]
+ __attribute__ ((aligned(__alignof__(std::__numpunct_cache<wchar_t>))));
+ fake_locale_cache_w numpunct_cache_w;
+#endif
+
// Globals for once-only runtime initialization of mutex objects. This
// allows static initialization of these objects on systems that need a
// function call to initialize a mutex. For example, see stl_threads.h.
diff --git a/libstdc++-v3/src/ios.cc b/libstdc++-v3/src/ios.cc
index ee4fd24..ee969b5 100644
--- a/libstdc++-v3/src/ios.cc
+++ b/libstdc++-v3/src/ios.cc
@@ -297,8 +297,8 @@ namespace std
return __old;
}
- ios_base::ios_base() : _M_callbacks(0), _M_word_size(_S_local_word_size),
- _M_word(_M_local_word), _M_locale_cache(0)
+ ios_base::ios_base()
+ : _M_callbacks(0), _M_word_size(_S_local_word_size), _M_word(_M_local_word)
{
// 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 73b028d..0936102 100644
--- a/libstdc++-v3/src/locale-inst.cc
+++ b/libstdc++-v3/src/locale-inst.cc
@@ -45,7 +45,6 @@ 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>;
@@ -54,11 +53,11 @@ 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
template class numpunct<char>;
+ template struct __numpunct_cache<char>;
template class numpunct_byname<char>;
template class num_get<char, istreambuf_iterator<char> >;
template class num_put<char, ostreambuf_iterator<char> >;
@@ -102,6 +101,7 @@ namespace std
#ifdef _GLIBCPP_USE_WCHAR_T
template class numpunct<wchar_t>;
+ template struct __numpunct_cache<wchar_t>;
template class numpunct_byname<wchar_t>;
template class num_get<wchar_t, istreambuf_iterator<wchar_t> >;
template class num_put<wchar_t, ostreambuf_iterator<wchar_t> >;
diff --git a/libstdc++-v3/src/locale.cc b/libstdc++-v3/src/locale.cc
index db08de0..7788a58 100644
--- a/libstdc++-v3/src/locale.cc
+++ b/libstdc++-v3/src/locale.cc
@@ -449,30 +449,37 @@ namespace std
locale::facet::
~facet() { }
- locale::facet::
- facet(size_t __refs) throw() : _M_references(__refs ? 1 : 0)
- { }
-
- void
- locale::facet::
- _M_add_reference() const throw()
- { __atomic_add(&_M_references, 1); }
+ template<>
+ const __numpunct_cache<char>&
+ __use_cache(const locale& __loc)
+ {
+ size_t __i = numpunct<char>::id._M_id();
+ const locale::facet** __caches = __loc._M_impl->_M_caches;
+ if (!__caches[__i])
+ {
+ __numpunct_cache<char>* __tmp = new __numpunct_cache<char>;
+ __tmp->_M_cache(__loc);
+ __loc._M_impl->_M_install_cache(__tmp, __i);
+ }
+ return static_cast<const __numpunct_cache<char>&>(*__caches[__i]);
+ }
- void
- locale::facet::
- _M_remove_reference() const throw()
- {
- if (__exchange_and_add(&_M_references, -1) == 1)
- {
- try
- { delete this; }
- catch (...)
- { }
- }
- }
-
- locale::id::id()
- { }
+#ifdef _GLIBCPP_USE_WCHAR_T
+ template<>
+ const __numpunct_cache<wchar_t>&
+ __use_cache(const locale& __loc)
+ {
+ size_t __i = numpunct<wchar_t>::id._M_id();
+ const locale::facet** __caches = __loc._M_impl->_M_caches;
+ if (!__caches[__i])
+ {
+ __numpunct_cache<wchar_t>* __tmp = new __numpunct_cache<wchar_t>;
+ __tmp->_M_cache(__loc);
+ __loc._M_impl->_M_install_cache(__tmp, __i);
+ }
+ return static_cast<const __numpunct_cache<wchar_t>&>(*__caches[__i]);
+ }
+#endif
// Definitions for static const data members of time_base
template<>
diff --git a/libstdc++-v3/src/localename.cc b/libstdc++-v3/src/localename.cc
index c09900b..424bc64 100644
--- a/libstdc++-v3/src/localename.cc
+++ b/libstdc++-v3/src/localename.cc
@@ -69,6 +69,12 @@ namespace __gnu_cxx
extern time_put<wchar_t> time_put_w;
extern std::messages<wchar_t> messages_w;
#endif
+
+ extern locale::facet* cache_vec[_GLIBCPP_NUM_FACETS];
+ extern std::__numpunct_cache<char> numpunct_cache_c;
+#ifdef _GLIBCPP_USE_WCHAR_T
+ extern std::__numpunct_cache<wchar_t> numpunct_cache_w;
+#endif
} // namespace __gnu_cxx
namespace std
@@ -83,6 +89,11 @@ namespace std
_M_facets[__i]->_M_remove_reference();
delete [] _M_facets;
+ for (size_t __i = 0; __i < _M_facets_size; ++__i)
+ if (_M_caches[__i])
+ _M_caches[__i]->_M_remove_reference();
+ delete [] _M_caches;
+
for (size_t __i = 0; __i < _S_categories_size; ++__i)
delete [] _M_names[__i];
delete [] _M_names;
@@ -91,7 +102,7 @@ namespace std
// Clone existing _Impl object.
locale::_Impl::
_Impl(const _Impl& __imp, size_t __refs)
- : _M_references(__refs), _M_facets_size(__imp._M_facets_size) // XXX
+ : _M_references(__refs), _M_facets_size(__imp._M_facets_size)
{
try
{
@@ -113,6 +124,22 @@ namespace std
try
{
+ _M_caches = new const facet*[_M_facets_size];
+ }
+ catch(...)
+ {
+ delete [] _M_caches;
+ __throw_exception_again;
+ }
+ for (size_t __i = 0; __i < _M_facets_size; ++__i)
+ {
+ _M_caches[__i] = __imp._M_caches[__i];
+ if (_M_caches[__i])
+ _M_caches[__i]->_M_add_reference();
+ }
+
+ try
+ {
_M_names = new char*[_S_categories_size];
}
catch(...)
@@ -131,10 +158,10 @@ namespace std
// Construct named _Impl.
locale::_Impl::
_Impl(const char* __s, size_t __refs)
- : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS)
+ : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS)
{
- // Initialize the underlying locale model, which also checks
- // to see if the given name is valid.
+ // Initialize the underlying locale model, which also checks to
+ // see if the given name is valid.
__c_locale __cloc;
locale::facet::_S_create_c_locale(__cloc, __s);
@@ -150,6 +177,18 @@ namespace std
__throw_exception_again;
}
+ try
+ {
+ _M_caches = new const facet*[_M_facets_size];
+ for (size_t __i = 0; __i < _M_facets_size; ++__i)
+ _M_caches[__i] = 0;
+ }
+ catch(...)
+ {
+ delete [] _M_caches;
+ __throw_exception_again;
+ }
+
// Name all the categories.
try
{
@@ -235,6 +274,10 @@ namespace std
for (size_t __i = 0; __i < _M_facets_size; ++__i)
_M_facets[__i] = 0;
+ _M_caches = new (&cache_vec) const facet*[_M_facets_size];
+ for (size_t __i = 0; __i < _M_facets_size; ++__i)
+ _M_caches[__i] = 0;
+
// Name all the categories.
_M_names = new (&name_vec) char*[_S_categories_size];
for (size_t __i = 0; __i < _S_categories_size; ++__i)
@@ -252,7 +295,12 @@ namespace std
// destroyed.
_M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1));
_M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1));
- _M_init_facet(new (&numpunct_c) numpunct<char>(1));
+
+ // Safe to cache this.
+ typedef __numpunct_cache<char> num_cache_c;
+ num_cache_c* __npc = new (&numpunct_cache_c) num_cache_c(2);
+ _M_init_facet(new (&numpunct_c) numpunct<char>(__npc, 1));
+
_M_init_facet(new (&num_get_c) num_get<char>(1));
_M_init_facet(new (&num_put_c) num_put<char>(1));
_M_init_facet(new (&collate_c) std::collate<char>(1));
@@ -264,10 +312,15 @@ namespace std
_M_init_facet(new (&time_get_c) time_get<char>(1));
_M_init_facet(new (&time_put_c) time_put<char>(1));
_M_init_facet(new (&messages_c) std::messages<char>(1));
+
#ifdef _GLIBCPP_USE_WCHAR_T
_M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1));
_M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1));
- _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(1));
+
+ typedef __numpunct_cache<wchar_t> num_cache_w;
+ num_cache_w* __npw = new (&numpunct_cache_w) num_cache_w(2);
+ _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(__npw, 1));
+
_M_init_facet(new (&num_get_w) num_get<wchar_t>(1));
_M_init_facet(new (&num_put_w) num_put<wchar_t>(1));
_M_init_facet(new (&collate_w) std::collate<wchar_t>(1));
@@ -280,6 +333,13 @@ namespace std
_M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
_M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
#endif
+
+ // This locale is safe to pre-cache, after all the facets have
+ // been installed.
+ _M_caches[numpunct<char>::id._M_id()] = __npc;
+#ifdef _GLIBCPP_USE_WCHAR_T
+ _M_caches[numpunct<wchar_t>::id._M_id()] = __npw;
+#endif
}
void
@@ -336,18 +396,31 @@ namespace std
// Check size of facet vector to ensure adequate room.
if (__index > _M_facets_size - 1)
{
- const facet** __old = _M_facets;
- const facet** __new;
const size_t __new_size = __index + 4;
- __new = new const facet*[__new_size];
+
+ // New facet array.
+ const facet** __oldf = _M_facets;
+ const facet** __newf;
+ __newf = new const facet*[__new_size];
+ for (size_t __i = 0; __i < _M_facets_size; ++__i)
+ __newf[__i] = _M_facets[__i];
+ for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
+ __newf[__i2] = 0;
+
+ // New cache array.
+ const facet** __oldc = _M_caches;
+ const facet** __newc;
+ __newc = new const facet*[__new_size];
for (size_t __i = 0; __i < _M_facets_size; ++__i)
- __new[__i] = _M_facets[__i];
+ __newc[__i] = _M_caches[__i];
for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
- __new[__i2] = 0;
+ __newc[__i2] = 0;
_M_facets_size = __new_size;
- _M_facets = __new;
- delete [] __old;
+ _M_facets = __newf;
+ _M_caches = __newc;
+ delete [] __oldf;
+ delete [] __oldc;
}
__fp->_M_add_reference();
@@ -365,6 +438,21 @@ namespace std
// swanky-fresh _Impl.
_M_facets[__index] = __fp;
}
+
+ // Ideally, it would be nice to only remove the caches that
+ // are now incorrect. However, some of the caches depend on
+ // multiple facets, and we only know about one facet
+ // here. It's no great loss: the first use of the new facet
+ // will create a new, correctly cached facet anyway.
+ for (size_t __i = 0; __i < _M_facets_size; ++__i)
+ {
+ const facet* __cpr = _M_caches[__i];
+ if (__cpr)
+ {
+ __cpr->_M_remove_reference();
+ _M_caches[__i] = 0;
+ }
+ }
}
}
} // namespace std
diff --git a/libstdc++-v3/testsuite/27_io/ios_base/cons/assign_neg.cc b/libstdc++-v3/testsuite/27_io/ios_base/cons/assign_neg.cc
index 7e13831..e6f9921 100644
--- a/libstdc++-v3/testsuite/27_io/ios_base/cons/assign_neg.cc
+++ b/libstdc++-v3/testsuite/27_io/ios_base/cons/assign_neg.cc
@@ -41,5 +41,5 @@ void test01()
io1 = io2;
}
// { dg-error "within this context" "" { target *-*-* } 41 }
-// { dg-error "is private" "" { target *-*-* } 666 }
+// { dg-error "is private" "" { target *-*-* } 696 }
// { dg-error "operator=" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/27_io/ios_base/cons/copy_neg.cc b/libstdc++-v3/testsuite/27_io/ios_base/cons/copy_neg.cc
index 5653148..5d77444 100644
--- a/libstdc++-v3/testsuite/27_io/ios_base/cons/copy_neg.cc
+++ b/libstdc++-v3/testsuite/27_io/ios_base/cons/copy_neg.cc
@@ -41,5 +41,5 @@ void test02()
test_base io2 = io1;
}
// { dg-error "within this context" "" { target *-*-* } 41 }
-// { dg-error "is private" "" { target *-*-* } 663 }
+// { dg-error "is private" "" { target *-*-* } 693 }
// { dg-error "copy constructor" "" { target *-*-* } 0 }