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