libstdc++
|
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