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