1 // Locale support -*- C++ -*- 2 3 // Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 /** @file locale_classes.tcc 26 * This is an internal header file, included by other library headers. 27 * You should not attempt to use it directly. 28 */ 29 30 // 31 // ISO C++ 14882: 22.1 Locales 32 // 33 34 #ifndef _LOCALE_CLASSES_TCC 35 #define _LOCALE_CLASSES_TCC 1 36 37 #pragma GCC system_header 38 39 _GLIBCXX_BEGIN_NAMESPACE(std) 40 41 template<typename _Facet> 42 locale:: 43 locale(const locale& __other, _Facet* __f) 44 { 45 _M_impl = new _Impl(*__other._M_impl, 1); 46 47 __try 48 { _M_impl->_M_install_facet(&_Facet::id, __f); } 49 __catch(...) 50 { 51 _M_impl->_M_remove_reference(); 52 __throw_exception_again; 53 } 54 delete [] _M_impl->_M_names[0]; 55 _M_impl->_M_names[0] = 0; // Unnamed. 56 } 57 58 template<typename _Facet> 59 locale 60 locale:: 61 combine(const locale& __other) const 62 { 63 _Impl* __tmp = new _Impl(*_M_impl, 1); 64 __try 65 { 66 __tmp->_M_replace_facet(__other._M_impl, &_Facet::id); 67 } 68 __catch(...) 69 { 70 __tmp->_M_remove_reference(); 71 __throw_exception_again; 72 } 73 return locale(__tmp); 74 } 75 76 template<typename _CharT, typename _Traits, typename _Alloc> 77 bool 78 locale:: 79 operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1, 80 const basic_string<_CharT, _Traits, _Alloc>& __s2) const 81 { 82 typedef std::collate<_CharT> __collate_type; 83 const __collate_type& __collate = use_facet<__collate_type>(*this); 84 return (__collate.compare(__s1.data(), __s1.data() + __s1.length(), 85 __s2.data(), __s2.data() + __s2.length()) < 0); 86 } 87 88 89 template<typename _Facet> 90 bool 91 has_facet(const locale& __loc) throw() 92 { 93 const size_t __i = _Facet::id._M_id(); 94 const locale::facet** __facets = __loc._M_impl->_M_facets; 95 return (__i < __loc._M_impl->_M_facets_size 96 #ifdef __GXX_RTTI 97 && dynamic_cast<const _Facet*>(__facets[__i])); 98 #else 99 && static_cast<const _Facet*>(__facets[__i])); 100 #endif 101 } 102 103 template<typename _Facet> 104 const _Facet& 105 use_facet(const locale& __loc) 106 { 107 const size_t __i = _Facet::id._M_id(); 108 const locale::facet** __facets = __loc._M_impl->_M_facets; 109 if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i]) 110 __throw_bad_cast(); 111 #ifdef __GXX_RTTI 112 return dynamic_cast<const _Facet&>(*__facets[__i]); 113 #else 114 return static_cast<const _Facet&>(*__facets[__i]); 115 #endif 116 } 117 118 119 // Generic version does nothing. 120 template<typename _CharT> 121 int 122 collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const 123 { return 0; } 124 125 // Generic version does nothing. 126 template<typename _CharT> 127 size_t 128 collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const 129 { return 0; } 130 131 template<typename _CharT> 132 int 133 collate<_CharT>:: 134 do_compare(const _CharT* __lo1, const _CharT* __hi1, 135 const _CharT* __lo2, const _CharT* __hi2) const 136 { 137 // strcoll assumes zero-terminated strings so we make a copy 138 // and then put a zero at the end. 139 const string_type __one(__lo1, __hi1); 140 const string_type __two(__lo2, __hi2); 141 142 const _CharT* __p = __one.c_str(); 143 const _CharT* __pend = __one.data() + __one.length(); 144 const _CharT* __q = __two.c_str(); 145 const _CharT* __qend = __two.data() + __two.length(); 146 147 // strcoll stops when it sees a nul character so we break 148 // the strings into zero-terminated substrings and pass those 149 // to strcoll. 150 for (;;) 151 { 152 const int __res = _M_compare(__p, __q); 153 if (__res) 154 return __res; 155 156 __p += char_traits<_CharT>::length(__p); 157 __q += char_traits<_CharT>::length(__q); 158 if (__p == __pend && __q == __qend) 159 return 0; 160 else if (__p == __pend) 161 return -1; 162 else if (__q == __qend) 163 return 1; 164 165 __p++; 166 __q++; 167 } 168 } 169 170 template<typename _CharT> 171 typename collate<_CharT>::string_type 172 collate<_CharT>:: 173 do_transform(const _CharT* __lo, const _CharT* __hi) const 174 { 175 string_type __ret; 176 177 // strxfrm assumes zero-terminated strings so we make a copy 178 const string_type __str(__lo, __hi); 179 180 const _CharT* __p = __str.c_str(); 181 const _CharT* __pend = __str.data() + __str.length(); 182 183 size_t __len = (__hi - __lo) * 2; 184 185 _CharT* __c = new _CharT[__len]; 186 187 __try 188 { 189 // strxfrm stops when it sees a nul character so we break 190 // the string into zero-terminated substrings and pass those 191 // to strxfrm. 192 for (;;) 193 { 194 // First try a buffer perhaps big enough. 195 size_t __res = _M_transform(__c, __p, __len); 196 // If the buffer was not large enough, try again with the 197 // correct size. 198 if (__res >= __len) 199 { 200 __len = __res + 1; 201 delete [] __c, __c = 0; 202 __c = new _CharT[__len]; 203 __res = _M_transform(__c, __p, __len); 204 } 205 206 __ret.append(__c, __res); 207 __p += char_traits<_CharT>::length(__p); 208 if (__p == __pend) 209 break; 210 211 __p++; 212 __ret.push_back(_CharT()); 213 } 214 } 215 __catch(...) 216 { 217 delete [] __c; 218 __throw_exception_again; 219 } 220 221 delete [] __c; 222 223 return __ret; 224 } 225 226 template<typename _CharT> 227 long 228 collate<_CharT>:: 229 do_hash(const _CharT* __lo, const _CharT* __hi) const 230 { 231 unsigned long __val = 0; 232 for (; __lo < __hi; ++__lo) 233 __val = 234 *__lo + ((__val << 7) 235 | (__val >> (__gnu_cxx::__numeric_traits<unsigned long>:: 236 __digits - 7))); 237 return static_cast<long>(__val); 238 } 239 240 // Inhibit implicit instantiations for required instantiations, 241 // which are defined via explicit instantiations elsewhere. 242 // NB: This syntax is a GNU extension. 243 #if _GLIBCXX_EXTERN_TEMPLATE 244 extern template class collate<char>; 245 extern template class collate_byname<char>; 246 247 extern template 248 const collate<char>& 249 use_facet<collate<char> >(const locale&); 250 251 extern template 252 bool 253 has_facet<collate<char> >(const locale&); 254 255 #ifdef _GLIBCXX_USE_WCHAR_T 256 extern template class collate<wchar_t>; 257 extern template class collate_byname<wchar_t>; 258 259 extern template 260 const collate<wchar_t>& 261 use_facet<collate<wchar_t> >(const locale&); 262 263 extern template 264 bool 265 has_facet<collate<wchar_t> >(const locale&); 266 #endif 267 #endif 268 269 _GLIBCXX_END_NAMESPACE 270 271 #endif 272