272 lines
7.2 KiB
C++
272 lines
7.2 KiB
C++
// Locale support -*- C++ -*-
|
|
|
|
// Copyright (C) 2007, 2008, 2009, 2010 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
|
|
|
|
_GLIBCXX_BEGIN_NAMESPACE(std)
|
|
|
|
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);
|
|
}
|
|
|
|
|
|
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
|
|
#ifdef __GXX_RTTI
|
|
&& dynamic_cast<const _Facet*>(__facets[__i]));
|
|
#else
|
|
&& static_cast<const _Facet*>(__facets[__i]));
|
|
#endif
|
|
}
|
|
|
|
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();
|
|
#ifdef __GXX_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.
|
|
// NB: This syntax is a GNU extension.
|
|
#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
|
|
|
|
#endif
|