+2004-05-03 Paolo Carlini <pcarlini@suse.de>
+
+ Optimize locale::_M_impl->_M_names for the most common cases:
+ !_M_names[0] means unnamed; !_M_names[1] means all the categories
+ the same name (_M_names[0] && _M_names[1] means that the full set
+ of _M_names must be processed, the general case).
+ * include/bits/locale_classes.h (locale::_Impl::_M_check_same_name):
+ Tweak, saving work when !_M_names[1].
+ (locale::locale(const locale&, _Facet*): Simplify: now just setting
+ _M_names[0] = 0 means unnamed.
+ * src/locale.cc (locale::operator==): Deal first with the common,
+ easy cases, otherwise fall back to locale::name().
+ (locale::name()): Tweak, if !_M_names[0] just return "*".
+ (locale::_Impl::_Impl(const _Impl&, size_t): Tweak, early stop
+ copying __imp._M_names if !__imp._M_names[0] or !__imp._M_names[1].
+ * src/locale_init.cc (locale::_Impl::_Impl(size_t)): Tweak.
+ * src/localename.cc (locale::_Impl::_Impl(const char*, size_t):
+ Simplify when !std::strchr, just updating _M_names[0]; clean up.
+ (locale::_Impl::_M_replace_categories): When !_M_names[1] prepare
+ for the general case (full set of names), then do the usual work;
+ clean up.
+
+ * src/locale.cc (locale::name()): Reserve space in __ret.
+ * src/locale_init.cc (locale::global(const locale&)): Save
+ the name in a temporary.
+ * src/localename.cc (locale::locale(const char*)): Reserve space
+ in __str.
+
2004-04-29 Paolo Carlini <pcarlini@suse.de>
* src/locale.cc (locale::operator==): Always avoid constructing
_M_check_same_name()
{
bool __ret = true;
- for (size_t __i = 0; __ret && __i < _S_categories_size - 1; ++__i)
- __ret = std::strcmp(_M_names[__i], _M_names[__i + 1]) == 0;
+ if (_M_names[1])
+ // We must actually compare all the _M_names: can be all equal!
+ for (size_t __i = 0; __ret && __i < _S_categories_size - 1; ++__i)
+ __ret = std::strcmp(_M_names[__i], _M_names[__i + 1]) == 0;
return __ret;
}
{
_M_impl = new _Impl(*__other._M_impl, 1);
- char* _M_tmp_names[_S_categories_size];
- size_t __i = 0;
try
- {
- for (; __i < _S_categories_size; ++__i)
- {
- _M_tmp_names[__i] = new char[2];
- std::strcpy(_M_tmp_names[__i], "*");
- }
- _M_impl->_M_install_facet(&_Facet::id, __f);
- }
+ { _M_impl->_M_install_facet(&_Facet::id, __f); }
catch(...)
{
_M_impl->_M_remove_reference();
- for (size_t __j = 0; __j < __i; ++__j)
- delete [] _M_tmp_names[__j];
__throw_exception_again;
}
-
- for (size_t __k = 0; __k < _S_categories_size; ++__k)
- {
- delete [] _M_impl->_M_names[__k];
- _M_impl->_M_names[__k] = _M_tmp_names[__k];
- }
+ delete [] _M_impl->_M_names[0];
+ _M_impl->_M_names[0] = 0; // Unnamed.
}
} // namespace std
bool
locale::operator==(const locale& __rhs) const throw()
{
- bool __ret = true;
+ // Deal first with the common cases, fast to process: refcopies,
+ // unnamed (i.e., !_M_names[0]), "simple" (!_M_names[1] => all the
+ // categories same name, i.e., _M_names[0]). Otherwise fall back
+ // to the general locale::name().
+ bool __ret;
if (_M_impl == __rhs._M_impl)
- ;
- else if (!std::strcmp(_M_impl->_M_names[0], "*"))
+ __ret = true;
+ else if (!_M_impl->_M_names[0] || !__rhs._M_impl->_M_names[0]
+ || std::strcmp(_M_impl->_M_names[0],
+ __rhs._M_impl->_M_names[0]) != 0)
__ret = false;
+ else if (!_M_impl->_M_names[1] && !__rhs._M_impl->_M_names[1])
+ __ret = true;
else
- for (size_t __i = 0; __ret && __i < _S_categories_size; ++__i)
- __ret = !std::strcmp(_M_impl->_M_names[__i],
- __rhs._M_impl->_M_names[__i]);
+ __ret = this->name() == __rhs.name();
return __ret;
}
locale::name() const
{
string __ret;
- if (_M_impl->_M_check_same_name())
+ if (!_M_impl->_M_names[0])
+ __ret = '*';
+ else if (_M_impl->_M_check_same_name())
__ret = _M_impl->_M_names[0];
else
{
+ __ret.reserve(128);
__ret += _S_categories[0];
__ret += '=';
__ret += _M_impl->_M_names[0];
for (size_t __i = 0; __i < _S_categories_size; ++__i)
_M_names[__i] = 0;
- // Name all the categories.
- for (size_t __i = 0; __i < _S_categories_size; ++__i)
+ // Name the categories.
+ for (size_t __i = 0; (__i < _S_categories_size
+ && __imp._M_names[__i]); ++__i)
{
- char* __new = new char[std::strlen(__imp._M_names[__i]) + 1];
- std::strcpy(__new, __imp._M_names[__i]);
- _M_names[__i] = __new;
+ const size_t __len = std::strlen(__imp._M_names[__i]) + 1;
+ _M_names[__i] = new char[__len];
+ std::memcpy(_M_names[__i], __imp._M_names[__i], __len);
}
}
catch(...)
}
}
-
// locale::id
// Definitions for static const data members of locale::id
_Atomic_word locale::id::_S_refcount; // init'd to 0 by linker
__glibcxx_mutex_lock(__gnu_internal::locale_global_mutex);
_Impl* __old = _S_global;
__other._M_impl->_M_add_reference();
- _S_global = __other._M_impl;
- if (__other.name() != "*")
- setlocale(LC_ALL, __other.name().c_str());
+ _S_global = __other._M_impl;
+ const string __other_name = __other.name();
+ if (__other_name != "*")
+ setlocale(LC_ALL, __other_name.c_str());
__glibcxx_mutex_unlock(__gnu_internal::locale_global_mutex);
// Reference count sanity check: one reference removed for the
for (size_t __i = 0; __i < _M_facets_size; ++__i)
_M_facets[__i] = _M_caches[__i] = 0;
- // Name all the categories.
+ // Name the categories.
_M_names = new (&name_vec) char*[_S_categories_size];
- for (size_t __i = 0; __i < _S_categories_size; ++__i)
- {
- _M_names[__i] = new (&name_c[__i]) char[2];
- std::strcpy(_M_names[__i], locale::facet::_S_get_c_name());
- }
+ _M_names[0] = new (&name_c[0]) char[2];
+ std::memcpy(_M_names[0], locale::facet::_S_get_c_name(), 2);
+ for (size_t __i = 1; __i < _S_categories_size; ++__i)
+ _M_names[__i] = 0;
// This is needed as presently the C++ version of "C" locales
// != data in the underlying locale model for __timepunct,
-// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
+// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
{
using namespace __gnu_cxx;
-
locale::locale(const char* __s)
{
if (__s)
if (__i < _S_categories_size)
{
string __str;
+ __str.reserve(128);
for (size_t __j = 0; __j < __i; ++__j)
{
__str += _S_categories[__j];
for (size_t __i = 0; __i < _S_categories_size; ++__i)
_M_names[__i] = 0;
- // Name all the categories.
+ // Name the categories.
const size_t __len = std::strlen(__s);
if (!std::strchr(__s, ';'))
{
- for (size_t __i = 0; __i < _S_categories_size; ++__i)
- {
- _M_names[__i] = new char[__len + 1];
- std::strcpy(_M_names[__i], __s);
- }
+ _M_names[0] = new char[__len + 1];
+ std::memcpy(_M_names[0], __s, __len + 1);
}
else
{
const char* __end = std::strchr(__beg, ';');
if (!__end)
__end = __s + __len;
- char* __new = new char[__end - __beg + 1];
- std::memcpy(__new, __beg, __end - __beg);
- __new[__end - __beg] = '\0';
- _M_names[__i] = __new;
+ _M_names[__i] = new char[__end - __beg + 1];
+ std::memcpy(_M_names[__i], __beg, __end - __beg);
+ _M_names[__i][__end - __beg] = '\0';
}
}
locale::_Impl::
_M_replace_categories(const _Impl* __imp, category __cat)
{
- for (size_t __ix = 0; __ix < _S_categories_size; ++__ix)
+ category __mask = 1;
+ const bool __have_names = _M_names[0] && __imp->_M_names[0];
+ for (size_t __ix = 0; __ix < _S_categories_size; ++__ix, __mask <<= 1)
{
- const category __mask = 1 << __ix;
if (__mask & __cat)
{
// Need to replace entry in _M_facets with other locale's info.
_M_replace_category(__imp, _S_facet_categories[__ix]);
// If both have names, go ahead and mangle.
- if (std::strcmp(_M_names[__ix], "*") != 0
- && std::strcmp(__imp->_M_names[__ix], "*") != 0)
+ if (__have_names)
{
- char* __new = new char[std::strlen(__imp->_M_names[__ix]) + 1];
- std::strcpy(__new, __imp->_M_names[__ix]);
+ if (!_M_names[1])
+ {
+ // A full set of _M_names must be prepared, all identical
+ // to _M_names[0] to begin with. Then, below, a few will
+ // be replaced by the corresponding __imp->_M_names. I.e.,
+ // not a "simple" locale anymore (see locale::operator==).
+ const size_t __len = std::strlen(_M_names[0]) + 1;
+ for (size_t __i = 1; __i < _S_categories_size; ++__i)
+ {
+ _M_names[__i] = new char[__len];
+ std::memcpy(_M_names[__i], _M_names[0], __len);
+ }
+ }
+ char* __src = __imp->_M_names[__ix] ? __imp->_M_names[__ix]
+ : __imp->_M_names[0];
+ const size_t __len = std::strlen(__src) + 1;
+ char* __new = new char[__len];
+ std::memcpy(__new, __src, __len);
delete [] _M_names[__ix];
_M_names[__ix] = __new;
}