1 // Locale support -*- C++ -*-
3 // Copyright (C) 2014-2015 Free Software Foundation, Inc.
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)
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
42 #if ! _GLIBCXX_USE_DUAL_ABI
43 # error This file should not be compiled for this configuration.
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
53 const facet
* _M_get() const { return _M_facet
; }
55 __shim(const __shim
&) = delete;
56 __shim
& operator=(const __shim
&) = delete;
60 __shim(const facet
* __f
) : _M_facet(__f
) { __f
->_M_add_reference(); }
62 ~__shim() { _M_facet
->_M_remove_reference(); }
65 const facet
* _M_facet
;
68 namespace __facet_shims
70 _GLIBCXX_BEGIN_NAMESPACE_VERSION
75 void __destroy_string(void* p
)
77 static_cast<std::basic_string
<C
>*>(p
)->~basic_string();
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.
85 struct __attribute__((may_alias
)) __str_rep
90 #ifdef _GLIBCXX_USE_WCHAR_T
97 operator const char*() const { return _M_pc
; }
98 #ifdef _GLIBCXX_USE_WCHAR_T
99 operator const wchar_t*() const { return _M_pwc
; }
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!");
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!");
118 # ifdef _GLIBCXX_USE_WCHAR_T
119 static_assert(sizeof(std::wstring
) == sizeof(std::string
),
120 "std::wstring and std::string are different sizes!");
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.
134 operator=(const basic_string
<C
>& s
)
138 ::new(_M_bytes
) basic_string
<C
>(s
);
139 #if ! _GLIBCXX_USE_CXX11_ABI
140 _M_str
._M_len
= s
.length();
142 _M_dtor
= __destroy_string
<C
>;
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.
150 _GLIBCXX_DEFAULT_ABI_TAG
151 operator basic_string
<C
>() const
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").
174 __numpunct_fill_cache(other_abi
, const facet
*, __numpunct_cache
<C
>*);
178 __collate_compare(other_abi
, const facet
*, const C
*, const C
*,
183 __collate_transform(other_abi
, const facet
*, __any_string
&,
188 __time_get_dateorder(other_abi
, const facet
* f
);
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
>
198 __moneypunct_fill_cache(other_abi
, const facet
*,
199 __moneypunct_cache
<C
, Intl
>*);
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
*);
209 ostreambuf_iterator
<C
>
210 __money_put(other_abi
, const facet
*, ostreambuf_iterator
<C
>, bool,
211 ios_base
&, C
, long double, const __any_string
*);
214 messages_base::catalog
215 __messages_open(other_abi
, const facet
*, const char*, size_t,
220 __messages_get(other_abi
, const facet
*, __any_string
&,
221 messages_base::catalog
, int, int, const C
*, size_t);
225 __messages_close(other_abi
, const facet
*, messages_base::catalog
);
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
);
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
) { }
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(),
270 do_transform(const _CharT
* lo
, const _CharT
* hi
) const
273 __collate_transform(other_abi
{}, _M_get(), st
, lo
, hi
);
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()); }
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
,
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
,
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
,
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
,
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
,
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
);
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
) { }
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
;
375 s
= __money_get(other_abi
{}, _M_get(), s
, end
, intl
, io
, err2
,
377 if (err2
== ios_base::goodbit
)
385 do_get(iter_type s
, iter_type end
, bool intl
, ios_base
& io
,
386 ios_base::iostate
& err
, string_type
& digits
) const
389 ios_base::iostate err2
= ios_base::goodbit
;
390 s
= __money_get(other_abi
{}, _M_get(), s
, end
, intl
, io
, err2
,
392 if (err2
== ios_base::goodbit
)
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
) { }
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
,
419 do_put(iter_type s
, bool intl
, ios_base
& io
,
420 char_type fill
, const string_type
& digits
) const
424 return __money_put(other_abi
{}, _M_get(), s
, intl
, io
, fill
, 0.L
,
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
) { }
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
);
446 do_get(catalog c
, int set
, int msgid
, const string_type
& dfault
) const
449 __messages_get(other_abi
{}, _M_get(), st
, c
, set
, msgid
,
450 dfault
.c_str(), dfault
.size());
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>;
480 __copy(const C
*& dest
, const basic_string
<C
>& s
)
482 auto len
= s
.length();
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.
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());
520 __numpunct_fill_cache(current_abi
, const facet
*, __numpunct_cache
<char>*);
522 #ifdef _GLIBCXX_USE_WCHAR_T
524 __numpunct_fill_cache(current_abi
, const facet
*, __numpunct_cache
<wchar_t>*);
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
);
536 __collate_compare(current_abi
, const facet
*, const char*, const char*,
537 const char*, const char*);
539 #ifdef _GLIBCXX_USE_WCHAR_T
541 __collate_compare(current_abi
, const facet
*, const wchar_t*, const wchar_t*,
542 const wchar_t*, const wchar_t*);
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
);
555 __collate_transform(current_abi
, const facet
*, __any_string
&,
556 const char*, const char*);
558 #ifdef _GLIBCXX_USE_WCHAR_T
560 __collate_transform(current_abi
, const facet
*, __any_string
&,
561 const wchar_t*, const wchar_t*);
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
>
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();
598 __moneypunct_fill_cache(current_abi
, const facet
*,
599 __moneypunct_cache
<char, true>*);
602 __moneypunct_fill_cache(current_abi
, const facet
*,
603 __moneypunct_cache
<char, false>*);
605 #ifdef _GLIBCXX_USE_WCHAR_T
607 __moneypunct_fill_cache(current_abi
, const facet
*,
608 __moneypunct_cache
<wchar_t, true>*);
611 __moneypunct_fill_cache(current_abi
, const facet
*,
612 __moneypunct_cache
<wchar_t, false>*);
616 messages_base::catalog
617 __messages_open(current_abi
, const facet
* f
, const char* s
, size_t n
,
620 auto* m
= static_cast<const messages
<C
>*>(f
);
622 return m
->open(str
, l
);
625 template messages_base::catalog
626 __messages_open
<char>(current_abi
, const facet
*, const char*, size_t,
629 #ifdef _GLIBCXX_USE_WCHAR_T
630 template messages_base::catalog
631 __messages_open
<wchar_t>(current_abi
, const facet
*, const char*, size_t,
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
));
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
651 __messages_get(current_abi
, const facet
*, __any_string
&,
652 messages_base::catalog
, int, int, const wchar_t*, size_t);
657 __messages_close(current_abi
, const facet
* f
, messages_base::catalog c
)
659 static_cast<const messages
<C
>*>(f
)->close(c
);
663 __messages_close
<char>(current_abi
, const facet
*, messages_base::catalog c
);
665 #ifdef _GLIBCXX_USE_WCHAR_T
667 __messages_close
<wchar_t>(current_abi
, const facet
*,
668 messages_base::catalog c
);
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
*);
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
);
694 return g
->get_time(beg
, end
, io
, err
, t
);
696 return g
->get_date(beg
, end
, io
, err
, t
);
698 return g
->get_weekday(beg
, end
, io
, err
, t
);
700 return g
->get_monthname(beg
, end
, io
, err
, t
);
702 return g
->get_year(beg
, end
, io
, err
, t
);
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);
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
);
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
)
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
*);
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
);
759 return m
->put(s
, intl
, io
, fill
, *digits
);
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
*);
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.
782 #if _GLIBCXX_USE_CXX11_ABI
783 locale::facet::_M_sso_shim(const locale::id
* which
) const
785 locale::facet::_M_cow_shim(const locale::id
* which
) const
788 using namespace __facet_shims
;
791 // If this is already a shim just use its underlying facet.
792 if (auto* p
= dynamic_cast<const __shim
*>(this))
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};
830 __throw_logic_error("cannot create shim for unknown locale::facet");
833 _GLIBCXX_END_NAMESPACE_VERSION