]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/bits/locale_classes.tcc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / include / bits / locale_classes.tcc
CommitLineData
84b31797
PC
1// Locale support -*- C++ -*-
2
83ffe9cd 3// Copyright (C) 2007-2023 Free Software Foundation, Inc.
84b31797
PC
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
748086b7 8// Free Software Foundation; either version 3, or (at your option)
84b31797
PC
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
748086b7
JJ
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.
84b31797 19
748086b7
JJ
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/>.
84b31797 24
f910786b 25/** @file bits/locale_classes.tcc
84b31797 26 * This is an internal header file, included by other library headers.
f910786b 27 * Do not attempt to use it directly. @headername{locale}
84b31797
PC
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
12ffa228
BK
39namespace std _GLIBCXX_VISIBILITY(default)
40{
41_GLIBCXX_BEGIN_NAMESPACE_VERSION
84b31797
PC
42
43 template<typename _Facet>
32f1271c
PC
44 locale::
45 locale(const locale& __other, _Facet* __f)
84b31797
PC
46 {
47 _M_impl = new _Impl(*__other._M_impl, 1);
48
bc2631e0 49 __try
84b31797 50 { _M_impl->_M_install_facet(&_Facet::id, __f); }
bc2631e0 51 __catch(...)
84b31797
PC
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
32f1271c
PC
62 locale::
63 combine(const locale& __other) const
84b31797
PC
64 {
65 _Impl* __tmp = new _Impl(*_M_impl, 1);
bc2631e0 66 __try
84b31797
PC
67 {
68 __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
69 }
bc2631e0 70 __catch(...)
84b31797
PC
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
32f1271c
PC
80 locale::
81 operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
82 const basic_string<_CharT, _Traits, _Alloc>& __s2) const
84b31797
PC
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
b3ac43a3
JW
90 template<typename _Facet>
91 inline const _Facet*
92 __try_use_facet(const locale& __loc) _GLIBCXX_NOTHROW
93 {
94 const size_t __i = _Facet::id._M_id();
95 const locale::facet** __facets = __loc._M_impl->_M_facets;
96
97 // We know these standard facets are always installed in every locale
98 // so dynamic_cast always succeeds, just use static_cast instead.
99#define _GLIBCXX_STD_FACET(...) \
100 if _GLIBCXX17_CONSTEXPR (__is_same(_Facet, __VA_ARGS__)) \
101 return static_cast<const _Facet*>(__facets[__i])
102
103 _GLIBCXX_STD_FACET(ctype<char>);
104 _GLIBCXX_STD_FACET(num_get<char>);
105 _GLIBCXX_STD_FACET(num_put<char>);
106 _GLIBCXX_STD_FACET(codecvt<char, char, mbstate_t>);
107 _GLIBCXX_STD_FACET(collate<char>);
108 _GLIBCXX_STD_FACET(moneypunct<char>);
109 _GLIBCXX_STD_FACET(moneypunct<char, true>);
110 _GLIBCXX_STD_FACET(money_get<char>);
111 _GLIBCXX_STD_FACET(money_put<char>);
112 _GLIBCXX_STD_FACET(numpunct<char>);
113 _GLIBCXX_STD_FACET(time_get<char>);
114 _GLIBCXX_STD_FACET(time_put<char>);
115 _GLIBCXX_STD_FACET(messages<char>);
116
117#ifdef _GLIBCXX_USE_WCHAR_T
118 _GLIBCXX_STD_FACET(ctype<wchar_t>);
119 _GLIBCXX_STD_FACET(num_get<wchar_t>);
120 _GLIBCXX_STD_FACET(num_put<wchar_t>);
121 _GLIBCXX_STD_FACET(codecvt<wchar_t, char, mbstate_t>);
122 _GLIBCXX_STD_FACET(collate<wchar_t>);
123 _GLIBCXX_STD_FACET(moneypunct<wchar_t>);
124 _GLIBCXX_STD_FACET(moneypunct<wchar_t, true>);
125 _GLIBCXX_STD_FACET(money_get<wchar_t>);
126 _GLIBCXX_STD_FACET(money_put<wchar_t>);
127 _GLIBCXX_STD_FACET(numpunct<wchar_t>);
128 _GLIBCXX_STD_FACET(time_get<wchar_t>);
129 _GLIBCXX_STD_FACET(time_put<wchar_t>);
130 _GLIBCXX_STD_FACET(messages<wchar_t>);
131#endif
132#ifdef _GLIBCXX_USE_CHAR8_T
133 _GLIBCXX_STD_FACET(codecvt<char8_t, char, mbstate_t>);
134#endif
135#if __cplusplus >= 201103L
136 _GLIBCXX_STD_FACET(codecvt<char16_t, char, mbstate_t>);
137 _GLIBCXX_STD_FACET(codecvt<char32_t, char, mbstate_t>);
138#endif
139
140#undef _GLIBCXX_STD_FACET
141
142 if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i])
143 return 0;
144
145#if __cpp_rtti
146 return dynamic_cast<const _Facet*>(__facets[__i]);
147#else
148 return static_cast<const _Facet*>(__facets[__i]);
149#endif
150 }
151
7897a1c0
BK
152 /**
153 * @brief Test for the presence of a facet.
e07b233d 154 * @ingroup locales
7897a1c0
BK
155 *
156 * has_facet tests the locale argument for the presence of the facet type
157 * provided as the template parameter. Facets derived from the facet
158 * parameter will also return true.
159 *
160 * @tparam _Facet The facet type to test the presence of.
161 * @param __loc The locale to test.
162 * @return true if @p __loc contains a facet of type _Facet, else false.
163 */
32f1271c 164 template<typename _Facet>
b3ac43a3 165 inline bool
32f1271c
PC
166 has_facet(const locale& __loc) throw()
167 {
b3ac43a3
JW
168#if __cplusplus >= 201103L
169 static_assert(__is_base_of(locale::facet, _Facet),
170 "template argument must be derived from locale::facet");
32f1271c 171#else
b3ac43a3 172 (void) static_cast<const _Facet*>(static_cast<const locale::facet*>(0));
32f1271c 173#endif
b3ac43a3 174 return std::__try_use_facet<_Facet>(__loc) != 0;
32f1271c
PC
175 }
176
7897a1c0
BK
177 /**
178 * @brief Return a facet.
e07b233d 179 * @ingroup locales
7897a1c0
BK
180 *
181 * use_facet looks for and returns a reference to a facet of type Facet
182 * where Facet is the template parameter. If has_facet(locale) is true,
183 * there is a suitable facet to return. It throws std::bad_cast if the
184 * locale doesn't contain a facet of type Facet.
185 *
186 * @tparam _Facet The facet type to access.
187 * @param __loc The locale to use.
188 * @return Reference to facet of type Facet.
189 * @throw std::bad_cast if @p __loc doesn't contain a facet of type _Facet.
190 */
d2249cd9
MP
191#pragma GCC diagnostic push
192#pragma GCC diagnostic ignored "-Wdangling-reference"
32f1271c 193 template<typename _Facet>
b3ac43a3 194 inline const _Facet&
32f1271c
PC
195 use_facet(const locale& __loc)
196 {
b3ac43a3
JW
197#if __cplusplus >= 201103L
198 static_assert(__is_base_of(locale::facet, _Facet),
199 "template argument must be derived from locale::facet");
32f1271c 200#else
b3ac43a3 201 (void) static_cast<const _Facet*>(static_cast<const locale::facet*>(0));
32f1271c 202#endif
b3ac43a3
JW
203 if (const _Facet* __f = std::__try_use_facet<_Facet>(__loc))
204 return *__f;
205 __throw_bad_cast();
32f1271c 206 }
d2249cd9 207#pragma GCC diagnostic pop
32f1271c
PC
208
209
84b31797
PC
210 // Generic version does nothing.
211 template<typename _CharT>
212 int
50a681c4 213 collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const throw ()
84b31797
PC
214 { return 0; }
215
216 // Generic version does nothing.
217 template<typename _CharT>
218 size_t
50a681c4 219 collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const throw ()
84b31797
PC
220 { return 0; }
221
222 template<typename _CharT>
223 int
224 collate<_CharT>::
225 do_compare(const _CharT* __lo1, const _CharT* __hi1,
226 const _CharT* __lo2, const _CharT* __hi2) const
227 {
228 // strcoll assumes zero-terminated strings so we make a copy
229 // and then put a zero at the end.
230 const string_type __one(__lo1, __hi1);
231 const string_type __two(__lo2, __hi2);
232
233 const _CharT* __p = __one.c_str();
234 const _CharT* __pend = __one.data() + __one.length();
235 const _CharT* __q = __two.c_str();
236 const _CharT* __qend = __two.data() + __two.length();
237
238 // strcoll stops when it sees a nul character so we break
239 // the strings into zero-terminated substrings and pass those
240 // to strcoll.
241 for (;;)
242 {
243 const int __res = _M_compare(__p, __q);
244 if (__res)
245 return __res;
246
247 __p += char_traits<_CharT>::length(__p);
248 __q += char_traits<_CharT>::length(__q);
249 if (__p == __pend && __q == __qend)
250 return 0;
251 else if (__p == __pend)
252 return -1;
253 else if (__q == __qend)
254 return 1;
255
256 __p++;
257 __q++;
258 }
259 }
260
261 template<typename _CharT>
262 typename collate<_CharT>::string_type
263 collate<_CharT>::
264 do_transform(const _CharT* __lo, const _CharT* __hi) const
265 {
266 string_type __ret;
267
268 // strxfrm assumes zero-terminated strings so we make a copy
269 const string_type __str(__lo, __hi);
270
271 const _CharT* __p = __str.c_str();
272 const _CharT* __pend = __str.data() + __str.length();
273
274 size_t __len = (__hi - __lo) * 2;
275
276 _CharT* __c = new _CharT[__len];
277
bc2631e0 278 __try
84b31797
PC
279 {
280 // strxfrm stops when it sees a nul character so we break
281 // the string into zero-terminated substrings and pass those
282 // to strxfrm.
283 for (;;)
284 {
285 // First try a buffer perhaps big enough.
286 size_t __res = _M_transform(__c, __p, __len);
287 // If the buffer was not large enough, try again with the
288 // correct size.
289 if (__res >= __len)
290 {
291 __len = __res + 1;
292 delete [] __c, __c = 0;
293 __c = new _CharT[__len];
294 __res = _M_transform(__c, __p, __len);
295 }
296
297 __ret.append(__c, __res);
298 __p += char_traits<_CharT>::length(__p);
299 if (__p == __pend)
300 break;
301
302 __p++;
303 __ret.push_back(_CharT());
304 }
305 }
bc2631e0 306 __catch(...)
84b31797
PC
307 {
308 delete [] __c;
309 __throw_exception_again;
310 }
311
312 delete [] __c;
313
314 return __ret;
315 }
316
317 template<typename _CharT>
318 long
319 collate<_CharT>::
320 do_hash(const _CharT* __lo, const _CharT* __hi) const
321 {
322 unsigned long __val = 0;
323 for (; __lo < __hi; ++__lo)
324 __val =
325 *__lo + ((__val << 7)
326 | (__val >> (__gnu_cxx::__numeric_traits<unsigned long>::
327 __digits - 7)));
328 return static_cast<long>(__val);
329 }
330
331 // Inhibit implicit instantiations for required instantiations,
332 // which are defined via explicit instantiations elsewhere.
84b31797
PC
333#if _GLIBCXX_EXTERN_TEMPLATE
334 extern template class collate<char>;
335 extern template class collate_byname<char>;
336
b3ac43a3
JW
337 extern template
338 const collate<char>*
339 __try_use_facet<collate<char> >(const locale&) _GLIBCXX_NOTHROW;
340
84b31797
PC
341 extern template
342 const collate<char>&
343 use_facet<collate<char> >(const locale&);
344
345 extern template
346 bool
347 has_facet<collate<char> >(const locale&);
348
349#ifdef _GLIBCXX_USE_WCHAR_T
350 extern template class collate<wchar_t>;
351 extern template class collate_byname<wchar_t>;
352
b3ac43a3
JW
353 extern template
354 const collate<wchar_t>*
355 __try_use_facet<collate<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
356
84b31797
PC
357 extern template
358 const collate<wchar_t>&
359 use_facet<collate<wchar_t> >(const locale&);
360
361 extern template
362 bool
363 has_facet<collate<wchar_t> >(const locale&);
364#endif
365#endif
366
12ffa228 367_GLIBCXX_END_NAMESPACE_VERSION
ed4f96af 368} // namespace std
84b31797
PC
369
370#endif