1// Locale support -*- C++ -*- 
2 
3// Copyright (C) 2007-2019 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 * @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 
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& 
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 
149 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 
155 collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const throw () 
156 { return 0; } 
157 
158 template<typename _CharT> 
159 int 
160 collate<_CharT>:: 
161 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>:: 
200 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>:: 
256 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