locale_classes.tcc
Go to the documentation of this file.
// Locale support -*- C++ -*-
// Copyright (C) 2007-2024 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
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
/** @file bits/locale_classes.tcc
* This is an internal header file, included by other library headers.
* Do not attempt to use it directly. @headername{locale}
*/
//
// ISO C++ 14882: 22.1 Locales
//
#ifndef _LOCALE_CLASSES_TCC
#define _LOCALE_CLASSES_TCC 1
#pragma GCC system_header
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Facet>
locale::
locale(const locale& __other, _Facet* __f)
{
_M_impl = new _Impl(*__other._M_impl, 1);
__try
{ _M_impl->_M_install_facet(&_Facet::id, __f); }
__catch(...)
{
_M_impl->_M_remove_reference();
__throw_exception_again;
}
delete [] _M_impl->_M_names[0];
_M_impl->_M_names[0] = 0; // Unnamed.
}
template<typename _Facet>
locale
locale::
combine(const locale& __other) const
{
_Impl* __tmp = new _Impl(*_M_impl, 1);
__try
{
__tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
}
__catch(...)
{
__tmp->_M_remove_reference();
__throw_exception_again;
}
return locale(__tmp);
}
template<typename _CharT, typename _Traits, typename _Alloc>
bool
locale::
operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
const basic_string<_CharT, _Traits, _Alloc>& __s2) const
{
typedef std::collate<_CharT> __collate_type;
const __collate_type& __collate = use_facet<__collate_type>(*this);
return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
__s2.data(), __s2.data() + __s2.length()) < 0);
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wc++17-extensions"
template<typename _Facet>
inline const _Facet*
__try_use_facet(const locale& __loc) _GLIBCXX_NOTHROW
{
const size_t __i = _Facet::id._M_id();
const locale::facet** __facets = __loc._M_impl->_M_facets;
// We know these standard facets are always installed in every locale
// so dynamic_cast always succeeds, just use static_cast instead.
#define _GLIBCXX_STD_FACET(...) \
if _GLIBCXX_CONSTEXPR (__is_same(_Facet, __VA_ARGS__)) \
return static_cast<const _Facet*>(__facets[__i])
_GLIBCXX_STD_FACET(ctype<char>);
_GLIBCXX_STD_FACET(num_get<char>);
_GLIBCXX_STD_FACET(num_put<char>);
_GLIBCXX_STD_FACET(codecvt<char, char, mbstate_t>);
_GLIBCXX_STD_FACET(collate<char>);
_GLIBCXX_STD_FACET(moneypunct<char>);
_GLIBCXX_STD_FACET(moneypunct<char, true>);
_GLIBCXX_STD_FACET(money_get<char>);
_GLIBCXX_STD_FACET(money_put<char>);
_GLIBCXX_STD_FACET(numpunct<char>);
_GLIBCXX_STD_FACET(time_get<char>);
_GLIBCXX_STD_FACET(time_put<char>);
_GLIBCXX_STD_FACET(messages<char>);
#ifdef _GLIBCXX_USE_WCHAR_T
_GLIBCXX_STD_FACET(ctype<wchar_t>);
_GLIBCXX_STD_FACET(num_get<wchar_t>);
_GLIBCXX_STD_FACET(num_put<wchar_t>);
_GLIBCXX_STD_FACET(codecvt<wchar_t, char, mbstate_t>);
_GLIBCXX_STD_FACET(collate<wchar_t>);
_GLIBCXX_STD_FACET(moneypunct<wchar_t>);
_GLIBCXX_STD_FACET(moneypunct<wchar_t, true>);
_GLIBCXX_STD_FACET(money_get<wchar_t>);
_GLIBCXX_STD_FACET(money_put<wchar_t>);
_GLIBCXX_STD_FACET(numpunct<wchar_t>);
_GLIBCXX_STD_FACET(time_get<wchar_t>);
_GLIBCXX_STD_FACET(time_put<wchar_t>);
_GLIBCXX_STD_FACET(messages<wchar_t>);
#endif
#if __cplusplus >= 201103L
_GLIBCXX_STD_FACET(codecvt<char16_t, char, mbstate_t>);
_GLIBCXX_STD_FACET(codecvt<char32_t, char, mbstate_t>);
#endif
#undef _GLIBCXX_STD_FACET
if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i])
return 0;
#if __cpp_rtti
return dynamic_cast<const _Facet*>(__facets[__i]);
#else
return static_cast<const _Facet*>(__facets[__i]);
#endif
}
#pragma GCC diagnostic pop
/**
* @brief Test for the presence of a facet.
* @ingroup locales
*
* has_facet tests the locale argument for the presence of the facet type
* provided as the template parameter. Facets derived from the facet
* parameter will also return true.
*
* @tparam _Facet The facet type to test the presence of.
* @param __loc The locale to test.
* @return true if @p __loc contains a facet of type _Facet, else false.
*/
template<typename _Facet>
_GLIBCXX_NODISCARD
inline bool
has_facet(const locale& __loc) throw()
{
#if __cplusplus >= 201103L
static_assert(__is_base_of(locale::facet, _Facet),
"template argument must be derived from locale::facet");
#else
(void) static_cast<const _Facet*>(static_cast<const locale::facet*>(0));
#endif
return std::__try_use_facet<_Facet>(__loc) != 0;
}
/**
* @brief Return a facet.
* @ingroup locales
*
* use_facet looks for and returns a reference to a facet of type Facet
* where Facet is the template parameter. If has_facet(locale) is true,
* there is a suitable facet to return. It throws std::bad_cast if the
* locale doesn't contain a facet of type Facet.
*
* @tparam _Facet The facet type to access.
* @param __loc The locale to use.
* @return Reference to facet of type Facet.
* @throw std::bad_cast if @p __loc doesn't contain a facet of type _Facet.
*/
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdangling-reference"
template<typename _Facet>
_GLIBCXX_NODISCARD
inline const _Facet&
use_facet(const locale& __loc)
{
#if __cplusplus >= 201103L
static_assert(__is_base_of(locale::facet, _Facet),
"template argument must be derived from locale::facet");
#else
(void) static_cast<const _Facet*>(static_cast<const locale::facet*>(0));
#endif
if (const _Facet* __f = std::__try_use_facet<_Facet>(__loc))
return *__f;
__throw_bad_cast();
}
#pragma GCC diagnostic pop
// Generic version does nothing.
template<typename _CharT>
int
collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const throw ()
{ return 0; }
// Generic version does nothing.
template<typename _CharT>
size_t
collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const throw ()
{ return 0; }
template<typename _CharT>
int
collate<_CharT>::
do_compare(const _CharT* __lo1, const _CharT* __hi1,
const _CharT* __lo2, const _CharT* __hi2) const
{
// strcoll assumes zero-terminated strings so we make a copy
// and then put a zero at the end.
const string_type __one(__lo1, __hi1);
const string_type __two(__lo2, __hi2);
const _CharT* __p = __one.c_str();
const _CharT* __pend = __one.data() + __one.length();
const _CharT* __q = __two.c_str();
const _CharT* __qend = __two.data() + __two.length();
// strcoll stops when it sees a nul character so we break
// the strings into zero-terminated substrings and pass those
// to strcoll.
for (;;)
{
const int __res = _M_compare(__p, __q);
if (__res)
return __res;
__p += char_traits<_CharT>::length(__p);
__q += char_traits<_CharT>::length(__q);
if (__p == __pend && __q == __qend)
return 0;
else if (__p == __pend)
return -1;
else if (__q == __qend)
return 1;
__p++;
__q++;
}
}
template<typename _CharT>
typename collate<_CharT>::string_type
collate<_CharT>::
do_transform(const _CharT* __lo, const _CharT* __hi) const
{
string_type __ret;
// strxfrm assumes zero-terminated strings so we make a copy
const string_type __str(__lo, __hi);
const _CharT* __p = __str.c_str();
const _CharT* __pend = __str.data() + __str.length();
size_t __len = (__hi - __lo) * 2;
_CharT* __c = new _CharT[__len];
__try
{
// strxfrm stops when it sees a nul character so we break
// the string into zero-terminated substrings and pass those
// to strxfrm.
for (;;)
{
// First try a buffer perhaps big enough.
size_t __res = _M_transform(__c, __p, __len);
// If the buffer was not large enough, try again with the
// correct size.
if (__res >= __len)
{
__len = __res + 1;
delete [] __c, __c = 0;
__c = new _CharT[__len];
__res = _M_transform(__c, __p, __len);
}
__ret.append(__c, __res);
__p += char_traits<_CharT>::length(__p);
if (__p == __pend)
break;
__p++;
__ret.push_back(_CharT());
}
}
__catch(...)
{
delete [] __c;
__throw_exception_again;
}
delete [] __c;
return __ret;
}
template<typename _CharT>
long
collate<_CharT>::
do_hash(const _CharT* __lo, const _CharT* __hi) const
{
unsigned long __val = 0;
for (; __lo < __hi; ++__lo)
__val =
*__lo + ((__val << 7)
| (__val >> (__gnu_cxx::__numeric_traits<unsigned long>::
__digits - 7)));
return static_cast<long>(__val);
}
// Inhibit implicit instantiations for required instantiations,
// which are defined via explicit instantiations elsewhere.
#if _GLIBCXX_EXTERN_TEMPLATE
extern template class collate<char>;
extern template class collate_byname<char>;
extern template
const collate<char>*
__try_use_facet<collate<char> >(const locale&) _GLIBCXX_NOTHROW;
extern template
const collate<char>&
use_facet<collate<char> >(const locale&);
extern template
bool
has_facet<collate<char> >(const locale&);
#ifdef _GLIBCXX_USE_WCHAR_T
extern template class collate<wchar_t>;
extern template class collate_byname<wchar_t>;
extern template
const collate<wchar_t>*
__try_use_facet<collate<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
extern template
const collate<wchar_t>&
use_facet<collate<wchar_t> >(const locale&);
extern template
bool
has_facet<collate<wchar_t> >(const locale&);
#endif
#endif
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif
std::has_facet
bool has_facet(const locale &__loc)
Test for the presence of a facet.
Definition locale_classes.tcc:167
std::use_facet
const _Facet & use_facet(const locale &__loc)
Return a facet.
Definition locale_classes.tcc:197
std
ISO C++ entities toplevel namespace is std.
std::basic_string
Managing sequences of characters and character-like objects.
Definition basic_string.h:87
std::basic_string::c_str
constexpr const _CharT * c_str() const noexcept
Return const pointer to null-terminated contents.
Definition basic_string.h:2640
std::basic_string::data
constexpr const _CharT * data() const noexcept
Return const pointer to contents.
Definition basic_string.h:2653
std::basic_string::length
constexpr size_type length() const noexcept
Returns the number of characters in the string, not including any null-termination.
Definition basic_string.h:1083
std::basic_string::append
constexpr basic_string & append(const basic_string &__str)
Append a string to this string.
Definition basic_string.h:1435
std::basic_string::push_back
constexpr void push_back(_CharT __c)
Append a single character.
Definition basic_string.h:1572
std::locale
Container class for localization functionality.
Definition locale_classes.h:67
std::locale::use_facet
friend const _Facet & use_facet(const locale &)
Return a facet.
Definition locale_classes.tcc:197
std::locale::combine
locale combine(const locale &__other) const
Construct locale with another facet.
Definition locale_classes.tcc:63
std::locale::operator()
bool operator()(const basic_string< _Char, _Traits, _Alloc > &__s1, const basic_string< _Char, _Traits, _Alloc > &__s2) const
Compare two strings according to collate.
std::locale::locale
locale()
Default constructor.
std::locale::facet
Localization functionality base class.
Definition locale_classes.h:397
std::__cxx11::collate
Facet for localized string comparison.
Definition locale_classes.h:680
std::__cxx11::collate::collate
collate(size_t __refs=0)
Constructor performs initialization.
Definition locale_classes.h:706
std::__cxx11::collate::string_type
basic_string< _CharT > string_type
Public typedefs.
Definition locale_classes.h:686
std::__cxx11::collate_byname
class collate_byname [22.2.4.2].
Definition locale_classes.h:854