1 // Locale support -*- C++ -*- 2 3 // Copyright (C) 2007-2022 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 bits/locale_classes.tcc 26 * This is an internal header file, included by other library headers. 27 * Do not attempt to use it directly. @headername{locale} 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 namespace std _GLIBCXX_VISIBILITY(default) 40 { 41 _GLIBCXX_BEGIN_NAMESPACE_VERSION 42 43 template<typename _Facet> 44 locale:: locale(const locale & __other,_Facet * __f)45 locale(const locale& __other, _Facet* __f) 46 { 47 _M_impl = new _Impl(*__other._M_impl, 1); 48 49 __try 50 { _M_impl->_M_install_facet(&_Facet::id, __f); } 51 __catch(...) 52 { 53 _M_impl->_M_remove_reference(); 54 __throw_exception_again; 55 } 56 delete [] _M_impl->_M_names[0]; 57 _M_impl->_M_names[0] = 0; // Unnamed. 58 } 59 60 template<typename _Facet> 61 locale 62 locale:: combine(const locale & __other) const63 combine(const locale& __other) const 64 { 65 _Impl* __tmp = new _Impl(*_M_impl, 1); 66 __try 67 { 68 __tmp->_M_replace_facet(__other._M_impl, &_Facet::id); 69 } 70 __catch(...) 71 { 72 __tmp->_M_remove_reference(); 73 __throw_exception_again; 74 } 75 return locale(__tmp); 76 } 77 78 template<typename _CharT, typename _Traits, typename _Alloc> 79 bool 80 locale:: operator ()(const basic_string<_CharT,_Traits,_Alloc> & __s1,const basic_string<_CharT,_Traits,_Alloc> & __s2) const81 operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1, 82 const basic_string<_CharT, _Traits, _Alloc>& __s2) const 83 { 84 typedef std::collate<_CharT> __collate_type; 85 const __collate_type& __collate = use_facet<__collate_type>(*this); 86 return (__collate.compare(__s1.data(), __s1.data() + __s1.length(), 87 __s2.data(), __s2.data() + __s2.length()) < 0); 88 } 89 90 /** 91 * @brief Test for the presence of a facet. 92 * @ingroup locales 93 * 94 * has_facet tests the locale argument for the presence of the facet type 95 * provided as the template parameter. Facets derived from the facet 96 * parameter will also return true. 97 * 98 * @tparam _Facet The facet type to test the presence of. 99 * @param __loc The locale to test. 100 * @return true if @p __loc contains a facet of type _Facet, else false. 101 */ 102 template<typename _Facet> 103 bool has_facet(const locale & __loc)104 has_facet(const locale& __loc) throw() 105 { 106 if _GLIBCXX17_CONSTEXPR (__is_same(_Facet, ctype<char>) 107 || __is_same(_Facet, num_get<char>) 108 || __is_same(_Facet, num_put<char>)) 109 return true; 110 #ifdef _GLIBCXX_USE_WCHAR_T 111 else if _GLIBCXX17_CONSTEXPR (__is_same(_Facet, ctype<wchar_t>) 112 || __is_same(_Facet, num_get<wchar_t>) 113 || __is_same(_Facet, num_put<wchar_t>)) 114 return true; 115 #endif 116 117 const size_t __i = _Facet::id._M_id(); 118 const locale::facet** __facets = __loc._M_impl->_M_facets; 119 return (__i < __loc._M_impl->_M_facets_size 120 #if __cpp_rtti 121 && dynamic_cast<const _Facet*>(__facets[__i])); 122 #else 123 && static_cast<const _Facet*>(__facets[__i])); 124 #endif 125 } 126 127 /** 128 * @brief Return a facet. 129 * @ingroup locales 130 * 131 * use_facet looks for and returns a reference to a facet of type Facet 132 * where Facet is the template parameter. If has_facet(locale) is true, 133 * there is a suitable facet to return. It throws std::bad_cast if the 134 * locale doesn't contain a facet of type Facet. 135 * 136 * @tparam _Facet The facet type to access. 137 * @param __loc The locale to use. 138 * @return Reference to facet of type Facet. 139 * @throw std::bad_cast if @p __loc doesn't contain a facet of type _Facet. 140 */ 141 template<typename _Facet> 142 const _Facet& use_facet(const locale & __loc)143 use_facet(const locale& __loc) 144 { 145 const size_t __i = _Facet::id._M_id(); 146 const locale::facet** __facets = __loc._M_impl->_M_facets; 147 148 if _GLIBCXX17_CONSTEXPR (__is_same(_Facet, ctype<char>) 149 || __is_same(_Facet, num_get<char>) 150 || __is_same(_Facet, num_put<char>)) 151 return static_cast<const _Facet&>(*__facets[__i]); 152 #ifdef _GLIBCXX_USE_WCHAR_T 153 else if _GLIBCXX17_CONSTEXPR (__is_same(_Facet, ctype<wchar_t>) 154 || __is_same(_Facet, num_get<wchar_t>) 155 || __is_same(_Facet, num_put<wchar_t>)) 156 return static_cast<const _Facet&>(*__facets[__i]); 157 #endif 158 159 if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i]) 160 __throw_bad_cast(); 161 #if __cpp_rtti 162 return dynamic_cast<const _Facet&>(*__facets[__i]); 163 #else 164 return static_cast<const _Facet&>(*__facets[__i]); 165 #endif 166 } 167 168 169 // Generic version does nothing. 170 template<typename _CharT> 171 int _M_compare(const _CharT *,const _CharT *) const172 collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const throw () 173 { return 0; } 174 175 // Generic version does nothing. 176 template<typename _CharT> 177 size_t _M_transform(_CharT *,const _CharT *,size_t) const178 collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const throw () 179 { return 0; } 180 181 template<typename _CharT> 182 int 183 collate<_CharT>:: do_compare(const _CharT * __lo1,const _CharT * __hi1,const _CharT * __lo2,const _CharT * __hi2) const184 do_compare(const _CharT* __lo1, const _CharT* __hi1, 185 const _CharT* __lo2, const _CharT* __hi2) const 186 { 187 // strcoll assumes zero-terminated strings so we make a copy 188 // and then put a zero at the end. 189 const string_type __one(__lo1, __hi1); 190 const string_type __two(__lo2, __hi2); 191 192 const _CharT* __p = __one.c_str(); 193 const _CharT* __pend = __one.data() + __one.length(); 194 const _CharT* __q = __two.c_str(); 195 const _CharT* __qend = __two.data() + __two.length(); 196 197 // strcoll stops when it sees a nul character so we break 198 // the strings into zero-terminated substrings and pass those 199 // to strcoll. 200 for (;;) 201 { 202 const int __res = _M_compare(__p, __q); 203 if (__res) 204 return __res; 205 206 __p += char_traits<_CharT>::length(__p); 207 __q += char_traits<_CharT>::length(__q); 208 if (__p == __pend && __q == __qend) 209 return 0; 210 else if (__p == __pend) 211 return -1; 212 else if (__q == __qend) 213 return 1; 214 215 __p++; 216 __q++; 217 } 218 } 219 220 template<typename _CharT> 221 typename collate<_CharT>::string_type 222 collate<_CharT>:: do_transform(const _CharT * __lo,const _CharT * __hi) const223 do_transform(const _CharT* __lo, const _CharT* __hi) const 224 { 225 string_type __ret; 226 227 // strxfrm assumes zero-terminated strings so we make a copy 228 const string_type __str(__lo, __hi); 229 230 const _CharT* __p = __str.c_str(); 231 const _CharT* __pend = __str.data() + __str.length(); 232 233 size_t __len = (__hi - __lo) * 2; 234 235 _CharT* __c = new _CharT[__len]; 236 237 __try 238 { 239 // strxfrm stops when it sees a nul character so we break 240 // the string into zero-terminated substrings and pass those 241 // to strxfrm. 242 for (;;) 243 { 244 // First try a buffer perhaps big enough. 245 size_t __res = _M_transform(__c, __p, __len); 246 // If the buffer was not large enough, try again with the 247 // correct size. 248 if (__res >= __len) 249 { 250 __len = __res + 1; 251 delete [] __c, __c = 0; 252 __c = new _CharT[__len]; 253 __res = _M_transform(__c, __p, __len); 254 } 255 256 __ret.append(__c, __res); 257 __p += char_traits<_CharT>::length(__p); 258 if (__p == __pend) 259 break; 260 261 __p++; 262 __ret.push_back(_CharT()); 263 } 264 } 265 __catch(...) 266 { 267 delete [] __c; 268 __throw_exception_again; 269 } 270 271 delete [] __c; 272 273 return __ret; 274 } 275 276 template<typename _CharT> 277 long 278 collate<_CharT>:: do_hash(const _CharT * __lo,const _CharT * __hi) const279 do_hash(const _CharT* __lo, const _CharT* __hi) const 280 { 281 unsigned long __val = 0; 282 for (; __lo < __hi; ++__lo) 283 __val = 284 *__lo + ((__val << 7) 285 | (__val >> (__gnu_cxx::__numeric_traits<unsigned long>:: 286 __digits - 7))); 287 return static_cast<long>(__val); 288 } 289 290 // Inhibit implicit instantiations for required instantiations, 291 // which are defined via explicit instantiations elsewhere. 292 #if _GLIBCXX_EXTERN_TEMPLATE 293 extern template class collate<char>; 294 extern template class collate_byname<char>; 295 296 extern template 297 const collate<char>& 298 use_facet<collate<char> >(const locale&); 299 300 extern template 301 bool 302 has_facet<collate<char> >(const locale&); 303 304 #ifdef _GLIBCXX_USE_WCHAR_T 305 extern template class collate<wchar_t>; 306 extern template class collate_byname<wchar_t>; 307 308 extern template 309 const collate<wchar_t>& 310 use_facet<collate<wchar_t> >(const locale&); 311 312 extern template 313 bool 314 has_facet<collate<wchar_t> >(const locale&); 315 #endif 316 #endif 317 318 _GLIBCXX_END_NAMESPACE_VERSION 319 } // namespace std 320 321 #endif 322