You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
299 lines
8.2 KiB
299 lines
8.2 KiB
3 years ago
|
// Locale support -*- C++ -*-
|
||
|
|
||
|
// Copyright (C) 2007-2021 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);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @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>
|
||
|
bool
|
||
|
has_facet(const locale& __loc) throw()
|
||
|
{
|
||
|
const size_t __i = _Facet::id._M_id();
|
||
|
const locale::facet** __facets = __loc._M_impl->_M_facets;
|
||
|
return (__i < __loc._M_impl->_M_facets_size
|
||
|
#if __cpp_rtti
|
||
|
&& dynamic_cast<const _Facet*>(__facets[__i]));
|
||
|
#else
|
||
|
&& static_cast<const _Facet*>(__facets[__i]));
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @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.
|
||
|
*/
|
||
|
template<typename _Facet>
|
||
|
const _Facet&
|
||
|
use_facet(const locale& __loc)
|
||
|
{
|
||
|
const size_t __i = _Facet::id._M_id();
|
||
|
const locale::facet** __facets = __loc._M_impl->_M_facets;
|
||
|
if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i])
|
||
|
__throw_bad_cast();
|
||
|
#if __cpp_rtti
|
||
|
return dynamic_cast<const _Facet&>(*__facets[__i]);
|
||
|
#else
|
||
|
return static_cast<const _Facet&>(*__facets[__i]);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
// 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>&
|
||
|
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>&
|
||
|
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
|