libstdc++
locale_classes.tcc
Go to the documentation of this file.
00001 // Locale support -*- C++ -*-
00002 
00003 // Copyright (C) 2007-2015 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file bits/locale_classes.tcc
00026  *  This is an internal header file, included by other library headers.
00027  *  Do not attempt to use it directly. @headername{locale}
00028  */
00029 
00030 //
00031 // ISO C++ 14882: 22.1  Locales
00032 //
00033 
00034 #ifndef _LOCALE_CLASSES_TCC
00035 #define _LOCALE_CLASSES_TCC 1
00036 
00037 #pragma GCC system_header
00038 
00039 namespace std _GLIBCXX_VISIBILITY(default)
00040 {
00041 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00042 
00043   template<typename _Facet>
00044     locale::
00045     locale(const locale& __other, _Facet* __f)
00046     {
00047       _M_impl = new _Impl(*__other._M_impl, 1);
00048 
00049       __try
00050         { _M_impl->_M_install_facet(&_Facet::id, __f); }
00051       __catch(...)
00052         {
00053           _M_impl->_M_remove_reference();
00054           __throw_exception_again;
00055         }
00056       delete [] _M_impl->_M_names[0];
00057       _M_impl->_M_names[0] = 0;   // Unnamed.
00058     }
00059 
00060   template<typename _Facet>
00061     locale
00062     locale::
00063     combine(const locale& __other) const
00064     {
00065       _Impl* __tmp = new _Impl(*_M_impl, 1);
00066       __try
00067         {
00068           __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
00069         }
00070       __catch(...)
00071         {
00072           __tmp->_M_remove_reference();
00073           __throw_exception_again;
00074         }
00075       return locale(__tmp);
00076     }
00077 
00078   template<typename _CharT, typename _Traits, typename _Alloc>
00079     bool
00080     locale::
00081     operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
00082                const basic_string<_CharT, _Traits, _Alloc>& __s2) const
00083     {
00084       typedef std::collate<_CharT> __collate_type;
00085       const __collate_type& __collate = use_facet<__collate_type>(*this);
00086       return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
00087                                 __s2.data(), __s2.data() + __s2.length()) < 0);
00088     }
00089 
00090   /**
00091    *  @brief  Test for the presence of a facet.
00092    *  @ingroup locales
00093    *
00094    *  has_facet tests the locale argument for the presence of the facet type
00095    *  provided as the template parameter.  Facets derived from the facet
00096    *  parameter will also return true.
00097    *
00098    *  @tparam  _Facet  The facet type to test the presence of.
00099    *  @param  __loc  The locale to test.
00100    *  @return  true if @p __loc contains a facet of type _Facet, else false.
00101   */
00102   template<typename _Facet>
00103     bool
00104     has_facet(const locale& __loc) throw()
00105     {
00106       const size_t __i = _Facet::id._M_id();
00107       const locale::facet** __facets = __loc._M_impl->_M_facets;
00108       return (__i < __loc._M_impl->_M_facets_size
00109 #if __cpp_rtti
00110               && dynamic_cast<const _Facet*>(__facets[__i]));
00111 #else
00112               && static_cast<const _Facet*>(__facets[__i]));
00113 #endif
00114     }
00115 
00116   /**
00117    *  @brief  Return a facet.
00118    *  @ingroup locales
00119    *
00120    *  use_facet looks for and returns a reference to a facet of type Facet
00121    *  where Facet is the template parameter.  If has_facet(locale) is true,
00122    *  there is a suitable facet to return.  It throws std::bad_cast if the
00123    *  locale doesn't contain a facet of type Facet.
00124    *
00125    *  @tparam  _Facet  The facet type to access.
00126    *  @param  __loc  The locale to use.
00127    *  @return  Reference to facet of type Facet.
00128    *  @throw  std::bad_cast if @p __loc doesn't contain a facet of type _Facet.
00129   */
00130   template<typename _Facet>
00131     const _Facet&
00132     use_facet(const locale& __loc)
00133     {
00134       const size_t __i = _Facet::id._M_id();
00135       const locale::facet** __facets = __loc._M_impl->_M_facets;
00136       if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i])
00137         __throw_bad_cast();
00138 #if __cpp_rtti
00139       return dynamic_cast<const _Facet&>(*__facets[__i]);
00140 #else
00141       return static_cast<const _Facet&>(*__facets[__i]);
00142 #endif
00143     }
00144 
00145 
00146   // Generic version does nothing.
00147   template<typename _CharT>
00148     int
00149     collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const throw ()
00150     { return 0; }
00151 
00152   // Generic version does nothing.
00153   template<typename _CharT>
00154     size_t
00155     collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const throw ()
00156     { return 0; }
00157 
00158   template<typename _CharT>
00159     int
00160     collate<_CharT>::
00161     do_compare(const _CharT* __lo1, const _CharT* __hi1,
00162                const _CharT* __lo2, const _CharT* __hi2) const
00163     {
00164       // strcoll assumes zero-terminated strings so we make a copy
00165       // and then put a zero at the end.
00166       const string_type __one(__lo1, __hi1);
00167       const string_type __two(__lo2, __hi2);
00168 
00169       const _CharT* __p = __one.c_str();
00170       const _CharT* __pend = __one.data() + __one.length();
00171       const _CharT* __q = __two.c_str();
00172       const _CharT* __qend = __two.data() + __two.length();
00173 
00174       // strcoll stops when it sees a nul character so we break
00175       // the strings into zero-terminated substrings and pass those
00176       // to strcoll.
00177       for (;;)
00178         {
00179           const int __res = _M_compare(__p, __q);
00180           if (__res)
00181             return __res;
00182 
00183           __p += char_traits<_CharT>::length(__p);
00184           __q += char_traits<_CharT>::length(__q);
00185           if (__p == __pend && __q == __qend)
00186             return 0;
00187           else if (__p == __pend)
00188             return -1;
00189           else if (__q == __qend)
00190             return 1;
00191 
00192           __p++;
00193           __q++;
00194         }
00195     }
00196 
00197   template<typename _CharT>
00198     typename collate<_CharT>::string_type
00199     collate<_CharT>::
00200     do_transform(const _CharT* __lo, const _CharT* __hi) const
00201     {
00202       string_type __ret;
00203 
00204       // strxfrm assumes zero-terminated strings so we make a copy
00205       const string_type __str(__lo, __hi);
00206 
00207       const _CharT* __p = __str.c_str();
00208       const _CharT* __pend = __str.data() + __str.length();
00209 
00210       size_t __len = (__hi - __lo) * 2;
00211 
00212       _CharT* __c = new _CharT[__len];
00213 
00214       __try
00215         {
00216           // strxfrm stops when it sees a nul character so we break
00217           // the string into zero-terminated substrings and pass those
00218           // to strxfrm.
00219           for (;;)
00220             {
00221               // First try a buffer perhaps big enough.
00222               size_t __res = _M_transform(__c, __p, __len);
00223               // If the buffer was not large enough, try again with the
00224               // correct size.
00225               if (__res >= __len)
00226                 {
00227                   __len = __res + 1;
00228                   delete [] __c, __c = 0;
00229                   __c = new _CharT[__len];
00230                   __res = _M_transform(__c, __p, __len);
00231                 }
00232 
00233               __ret.append(__c, __res);
00234               __p += char_traits<_CharT>::length(__p);
00235               if (__p == __pend)
00236                 break;
00237 
00238               __p++;
00239               __ret.push_back(_CharT());
00240             }
00241         }
00242       __catch(...)
00243         {
00244           delete [] __c;
00245           __throw_exception_again;
00246         }
00247 
00248       delete [] __c;
00249 
00250       return __ret;
00251     }
00252 
00253   template<typename _CharT>
00254     long
00255     collate<_CharT>::
00256     do_hash(const _CharT* __lo, const _CharT* __hi) const
00257     {
00258       unsigned long __val = 0;
00259       for (; __lo < __hi; ++__lo)
00260         __val =
00261           *__lo + ((__val << 7)
00262                    | (__val >> (__gnu_cxx::__numeric_traits<unsigned long>::
00263                                 __digits - 7)));
00264       return static_cast<long>(__val);
00265     }
00266 
00267   // Inhibit implicit instantiations for required instantiations,
00268   // which are defined via explicit instantiations elsewhere.
00269 #if _GLIBCXX_EXTERN_TEMPLATE
00270   extern template class collate<char>;
00271   extern template class collate_byname<char>;
00272 
00273   extern template
00274     const collate<char>&
00275     use_facet<collate<char> >(const locale&);
00276 
00277   extern template
00278     bool
00279     has_facet<collate<char> >(const locale&);
00280 
00281 #ifdef _GLIBCXX_USE_WCHAR_T
00282   extern template class collate<wchar_t>;
00283   extern template class collate_byname<wchar_t>;
00284 
00285   extern template
00286     const collate<wchar_t>&
00287     use_facet<collate<wchar_t> >(const locale&);
00288 
00289   extern template
00290     bool
00291     has_facet<collate<wchar_t> >(const locale&);
00292 #endif
00293 #endif
00294 
00295 _GLIBCXX_END_NAMESPACE_VERSION
00296 } // namespace std
00297 
00298 #endif