]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/src/c++11/cxx11-shim_facets.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / src / c++11 / cxx11-shim_facets.cc
CommitLineData
34a2b755
JW
1// Locale support -*- C++ -*-
2
83ffe9cd 3// Copyright (C) 2014-2023 Free Software Foundation, Inc.
34a2b755
JW
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//
26// ISO C++ 14882: 22.1 Locales
27//
28
29// This file defines classes that behave like the standard predefined locale
30// facets (collate, money_get etc.) except that they forward all virtual
31// functions to another facet which uses a different std::string ABI,
32// converting between string types as needed.
33// When a user replaces one of the relevant facets the corresponding shim in
34// this file is used so that the replacement facet can be used (via the shim)
35// in code that uses the other std::string ABI from the replacing code.
36
37#ifndef _GLIBCXX_USE_CXX11_ABI
38# define _GLIBCXX_USE_CXX11_ABI 1
39#endif
40#include <locale>
41
42#if ! _GLIBCXX_USE_DUAL_ABI
43# error This file should not be compiled for this configuration.
44#endif
45
46namespace std _GLIBCXX_VISIBILITY(default)
47{
4a15d842
FD
48_GLIBCXX_BEGIN_NAMESPACE_VERSION
49
34a2b755
JW
50 // Base class of facet shims, holds a reference to the underlying facet
51 // that the shim forwards to.
52 class locale::facet::__shim
53 {
54 public:
55 const facet* _M_get() const { return _M_facet; }
56
57 __shim(const __shim&) = delete;
58 __shim& operator=(const __shim&) = delete;
59
60 protected:
61 explicit
62 __shim(const facet* __f) : _M_facet(__f) { __f->_M_add_reference(); }
63
64 ~__shim() { _M_facet->_M_remove_reference(); }
65
66 private:
67 const facet* _M_facet;
68 };
69
70namespace __facet_shims
71{
34a2b755
JW
72 namespace // unnamed
73 {
74 template<typename C>
75 void __destroy_string(void* p)
76 {
77 static_cast<std::basic_string<C>*>(p)->~basic_string();
78 }
79 } // namespace
80
81 // Manages a buffer of uninitialized memory that can store a std::string
82 // or std::wstring, using either ABI, and convert to the other ABI.
83 class __any_string
84 {
85 struct __attribute__((may_alias)) __str_rep
86 {
87 union {
88 const void* _M_p;
89 char* _M_pc;
1b9ad1d9 90#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755 91 wchar_t* _M_pwc;
1b9ad1d9 92#endif
34a2b755
JW
93 };
94 size_t _M_len;
95 char _M_unused[16];
96
97 operator const char*() const { return _M_pc; }
1b9ad1d9 98#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755 99 operator const wchar_t*() const { return _M_pwc; }
1b9ad1d9 100#endif
34a2b755
JW
101 };
102 union {
103 __str_rep _M_str;
104 char _M_bytes[sizeof(__str_rep)];
105 };
106 using __dtor_func = void(*)(void*);
107 __dtor_func _M_dtor = nullptr;
108
109#if _GLIBCXX_USE_CXX11_ABI
110 // SSO strings overlay the entire __str_rep structure.
111 static_assert(sizeof(std::string) == sizeof(__str_rep),
112 "std::string changed size!");
113#else
114 // COW strings overlay just the pointer, the length is stored manually.
115 static_assert(sizeof(std::string) == sizeof(__str_rep::_M_p),
116 "std::string changed size!");
117#endif
118# ifdef _GLIBCXX_USE_WCHAR_T
119 static_assert(sizeof(std::wstring) == sizeof(std::string),
120 "std::wstring and std::string are different sizes!");
121# endif
122
123 public:
124 __any_string() = default;
125 ~__any_string() { if (_M_dtor) _M_dtor(_M_bytes); }
126
127 __any_string(const __any_string&) = delete;
128 __any_string& operator=(const __any_string&) = delete;
129
130 // Store a string (and its length if needed) in the buffer and
131 // set _M_dtor to the function that runs the right destructor.
132 template<typename C>
133 __any_string&
134 operator=(const basic_string<C>& s)
135 {
136 if (_M_dtor)
137 _M_dtor(_M_bytes);
138 ::new(_M_bytes) basic_string<C>(s);
139#if ! _GLIBCXX_USE_CXX11_ABI
140 _M_str._M_len = s.length();
141#endif
142 _M_dtor = __destroy_string<C>;
143 return *this;
144 }
145
146 // Create a new string with a copy of the characters in the stored string.
147 // The returned object will match the caller's string ABI, even when the
148 // stored string doesn't.
149 template<typename C>
168ad5f5 150 _GLIBCXX_DEFAULT_ABI_TAG
34a2b755
JW
151 operator basic_string<C>() const
152 {
153 if (!_M_dtor)
154 __throw_logic_error("uninitialized __any_string");
155 return basic_string<C>(static_cast<const C*>(_M_str), _M_str._M_len);
156 }
157 };
158
159 // This file is compiled twice, with and without this macro defined.
160 // Define tag types to distinguish between the two cases and to allow
161 // overloading on the tag.
162 using current_abi = __bool_constant<_GLIBCXX_USE_CXX11_ABI>;
163 using other_abi = __bool_constant<!_GLIBCXX_USE_CXX11_ABI>;
164
165 using facet = locale::facet;
166
167 // Declare the functions that shims defined in this file will call to
168 // perform work in the context of the other ABI.
169 // These will be defined when this file is recompiled for the other ABI
170 // (at which point what is now "current_abi" will become "other_abi").
171
172 template<typename C>
173 void
831a3a9e 174 __numpunct_fill_cache(other_abi, const facet*, __numpunct_cache<C>*);
34a2b755
JW
175
176 template<typename C>
177 int
178 __collate_compare(other_abi, const facet*, const C*, const C*,
179 const C*, const C*);
180
181 template<typename C>
182 void
183 __collate_transform(other_abi, const facet*, __any_string&,
184 const C*, const C*);
185
186 template<typename C>
187 time_base::dateorder
188 __time_get_dateorder(other_abi, const facet* f);
189
190 template<typename C>
191 istreambuf_iterator<C>
192 __time_get(other_abi, const facet* f,
193 istreambuf_iterator<C> beg, istreambuf_iterator<C> end,
194 ios_base& io, ios_base::iostate& err, tm* t, char which);
195
196 template<typename C, bool Intl>
197 void
198 __moneypunct_fill_cache(other_abi, const facet*,
199 __moneypunct_cache<C, Intl>*);
200
201 template<typename C>
202 istreambuf_iterator<C>
203 __money_get(other_abi, const facet*,
204 istreambuf_iterator<C>, istreambuf_iterator<C>,
205 bool, ios_base&, ios_base::iostate&,
206 long double*, __any_string*);
207
208 template<typename C>
209 ostreambuf_iterator<C>
210 __money_put(other_abi, const facet*, ostreambuf_iterator<C>, bool,
211 ios_base&, C, long double, const __any_string*);
212
213 template<typename C>
214 messages_base::catalog
215 __messages_open(other_abi, const facet*, const char*, size_t,
216 const locale&);
217
218 template<typename C>
219 void
220 __messages_get(other_abi, const facet*, __any_string&,
221 messages_base::catalog, int, int, const C*, size_t);
222
223 template<typename C>
224 void
225 __messages_close(other_abi, const facet*, messages_base::catalog);
226
f9bd185f
JW
227#pragma GCC diagnostic push
228// Suppress -Wabi=2 warnings due to empty struct argument passing changes.
229// TODO This should use -Wabi=12 but that currently fails (PR c++/87611).
230#pragma GCC diagnostic ignored "-Wabi"
231
34a2b755
JW
232 namespace // unnamed
233 {
b497fbc1
JW
234 struct __shim_accessor : facet
235 {
236 using facet::__shim; // Redeclare protected member as public.
237 };
238 using __shim = __shim_accessor::__shim;
239
34a2b755 240 template<typename _CharT>
b497fbc1 241 struct numpunct_shim : std::numpunct<_CharT>, __shim
34a2b755
JW
242 {
243 typedef typename numpunct<_CharT>::__cache_type __cache_type;
244
245 // f must point to a type derived from numpunct<C>[abi:other]
246 numpunct_shim(const facet* f, __cache_type* c = new __cache_type)
247 : std::numpunct<_CharT>(c), __shim(f), _M_cache(c)
248 {
831a3a9e 249 __numpunct_fill_cache(other_abi{}, f, c);
34a2b755
JW
250 }
251
831a3a9e
JW
252 ~numpunct_shim()
253 {
254 // Stop GNU locale's ~numpunct() from freeing the cached string.
255 _M_cache->_M_grouping_size = 0;
256 }
34a2b755 257
831a3a9e 258 // No need to override any virtual functions, the base definitions
34a2b755
JW
259 // will return the cached data.
260
261 __cache_type* _M_cache;
34a2b755
JW
262 };
263
34a2b755 264 template<typename _CharT>
b497fbc1 265 struct collate_shim : std::collate<_CharT>, __shim
34a2b755
JW
266 {
267 typedef basic_string<_CharT> string_type;
268
269 // f must point to a type derived from collate<C>[abi:other]
270 collate_shim(const facet* f) : __shim(f) { }
271
272 virtual int
273 do_compare(const _CharT* lo1, const _CharT* hi1,
274 const _CharT* lo2, const _CharT* hi2) const
275 {
276 return __collate_compare(other_abi{}, _M_get(),
277 lo1, hi1, lo2, hi2);
278 }
279
280 virtual string_type
281 do_transform(const _CharT* lo, const _CharT* hi) const
282 {
283 __any_string st;
284 __collate_transform(other_abi{}, _M_get(), st, lo, hi);
285 return st;
286 }
287 };
288
34a2b755 289 template<typename _CharT>
b497fbc1 290 struct time_get_shim : std::time_get<_CharT>, __shim
34a2b755
JW
291 {
292 typedef typename std::time_get<_CharT>::iter_type iter_type;
293 typedef typename std::time_get<_CharT>::char_type char_type;
294
295 // f must point to a type derived from time_get<C>[abi:other]
296 time_get_shim(const facet* f) : __shim(f) { }
297
298 virtual time_base::dateorder
299 do_date_order() const
300 { return __time_get_dateorder<_CharT>(other_abi{}, _M_get()); }
301
302 virtual iter_type
303 do_get_time(iter_type beg, iter_type end, ios_base& io,
304 ios_base::iostate& err, tm* t) const
305 {
306 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
307 't');
308 }
309
310 virtual iter_type
311 do_get_date(iter_type beg, iter_type end, ios_base& io,
312 ios_base::iostate& err, tm* t) const
313 {
314 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
315 'd');
316 }
317
318 virtual iter_type
319 do_get_weekday(iter_type beg, iter_type end, ios_base& io,
320 ios_base::iostate& err, tm* t) const
321 {
322 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
323 'w');
324 }
325
326 virtual iter_type
327 do_get_monthname(iter_type beg, iter_type end, ios_base& io,
328 ios_base::iostate& err, tm* t) const
329 {
330 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
331 'm');
332 }
333
334 virtual iter_type
335 do_get_year(iter_type beg, iter_type end, ios_base& io,
336 ios_base::iostate& err, tm* t) const
337 {
338 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
339 'y');
340 }
341 };
342
343 template<typename _CharT, bool _Intl>
b497fbc1 344 struct moneypunct_shim : std::moneypunct<_CharT, _Intl>, __shim
34a2b755
JW
345 {
346 typedef typename moneypunct<_CharT, _Intl>::__cache_type __cache_type;
347
348 // f must point to a type derived from moneypunct<C>[abi:other]
349 moneypunct_shim(const facet* f, __cache_type* c = new __cache_type)
350 : std::moneypunct<_CharT, _Intl>(c), __shim(f), _M_cache(c)
351 {
352 __moneypunct_fill_cache(other_abi{}, f, c);
353 }
354
355 ~moneypunct_shim()
356 {
831a3a9e 357 // Stop GNU locale's ~moneypunct() from freeing the cached strings.
34a2b755
JW
358 _M_cache->_M_grouping_size = 0;
359 _M_cache->_M_curr_symbol_size = 0;
360 _M_cache->_M_positive_sign_size = 0;
361 _M_cache->_M_negative_sign_size = 0;
362 }
363
364 // No need to override any virtual functions, the base definitions
365 // will return the cached data.
366
367 __cache_type* _M_cache;
368 };
369
34a2b755 370 template<typename _CharT>
b497fbc1 371 struct money_get_shim : std::money_get<_CharT>, __shim
34a2b755
JW
372 {
373 typedef typename std::money_get<_CharT>::iter_type iter_type;
374 typedef typename std::money_get<_CharT>::char_type char_type;
375 typedef typename std::money_get<_CharT>::string_type string_type;
376
377 // f must point to a type derived from money_get<C>[abi:other]
378 money_get_shim(const facet* f) : __shim(f) { }
379
380 virtual iter_type
381 do_get(iter_type s, iter_type end, bool intl, ios_base& io,
382 ios_base::iostate& err, long double& units) const
383 {
384 ios_base::iostate err2 = ios_base::goodbit;
385 long double units2;
386 s = __money_get(other_abi{}, _M_get(), s, end, intl, io, err2,
387 &units2, nullptr);
388 if (err2 == ios_base::goodbit)
389 units = units2;
390 else
391 err = err2;
392 return s;
393 }
394
395 virtual iter_type
396 do_get(iter_type s, iter_type end, bool intl, ios_base& io,
397 ios_base::iostate& err, string_type& digits) const
398 {
399 __any_string st;
400 ios_base::iostate err2 = ios_base::goodbit;
401 s = __money_get(other_abi{}, _M_get(), s, end, intl, io, err2,
402 nullptr, &st);
403 if (err2 == ios_base::goodbit)
404 digits = st;
405 else
406 err = err2;
407 return s;
408 }
409 };
410
34a2b755 411 template<typename _CharT>
b497fbc1 412 struct money_put_shim : std::money_put<_CharT>, __shim
34a2b755
JW
413 {
414 typedef typename std::money_put<_CharT>::iter_type iter_type;
415 typedef typename std::money_put<_CharT>::char_type char_type;
416 typedef typename std::money_put<_CharT>::string_type string_type;
417
418 // f must point to a type derived from money_put<C>[abi:other]
419 money_put_shim(const facet* f) : __shim(f) { }
420
421 virtual iter_type
422 do_put(iter_type s, bool intl, ios_base& io,
423 char_type fill, long double units) const
424 {
425 return __money_put(other_abi{}, _M_get(), s, intl, io, fill, units,
426 nullptr);
427 }
428
429 virtual iter_type
430 do_put(iter_type s, bool intl, ios_base& io,
431 char_type fill, const string_type& digits) const
432 {
433 __any_string st;
434 st = digits;
435 return __money_put(other_abi{}, _M_get(), s, intl, io, fill, 0.L,
436 &st);
437 }
438 };
439
34a2b755 440 template<typename _CharT>
b497fbc1 441 struct messages_shim : std::messages<_CharT>, __shim
34a2b755
JW
442 {
443 typedef messages_base::catalog catalog;
444 typedef basic_string<_CharT> string_type;
445
446 // f must point to a type derived from messages<C>[abi:other]
447 messages_shim(const facet* f) : __shim(f) { }
448
449 virtual catalog
450 do_open(const basic_string<char>& s, const locale& l) const
451 {
452 return __messages_open<_CharT>(other_abi{}, _M_get(),
453 s.c_str(), s.size(), l);
454 }
455
456 virtual string_type
457 do_get(catalog c, int set, int msgid, const string_type& dfault) const
458 {
459 __any_string st;
460 __messages_get(other_abi{}, _M_get(), st, c, set, msgid,
461 dfault.c_str(), dfault.size());
462 return st;
463 }
464
465 virtual void
466 do_close(catalog c) const
467 {
468 __messages_close<_CharT>(other_abi{}, _M_get(), c);
469 }
470 };
471
d8b7282e
JW
472 template struct numpunct_shim<char>;
473 template struct collate_shim<char>;
474 template struct moneypunct_shim<char, true>;
475 template struct moneypunct_shim<char, false>;
476 template struct money_get_shim<char>;
477 template struct money_put_shim<char>;
478 template struct messages_shim<char>;
1b9ad1d9 479#ifdef _GLIBCXX_USE_WCHAR_T
d8b7282e
JW
480 template struct numpunct_shim<wchar_t>;
481 template struct collate_shim<wchar_t>;
482 template struct moneypunct_shim<wchar_t, true>;
483 template struct moneypunct_shim<wchar_t, false>;
484 template struct money_get_shim<wchar_t>;
485 template struct money_put_shim<wchar_t>;
486 template struct messages_shim<wchar_t>;
1b9ad1d9 487#endif
34a2b755
JW
488
489 template<typename C>
490 inline size_t
491 __copy(const C*& dest, const basic_string<C>& s)
492 {
493 auto len = s.length();
494 C* p = new C[len+1];
495 s.copy(p, len);
496 p[len] = '\0';
497 dest = p;
498 return len;
499 }
500
501 } // namespace
502
503 // Now define and instantiate the functions that will be called by the
504 // shim facets defined when this file is recompiled for the other ABI.
505
831a3a9e
JW
506 // Cache the values returned by the numpunct facet f.
507 // Sets c->_M_allocated so that the __numpunct_cache destructor will
508 // delete[] the strings allocated by this function.
34a2b755
JW
509 template<typename C>
510 void
831a3a9e 511 __numpunct_fill_cache(current_abi, const facet* f, __numpunct_cache<C>* c)
34a2b755
JW
512 {
513 auto* m = static_cast<const numpunct<C>*>(f);
514
515 c->_M_decimal_point = m->decimal_point();
516 c->_M_thousands_sep = m->thousands_sep();
517
831a3a9e 518 c->_M_grouping = nullptr;
34a2b755
JW
519 c->_M_truename = nullptr;
520 c->_M_falsename = nullptr;
521 // set _M_allocated so that if any allocation fails the previously
831a3a9e 522 // allocated strings will be deleted in ~__numpunct_cache()
34a2b755
JW
523 c->_M_allocated = true;
524
831a3a9e 525 c->_M_grouping_size = __copy(c->_M_grouping, m->grouping());
34a2b755
JW
526 c->_M_truename_size = __copy(c->_M_truename, m->truename());
527 c->_M_falsename_size = __copy(c->_M_falsename, m->falsename());
34a2b755
JW
528 }
529
530 template void
831a3a9e 531 __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<char>*);
34a2b755 532
1b9ad1d9 533#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755 534 template void
831a3a9e 535 __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<wchar_t>*);
1b9ad1d9 536#endif
34a2b755
JW
537
538 template<typename C>
539 int
540 __collate_compare(current_abi, const facet* f, const C* lo1, const C* hi1,
541 const C* lo2, const C* hi2)
542 {
543 return static_cast<const collate<C>*>(f)->compare(lo1, hi1, lo2, hi2);
544 }
545
546 template int
547 __collate_compare(current_abi, const facet*, const char*, const char*,
548 const char*, const char*);
549
1b9ad1d9 550#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
551 template int
552 __collate_compare(current_abi, const facet*, const wchar_t*, const wchar_t*,
553 const wchar_t*, const wchar_t*);
1b9ad1d9 554#endif
34a2b755
JW
555
556 template<typename C>
557 void
558 __collate_transform(current_abi, const facet* f, __any_string& st,
559 const C* __lo, const C* __hi)
560 {
561 auto* c = static_cast<const collate<C>*>(f);
562 st = c->transform(__lo, __hi);
563 }
564
565 template void
566 __collate_transform(current_abi, const facet*, __any_string&,
567 const char*, const char*);
568
1b9ad1d9 569#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
570 template void
571 __collate_transform(current_abi, const facet*, __any_string&,
572 const wchar_t*, const wchar_t*);
1b9ad1d9 573#endif
34a2b755 574
831a3a9e
JW
575 // Cache the values returned by the moneypunct facet, f.
576 // Sets c->_M_allocated so that the __moneypunct_cache destructor will
577 // delete[] the strings allocated by this function.
34a2b755
JW
578 template<typename C, bool Intl>
579 void
580 __moneypunct_fill_cache(current_abi, const facet* f,
581 __moneypunct_cache<C, Intl>* c)
582 {
583 auto* m = static_cast<const moneypunct<C, Intl>*>(f);
584
585 c->_M_decimal_point = m->decimal_point();
586 c->_M_thousands_sep = m->thousands_sep();
587 c->_M_frac_digits = m->frac_digits();
588
589 c->_M_grouping = nullptr;
590 c->_M_curr_symbol = nullptr;
591 c->_M_positive_sign = nullptr;
592 c->_M_negative_sign = nullptr;
831a3a9e
JW
593 // Set _M_allocated so that if any allocation fails the previously
594 // allocated strings will be deleted in ~__moneypunct_cache().
34a2b755
JW
595 c->_M_allocated = true;
596
597 c->_M_grouping_size = __copy(c->_M_grouping, m->grouping());
598 c->_M_curr_symbol_size = __copy(c->_M_curr_symbol, m->curr_symbol());
599 c->_M_positive_sign_size
600 = __copy(c->_M_positive_sign, m->positive_sign());
601 c->_M_negative_sign_size
602 = __copy(c->_M_negative_sign, m->negative_sign());
603
604 c->_M_pos_format = m->pos_format();
605 c->_M_neg_format = m->neg_format();
606 }
607
608 template void
609 __moneypunct_fill_cache(current_abi, const facet*,
610 __moneypunct_cache<char, true>*);
611
612 template void
613 __moneypunct_fill_cache(current_abi, const facet*,
614 __moneypunct_cache<char, false>*);
615
1b9ad1d9 616#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
617 template void
618 __moneypunct_fill_cache(current_abi, const facet*,
619 __moneypunct_cache<wchar_t, true>*);
620
621 template void
622 __moneypunct_fill_cache(current_abi, const facet*,
623 __moneypunct_cache<wchar_t, false>*);
1b9ad1d9 624#endif
34a2b755
JW
625
626 template<typename C>
627 messages_base::catalog
628 __messages_open(current_abi, const facet* f, const char* s, size_t n,
629 const locale& l)
630 {
631 auto* m = static_cast<const messages<C>*>(f);
632 string str(s, n);
633 return m->open(str, l);
634 }
635
636 template messages_base::catalog
637 __messages_open<char>(current_abi, const facet*, const char*, size_t,
638 const locale&);
639
1b9ad1d9 640#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
641 template messages_base::catalog
642 __messages_open<wchar_t>(current_abi, const facet*, const char*, size_t,
643 const locale&);
1b9ad1d9 644#endif
34a2b755
JW
645
646 template<typename C>
647 void
648 __messages_get(current_abi, const facet* f, __any_string& st,
649 messages_base::catalog c, int set, int msgid,
650 const C* s, size_t n)
651 {
652 auto* m = static_cast<const messages<C>*>(f);
653 st = m->get(c, set, msgid, basic_string<C>(s, n));
654 }
655
656 template void
657 __messages_get(current_abi, const facet*, __any_string&,
658 messages_base::catalog, int, int, const char*, size_t);
659
1b9ad1d9 660#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
661 template void
662 __messages_get(current_abi, const facet*, __any_string&,
663 messages_base::catalog, int, int, const wchar_t*, size_t);
1b9ad1d9 664#endif
34a2b755
JW
665
666 template<typename C>
667 void
668 __messages_close(current_abi, const facet* f, messages_base::catalog c)
669 {
670 static_cast<const messages<C>*>(f)->close(c);
671 }
672
673 template void
674 __messages_close<char>(current_abi, const facet*, messages_base::catalog c);
675
1b9ad1d9 676#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
677 template void
678 __messages_close<wchar_t>(current_abi, const facet*,
679 messages_base::catalog c);
1b9ad1d9 680#endif
34a2b755
JW
681
682 template<typename C>
683 time_base::dateorder
684 __time_get_dateorder(current_abi, const facet* f)
685 { return static_cast<const time_get<C>*>(f)->date_order(); }
686
687 template time_base::dateorder
688 __time_get_dateorder<char>(current_abi, const facet*);
689
1b9ad1d9 690#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
691 template time_base::dateorder
692 __time_get_dateorder<wchar_t>(current_abi, const facet*);
1b9ad1d9 693#endif
34a2b755
JW
694
695 template<typename C>
696 istreambuf_iterator<C>
697 __time_get(current_abi, const facet* f,
698 istreambuf_iterator<C> beg, istreambuf_iterator<C> end,
699 ios_base& io, ios_base::iostate& err, tm* t, char which)
700 {
701 auto* g = static_cast<const time_get<C>*>(f);
702 switch(which)
703 {
704 case 't':
705 return g->get_time(beg, end, io, err, t);
706 case 'd':
707 return g->get_date(beg, end, io, err, t);
708 case 'w':
709 return g->get_weekday(beg, end, io, err, t);
710 case 'm':
711 return g->get_monthname(beg, end, io, err, t);
712 case 'y':
713 return g->get_year(beg, end, io, err, t);
714 default:
715 __builtin_unreachable();
716 }
717 }
718
719 template istreambuf_iterator<char>
720 __time_get(current_abi, const facet*,
721 istreambuf_iterator<char>, istreambuf_iterator<char>,
722 ios_base&, ios_base::iostate&, tm*, char);
723
1b9ad1d9 724#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
725 template istreambuf_iterator<wchar_t>
726 __time_get(current_abi, const facet*,
727 istreambuf_iterator<wchar_t>, istreambuf_iterator<wchar_t>,
728 ios_base&, ios_base::iostate&, tm*, char);
1b9ad1d9 729#endif
34a2b755
JW
730
731 template<typename C>
732 istreambuf_iterator<C>
733 __money_get(current_abi, const facet* f,
734 istreambuf_iterator<C> s, istreambuf_iterator<C> end,
735 bool intl, ios_base& str, ios_base::iostate& err,
736 long double* units, __any_string* digits)
737 {
738 auto* m = static_cast<const money_get<C>*>(f);
739 if (units)
740 return m->get(s, end, intl, str, err, *units);
741 basic_string<C> digits2;
742 s = m->get(s, end, intl, str, err, digits2);
743 if (err == ios_base::goodbit)
744 *digits = digits2;
745 return s;
746 }
747
748 template istreambuf_iterator<char>
749 __money_get(current_abi, const facet*,
750 istreambuf_iterator<char>, istreambuf_iterator<char>,
751 bool, ios_base&, ios_base::iostate&,
752 long double*, __any_string*);
753
1b9ad1d9 754#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
755 template istreambuf_iterator<wchar_t>
756 __money_get(current_abi, const facet*,
757 istreambuf_iterator<wchar_t>, istreambuf_iterator<wchar_t>,
758 bool, ios_base&, ios_base::iostate&,
759 long double*, __any_string*);
1b9ad1d9 760#endif
34a2b755
JW
761
762 template<typename C>
763 ostreambuf_iterator<C>
764 __money_put(current_abi, const facet* f, ostreambuf_iterator<C> s,
765 bool intl, ios_base& io, C fill, long double units,
766 const __any_string* digits)
767 {
768 auto* m = static_cast<const money_put<C>*>(f);
769 if (digits)
770 return m->put(s, intl, io, fill, *digits);
771 else
772 return m->put(s, intl, io, fill, units);
773 }
774
f9bd185f
JW
775#pragma GCC diagnostic pop
776
34a2b755
JW
777 template ostreambuf_iterator<char>
778 __money_put(current_abi, const facet*, ostreambuf_iterator<char>,
779 bool, ios_base&, char, long double, const __any_string*);
780
1b9ad1d9 781#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
782 template ostreambuf_iterator<wchar_t>
783 __money_put(current_abi, const facet*, ostreambuf_iterator<wchar_t>,
784 bool, ios_base&, wchar_t, long double, const __any_string*);
1b9ad1d9 785#endif
34a2b755 786
34a2b755
JW
787} // namespace __facet_shims
788
34a2b755
JW
789 // Create a new shim facet of type WHICH that forwards calls to F.
790 // F is the replacement facet provided by the user, WHICH is the ID of
791 // F's "other ABI twin" which we are replacing with a shim.
792 const locale::facet*
793#if _GLIBCXX_USE_CXX11_ABI
794 locale::facet::_M_sso_shim(const locale::id* which) const
795#else
796 locale::facet::_M_cow_shim(const locale::id* which) const
797#endif
798 {
799 using namespace __facet_shims;
800
5e67acc9 801#if __cpp_rtti
34a2b755
JW
802 // If this is already a shim just use its underlying facet.
803 if (auto* p = dynamic_cast<const __shim*>(this))
804 return p->_M_get();
5e67acc9 805#endif
34a2b755
JW
806
807 if (which == &numpunct<char>::id)
808 return new numpunct_shim<char>{this};
809 if (which == &std::collate<char>::id)
810 return new collate_shim<char>{this};
811 if (which == &time_get<char>::id)
812 return new time_get_shim<char>{this};
813 if (which == &money_get<char>::id)
814 return new money_get_shim<char>{this};
815 if (which == &money_put<char>::id)
816 return new money_put_shim<char>{this};
817 if (which == &moneypunct<char, true>::id)
818 return new moneypunct_shim<char, true>{this};
819 if (which == &moneypunct<char, false>::id)
820 return new moneypunct_shim<char, false>{this};
821 if (which == &std::messages<char>::id)
822 return new messages_shim<char>{this};
823#ifdef _GLIBCXX_USE_WCHAR_T
824 if (which == &numpunct<wchar_t>::id)
825 return new numpunct_shim<wchar_t>{this};
826 if (which == &std::collate<wchar_t>::id)
827 return new collate_shim<wchar_t>{this};
828 if (which == &time_get<wchar_t>::id)
829 return new time_get_shim<wchar_t>{this};
830 if (which == &money_get<wchar_t>::id)
831 return new money_get_shim<wchar_t>{this};
832 if (which == &money_put<wchar_t>::id)
833 return new money_put_shim<wchar_t>{this};
834 if (which == &moneypunct<wchar_t, true>::id)
835 return new moneypunct_shim<wchar_t, true>{this};
836 if (which == &moneypunct<wchar_t, false>::id)
837 return new moneypunct_shim<wchar_t, false>{this};
838 if (which == &std::messages<wchar_t>::id)
839 return new messages_shim<wchar_t>{this};
840#endif
841 __throw_logic_error("cannot create shim for unknown locale::facet");
842 }
843
844_GLIBCXX_END_NAMESPACE_VERSION
845} // namespace std