libstdc++
locale_classes.tcc
Go to the documentation of this file.
00001 // Locale support -*- C++ -*-
00002 
00003 // Copyright (C) 2007, 2008, 2009, 2010, 2011 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    *
00093    *  has_facet tests the locale argument for the presence of the facet type
00094    *  provided as the template parameter.  Facets derived from the facet
00095    *  parameter will also return true.
00096    *
00097    *  @tparam  _Facet  The facet type to test the presence of.
00098    *  @param  __loc  The locale to test.
00099    *  @return  true if @p __loc contains a facet of type _Facet, else false.
00100   */
00101   template<typename _Facet>
00102     bool
00103     has_facet(const locale& __loc) throw()
00104     {
00105       const size_t __i = _Facet::id._M_id();
00106       const locale::facet** __facets = __loc._M_impl->_M_facets;
00107       return (__i < __loc._M_impl->_M_facets_size
00108 #ifdef __GXX_RTTI
00109           && dynamic_cast<const _Facet*>(__facets[__i]));
00110 #else
00111               && static_cast<const _Facet*>(__facets[__i]));
00112 #endif
00113     }
00114 
00115   /**
00116    *  @brief  Return a facet.
00117    *
00118    *  use_facet looks for and returns a reference to a facet of type Facet
00119    *  where Facet is the template parameter.  If has_facet(locale) is true,
00120    *  there is a suitable facet to return.  It throws std::bad_cast if the
00121    *  locale doesn't contain a facet of type Facet.
00122    *
00123    *  @tparam  _Facet  The facet type to access.
00124    *  @param  __loc  The locale to use.
00125    *  @return  Reference to facet of type Facet.
00126    *  @throw  std::bad_cast if @p __loc doesn't contain a facet of type _Facet.
00127   */
00128   template<typename _Facet>
00129     const _Facet&
00130     use_facet(const locale& __loc)
00131     {
00132       const size_t __i = _Facet::id._M_id();
00133       const locale::facet** __facets = __loc._M_impl->_M_facets;
00134       if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i])
00135         __throw_bad_cast();
00136 #ifdef __GXX_RTTI
00137       return dynamic_cast<const _Facet&>(*__facets[__i]);
00138 #else
00139       return static_cast<const _Facet&>(*__facets[__i]);
00140 #endif
00141     }
00142 
00143 
00144   // Generic version does nothing.
00145   template<typename _CharT>
00146     int
00147     collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const throw ()
00148     { return 0; }
00149 
00150   // Generic version does nothing.
00151   template<typename _CharT>
00152     size_t
00153     collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const throw ()
00154     { return 0; }
00155 
00156   template<typename _CharT>
00157     int
00158     collate<_CharT>::
00159     do_compare(const _CharT* __lo1, const _CharT* __hi1,
00160            const _CharT* __lo2, const _CharT* __hi2) const
00161     {
00162       // strcoll assumes zero-terminated strings so we make a copy
00163       // and then put a zero at the end.
00164       const string_type __one(__lo1, __hi1);
00165       const string_type __two(__lo2, __hi2);
00166 
00167       const _CharT* __p = __one.c_str();
00168       const _CharT* __pend = __one.data() + __one.length();
00169       const _CharT* __q = __two.c_str();
00170       const _CharT* __qend = __two.data() + __two.length();
00171 
00172       // strcoll stops when it sees a nul character so we break
00173       // the strings into zero-terminated substrings and pass those
00174       // to strcoll.
00175       for (;;)
00176     {
00177       const int __res = _M_compare(__p, __q);
00178       if (__res)
00179         return __res;
00180 
00181       __p += char_traits<_CharT>::length(__p);
00182       __q += char_traits<_CharT>::length(__q);
00183       if (__p == __pend && __q == __qend)
00184         return 0;
00185       else if (__p == __pend)
00186         return -1;
00187       else if (__q == __qend)
00188         return 1;
00189 
00190       __p++;
00191       __q++;
00192     }
00193     }
00194 
00195   template<typename _CharT>
00196     typename collate<_CharT>::string_type
00197     collate<_CharT>::
00198     do_transform(const _CharT* __lo, const _CharT* __hi) const
00199     {
00200       string_type __ret;
00201 
00202       // strxfrm assumes zero-terminated strings so we make a copy
00203       const string_type __str(__lo, __hi);
00204 
00205       const _CharT* __p = __str.c_str();
00206       const _CharT* __pend = __str.data() + __str.length();
00207 
00208       size_t __len = (__hi - __lo) * 2;
00209 
00210       _CharT* __c = new _CharT[__len];
00211 
00212       __try
00213     {
00214       // strxfrm stops when it sees a nul character so we break
00215       // the string into zero-terminated substrings and pass those
00216       // to strxfrm.
00217       for (;;)
00218         {
00219           // First try a buffer perhaps big enough.
00220           size_t __res = _M_transform(__c, __p, __len);
00221           // If the buffer was not large enough, try again with the
00222           // correct size.
00223           if (__res >= __len)
00224         {
00225           __len = __res + 1;
00226           delete [] __c, __c = 0;
00227           __c = new _CharT[__len];
00228           __res = _M_transform(__c, __p, __len);
00229         }
00230 
00231           __ret.append(__c, __res);
00232           __p += char_traits<_CharT>::length(__p);
00233           if (__p == __pend)
00234         break;
00235 
00236           __p++;
00237           __ret.push_back(_CharT());
00238         }
00239     }
00240       __catch(...)
00241     {
00242       delete [] __c;
00243       __throw_exception_again;
00244     }
00245 
00246       delete [] __c;
00247 
00248       return __ret;
00249     }
00250 
00251   template<typename _CharT>
00252     long
00253     collate<_CharT>::
00254     do_hash(const _CharT* __lo, const _CharT* __hi) const
00255     {
00256       unsigned long __val = 0;
00257       for (; __lo < __hi; ++__lo)
00258     __val =
00259       *__lo + ((__val << 7)
00260            | (__val >> (__gnu_cxx::__numeric_traits<unsigned long>::
00261                 __digits - 7)));
00262       return static_cast<long>(__val);
00263     }
00264 
00265   // Inhibit implicit instantiations for required instantiations,
00266   // which are defined via explicit instantiations elsewhere.
00267 #if _GLIBCXX_EXTERN_TEMPLATE
00268   extern template class collate<char>;
00269   extern template class collate_byname<char>;
00270 
00271   extern template
00272     const collate<char>&
00273     use_facet<collate<char> >(const locale&);
00274 
00275   extern template
00276     bool
00277     has_facet<collate<char> >(const locale&);
00278 
00279 #ifdef _GLIBCXX_USE_WCHAR_T
00280   extern template class collate<wchar_t>;
00281   extern template class collate_byname<wchar_t>;
00282 
00283   extern template
00284     const collate<wchar_t>&
00285     use_facet<collate<wchar_t> >(const locale&);
00286 
00287   extern template
00288     bool
00289     has_facet<collate<wchar_t> >(const locale&);
00290 #endif
00291 #endif
00292 
00293 _GLIBCXX_END_NAMESPACE_VERSION
00294 } // namespace std
00295 
00296 #endif