]> 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
85ec4feb 3// Copyright (C) 2014-2018 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
227 namespace // unnamed
228 {
b497fbc1
JW
229 struct __shim_accessor : facet
230 {
231 using facet::__shim; // Redeclare protected member as public.
232 };
233 using __shim = __shim_accessor::__shim;
234
34a2b755 235 template<typename _CharT>
b497fbc1 236 struct numpunct_shim : std::numpunct<_CharT>, __shim
34a2b755
JW
237 {
238 typedef typename numpunct<_CharT>::__cache_type __cache_type;
239
240 // f must point to a type derived from numpunct<C>[abi:other]
241 numpunct_shim(const facet* f, __cache_type* c = new __cache_type)
242 : std::numpunct<_CharT>(c), __shim(f), _M_cache(c)
243 {
831a3a9e 244 __numpunct_fill_cache(other_abi{}, f, c);
34a2b755
JW
245 }
246
831a3a9e
JW
247 ~numpunct_shim()
248 {
249 // Stop GNU locale's ~numpunct() from freeing the cached string.
250 _M_cache->_M_grouping_size = 0;
251 }
34a2b755 252
831a3a9e 253 // No need to override any virtual functions, the base definitions
34a2b755
JW
254 // will return the cached data.
255
256 __cache_type* _M_cache;
34a2b755
JW
257 };
258
34a2b755 259 template<typename _CharT>
b497fbc1 260 struct collate_shim : std::collate<_CharT>, __shim
34a2b755
JW
261 {
262 typedef basic_string<_CharT> string_type;
263
264 // f must point to a type derived from collate<C>[abi:other]
265 collate_shim(const facet* f) : __shim(f) { }
266
267 virtual int
268 do_compare(const _CharT* lo1, const _CharT* hi1,
269 const _CharT* lo2, const _CharT* hi2) const
270 {
271 return __collate_compare(other_abi{}, _M_get(),
272 lo1, hi1, lo2, hi2);
273 }
274
275 virtual string_type
276 do_transform(const _CharT* lo, const _CharT* hi) const
277 {
278 __any_string st;
279 __collate_transform(other_abi{}, _M_get(), st, lo, hi);
280 return st;
281 }
282 };
283
34a2b755 284 template<typename _CharT>
b497fbc1 285 struct time_get_shim : std::time_get<_CharT>, __shim
34a2b755
JW
286 {
287 typedef typename std::time_get<_CharT>::iter_type iter_type;
288 typedef typename std::time_get<_CharT>::char_type char_type;
289
290 // f must point to a type derived from time_get<C>[abi:other]
291 time_get_shim(const facet* f) : __shim(f) { }
292
293 virtual time_base::dateorder
294 do_date_order() const
295 { return __time_get_dateorder<_CharT>(other_abi{}, _M_get()); }
296
297 virtual iter_type
298 do_get_time(iter_type beg, iter_type end, ios_base& io,
299 ios_base::iostate& err, tm* t) const
300 {
301 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
302 't');
303 }
304
305 virtual iter_type
306 do_get_date(iter_type beg, iter_type end, ios_base& io,
307 ios_base::iostate& err, tm* t) const
308 {
309 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
310 'd');
311 }
312
313 virtual iter_type
314 do_get_weekday(iter_type beg, iter_type end, ios_base& io,
315 ios_base::iostate& err, tm* t) const
316 {
317 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
318 'w');
319 }
320
321 virtual iter_type
322 do_get_monthname(iter_type beg, iter_type end, ios_base& io,
323 ios_base::iostate& err, tm* t) const
324 {
325 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
326 'm');
327 }
328
329 virtual iter_type
330 do_get_year(iter_type beg, iter_type end, ios_base& io,
331 ios_base::iostate& err, tm* t) const
332 {
333 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
334 'y');
335 }
336 };
337
338 template<typename _CharT, bool _Intl>
b497fbc1 339 struct moneypunct_shim : std::moneypunct<_CharT, _Intl>, __shim
34a2b755
JW
340 {
341 typedef typename moneypunct<_CharT, _Intl>::__cache_type __cache_type;
342
343 // f must point to a type derived from moneypunct<C>[abi:other]
344 moneypunct_shim(const facet* f, __cache_type* c = new __cache_type)
345 : std::moneypunct<_CharT, _Intl>(c), __shim(f), _M_cache(c)
346 {
347 __moneypunct_fill_cache(other_abi{}, f, c);
348 }
349
350 ~moneypunct_shim()
351 {
831a3a9e 352 // Stop GNU locale's ~moneypunct() from freeing the cached strings.
34a2b755
JW
353 _M_cache->_M_grouping_size = 0;
354 _M_cache->_M_curr_symbol_size = 0;
355 _M_cache->_M_positive_sign_size = 0;
356 _M_cache->_M_negative_sign_size = 0;
357 }
358
359 // No need to override any virtual functions, the base definitions
360 // will return the cached data.
361
362 __cache_type* _M_cache;
363 };
364
34a2b755 365 template<typename _CharT>
b497fbc1 366 struct money_get_shim : std::money_get<_CharT>, __shim
34a2b755
JW
367 {
368 typedef typename std::money_get<_CharT>::iter_type iter_type;
369 typedef typename std::money_get<_CharT>::char_type char_type;
370 typedef typename std::money_get<_CharT>::string_type string_type;
371
372 // f must point to a type derived from money_get<C>[abi:other]
373 money_get_shim(const facet* f) : __shim(f) { }
374
375 virtual iter_type
376 do_get(iter_type s, iter_type end, bool intl, ios_base& io,
377 ios_base::iostate& err, long double& units) const
378 {
379 ios_base::iostate err2 = ios_base::goodbit;
380 long double units2;
381 s = __money_get(other_abi{}, _M_get(), s, end, intl, io, err2,
382 &units2, nullptr);
383 if (err2 == ios_base::goodbit)
384 units = units2;
385 else
386 err = err2;
387 return s;
388 }
389
390 virtual iter_type
391 do_get(iter_type s, iter_type end, bool intl, ios_base& io,
392 ios_base::iostate& err, string_type& digits) const
393 {
394 __any_string st;
395 ios_base::iostate err2 = ios_base::goodbit;
396 s = __money_get(other_abi{}, _M_get(), s, end, intl, io, err2,
397 nullptr, &st);
398 if (err2 == ios_base::goodbit)
399 digits = st;
400 else
401 err = err2;
402 return s;
403 }
404 };
405
34a2b755 406 template<typename _CharT>
b497fbc1 407 struct money_put_shim : std::money_put<_CharT>, __shim
34a2b755
JW
408 {
409 typedef typename std::money_put<_CharT>::iter_type iter_type;
410 typedef typename std::money_put<_CharT>::char_type char_type;
411 typedef typename std::money_put<_CharT>::string_type string_type;
412
413 // f must point to a type derived from money_put<C>[abi:other]
414 money_put_shim(const facet* f) : __shim(f) { }
415
416 virtual iter_type
417 do_put(iter_type s, bool intl, ios_base& io,
418 char_type fill, long double units) const
419 {
420 return __money_put(other_abi{}, _M_get(), s, intl, io, fill, units,
421 nullptr);
422 }
423
424 virtual iter_type
425 do_put(iter_type s, bool intl, ios_base& io,
426 char_type fill, const string_type& digits) const
427 {
428 __any_string st;
429 st = digits;
430 return __money_put(other_abi{}, _M_get(), s, intl, io, fill, 0.L,
431 &st);
432 }
433 };
434
34a2b755 435 template<typename _CharT>
b497fbc1 436 struct messages_shim : std::messages<_CharT>, __shim
34a2b755
JW
437 {
438 typedef messages_base::catalog catalog;
439 typedef basic_string<_CharT> string_type;
440
441 // f must point to a type derived from messages<C>[abi:other]
442 messages_shim(const facet* f) : __shim(f) { }
443
444 virtual catalog
445 do_open(const basic_string<char>& s, const locale& l) const
446 {
447 return __messages_open<_CharT>(other_abi{}, _M_get(),
448 s.c_str(), s.size(), l);
449 }
450
451 virtual string_type
452 do_get(catalog c, int set, int msgid, const string_type& dfault) const
453 {
454 __any_string st;
455 __messages_get(other_abi{}, _M_get(), st, c, set, msgid,
456 dfault.c_str(), dfault.size());
457 return st;
458 }
459
460 virtual void
461 do_close(catalog c) const
462 {
463 __messages_close<_CharT>(other_abi{}, _M_get(), c);
464 }
465 };
466
1b9ad1d9
JW
467 template class numpunct_shim<char>;
468 template class collate_shim<char>;
469 template class moneypunct_shim<char, true>;
470 template class moneypunct_shim<char, false>;
471 template class money_get_shim<char>;
472 template class money_put_shim<char>;
34a2b755 473 template class messages_shim<char>;
1b9ad1d9
JW
474#ifdef _GLIBCXX_USE_WCHAR_T
475 template class numpunct_shim<wchar_t>;
476 template class collate_shim<wchar_t>;
477 template class moneypunct_shim<wchar_t, true>;
478 template class moneypunct_shim<wchar_t, false>;
479 template class money_get_shim<wchar_t>;
480 template class money_put_shim<wchar_t>;
34a2b755 481 template class messages_shim<wchar_t>;
1b9ad1d9 482#endif
34a2b755
JW
483
484 template<typename C>
485 inline size_t
486 __copy(const C*& dest, const basic_string<C>& s)
487 {
488 auto len = s.length();
489 C* p = new C[len+1];
490 s.copy(p, len);
491 p[len] = '\0';
492 dest = p;
493 return len;
494 }
495
496 } // namespace
497
498 // Now define and instantiate the functions that will be called by the
499 // shim facets defined when this file is recompiled for the other ABI.
500
831a3a9e
JW
501 // Cache the values returned by the numpunct facet f.
502 // Sets c->_M_allocated so that the __numpunct_cache destructor will
503 // delete[] the strings allocated by this function.
34a2b755
JW
504 template<typename C>
505 void
831a3a9e 506 __numpunct_fill_cache(current_abi, const facet* f, __numpunct_cache<C>* c)
34a2b755
JW
507 {
508 auto* m = static_cast<const numpunct<C>*>(f);
509
510 c->_M_decimal_point = m->decimal_point();
511 c->_M_thousands_sep = m->thousands_sep();
512
831a3a9e 513 c->_M_grouping = nullptr;
34a2b755
JW
514 c->_M_truename = nullptr;
515 c->_M_falsename = nullptr;
516 // set _M_allocated so that if any allocation fails the previously
831a3a9e 517 // allocated strings will be deleted in ~__numpunct_cache()
34a2b755
JW
518 c->_M_allocated = true;
519
831a3a9e 520 c->_M_grouping_size = __copy(c->_M_grouping, m->grouping());
34a2b755
JW
521 c->_M_truename_size = __copy(c->_M_truename, m->truename());
522 c->_M_falsename_size = __copy(c->_M_falsename, m->falsename());
34a2b755
JW
523 }
524
525 template void
831a3a9e 526 __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<char>*);
34a2b755 527
1b9ad1d9 528#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755 529 template void
831a3a9e 530 __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<wchar_t>*);
1b9ad1d9 531#endif
34a2b755
JW
532
533 template<typename C>
534 int
535 __collate_compare(current_abi, const facet* f, const C* lo1, const C* hi1,
536 const C* lo2, const C* hi2)
537 {
538 return static_cast<const collate<C>*>(f)->compare(lo1, hi1, lo2, hi2);
539 }
540
541 template int
542 __collate_compare(current_abi, const facet*, const char*, const char*,
543 const char*, const char*);
544
1b9ad1d9 545#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
546 template int
547 __collate_compare(current_abi, const facet*, const wchar_t*, const wchar_t*,
548 const wchar_t*, const wchar_t*);
1b9ad1d9 549#endif
34a2b755
JW
550
551 template<typename C>
552 void
553 __collate_transform(current_abi, const facet* f, __any_string& st,
554 const C* __lo, const C* __hi)
555 {
556 auto* c = static_cast<const collate<C>*>(f);
557 st = c->transform(__lo, __hi);
558 }
559
560 template void
561 __collate_transform(current_abi, const facet*, __any_string&,
562 const char*, const char*);
563
1b9ad1d9 564#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
565 template void
566 __collate_transform(current_abi, const facet*, __any_string&,
567 const wchar_t*, const wchar_t*);
1b9ad1d9 568#endif
34a2b755 569
831a3a9e
JW
570 // Cache the values returned by the moneypunct facet, f.
571 // Sets c->_M_allocated so that the __moneypunct_cache destructor will
572 // delete[] the strings allocated by this function.
34a2b755
JW
573 template<typename C, bool Intl>
574 void
575 __moneypunct_fill_cache(current_abi, const facet* f,
576 __moneypunct_cache<C, Intl>* c)
577 {
578 auto* m = static_cast<const moneypunct<C, Intl>*>(f);
579
580 c->_M_decimal_point = m->decimal_point();
581 c->_M_thousands_sep = m->thousands_sep();
582 c->_M_frac_digits = m->frac_digits();
583
584 c->_M_grouping = nullptr;
585 c->_M_curr_symbol = nullptr;
586 c->_M_positive_sign = nullptr;
587 c->_M_negative_sign = nullptr;
831a3a9e
JW
588 // Set _M_allocated so that if any allocation fails the previously
589 // allocated strings will be deleted in ~__moneypunct_cache().
34a2b755
JW
590 c->_M_allocated = true;
591
592 c->_M_grouping_size = __copy(c->_M_grouping, m->grouping());
593 c->_M_curr_symbol_size = __copy(c->_M_curr_symbol, m->curr_symbol());
594 c->_M_positive_sign_size
595 = __copy(c->_M_positive_sign, m->positive_sign());
596 c->_M_negative_sign_size
597 = __copy(c->_M_negative_sign, m->negative_sign());
598
599 c->_M_pos_format = m->pos_format();
600 c->_M_neg_format = m->neg_format();
601 }
602
603 template void
604 __moneypunct_fill_cache(current_abi, const facet*,
605 __moneypunct_cache<char, true>*);
606
607 template void
608 __moneypunct_fill_cache(current_abi, const facet*,
609 __moneypunct_cache<char, false>*);
610
1b9ad1d9 611#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
612 template void
613 __moneypunct_fill_cache(current_abi, const facet*,
614 __moneypunct_cache<wchar_t, true>*);
615
616 template void
617 __moneypunct_fill_cache(current_abi, const facet*,
618 __moneypunct_cache<wchar_t, false>*);
1b9ad1d9 619#endif
34a2b755
JW
620
621 template<typename C>
622 messages_base::catalog
623 __messages_open(current_abi, const facet* f, const char* s, size_t n,
624 const locale& l)
625 {
626 auto* m = static_cast<const messages<C>*>(f);
627 string str(s, n);
628 return m->open(str, l);
629 }
630
631 template messages_base::catalog
632 __messages_open<char>(current_abi, const facet*, const char*, size_t,
633 const locale&);
634
1b9ad1d9 635#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
636 template messages_base::catalog
637 __messages_open<wchar_t>(current_abi, const facet*, const char*, size_t,
638 const locale&);
1b9ad1d9 639#endif
34a2b755
JW
640
641 template<typename C>
642 void
643 __messages_get(current_abi, const facet* f, __any_string& st,
644 messages_base::catalog c, int set, int msgid,
645 const C* s, size_t n)
646 {
647 auto* m = static_cast<const messages<C>*>(f);
648 st = m->get(c, set, msgid, basic_string<C>(s, n));
649 }
650
651 template void
652 __messages_get(current_abi, const facet*, __any_string&,
653 messages_base::catalog, int, int, const char*, size_t);
654
1b9ad1d9 655#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
656 template void
657 __messages_get(current_abi, const facet*, __any_string&,
658 messages_base::catalog, int, int, const wchar_t*, size_t);
1b9ad1d9 659#endif
34a2b755
JW
660
661 template<typename C>
662 void
663 __messages_close(current_abi, const facet* f, messages_base::catalog c)
664 {
665 static_cast<const messages<C>*>(f)->close(c);
666 }
667
668 template void
669 __messages_close<char>(current_abi, const facet*, messages_base::catalog c);
670
1b9ad1d9 671#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
672 template void
673 __messages_close<wchar_t>(current_abi, const facet*,
674 messages_base::catalog c);
1b9ad1d9 675#endif
34a2b755
JW
676
677 template<typename C>
678 time_base::dateorder
679 __time_get_dateorder(current_abi, const facet* f)
680 { return static_cast<const time_get<C>*>(f)->date_order(); }
681
682 template time_base::dateorder
683 __time_get_dateorder<char>(current_abi, const facet*);
684
1b9ad1d9 685#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
686 template time_base::dateorder
687 __time_get_dateorder<wchar_t>(current_abi, const facet*);
1b9ad1d9 688#endif
34a2b755
JW
689
690 template<typename C>
691 istreambuf_iterator<C>
692 __time_get(current_abi, const facet* f,
693 istreambuf_iterator<C> beg, istreambuf_iterator<C> end,
694 ios_base& io, ios_base::iostate& err, tm* t, char which)
695 {
696 auto* g = static_cast<const time_get<C>*>(f);
697 switch(which)
698 {
699 case 't':
700 return g->get_time(beg, end, io, err, t);
701 case 'd':
702 return g->get_date(beg, end, io, err, t);
703 case 'w':
704 return g->get_weekday(beg, end, io, err, t);
705 case 'm':
706 return g->get_monthname(beg, end, io, err, t);
707 case 'y':
708 return g->get_year(beg, end, io, err, t);
709 default:
710 __builtin_unreachable();
711 }
712 }
713
714 template istreambuf_iterator<char>
715 __time_get(current_abi, const facet*,
716 istreambuf_iterator<char>, istreambuf_iterator<char>,
717 ios_base&, ios_base::iostate&, tm*, char);
718
1b9ad1d9 719#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
720 template istreambuf_iterator<wchar_t>
721 __time_get(current_abi, const facet*,
722 istreambuf_iterator<wchar_t>, istreambuf_iterator<wchar_t>,
723 ios_base&, ios_base::iostate&, tm*, char);
1b9ad1d9 724#endif
34a2b755
JW
725
726 template<typename C>
727 istreambuf_iterator<C>
728 __money_get(current_abi, const facet* f,
729 istreambuf_iterator<C> s, istreambuf_iterator<C> end,
730 bool intl, ios_base& str, ios_base::iostate& err,
731 long double* units, __any_string* digits)
732 {
733 auto* m = static_cast<const money_get<C>*>(f);
734 if (units)
735 return m->get(s, end, intl, str, err, *units);
736 basic_string<C> digits2;
737 s = m->get(s, end, intl, str, err, digits2);
738 if (err == ios_base::goodbit)
739 *digits = digits2;
740 return s;
741 }
742
743 template istreambuf_iterator<char>
744 __money_get(current_abi, const facet*,
745 istreambuf_iterator<char>, istreambuf_iterator<char>,
746 bool, ios_base&, ios_base::iostate&,
747 long double*, __any_string*);
748
1b9ad1d9 749#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
750 template istreambuf_iterator<wchar_t>
751 __money_get(current_abi, const facet*,
752 istreambuf_iterator<wchar_t>, istreambuf_iterator<wchar_t>,
753 bool, ios_base&, ios_base::iostate&,
754 long double*, __any_string*);
1b9ad1d9 755#endif
34a2b755
JW
756
757 template<typename C>
758 ostreambuf_iterator<C>
759 __money_put(current_abi, const facet* f, ostreambuf_iterator<C> s,
760 bool intl, ios_base& io, C fill, long double units,
761 const __any_string* digits)
762 {
763 auto* m = static_cast<const money_put<C>*>(f);
764 if (digits)
765 return m->put(s, intl, io, fill, *digits);
766 else
767 return m->put(s, intl, io, fill, units);
768 }
769
770 template ostreambuf_iterator<char>
771 __money_put(current_abi, const facet*, ostreambuf_iterator<char>,
772 bool, ios_base&, char, long double, const __any_string*);
773
1b9ad1d9 774#ifdef _GLIBCXX_USE_WCHAR_T
34a2b755
JW
775 template ostreambuf_iterator<wchar_t>
776 __money_put(current_abi, const facet*, ostreambuf_iterator<wchar_t>,
777 bool, ios_base&, wchar_t, long double, const __any_string*);
1b9ad1d9 778#endif
34a2b755 779
34a2b755
JW
780} // namespace __facet_shims
781
34a2b755
JW
782 // Create a new shim facet of type WHICH that forwards calls to F.
783 // F is the replacement facet provided by the user, WHICH is the ID of
784 // F's "other ABI twin" which we are replacing with a shim.
785 const locale::facet*
786#if _GLIBCXX_USE_CXX11_ABI
787 locale::facet::_M_sso_shim(const locale::id* which) const
788#else
789 locale::facet::_M_cow_shim(const locale::id* which) const
790#endif
791 {
792 using namespace __facet_shims;
793
5e67acc9 794#if __cpp_rtti
34a2b755
JW
795 // If this is already a shim just use its underlying facet.
796 if (auto* p = dynamic_cast<const __shim*>(this))
797 return p->_M_get();
5e67acc9 798#endif
34a2b755
JW
799
800 if (which == &numpunct<char>::id)
801 return new numpunct_shim<char>{this};
802 if (which == &std::collate<char>::id)
803 return new collate_shim<char>{this};
804 if (which == &time_get<char>::id)
805 return new time_get_shim<char>{this};
806 if (which == &money_get<char>::id)
807 return new money_get_shim<char>{this};
808 if (which == &money_put<char>::id)
809 return new money_put_shim<char>{this};
810 if (which == &moneypunct<char, true>::id)
811 return new moneypunct_shim<char, true>{this};
812 if (which == &moneypunct<char, false>::id)
813 return new moneypunct_shim<char, false>{this};
814 if (which == &std::messages<char>::id)
815 return new messages_shim<char>{this};
816#ifdef _GLIBCXX_USE_WCHAR_T
817 if (which == &numpunct<wchar_t>::id)
818 return new numpunct_shim<wchar_t>{this};
819 if (which == &std::collate<wchar_t>::id)
820 return new collate_shim<wchar_t>{this};
821 if (which == &time_get<wchar_t>::id)
822 return new time_get_shim<wchar_t>{this};
823 if (which == &money_get<wchar_t>::id)
824 return new money_get_shim<wchar_t>{this};
825 if (which == &money_put<wchar_t>::id)
826 return new money_put_shim<wchar_t>{this};
827 if (which == &moneypunct<wchar_t, true>::id)
828 return new moneypunct_shim<wchar_t, true>{this};
829 if (which == &moneypunct<wchar_t, false>::id)
830 return new moneypunct_shim<wchar_t, false>{this};
831 if (which == &std::messages<wchar_t>::id)
832 return new messages_shim<wchar_t>{this};
833#endif
834 __throw_logic_error("cannot create shim for unknown locale::facet");
835 }
836
837_GLIBCXX_END_NAMESPACE_VERSION
838} // namespace std