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