PR c++/65046
[official-gcc.git] / libstdc++-v3 / src / c++11 / cxx11-shim_facets.cc
blob4e30088bac3732520c35744018ed8bd5940277b0
1 // Locale support -*- C++ -*-
3 // Copyright (C) 2014-2015 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 // Base class of facet shims, holds a reference to the underlying facet
49 // that the shim forwards to.
50 class locale::facet::__shim
52 public:
53 const facet* _M_get() const { return _M_facet; }
55 __shim(const __shim&) = delete;
56 __shim& operator=(const __shim&) = delete;
58 protected:
59 explicit
60 __shim(const facet* __f) : _M_facet(__f) { __f->_M_add_reference(); }
62 ~__shim() { _M_facet->_M_remove_reference(); }
64 private:
65 const facet* _M_facet;
68 namespace __facet_shims
70 _GLIBCXX_BEGIN_NAMESPACE_VERSION
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 template<typename _CharT>
230 struct numpunct_shim : std::numpunct<_CharT>, facet::__shim
232 typedef typename numpunct<_CharT>::__cache_type __cache_type;
234 // f must point to a type derived from numpunct<C>[abi:other]
235 numpunct_shim(const facet* f, __cache_type* c = new __cache_type)
236 : std::numpunct<_CharT>(c), __shim(f), _M_cache(c)
238 __numpunct_fill_cache(other_abi{}, f, c);
241 ~numpunct_shim()
243 // Stop GNU locale's ~numpunct() from freeing the cached string.
244 _M_cache->_M_grouping_size = 0;
247 // No need to override any virtual functions, the base definitions
248 // will return the cached data.
250 __cache_type* _M_cache;
253 template<typename _CharT>
254 struct collate_shim : std::collate<_CharT>, facet::__shim
256 typedef basic_string<_CharT> string_type;
258 // f must point to a type derived from collate<C>[abi:other]
259 collate_shim(const facet* f) : __shim(f) { }
261 virtual int
262 do_compare(const _CharT* lo1, const _CharT* hi1,
263 const _CharT* lo2, const _CharT* hi2) const
265 return __collate_compare(other_abi{}, _M_get(),
266 lo1, hi1, lo2, hi2);
269 virtual string_type
270 do_transform(const _CharT* lo, const _CharT* hi) const
272 __any_string st;
273 __collate_transform(other_abi{}, _M_get(), st, lo, hi);
274 return st;
278 template<typename _CharT>
279 struct time_get_shim : std::time_get<_CharT>, facet::__shim
281 typedef typename std::time_get<_CharT>::iter_type iter_type;
282 typedef typename std::time_get<_CharT>::char_type char_type;
284 // f must point to a type derived from time_get<C>[abi:other]
285 time_get_shim(const facet* f) : __shim(f) { }
287 virtual time_base::dateorder
288 do_date_order() const
289 { return __time_get_dateorder<_CharT>(other_abi{}, _M_get()); }
291 virtual iter_type
292 do_get_time(iter_type beg, iter_type end, ios_base& io,
293 ios_base::iostate& err, tm* t) const
295 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
296 't');
299 virtual iter_type
300 do_get_date(iter_type beg, iter_type end, ios_base& io,
301 ios_base::iostate& err, tm* t) const
303 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
304 'd');
307 virtual iter_type
308 do_get_weekday(iter_type beg, iter_type end, ios_base& io,
309 ios_base::iostate& err, tm* t) const
311 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
312 'w');
315 virtual iter_type
316 do_get_monthname(iter_type beg, iter_type end, ios_base& io,
317 ios_base::iostate& err, tm* t) const
319 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
320 'm');
323 virtual iter_type
324 do_get_year(iter_type beg, iter_type end, ios_base& io,
325 ios_base::iostate& err, tm* t) const
327 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
328 'y');
332 template<typename _CharT, bool _Intl>
333 struct moneypunct_shim : std::moneypunct<_CharT, _Intl>, facet::__shim
335 typedef typename moneypunct<_CharT, _Intl>::__cache_type __cache_type;
337 // f must point to a type derived from moneypunct<C>[abi:other]
338 moneypunct_shim(const facet* f, __cache_type* c = new __cache_type)
339 : std::moneypunct<_CharT, _Intl>(c), __shim(f), _M_cache(c)
341 __moneypunct_fill_cache(other_abi{}, f, c);
344 ~moneypunct_shim()
346 // Stop GNU locale's ~moneypunct() from freeing the cached strings.
347 _M_cache->_M_grouping_size = 0;
348 _M_cache->_M_curr_symbol_size = 0;
349 _M_cache->_M_positive_sign_size = 0;
350 _M_cache->_M_negative_sign_size = 0;
353 // No need to override any virtual functions, the base definitions
354 // will return the cached data.
356 __cache_type* _M_cache;
359 template<typename _CharT>
360 struct money_get_shim : std::money_get<_CharT>, facet::__shim
362 typedef typename std::money_get<_CharT>::iter_type iter_type;
363 typedef typename std::money_get<_CharT>::char_type char_type;
364 typedef typename std::money_get<_CharT>::string_type string_type;
366 // f must point to a type derived from money_get<C>[abi:other]
367 money_get_shim(const facet* f) : __shim(f) { }
369 virtual iter_type
370 do_get(iter_type s, iter_type end, bool intl, ios_base& io,
371 ios_base::iostate& err, long double& units) const
373 ios_base::iostate err2 = ios_base::goodbit;
374 long double units2;
375 s = __money_get(other_abi{}, _M_get(), s, end, intl, io, err2,
376 &units2, nullptr);
377 if (err2 == ios_base::goodbit)
378 units = units2;
379 else
380 err = err2;
381 return s;
384 virtual iter_type
385 do_get(iter_type s, iter_type end, bool intl, ios_base& io,
386 ios_base::iostate& err, string_type& digits) const
388 __any_string st;
389 ios_base::iostate err2 = ios_base::goodbit;
390 s = __money_get(other_abi{}, _M_get(), s, end, intl, io, err2,
391 nullptr, &st);
392 if (err2 == ios_base::goodbit)
393 digits = st;
394 else
395 err = err2;
396 return s;
400 template<typename _CharT>
401 struct money_put_shim : std::money_put<_CharT>, facet::__shim
403 typedef typename std::money_put<_CharT>::iter_type iter_type;
404 typedef typename std::money_put<_CharT>::char_type char_type;
405 typedef typename std::money_put<_CharT>::string_type string_type;
407 // f must point to a type derived from money_put<C>[abi:other]
408 money_put_shim(const facet* f) : __shim(f) { }
410 virtual iter_type
411 do_put(iter_type s, bool intl, ios_base& io,
412 char_type fill, long double units) const
414 return __money_put(other_abi{}, _M_get(), s, intl, io, fill, units,
415 nullptr);
418 virtual iter_type
419 do_put(iter_type s, bool intl, ios_base& io,
420 char_type fill, const string_type& digits) const
422 __any_string st;
423 st = digits;
424 return __money_put(other_abi{}, _M_get(), s, intl, io, fill, 0.L,
425 &st);
429 template<typename _CharT>
430 struct messages_shim : std::messages<_CharT>, facet::__shim
432 typedef messages_base::catalog catalog;
433 typedef basic_string<_CharT> string_type;
435 // f must point to a type derived from messages<C>[abi:other]
436 messages_shim(const facet* f) : __shim(f) { }
438 virtual catalog
439 do_open(const basic_string<char>& s, const locale& l) const
441 return __messages_open<_CharT>(other_abi{}, _M_get(),
442 s.c_str(), s.size(), l);
445 virtual string_type
446 do_get(catalog c, int set, int msgid, const string_type& dfault) const
448 __any_string st;
449 __messages_get(other_abi{}, _M_get(), st, c, set, msgid,
450 dfault.c_str(), dfault.size());
451 return st;
454 virtual void
455 do_close(catalog c) const
457 __messages_close<_CharT>(other_abi{}, _M_get(), c);
461 template class numpunct_shim<char>;
462 template class collate_shim<char>;
463 template class moneypunct_shim<char, true>;
464 template class moneypunct_shim<char, false>;
465 template class money_get_shim<char>;
466 template class money_put_shim<char>;
467 template class messages_shim<char>;
468 #ifdef _GLIBCXX_USE_WCHAR_T
469 template class numpunct_shim<wchar_t>;
470 template class collate_shim<wchar_t>;
471 template class moneypunct_shim<wchar_t, true>;
472 template class moneypunct_shim<wchar_t, false>;
473 template class money_get_shim<wchar_t>;
474 template class money_put_shim<wchar_t>;
475 template class messages_shim<wchar_t>;
476 #endif
478 template<typename C>
479 inline size_t
480 __copy(const C*& dest, const basic_string<C>& s)
482 auto len = s.length();
483 C* p = new C[len+1];
484 s.copy(p, len);
485 p[len] = '\0';
486 dest = p;
487 return len;
490 } // namespace
492 // Now define and instantiate the functions that will be called by the
493 // shim facets defined when this file is recompiled for the other ABI.
495 // Cache the values returned by the numpunct facet f.
496 // Sets c->_M_allocated so that the __numpunct_cache destructor will
497 // delete[] the strings allocated by this function.
498 template<typename C>
499 void
500 __numpunct_fill_cache(current_abi, const facet* f, __numpunct_cache<C>* c)
502 auto* m = static_cast<const numpunct<C>*>(f);
504 c->_M_decimal_point = m->decimal_point();
505 c->_M_thousands_sep = m->thousands_sep();
507 c->_M_grouping = nullptr;
508 c->_M_truename = nullptr;
509 c->_M_falsename = nullptr;
510 // set _M_allocated so that if any allocation fails the previously
511 // allocated strings will be deleted in ~__numpunct_cache()
512 c->_M_allocated = true;
514 c->_M_grouping_size = __copy(c->_M_grouping, m->grouping());
515 c->_M_truename_size = __copy(c->_M_truename, m->truename());
516 c->_M_falsename_size = __copy(c->_M_falsename, m->falsename());
519 template void
520 __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<char>*);
522 #ifdef _GLIBCXX_USE_WCHAR_T
523 template void
524 __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<wchar_t>*);
525 #endif
527 template<typename C>
529 __collate_compare(current_abi, const facet* f, const C* lo1, const C* hi1,
530 const C* lo2, const C* hi2)
532 return static_cast<const collate<C>*>(f)->compare(lo1, hi1, lo2, hi2);
535 template int
536 __collate_compare(current_abi, const facet*, const char*, const char*,
537 const char*, const char*);
539 #ifdef _GLIBCXX_USE_WCHAR_T
540 template int
541 __collate_compare(current_abi, const facet*, const wchar_t*, const wchar_t*,
542 const wchar_t*, const wchar_t*);
543 #endif
545 template<typename C>
546 void
547 __collate_transform(current_abi, const facet* f, __any_string& st,
548 const C* __lo, const C* __hi)
550 auto* c = static_cast<const collate<C>*>(f);
551 st = c->transform(__lo, __hi);
554 template void
555 __collate_transform(current_abi, const facet*, __any_string&,
556 const char*, const char*);
558 #ifdef _GLIBCXX_USE_WCHAR_T
559 template void
560 __collate_transform(current_abi, const facet*, __any_string&,
561 const wchar_t*, const wchar_t*);
562 #endif
564 // Cache the values returned by the moneypunct facet, f.
565 // Sets c->_M_allocated so that the __moneypunct_cache destructor will
566 // delete[] the strings allocated by this function.
567 template<typename C, bool Intl>
568 void
569 __moneypunct_fill_cache(current_abi, const facet* f,
570 __moneypunct_cache<C, Intl>* c)
572 auto* m = static_cast<const moneypunct<C, Intl>*>(f);
574 c->_M_decimal_point = m->decimal_point();
575 c->_M_thousands_sep = m->thousands_sep();
576 c->_M_frac_digits = m->frac_digits();
578 c->_M_grouping = nullptr;
579 c->_M_curr_symbol = nullptr;
580 c->_M_positive_sign = nullptr;
581 c->_M_negative_sign = nullptr;
582 // Set _M_allocated so that if any allocation fails the previously
583 // allocated strings will be deleted in ~__moneypunct_cache().
584 c->_M_allocated = true;
586 c->_M_grouping_size = __copy(c->_M_grouping, m->grouping());
587 c->_M_curr_symbol_size = __copy(c->_M_curr_symbol, m->curr_symbol());
588 c->_M_positive_sign_size
589 = __copy(c->_M_positive_sign, m->positive_sign());
590 c->_M_negative_sign_size
591 = __copy(c->_M_negative_sign, m->negative_sign());
593 c->_M_pos_format = m->pos_format();
594 c->_M_neg_format = m->neg_format();
597 template void
598 __moneypunct_fill_cache(current_abi, const facet*,
599 __moneypunct_cache<char, true>*);
601 template void
602 __moneypunct_fill_cache(current_abi, const facet*,
603 __moneypunct_cache<char, false>*);
605 #ifdef _GLIBCXX_USE_WCHAR_T
606 template void
607 __moneypunct_fill_cache(current_abi, const facet*,
608 __moneypunct_cache<wchar_t, true>*);
610 template void
611 __moneypunct_fill_cache(current_abi, const facet*,
612 __moneypunct_cache<wchar_t, false>*);
613 #endif
615 template<typename C>
616 messages_base::catalog
617 __messages_open(current_abi, const facet* f, const char* s, size_t n,
618 const locale& l)
620 auto* m = static_cast<const messages<C>*>(f);
621 string str(s, n);
622 return m->open(str, l);
625 template messages_base::catalog
626 __messages_open<char>(current_abi, const facet*, const char*, size_t,
627 const locale&);
629 #ifdef _GLIBCXX_USE_WCHAR_T
630 template messages_base::catalog
631 __messages_open<wchar_t>(current_abi, const facet*, const char*, size_t,
632 const locale&);
633 #endif
635 template<typename C>
636 void
637 __messages_get(current_abi, const facet* f, __any_string& st,
638 messages_base::catalog c, int set, int msgid,
639 const C* s, size_t n)
641 auto* m = static_cast<const messages<C>*>(f);
642 st = m->get(c, set, msgid, basic_string<C>(s, n));
645 template void
646 __messages_get(current_abi, const facet*, __any_string&,
647 messages_base::catalog, int, int, const char*, size_t);
649 #ifdef _GLIBCXX_USE_WCHAR_T
650 template void
651 __messages_get(current_abi, const facet*, __any_string&,
652 messages_base::catalog, int, int, const wchar_t*, size_t);
653 #endif
655 template<typename C>
656 void
657 __messages_close(current_abi, const facet* f, messages_base::catalog c)
659 static_cast<const messages<C>*>(f)->close(c);
662 template void
663 __messages_close<char>(current_abi, const facet*, messages_base::catalog c);
665 #ifdef _GLIBCXX_USE_WCHAR_T
666 template void
667 __messages_close<wchar_t>(current_abi, const facet*,
668 messages_base::catalog c);
669 #endif
671 template<typename C>
672 time_base::dateorder
673 __time_get_dateorder(current_abi, const facet* f)
674 { return static_cast<const time_get<C>*>(f)->date_order(); }
676 template time_base::dateorder
677 __time_get_dateorder<char>(current_abi, const facet*);
679 #ifdef _GLIBCXX_USE_WCHAR_T
680 template time_base::dateorder
681 __time_get_dateorder<wchar_t>(current_abi, const facet*);
682 #endif
684 template<typename C>
685 istreambuf_iterator<C>
686 __time_get(current_abi, const facet* f,
687 istreambuf_iterator<C> beg, istreambuf_iterator<C> end,
688 ios_base& io, ios_base::iostate& err, tm* t, char which)
690 auto* g = static_cast<const time_get<C>*>(f);
691 switch(which)
693 case 't':
694 return g->get_time(beg, end, io, err, t);
695 case 'd':
696 return g->get_date(beg, end, io, err, t);
697 case 'w':
698 return g->get_weekday(beg, end, io, err, t);
699 case 'm':
700 return g->get_monthname(beg, end, io, err, t);
701 case 'y':
702 return g->get_year(beg, end, io, err, t);
703 default:
704 __builtin_unreachable();
708 template istreambuf_iterator<char>
709 __time_get(current_abi, const facet*,
710 istreambuf_iterator<char>, istreambuf_iterator<char>,
711 ios_base&, ios_base::iostate&, tm*, char);
713 #ifdef _GLIBCXX_USE_WCHAR_T
714 template istreambuf_iterator<wchar_t>
715 __time_get(current_abi, const facet*,
716 istreambuf_iterator<wchar_t>, istreambuf_iterator<wchar_t>,
717 ios_base&, ios_base::iostate&, tm*, char);
718 #endif
720 template<typename C>
721 istreambuf_iterator<C>
722 __money_get(current_abi, const facet* f,
723 istreambuf_iterator<C> s, istreambuf_iterator<C> end,
724 bool intl, ios_base& str, ios_base::iostate& err,
725 long double* units, __any_string* digits)
727 auto* m = static_cast<const money_get<C>*>(f);
728 if (units)
729 return m->get(s, end, intl, str, err, *units);
730 basic_string<C> digits2;
731 s = m->get(s, end, intl, str, err, digits2);
732 if (err == ios_base::goodbit)
733 *digits = digits2;
734 return s;
737 template istreambuf_iterator<char>
738 __money_get(current_abi, const facet*,
739 istreambuf_iterator<char>, istreambuf_iterator<char>,
740 bool, ios_base&, ios_base::iostate&,
741 long double*, __any_string*);
743 #ifdef _GLIBCXX_USE_WCHAR_T
744 template istreambuf_iterator<wchar_t>
745 __money_get(current_abi, const facet*,
746 istreambuf_iterator<wchar_t>, istreambuf_iterator<wchar_t>,
747 bool, ios_base&, ios_base::iostate&,
748 long double*, __any_string*);
749 #endif
751 template<typename C>
752 ostreambuf_iterator<C>
753 __money_put(current_abi, const facet* f, ostreambuf_iterator<C> s,
754 bool intl, ios_base& io, C fill, long double units,
755 const __any_string* digits)
757 auto* m = static_cast<const money_put<C>*>(f);
758 if (digits)
759 return m->put(s, intl, io, fill, *digits);
760 else
761 return m->put(s, intl, io, fill, units);
764 template ostreambuf_iterator<char>
765 __money_put(current_abi, const facet*, ostreambuf_iterator<char>,
766 bool, ios_base&, char, long double, const __any_string*);
768 #ifdef _GLIBCXX_USE_WCHAR_T
769 template ostreambuf_iterator<wchar_t>
770 __money_put(current_abi, const facet*, ostreambuf_iterator<wchar_t>,
771 bool, ios_base&, wchar_t, long double, const __any_string*);
772 #endif
774 _GLIBCXX_END_NAMESPACE_VERSION
775 } // namespace __facet_shims
777 _GLIBCXX_BEGIN_NAMESPACE_VERSION
778 // Create a new shim facet of type WHICH that forwards calls to F.
779 // F is the replacement facet provided by the user, WHICH is the ID of
780 // F's "other ABI twin" which we are replacing with a shim.
781 const locale::facet*
782 #if _GLIBCXX_USE_CXX11_ABI
783 locale::facet::_M_sso_shim(const locale::id* which) const
784 #else
785 locale::facet::_M_cow_shim(const locale::id* which) const
786 #endif
788 using namespace __facet_shims;
790 #if __cpp_rtti
791 // If this is already a shim just use its underlying facet.
792 if (auto* p = dynamic_cast<const __shim*>(this))
793 return p->_M_get();
794 #endif
796 if (which == &numpunct<char>::id)
797 return new numpunct_shim<char>{this};
798 if (which == &std::collate<char>::id)
799 return new collate_shim<char>{this};
800 if (which == &time_get<char>::id)
801 return new time_get_shim<char>{this};
802 if (which == &money_get<char>::id)
803 return new money_get_shim<char>{this};
804 if (which == &money_put<char>::id)
805 return new money_put_shim<char>{this};
806 if (which == &moneypunct<char, true>::id)
807 return new moneypunct_shim<char, true>{this};
808 if (which == &moneypunct<char, false>::id)
809 return new moneypunct_shim<char, false>{this};
810 if (which == &std::messages<char>::id)
811 return new messages_shim<char>{this};
812 #ifdef _GLIBCXX_USE_WCHAR_T
813 if (which == &numpunct<wchar_t>::id)
814 return new numpunct_shim<wchar_t>{this};
815 if (which == &std::collate<wchar_t>::id)
816 return new collate_shim<wchar_t>{this};
817 if (which == &time_get<wchar_t>::id)
818 return new time_get_shim<wchar_t>{this};
819 if (which == &money_get<wchar_t>::id)
820 return new money_get_shim<wchar_t>{this};
821 if (which == &money_put<wchar_t>::id)
822 return new money_put_shim<wchar_t>{this};
823 if (which == &moneypunct<wchar_t, true>::id)
824 return new moneypunct_shim<wchar_t, true>{this};
825 if (which == &moneypunct<wchar_t, false>::id)
826 return new moneypunct_shim<wchar_t, false>{this};
827 if (which == &std::messages<wchar_t>::id)
828 return new messages_shim<wchar_t>{this};
829 #endif
830 __throw_logic_error("cannot create shim for unknown locale::facet");
833 _GLIBCXX_END_NAMESPACE_VERSION
834 } // namespace std