1 // Locale support -*- C++ -*- 2 3 // Copyright (C) 2007-2020 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 const size_t __i = _Facet::id._M_id(); 107 const locale::facet** __facets = __loc._M_impl->_M_facets; 108 return (__i < __loc._M_impl->_M_facets_size 109 #if __cpp_rtti 110 && dynamic_cast<const _Facet*>(__facets[__i])); 111 #else 112 && static_cast<const _Facet*>(__facets[__i])); 113 #endif 114 } 115 116 /** 117 * @brief Return a facet. 118 * @ingroup locales 119 * 120 * use_facet looks for and returns a reference to a facet of type Facet 121 * where Facet is the template parameter. If has_facet(locale) is true, 122 * there is a suitable facet to return. It throws std::bad_cast if the 123 * locale doesn't contain a facet of type Facet. 124 * 125 * @tparam _Facet The facet type to access. 126 * @param __loc The locale to use. 127 * @return Reference to facet of type Facet. 128 * @throw std::bad_cast if @p __loc doesn't contain a facet of type _Facet. 129 */ 130 template<typename _Facet> 131 const _Facet& use_facet(const locale & __loc)132 use_facet(const locale& __loc) 133 { 134 const size_t __i = _Facet::id._M_id(); 135 const locale::facet** __facets = __loc._M_impl->_M_facets; 136 if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i]) 137 __throw_bad_cast(); 138 #if __cpp_rtti 139 return dynamic_cast<const _Facet&>(*__facets[__i]); 140 #else 141 return static_cast<const _Facet&>(*__facets[__i]); 142 #endif 143 } 144 145 146 // Generic version does nothing. 147 template<typename _CharT> 148 int _M_compare(const _CharT *,const _CharT *) const149 collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const throw () 150 { return 0; } 151 152 // Generic version does nothing. 153 template<typename _CharT> 154 size_t _M_transform(_CharT *,const _CharT *,size_t) const155 collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const throw () 156 { return 0; } 157 158 template<typename _CharT> 159 int 160 collate<_CharT>:: do_compare(const _CharT * __lo1,const _CharT * __hi1,const _CharT * __lo2,const _CharT * __hi2) const161 do_compare(const _CharT* __lo1, const _CharT* __hi1, 162 const _CharT* __lo2, const _CharT* __hi2) const 163 { 164 // strcoll assumes zero-terminated strings so we make a copy 165 // and then put a zero at the end. 166 const string_type __one(__lo1, __hi1); 167 const string_type __two(__lo2, __hi2); 168 169 const _CharT* __p = __one.c_str(); 170 const _CharT* __pend = __one.data() + __one.length(); 171 const _CharT* __q = __two.c_str(); 172 const _CharT* __qend = __two.data() + __two.length(); 173 174 // strcoll stops when it sees a nul character so we break 175 // the strings into zero-terminated substrings and pass those 176 // to strcoll. 177 for (;;) 178 { 179 const int __res = _M_compare(__p, __q); 180 if (__res) 181 return __res; 182 183 __p += char_traits<_CharT>::length(__p); 184 __q += char_traits<_CharT>::length(__q); 185 if (__p == __pend && __q == __qend) 186 return 0; 187 else if (__p == __pend) 188 return -1; 189 else if (__q == __qend) 190 return 1; 191 192 __p++; 193 __q++; 194 } 195 } 196 197 template<typename _CharT> 198 typename collate<_CharT>::string_type 199 collate<_CharT>:: do_transform(const _CharT * __lo,const _CharT * __hi) const200 do_transform(const _CharT* __lo, const _CharT* __hi) const 201 { 202 string_type __ret; 203 204 // strxfrm assumes zero-terminated strings so we make a copy 205 const string_type __str(__lo, __hi); 206 207 const _CharT* __p = __str.c_str(); 208 const _CharT* __pend = __str.data() + __str.length(); 209 210 size_t __len = (__hi - __lo) * 2; 211 212 _CharT* __c = new _CharT[__len]; 213 214 __try 215 { 216 // strxfrm stops when it sees a nul character so we break 217 // the string into zero-terminated substrings and pass those 218 // to strxfrm. 219 for (;;) 220 { 221 // First try a buffer perhaps big enough. 222 size_t __res = _M_transform(__c, __p, __len); 223 // If the buffer was not large enough, try again with the 224 // correct size. 225 if (__res >= __len) 226 { 227 __len = __res + 1; 228 delete [] __c, __c = 0; 229 __c = new _CharT[__len]; 230 __res = _M_transform(__c, __p, __len); 231 } 232 233 __ret.append(__c, __res); 234 __p += char_traits<_CharT>::length(__p); 235 if (__p == __pend) 236 break; 237 238 __p++; 239 __ret.push_back(_CharT()); 240 } 241 } 242 __catch(...) 243 { 244 delete [] __c; 245 __throw_exception_again; 246 } 247 248 delete [] __c; 249 250 return __ret; 251 } 252 253 template<typename _CharT> 254 long 255 collate<_CharT>:: do_hash(const _CharT * __lo,const _CharT * __hi) const256 do_hash(const _CharT* __lo, const _CharT* __hi) const 257 { 258 unsigned long __val = 0; 259 for (; __lo < __hi; ++__lo) 260 __val = 261 *__lo + ((__val << 7) 262 | (__val >> (__gnu_cxx::__numeric_traits<unsigned long>:: 263 __digits - 7))); 264 return static_cast<long>(__val); 265 } 266 267 // Inhibit implicit instantiations for required instantiations, 268 // which are defined via explicit instantiations elsewhere. 269 #if _GLIBCXX_EXTERN_TEMPLATE 270 extern template class collate<char>; 271 extern template class collate_byname<char>; 272 273 extern template 274 const collate<char>& 275 use_facet<collate<char> >(const locale&); 276 277 extern template 278 bool 279 has_facet<collate<char> >(const locale&); 280 281 #ifdef _GLIBCXX_USE_WCHAR_T 282 extern template class collate<wchar_t>; 283 extern template class collate_byname<wchar_t>; 284 285 extern template 286 const collate<wchar_t>& 287 use_facet<collate<wchar_t> >(const locale&); 288 289 extern template 290 bool 291 has_facet<collate<wchar_t> >(const locale&); 292 #endif 293 #endif 294 295 _GLIBCXX_END_NAMESPACE_VERSION 296 } // namespace std 297 298 #endif 299