libstdc++
|
00001 // Locale support -*- C++ -*- 00002 00003 // Copyright (C) 2007-2013 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 #ifdef __GXX_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 #ifdef __GXX_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