Import GCC-8 to a new vendor branch
[dragonfly.git] / contrib / gcc-8.0 / libstdc++-v3 / src / c++11 / cxx11-shim_facets.cc
blob017b0a0fdb61fadae5c7dc12d5f15e28c224be47
1 // Locale support -*- C++ -*-
3 // Copyright (C) 2014-2018 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.
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.
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.
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/>.
26 // ISO C++ 14882: 22.1 Locales
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.
37 #ifndef _GLIBCXX_USE_CXX11_ABI
38 # define _GLIBCXX_USE_CXX11_ABI 1
39 #endif
40 #include <locale>
42 #if ! _GLIBCXX_USE_DUAL_ABI
43 # error This file should not be compiled for this configuration.
44 #endif
46 namespace std _GLIBCXX_VISIBILITY(default)
48 _GLIBCXX_BEGIN_NAMESPACE_VERSION
50 // Base class of facet shims, holds a reference to the underlying facet
51 // that the shim forwards to.
52 class locale::facet::__shim
54 public:
55 const facet* _M_get() const { return _M_facet; }
57 __shim(const __shim&) = delete;
58 __shim& operator=(const __shim&) = delete;
60 protected:
61 explicit
62 __shim(const facet* __f) : _M_facet(__f) { __f->_M_add_reference(); }
64 ~__shim() { _M_facet->_M_remove_reference(); }
66 private:
67 const facet* _M_facet;
70 namespace __facet_shims
72 namespace // unnamed
74 template<typename C>
75 void __destroy_string(void* p)
77 static_cast<std::basic_string<C>*>(p)->~basic_string();
79 } // namespace
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
85 struct __attribute__((may_alias)) __str_rep
87 union {
88 const void* _M_p;
89 char* _M_pc;
90 #ifdef _GLIBCXX_USE_WCHAR_T
91 wchar_t* _M_pwc;
92 #endif
94 size_t _M_len;
95 char _M_unused[16];
97 operator const char*() const { return _M_pc; }
98 #ifdef _GLIBCXX_USE_WCHAR_T
99 operator const wchar_t*() const { return _M_pwc; }
100 #endif
102 union {
103 __str_rep _M_str;
104 char _M_bytes[sizeof(__str_rep)];
106 using __dtor_func = void(*)(void*);
107 __dtor_func _M_dtor = nullptr;
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
123 public:
124 __any_string() = default;
125 ~__any_string() { if (_M_dtor) _M_dtor(_M_bytes); }
127 __any_string(const __any_string&) = delete;
128 __any_string& operator=(const __any_string&) = delete;
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)
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;
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>
150 _GLIBCXX_DEFAULT_ABI_TAG
151 operator basic_string<C>() const
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);
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>;
165 using facet = locale::facet;
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").
172 template<typename C>
173 void
174 __numpunct_fill_cache(other_abi, const facet*, __numpunct_cache<C>*);
176 template<typename C>
178 __collate_compare(other_abi, const facet*, const C*, const C*,
179 const C*, const C*);
181 template<typename C>
182 void
183 __collate_transform(other_abi, const facet*, __any_string&,
184 const C*, const C*);
186 template<typename C>
187 time_base::dateorder
188 __time_get_dateorder(other_abi, const facet* f);
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);
196 template<typename C, bool Intl>
197 void
198 __moneypunct_fill_cache(other_abi, const facet*,
199 __moneypunct_cache<C, Intl>*);
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*);
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*);
213 template<typename C>
214 messages_base::catalog
215 __messages_open(other_abi, const facet*, const char*, size_t,
216 const locale&);
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);
223 template<typename C>
224 void
225 __messages_close(other_abi, const facet*, messages_base::catalog);
227 namespace // unnamed
229 struct __shim_accessor : facet
231 using facet::__shim; // Redeclare protected member as public.
233 using __shim = __shim_accessor::__shim;
235 template<typename _CharT>
236 struct numpunct_shim : std::numpunct<_CharT>, __shim
238 typedef typename numpunct<_CharT>::__cache_type __cache_type;
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)
244 __numpunct_fill_cache(other_abi{}, f, c);
247 ~numpunct_shim()
249 // Stop GNU locale's ~numpunct() from freeing the cached string.
250 _M_cache->_M_grouping_size = 0;
253 // No need to override any virtual functions, the base definitions
254 // will return the cached data.
256 __cache_type* _M_cache;
259 template<typename _CharT>
260 struct collate_shim : std::collate<_CharT>, __shim
262 typedef basic_string<_CharT> string_type;
264 // f must point to a type derived from collate<C>[abi:other]
265 collate_shim(const facet* f) : __shim(f) { }
267 virtual int
268 do_compare(const _CharT* lo1, const _CharT* hi1,
269 const _CharT* lo2, const _CharT* hi2) const
271 return __collate_compare(other_abi{}, _M_get(),
272 lo1, hi1, lo2, hi2);
275 virtual string_type
276 do_transform(const _CharT* lo, const _CharT* hi) const
278 __any_string st;
279 __collate_transform(other_abi{}, _M_get(), st, lo, hi);
280 return st;
284 template<typename _CharT>
285 struct time_get_shim : std::time_get<_CharT>, __shim
287 typedef typename std::time_get<_CharT>::iter_type iter_type;
288 typedef typename std::time_get<_CharT>::char_type char_type;
290 // f must point to a type derived from time_get<C>[abi:other]
291 time_get_shim(const facet* f) : __shim(f) { }
293 virtual time_base::dateorder
294 do_date_order() const
295 { return __time_get_dateorder<_CharT>(other_abi{}, _M_get()); }
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
301 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
302 't');
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
309 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
310 'd');
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
317 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
318 'w');
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
325 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
326 'm');
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
333 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
334 'y');
338 template<typename _CharT, bool _Intl>
339 struct moneypunct_shim : std::moneypunct<_CharT, _Intl>, __shim
341 typedef typename moneypunct<_CharT, _Intl>::__cache_type __cache_type;
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)
347 __moneypunct_fill_cache(other_abi{}, f, c);
350 ~moneypunct_shim()
352 // Stop GNU locale's ~moneypunct() from freeing the cached strings.
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;
359 // No need to override any virtual functions, the base definitions
360 // will return the cached data.
362 __cache_type* _M_cache;
365 template<typename _CharT>
366 struct money_get_shim : std::money_get<_CharT>, __shim
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;
372 // f must point to a type derived from money_get<C>[abi:other]
373 money_get_shim(const facet* f) : __shim(f) { }
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
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;
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
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;
406 template<typename _CharT>
407 struct money_put_shim : std::money_put<_CharT>, __shim
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;
413 // f must point to a type derived from money_put<C>[abi:other]
414 money_put_shim(const facet* f) : __shim(f) { }
416 virtual iter_type
417 do_put(iter_type s, bool intl, ios_base& io,
418 char_type fill, long double units) const
420 return __money_put(other_abi{}, _M_get(), s, intl, io, fill, units,
421 nullptr);
424 virtual iter_type
425 do_put(iter_type s, bool intl, ios_base& io,
426 char_type fill, const string_type& digits) const
428 __any_string st;
429 st = digits;
430 return __money_put(other_abi{}, _M_get(), s, intl, io, fill, 0.L,
431 &st);
435 template<typename _CharT>
436 struct messages_shim : std::messages<_CharT>, __shim
438 typedef messages_base::catalog catalog;
439 typedef basic_string<_CharT> string_type;
441 // f must point to a type derived from messages<C>[abi:other]
442 messages_shim(const facet* f) : __shim(f) { }
444 virtual catalog
445 do_open(const basic_string<char>& s, const locale& l) const
447 return __messages_open<_CharT>(other_abi{}, _M_get(),
448 s.c_str(), s.size(), l);
451 virtual string_type
452 do_get(catalog c, int set, int msgid, const string_type& dfault) const
454 __any_string st;
455 __messages_get(other_abi{}, _M_get(), st, c, set, msgid,
456 dfault.c_str(), dfault.size());
457 return st;
460 virtual void
461 do_close(catalog c) const
463 __messages_close<_CharT>(other_abi{}, _M_get(), c);
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>;
473 template class messages_shim<char>;
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>;
481 template class messages_shim<wchar_t>;
482 #endif
484 template<typename C>
485 inline size_t
486 __copy(const C*& dest, const basic_string<C>& s)
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;
496 } // namespace
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.
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.
504 template<typename C>
505 void
506 __numpunct_fill_cache(current_abi, const facet* f, __numpunct_cache<C>* c)
508 auto* m = static_cast<const numpunct<C>*>(f);
510 c->_M_decimal_point = m->decimal_point();
511 c->_M_thousands_sep = m->thousands_sep();
513 c->_M_grouping = nullptr;
514 c->_M_truename = nullptr;
515 c->_M_falsename = nullptr;
516 // set _M_allocated so that if any allocation fails the previously
517 // allocated strings will be deleted in ~__numpunct_cache()
518 c->_M_allocated = true;
520 c->_M_grouping_size = __copy(c->_M_grouping, m->grouping());
521 c->_M_truename_size = __copy(c->_M_truename, m->truename());
522 c->_M_falsename_size = __copy(c->_M_falsename, m->falsename());
525 template void
526 __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<char>*);
528 #ifdef _GLIBCXX_USE_WCHAR_T
529 template void
530 __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<wchar_t>*);
531 #endif
533 template<typename C>
535 __collate_compare(current_abi, const facet* f, const C* lo1, const C* hi1,
536 const C* lo2, const C* hi2)
538 return static_cast<const collate<C>*>(f)->compare(lo1, hi1, lo2, hi2);
541 template int
542 __collate_compare(current_abi, const facet*, const char*, const char*,
543 const char*, const char*);
545 #ifdef _GLIBCXX_USE_WCHAR_T
546 template int
547 __collate_compare(current_abi, const facet*, const wchar_t*, const wchar_t*,
548 const wchar_t*, const wchar_t*);
549 #endif
551 template<typename C>
552 void
553 __collate_transform(current_abi, const facet* f, __any_string& st,
554 const C* __lo, const C* __hi)
556 auto* c = static_cast<const collate<C>*>(f);
557 st = c->transform(__lo, __hi);
560 template void
561 __collate_transform(current_abi, const facet*, __any_string&,
562 const char*, const char*);
564 #ifdef _GLIBCXX_USE_WCHAR_T
565 template void
566 __collate_transform(current_abi, const facet*, __any_string&,
567 const wchar_t*, const wchar_t*);
568 #endif
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.
573 template<typename C, bool Intl>
574 void
575 __moneypunct_fill_cache(current_abi, const facet* f,
576 __moneypunct_cache<C, Intl>* c)
578 auto* m = static_cast<const moneypunct<C, Intl>*>(f);
580 c->_M_decimal_point = m->decimal_point();
581 c->_M_thousands_sep = m->thousands_sep();
582 c->_M_frac_digits = m->frac_digits();
584 c->_M_grouping = nullptr;
585 c->_M_curr_symbol = nullptr;
586 c->_M_positive_sign = nullptr;
587 c->_M_negative_sign = nullptr;
588 // Set _M_allocated so that if any allocation fails the previously
589 // allocated strings will be deleted in ~__moneypunct_cache().
590 c->_M_allocated = true;
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());
599 c->_M_pos_format = m->pos_format();
600 c->_M_neg_format = m->neg_format();
603 template void
604 __moneypunct_fill_cache(current_abi, const facet*,
605 __moneypunct_cache<char, true>*);
607 template void
608 __moneypunct_fill_cache(current_abi, const facet*,
609 __moneypunct_cache<char, false>*);
611 #ifdef _GLIBCXX_USE_WCHAR_T
612 template void
613 __moneypunct_fill_cache(current_abi, const facet*,
614 __moneypunct_cache<wchar_t, true>*);
616 template void
617 __moneypunct_fill_cache(current_abi, const facet*,
618 __moneypunct_cache<wchar_t, false>*);
619 #endif
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)
626 auto* m = static_cast<const messages<C>*>(f);
627 string str(s, n);
628 return m->open(str, l);
631 template messages_base::catalog
632 __messages_open<char>(current_abi, const facet*, const char*, size_t,
633 const locale&);
635 #ifdef _GLIBCXX_USE_WCHAR_T
636 template messages_base::catalog
637 __messages_open<wchar_t>(current_abi, const facet*, const char*, size_t,
638 const locale&);
639 #endif
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)
647 auto* m = static_cast<const messages<C>*>(f);
648 st = m->get(c, set, msgid, basic_string<C>(s, n));
651 template void
652 __messages_get(current_abi, const facet*, __any_string&,
653 messages_base::catalog, int, int, const char*, size_t);
655 #ifdef _GLIBCXX_USE_WCHAR_T
656 template void
657 __messages_get(current_abi, const facet*, __any_string&,
658 messages_base::catalog, int, int, const wchar_t*, size_t);
659 #endif
661 template<typename C>
662 void
663 __messages_close(current_abi, const facet* f, messages_base::catalog c)
665 static_cast<const messages<C>*>(f)->close(c);
668 template void
669 __messages_close<char>(current_abi, const facet*, messages_base::catalog c);
671 #ifdef _GLIBCXX_USE_WCHAR_T
672 template void
673 __messages_close<wchar_t>(current_abi, const facet*,
674 messages_base::catalog c);
675 #endif
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(); }
682 template time_base::dateorder
683 __time_get_dateorder<char>(current_abi, const facet*);
685 #ifdef _GLIBCXX_USE_WCHAR_T
686 template time_base::dateorder
687 __time_get_dateorder<wchar_t>(current_abi, const facet*);
688 #endif
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)
696 auto* g = static_cast<const time_get<C>*>(f);
697 switch(which)
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();
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);
719 #ifdef _GLIBCXX_USE_WCHAR_T
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);
724 #endif
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)
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;
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*);
749 #ifdef _GLIBCXX_USE_WCHAR_T
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*);
755 #endif
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)
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);
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*);
774 #ifdef _GLIBCXX_USE_WCHAR_T
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*);
778 #endif
780 } // namespace __facet_shims
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
792 using namespace __facet_shims;
794 #if __cpp_rtti
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();
798 #endif
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");
837 _GLIBCXX_END_NAMESPACE_VERSION
838 } // namespace std