// Locale support -*- C++ -*-
|
// Locale support -*- C++ -*-
|
|
|
// Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
|
// Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
|
//
|
//
|
// This file is part of the GNU ISO C++ Library. This library is free
|
// 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
|
// software; you can redistribute it and/or modify it under the
|
// terms of the GNU General Public License as published by the
|
// terms of the GNU General Public License as published by the
|
// Free Software Foundation; either version 3, or (at your option)
|
// Free Software Foundation; either version 3, or (at your option)
|
// any later version.
|
// any later version.
|
|
|
// This library is distributed in the hope that it will be useful,
|
// This library is distributed in the hope that it will be useful,
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
|
|
// Under Section 7 of GPL version 3, you are granted additional
|
// Under Section 7 of GPL version 3, you are granted additional
|
// permissions described in the GCC Runtime Library Exception, version
|
// permissions described in the GCC Runtime Library Exception, version
|
// 3.1, as published by the Free Software Foundation.
|
// 3.1, as published by the Free Software Foundation.
|
|
|
// You should have received a copy of the GNU General Public License and
|
// 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;
|
// a copy of the GCC Runtime Library Exception along with this program;
|
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
// .
|
// .
|
|
|
/** @file locale_classes.tcc
|
/** @file locale_classes.tcc
|
* This is an internal header file, included by other library headers.
|
* This is an internal header file, included by other library headers.
|
* You should not attempt to use it directly.
|
* You should not attempt to use it directly.
|
*/
|
*/
|
|
|
//
|
//
|
// ISO C++ 14882: 22.1 Locales
|
// ISO C++ 14882: 22.1 Locales
|
//
|
//
|
|
|
#ifndef _LOCALE_CLASSES_TCC
|
#ifndef _LOCALE_CLASSES_TCC
|
#define _LOCALE_CLASSES_TCC 1
|
#define _LOCALE_CLASSES_TCC 1
|
|
|
#pragma GCC system_header
|
#pragma GCC system_header
|
|
|
_GLIBCXX_BEGIN_NAMESPACE(std)
|
_GLIBCXX_BEGIN_NAMESPACE(std)
|
|
|
template
|
template
|
locale::
|
locale::
|
locale(const locale& __other, _Facet* __f)
|
locale(const locale& __other, _Facet* __f)
|
{
|
{
|
_M_impl = new _Impl(*__other._M_impl, 1);
|
_M_impl = new _Impl(*__other._M_impl, 1);
|
|
|
__try
|
__try
|
{ _M_impl->_M_install_facet(&_Facet::id, __f); }
|
{ _M_impl->_M_install_facet(&_Facet::id, __f); }
|
__catch(...)
|
__catch(...)
|
{
|
{
|
_M_impl->_M_remove_reference();
|
_M_impl->_M_remove_reference();
|
__throw_exception_again;
|
__throw_exception_again;
|
}
|
}
|
delete [] _M_impl->_M_names[0];
|
delete [] _M_impl->_M_names[0];
|
_M_impl->_M_names[0] = 0; // Unnamed.
|
_M_impl->_M_names[0] = 0; // Unnamed.
|
}
|
}
|
|
|
template
|
template
|
locale
|
locale
|
locale::
|
locale::
|
combine(const locale& __other) const
|
combine(const locale& __other) const
|
{
|
{
|
_Impl* __tmp = new _Impl(*_M_impl, 1);
|
_Impl* __tmp = new _Impl(*_M_impl, 1);
|
__try
|
__try
|
{
|
{
|
__tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
|
__tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
|
}
|
}
|
__catch(...)
|
__catch(...)
|
{
|
{
|
__tmp->_M_remove_reference();
|
__tmp->_M_remove_reference();
|
__throw_exception_again;
|
__throw_exception_again;
|
}
|
}
|
return locale(__tmp);
|
return locale(__tmp);
|
}
|
}
|
|
|
template
|
template
|
bool
|
bool
|
locale::
|
locale::
|
operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
|
operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
|
const basic_string<_CharT, _Traits, _Alloc>& __s2) const
|
const basic_string<_CharT, _Traits, _Alloc>& __s2) const
|
{
|
{
|
typedef std::collate<_CharT> __collate_type;
|
typedef std::collate<_CharT> __collate_type;
|
const __collate_type& __collate = use_facet<__collate_type>(*this);
|
const __collate_type& __collate = use_facet<__collate_type>(*this);
|
return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
|
return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
|
__s2.data(), __s2.data() + __s2.length()) < 0);
|
__s2.data(), __s2.data() + __s2.length()) < 0);
|
}
|
}
|
|
|
|
|
template
|
template
|
bool
|
bool
|
has_facet(const locale& __loc) throw()
|
has_facet(const locale& __loc) throw()
|
{
|
{
|
const size_t __i = _Facet::id._M_id();
|
const size_t __i = _Facet::id._M_id();
|
const locale::facet** __facets = __loc._M_impl->_M_facets;
|
const locale::facet** __facets = __loc._M_impl->_M_facets;
|
return (__i < __loc._M_impl->_M_facets_size
|
return (__i < __loc._M_impl->_M_facets_size
|
#ifdef __GXX_RTTI
|
#ifdef __GXX_RTTI
|
&& dynamic_cast(__facets[__i]));
|
&& dynamic_cast(__facets[__i]));
|
#else
|
#else
|
&& static_cast(__facets[__i]));
|
&& static_cast(__facets[__i]));
|
#endif
|
#endif
|
}
|
}
|
|
|
template
|
template
|
const _Facet&
|
const _Facet&
|
use_facet(const locale& __loc)
|
use_facet(const locale& __loc)
|
{
|
{
|
const size_t __i = _Facet::id._M_id();
|
const size_t __i = _Facet::id._M_id();
|
const locale::facet** __facets = __loc._M_impl->_M_facets;
|
const locale::facet** __facets = __loc._M_impl->_M_facets;
|
if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i])
|
if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i])
|
__throw_bad_cast();
|
__throw_bad_cast();
|
#ifdef __GXX_RTTI
|
#ifdef __GXX_RTTI
|
return dynamic_cast(*__facets[__i]);
|
return dynamic_cast(*__facets[__i]);
|
#else
|
#else
|
return static_cast(*__facets[__i]);
|
return static_cast(*__facets[__i]);
|
#endif
|
#endif
|
}
|
}
|
|
|
|
|
// Generic version does nothing.
|
// Generic version does nothing.
|
template
|
template
|
int
|
int
|
collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const throw ()
|
collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const throw ()
|
{ return 0; }
|
{ return 0; }
|
|
|
// Generic version does nothing.
|
// Generic version does nothing.
|
template
|
template
|
size_t
|
size_t
|
collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const throw ()
|
collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const throw ()
|
{ return 0; }
|
{ return 0; }
|
|
|
template
|
template
|
int
|
int
|
collate<_CharT>::
|
collate<_CharT>::
|
do_compare(const _CharT* __lo1, const _CharT* __hi1,
|
do_compare(const _CharT* __lo1, const _CharT* __hi1,
|
const _CharT* __lo2, const _CharT* __hi2) const
|
const _CharT* __lo2, const _CharT* __hi2) const
|
{
|
{
|
// strcoll assumes zero-terminated strings so we make a copy
|
// strcoll assumes zero-terminated strings so we make a copy
|
// and then put a zero at the end.
|
// and then put a zero at the end.
|
const string_type __one(__lo1, __hi1);
|
const string_type __one(__lo1, __hi1);
|
const string_type __two(__lo2, __hi2);
|
const string_type __two(__lo2, __hi2);
|
|
|
const _CharT* __p = __one.c_str();
|
const _CharT* __p = __one.c_str();
|
const _CharT* __pend = __one.data() + __one.length();
|
const _CharT* __pend = __one.data() + __one.length();
|
const _CharT* __q = __two.c_str();
|
const _CharT* __q = __two.c_str();
|
const _CharT* __qend = __two.data() + __two.length();
|
const _CharT* __qend = __two.data() + __two.length();
|
|
|
// strcoll stops when it sees a nul character so we break
|
// strcoll stops when it sees a nul character so we break
|
// the strings into zero-terminated substrings and pass those
|
// the strings into zero-terminated substrings and pass those
|
// to strcoll.
|
// to strcoll.
|
for (;;)
|
for (;;)
|
{
|
{
|
const int __res = _M_compare(__p, __q);
|
const int __res = _M_compare(__p, __q);
|
if (__res)
|
if (__res)
|
return __res;
|
return __res;
|
|
|
__p += char_traits<_CharT>::length(__p);
|
__p += char_traits<_CharT>::length(__p);
|
__q += char_traits<_CharT>::length(__q);
|
__q += char_traits<_CharT>::length(__q);
|
if (__p == __pend && __q == __qend)
|
if (__p == __pend && __q == __qend)
|
return 0;
|
return 0;
|
else if (__p == __pend)
|
else if (__p == __pend)
|
return -1;
|
return -1;
|
else if (__q == __qend)
|
else if (__q == __qend)
|
return 1;
|
return 1;
|
|
|
__p++;
|
__p++;
|
__q++;
|
__q++;
|
}
|
}
|
}
|
}
|
|
|
template
|
template
|
typename collate<_CharT>::string_type
|
typename collate<_CharT>::string_type
|
collate<_CharT>::
|
collate<_CharT>::
|
do_transform(const _CharT* __lo, const _CharT* __hi) const
|
do_transform(const _CharT* __lo, const _CharT* __hi) const
|
{
|
{
|
string_type __ret;
|
string_type __ret;
|
|
|
// strxfrm assumes zero-terminated strings so we make a copy
|
// strxfrm assumes zero-terminated strings so we make a copy
|
const string_type __str(__lo, __hi);
|
const string_type __str(__lo, __hi);
|
|
|
const _CharT* __p = __str.c_str();
|
const _CharT* __p = __str.c_str();
|
const _CharT* __pend = __str.data() + __str.length();
|
const _CharT* __pend = __str.data() + __str.length();
|
|
|
size_t __len = (__hi - __lo) * 2;
|
size_t __len = (__hi - __lo) * 2;
|
|
|
_CharT* __c = new _CharT[__len];
|
_CharT* __c = new _CharT[__len];
|
|
|
__try
|
__try
|
{
|
{
|
// strxfrm stops when it sees a nul character so we break
|
// strxfrm stops when it sees a nul character so we break
|
// the string into zero-terminated substrings and pass those
|
// the string into zero-terminated substrings and pass those
|
// to strxfrm.
|
// to strxfrm.
|
for (;;)
|
for (;;)
|
{
|
{
|
// First try a buffer perhaps big enough.
|
// First try a buffer perhaps big enough.
|
size_t __res = _M_transform(__c, __p, __len);
|
size_t __res = _M_transform(__c, __p, __len);
|
// If the buffer was not large enough, try again with the
|
// If the buffer was not large enough, try again with the
|
// correct size.
|
// correct size.
|
if (__res >= __len)
|
if (__res >= __len)
|
{
|
{
|
__len = __res + 1;
|
__len = __res + 1;
|
delete [] __c, __c = 0;
|
delete [] __c, __c = 0;
|
__c = new _CharT[__len];
|
__c = new _CharT[__len];
|
__res = _M_transform(__c, __p, __len);
|
__res = _M_transform(__c, __p, __len);
|
}
|
}
|
|
|
__ret.append(__c, __res);
|
__ret.append(__c, __res);
|
__p += char_traits<_CharT>::length(__p);
|
__p += char_traits<_CharT>::length(__p);
|
if (__p == __pend)
|
if (__p == __pend)
|
break;
|
break;
|
|
|
__p++;
|
__p++;
|
__ret.push_back(_CharT());
|
__ret.push_back(_CharT());
|
}
|
}
|
}
|
}
|
__catch(...)
|
__catch(...)
|
{
|
{
|
delete [] __c;
|
delete [] __c;
|
__throw_exception_again;
|
__throw_exception_again;
|
}
|
}
|
|
|
delete [] __c;
|
delete [] __c;
|
|
|
return __ret;
|
return __ret;
|
}
|
}
|
|
|
template
|
template
|
long
|
long
|
collate<_CharT>::
|
collate<_CharT>::
|
do_hash(const _CharT* __lo, const _CharT* __hi) const
|
do_hash(const _CharT* __lo, const _CharT* __hi) const
|
{
|
{
|
unsigned long __val = 0;
|
unsigned long __val = 0;
|
for (; __lo < __hi; ++__lo)
|
for (; __lo < __hi; ++__lo)
|
__val =
|
__val =
|
*__lo + ((__val << 7)
|
*__lo + ((__val << 7)
|
| (__val >> (__gnu_cxx::__numeric_traits::
|
| (__val >> (__gnu_cxx::__numeric_traits::
|
__digits - 7)));
|
__digits - 7)));
|
return static_cast(__val);
|
return static_cast(__val);
|
}
|
}
|
|
|
// Inhibit implicit instantiations for required instantiations,
|
// Inhibit implicit instantiations for required instantiations,
|
// which are defined via explicit instantiations elsewhere.
|
// which are defined via explicit instantiations elsewhere.
|
// NB: This syntax is a GNU extension.
|
// NB: This syntax is a GNU extension.
|
#if _GLIBCXX_EXTERN_TEMPLATE
|
#if _GLIBCXX_EXTERN_TEMPLATE
|
extern template class collate;
|
extern template class collate;
|
extern template class collate_byname;
|
extern template class collate_byname;
|
|
|
extern template
|
extern template
|
const collate&
|
const collate&
|
use_facet >(const locale&);
|
use_facet >(const locale&);
|
|
|
extern template
|
extern template
|
bool
|
bool
|
has_facet >(const locale&);
|
has_facet >(const locale&);
|
|
|
#ifdef _GLIBCXX_USE_WCHAR_T
|
#ifdef _GLIBCXX_USE_WCHAR_T
|
extern template class collate;
|
extern template class collate;
|
extern template class collate_byname;
|
extern template class collate_byname;
|
|
|
extern template
|
extern template
|
const collate&
|
const collate&
|
use_facet >(const locale&);
|
use_facet >(const locale&);
|
|
|
extern template
|
extern template
|
bool
|
bool
|
has_facet >(const locale&);
|
has_facet >(const locale&);
|
#endif
|
#endif
|
#endif
|
#endif
|
|
|
_GLIBCXX_END_NAMESPACE
|
_GLIBCXX_END_NAMESPACE
|
|
|
#endif
|
#endif
|
|
|