Home | History | Annotate | Download | only in bits
      1 // Locale support -*- C++ -*-
      2 
      3 // Copyright (C) 2007-2013 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 bits/locale_classes.tcc
     26  *  This is an internal header file, included by other library headers.
     27  *  Do not attempt to use it directly. @headername{locale}
     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 namespace std _GLIBCXX_VISIBILITY(default)
     40 {
     41 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     42 
     43   template<typename _Facet>
     44     locale::
     45     locale(const locale& __other, _Facet* __f)
     46     {
     47       _M_impl = new _Impl(*__other._M_impl, 1);
     48 
     49       __try
     50 	{ _M_impl->_M_install_facet(&_Facet::id, __f); }
     51       __catch(...)
     52 	{
     53 	  _M_impl->_M_remove_reference();
     54 	  __throw_exception_again;
     55 	}
     56       delete [] _M_impl->_M_names[0];
     57       _M_impl->_M_names[0] = 0;   // Unnamed.
     58     }
     59 
     60   template<typename _Facet>
     61     locale
     62     locale::
     63     combine(const locale& __other) const
     64     {
     65       _Impl* __tmp = new _Impl(*_M_impl, 1);
     66       __try
     67 	{
     68 	  __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
     69 	}
     70       __catch(...)
     71 	{
     72 	  __tmp->_M_remove_reference();
     73 	  __throw_exception_again;
     74 	}
     75       return locale(__tmp);
     76     }
     77 
     78   template<typename _CharT, typename _Traits, typename _Alloc>
     79     bool
     80     locale::
     81     operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
     82 	       const basic_string<_CharT, _Traits, _Alloc>& __s2) const
     83     {
     84       typedef std::collate<_CharT> __collate_type;
     85       const __collate_type& __collate = use_facet<__collate_type>(*this);
     86       return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
     87 				__s2.data(), __s2.data() + __s2.length()) < 0);
     88     }
     89 
     90   /**
     91    *  @brief  Test for the presence of a facet.
     92    *  @ingroup locales
     93    *
     94    *  has_facet tests the locale argument for the presence of the facet type
     95    *  provided as the template parameter.  Facets derived from the facet
     96    *  parameter will also return true.
     97    *
     98    *  @tparam  _Facet  The facet type to test the presence of.
     99    *  @param  __loc  The locale to test.
    100    *  @return  true if @p __loc contains a facet of type _Facet, else false.
    101   */
    102   template<typename _Facet>
    103     bool
    104     has_facet(const locale& __loc) throw()
    105     {
    106       const size_t __i = _Facet::id._M_id();
    107       const locale::facet** __facets = __loc._M_impl->_M_facets;
    108       return (__i < __loc._M_impl->_M_facets_size
    109 #ifdef __GXX_RTTI
    110 	      && dynamic_cast<const _Facet*>(__facets[__i]));
    111 #else
    112               && static_cast<const _Facet*>(__facets[__i]));
    113 #endif
    114     }
    115 
    116   /**
    117    *  @brief  Return a facet.
    118    *  @ingroup locales
    119    *
    120    *  use_facet looks for and returns a reference to a facet of type Facet
    121    *  where Facet is the template parameter.  If has_facet(locale) is true,
    122    *  there is a suitable facet to return.  It throws std::bad_cast if the
    123    *  locale doesn't contain a facet of type Facet.
    124    *
    125    *  @tparam  _Facet  The facet type to access.
    126    *  @param  __loc  The locale to use.
    127    *  @return  Reference to facet of type Facet.
    128    *  @throw  std::bad_cast if @p __loc doesn't contain a facet of type _Facet.
    129   */
    130   template<typename _Facet>
    131     const _Facet&
    132     use_facet(const locale& __loc)
    133     {
    134       const size_t __i = _Facet::id._M_id();
    135       const locale::facet** __facets = __loc._M_impl->_M_facets;
    136       if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i])
    137         __throw_bad_cast();
    138 #ifdef __GXX_RTTI
    139       return dynamic_cast<const _Facet&>(*__facets[__i]);
    140 #else
    141       return static_cast<const _Facet&>(*__facets[__i]);
    142 #endif
    143     }
    144 
    145 
    146   // Generic version does nothing.
    147   template<typename _CharT>
    148     int
    149     collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const throw ()
    150     { return 0; }
    151 
    152   // Generic version does nothing.
    153   template<typename _CharT>
    154     size_t
    155     collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const throw ()
    156     { return 0; }
    157 
    158   template<typename _CharT>
    159     int
    160     collate<_CharT>::
    161     do_compare(const _CharT* __lo1, const _CharT* __hi1,
    162 	       const _CharT* __lo2, const _CharT* __hi2) const
    163     {
    164       // strcoll assumes zero-terminated strings so we make a copy
    165       // and then put a zero at the end.
    166       const string_type __one(__lo1, __hi1);
    167       const string_type __two(__lo2, __hi2);
    168 
    169       const _CharT* __p = __one.c_str();
    170       const _CharT* __pend = __one.data() + __one.length();
    171       const _CharT* __q = __two.c_str();
    172       const _CharT* __qend = __two.data() + __two.length();
    173 
    174       // strcoll stops when it sees a nul character so we break
    175       // the strings into zero-terminated substrings and pass those
    176       // to strcoll.
    177       for (;;)
    178 	{
    179 	  const int __res = _M_compare(__p, __q);
    180 	  if (__res)
    181 	    return __res;
    182 
    183 	  __p += char_traits<_CharT>::length(__p);
    184 	  __q += char_traits<_CharT>::length(__q);
    185 	  if (__p == __pend && __q == __qend)
    186 	    return 0;
    187 	  else if (__p == __pend)
    188 	    return -1;
    189 	  else if (__q == __qend)
    190 	    return 1;
    191 
    192 	  __p++;
    193 	  __q++;
    194 	}
    195     }
    196 
    197   template<typename _CharT>
    198     typename collate<_CharT>::string_type
    199     collate<_CharT>::
    200     do_transform(const _CharT* __lo, const _CharT* __hi) const
    201     {
    202       string_type __ret;
    203 
    204       // strxfrm assumes zero-terminated strings so we make a copy
    205       const string_type __str(__lo, __hi);
    206 
    207       const _CharT* __p = __str.c_str();
    208       const _CharT* __pend = __str.data() + __str.length();
    209 
    210       size_t __len = (__hi - __lo) * 2;
    211 
    212       _CharT* __c = new _CharT[__len];
    213 
    214       __try
    215 	{
    216 	  // strxfrm stops when it sees a nul character so we break
    217 	  // the string into zero-terminated substrings and pass those
    218 	  // to strxfrm.
    219 	  for (;;)
    220 	    {
    221 	      // First try a buffer perhaps big enough.
    222 	      size_t __res = _M_transform(__c, __p, __len);
    223 	      // If the buffer was not large enough, try again with the
    224 	      // correct size.
    225 	      if (__res >= __len)
    226 		{
    227 		  __len = __res + 1;
    228 		  delete [] __c, __c = 0;
    229 		  __c = new _CharT[__len];
    230 		  __res = _M_transform(__c, __p, __len);
    231 		}
    232 
    233 	      __ret.append(__c, __res);
    234 	      __p += char_traits<_CharT>::length(__p);
    235 	      if (__p == __pend)
    236 		break;
    237 
    238 	      __p++;
    239 	      __ret.push_back(_CharT());
    240 	    }
    241 	}
    242       __catch(...)
    243 	{
    244 	  delete [] __c;
    245 	  __throw_exception_again;
    246 	}
    247 
    248       delete [] __c;
    249 
    250       return __ret;
    251     }
    252 
    253   template<typename _CharT>
    254     long
    255     collate<_CharT>::
    256     do_hash(const _CharT* __lo, const _CharT* __hi) const
    257     {
    258       unsigned long __val = 0;
    259       for (; __lo < __hi; ++__lo)
    260 	__val =
    261 	  *__lo + ((__val << 7)
    262 		   | (__val >> (__gnu_cxx::__numeric_traits<unsigned long>::
    263 				__digits - 7)));
    264       return static_cast<long>(__val);
    265     }
    266 
    267   // Inhibit implicit instantiations for required instantiations,
    268   // which are defined via explicit instantiations elsewhere.
    269 #if _GLIBCXX_EXTERN_TEMPLATE
    270   extern template class collate<char>;
    271   extern template class collate_byname<char>;
    272 
    273   extern template
    274     const collate<char>&
    275     use_facet<collate<char> >(const locale&);
    276 
    277   extern template
    278     bool
    279     has_facet<collate<char> >(const locale&);
    280 
    281 #ifdef _GLIBCXX_USE_WCHAR_T
    282   extern template class collate<wchar_t>;
    283   extern template class collate_byname<wchar_t>;
    284 
    285   extern template
    286     const collate<wchar_t>&
    287     use_facet<collate<wchar_t> >(const locale&);
    288 
    289   extern template
    290     bool
    291     has_facet<collate<wchar_t> >(const locale&);
    292 #endif
    293 #endif
    294 
    295 _GLIBCXX_END_NAMESPACE_VERSION
    296 } // namespace std
    297 
    298 #endif
    299