Home | History | Annotate | Download | only in bits
      1 // Locale support -*- C++ -*-
      2 
      3 // Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file locale_classes.tcc
     26  *  This is an internal header file, included by other library headers.
     27  *  You should not attempt to use it directly.
     28  */
     29 
     30 //
     31 // ISO C++ 14882: 22.1  Locales
     32 //
     33 
     34 #ifndef _LOCALE_CLASSES_TCC
     35 #define _LOCALE_CLASSES_TCC 1
     36 
     37 #pragma GCC system_header
     38 
     39 _GLIBCXX_BEGIN_NAMESPACE(std)
     40 
     41   template<typename _Facet>
     42     locale::
     43     locale(const locale& __other, _Facet* __f)
     44     {
     45       _M_impl = new _Impl(*__other._M_impl, 1);
     46 
     47       __try
     48 	{ _M_impl->_M_install_facet(&_Facet::id, __f); }
     49       __catch(...)
     50 	{
     51 	  _M_impl->_M_remove_reference();
     52 	  __throw_exception_again;
     53 	}
     54       delete [] _M_impl->_M_names[0];
     55       _M_impl->_M_names[0] = 0;   // Unnamed.
     56     }
     57 
     58   template<typename _Facet>
     59     locale
     60     locale::
     61     combine(const locale& __other) const
     62     {
     63       _Impl* __tmp = new _Impl(*_M_impl, 1);
     64       __try
     65 	{
     66 	  __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
     67 	}
     68       __catch(...)
     69 	{
     70 	  __tmp->_M_remove_reference();
     71 	  __throw_exception_again;
     72 	}
     73       return locale(__tmp);
     74     }
     75 
     76   template<typename _CharT, typename _Traits, typename _Alloc>
     77     bool
     78     locale::
     79     operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
     80 	       const basic_string<_CharT, _Traits, _Alloc>& __s2) const
     81     {
     82       typedef std::collate<_CharT> __collate_type;
     83       const __collate_type& __collate = use_facet<__collate_type>(*this);
     84       return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
     85 				__s2.data(), __s2.data() + __s2.length()) < 0);
     86     }
     87 
     88 
     89   template<typename _Facet>
     90     bool
     91     has_facet(const locale& __loc) throw()
     92     {
     93       const size_t __i = _Facet::id._M_id();
     94       const locale::facet** __facets = __loc._M_impl->_M_facets;
     95       return (__i < __loc._M_impl->_M_facets_size
     96 #ifdef __GXX_RTTI
     97 	      && dynamic_cast<const _Facet*>(__facets[__i]));
     98 #else
     99               && static_cast<const _Facet*>(__facets[__i]));
    100 #endif
    101     }
    102 
    103   template<typename _Facet>
    104     const _Facet&
    105     use_facet(const locale& __loc)
    106     {
    107       const size_t __i = _Facet::id._M_id();
    108       const locale::facet** __facets = __loc._M_impl->_M_facets;
    109       if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i])
    110         __throw_bad_cast();
    111 #ifdef __GXX_RTTI
    112       return dynamic_cast<const _Facet&>(*__facets[__i]);
    113 #else
    114       return static_cast<const _Facet&>(*__facets[__i]);
    115 #endif
    116     }
    117 
    118 
    119   // Generic version does nothing.
    120   template<typename _CharT>
    121     int
    122     collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const
    123     { return 0; }
    124 
    125   // Generic version does nothing.
    126   template<typename _CharT>
    127     size_t
    128     collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const
    129     { return 0; }
    130 
    131   template<typename _CharT>
    132     int
    133     collate<_CharT>::
    134     do_compare(const _CharT* __lo1, const _CharT* __hi1,
    135 	       const _CharT* __lo2, const _CharT* __hi2) const
    136     {
    137       // strcoll assumes zero-terminated strings so we make a copy
    138       // and then put a zero at the end.
    139       const string_type __one(__lo1, __hi1);
    140       const string_type __two(__lo2, __hi2);
    141 
    142       const _CharT* __p = __one.c_str();
    143       const _CharT* __pend = __one.data() + __one.length();
    144       const _CharT* __q = __two.c_str();
    145       const _CharT* __qend = __two.data() + __two.length();
    146 
    147       // strcoll stops when it sees a nul character so we break
    148       // the strings into zero-terminated substrings and pass those
    149       // to strcoll.
    150       for (;;)
    151 	{
    152 	  const int __res = _M_compare(__p, __q);
    153 	  if (__res)
    154 	    return __res;
    155 
    156 	  __p += char_traits<_CharT>::length(__p);
    157 	  __q += char_traits<_CharT>::length(__q);
    158 	  if (__p == __pend && __q == __qend)
    159 	    return 0;
    160 	  else if (__p == __pend)
    161 	    return -1;
    162 	  else if (__q == __qend)
    163 	    return 1;
    164 
    165 	  __p++;
    166 	  __q++;
    167 	}
    168     }
    169 
    170   template<typename _CharT>
    171     typename collate<_CharT>::string_type
    172     collate<_CharT>::
    173     do_transform(const _CharT* __lo, const _CharT* __hi) const
    174     {
    175       string_type __ret;
    176 
    177       // strxfrm assumes zero-terminated strings so we make a copy
    178       const string_type __str(__lo, __hi);
    179 
    180       const _CharT* __p = __str.c_str();
    181       const _CharT* __pend = __str.data() + __str.length();
    182 
    183       size_t __len = (__hi - __lo) * 2;
    184 
    185       _CharT* __c = new _CharT[__len];
    186 
    187       __try
    188 	{
    189 	  // strxfrm stops when it sees a nul character so we break
    190 	  // the string into zero-terminated substrings and pass those
    191 	  // to strxfrm.
    192 	  for (;;)
    193 	    {
    194 	      // First try a buffer perhaps big enough.
    195 	      size_t __res = _M_transform(__c, __p, __len);
    196 	      // If the buffer was not large enough, try again with the
    197 	      // correct size.
    198 	      if (__res >= __len)
    199 		{
    200 		  __len = __res + 1;
    201 		  delete [] __c, __c = 0;
    202 		  __c = new _CharT[__len];
    203 		  __res = _M_transform(__c, __p, __len);
    204 		}
    205 
    206 	      __ret.append(__c, __res);
    207 	      __p += char_traits<_CharT>::length(__p);
    208 	      if (__p == __pend)
    209 		break;
    210 
    211 	      __p++;
    212 	      __ret.push_back(_CharT());
    213 	    }
    214 	}
    215       __catch(...)
    216 	{
    217 	  delete [] __c;
    218 	  __throw_exception_again;
    219 	}
    220 
    221       delete [] __c;
    222 
    223       return __ret;
    224     }
    225 
    226   template<typename _CharT>
    227     long
    228     collate<_CharT>::
    229     do_hash(const _CharT* __lo, const _CharT* __hi) const
    230     {
    231       unsigned long __val = 0;
    232       for (; __lo < __hi; ++__lo)
    233 	__val =
    234 	  *__lo + ((__val << 7)
    235 		   | (__val >> (__gnu_cxx::__numeric_traits<unsigned long>::
    236 				__digits - 7)));
    237       return static_cast<long>(__val);
    238     }
    239 
    240   // Inhibit implicit instantiations for required instantiations,
    241   // which are defined via explicit instantiations elsewhere.
    242   // NB: This syntax is a GNU extension.
    243 #if _GLIBCXX_EXTERN_TEMPLATE
    244   extern template class collate<char>;
    245   extern template class collate_byname<char>;
    246 
    247   extern template
    248     const collate<char>&
    249     use_facet<collate<char> >(const locale&);
    250 
    251   extern template
    252     bool
    253     has_facet<collate<char> >(const locale&);
    254 
    255 #ifdef _GLIBCXX_USE_WCHAR_T
    256   extern template class collate<wchar_t>;
    257   extern template class collate_byname<wchar_t>;
    258 
    259   extern template
    260     const collate<wchar_t>&
    261     use_facet<collate<wchar_t> >(const locale&);
    262 
    263   extern template
    264     bool
    265     has_facet<collate<wchar_t> >(const locale&);
    266 #endif
    267 #endif
    268 
    269 _GLIBCXX_END_NAMESPACE
    270 
    271 #endif
    272