1 // Locale support -*- C++ -*-
3 // Copyright (C) 2014-2017 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 _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
55 const facet
* _M_get() const { return _M_facet
; }
57 __shim(const __shim
&) = delete;
58 __shim
& operator=(const __shim
&) = delete;
62 __shim(const facet
* __f
) : _M_facet(__f
) { __f
->_M_add_reference(); }
64 ~__shim() { _M_facet
->_M_remove_reference(); }
67 const facet
* _M_facet
;
70 namespace __facet_shims
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 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
);
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
) { }
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(),
276 do_transform(const _CharT
* lo
, const _CharT
* hi
) const
279 __collate_transform(other_abi
{}, _M_get(), st
, lo
, hi
);
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()); }
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
,
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
,
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
,
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
,
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
,
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
);
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
) { }
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
;
381 s
= __money_get(other_abi
{}, _M_get(), s
, end
, intl
, io
, err2
,
383 if (err2
== ios_base::goodbit
)
391 do_get(iter_type s
, iter_type end
, bool intl
, ios_base
& io
,
392 ios_base::iostate
& err
, string_type
& digits
) const
395 ios_base::iostate err2
= ios_base::goodbit
;
396 s
= __money_get(other_abi
{}, _M_get(), s
, end
, intl
, io
, err2
,
398 if (err2
== ios_base::goodbit
)
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
) { }
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
,
425 do_put(iter_type s
, bool intl
, ios_base
& io
,
426 char_type fill
, const string_type
& digits
) const
430 return __money_put(other_abi
{}, _M_get(), s
, intl
, io
, fill
, 0.L
,
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
) { }
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
);
452 do_get(catalog c
, int set
, int msgid
, const string_type
& dfault
) const
455 __messages_get(other_abi
{}, _M_get(), st
, c
, set
, msgid
,
456 dfault
.c_str(), dfault
.size());
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>;
486 __copy(const C
*& dest
, const basic_string
<C
>& s
)
488 auto len
= s
.length();
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.
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());
526 __numpunct_fill_cache(current_abi
, const facet
*, __numpunct_cache
<char>*);
528 #ifdef _GLIBCXX_USE_WCHAR_T
530 __numpunct_fill_cache(current_abi
, const facet
*, __numpunct_cache
<wchar_t>*);
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
);
542 __collate_compare(current_abi
, const facet
*, const char*, const char*,
543 const char*, const char*);
545 #ifdef _GLIBCXX_USE_WCHAR_T
547 __collate_compare(current_abi
, const facet
*, const wchar_t*, const wchar_t*,
548 const wchar_t*, const wchar_t*);
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
);
561 __collate_transform(current_abi
, const facet
*, __any_string
&,
562 const char*, const char*);
564 #ifdef _GLIBCXX_USE_WCHAR_T
566 __collate_transform(current_abi
, const facet
*, __any_string
&,
567 const wchar_t*, const wchar_t*);
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
>
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();
604 __moneypunct_fill_cache(current_abi
, const facet
*,
605 __moneypunct_cache
<char, true>*);
608 __moneypunct_fill_cache(current_abi
, const facet
*,
609 __moneypunct_cache
<char, false>*);
611 #ifdef _GLIBCXX_USE_WCHAR_T
613 __moneypunct_fill_cache(current_abi
, const facet
*,
614 __moneypunct_cache
<wchar_t, true>*);
617 __moneypunct_fill_cache(current_abi
, const facet
*,
618 __moneypunct_cache
<wchar_t, false>*);
622 messages_base::catalog
623 __messages_open(current_abi
, const facet
* f
, const char* s
, size_t n
,
626 auto* m
= static_cast<const messages
<C
>*>(f
);
628 return m
->open(str
, l
);
631 template messages_base::catalog
632 __messages_open
<char>(current_abi
, const facet
*, const char*, size_t,
635 #ifdef _GLIBCXX_USE_WCHAR_T
636 template messages_base::catalog
637 __messages_open
<wchar_t>(current_abi
, const facet
*, const char*, size_t,
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
));
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
657 __messages_get(current_abi
, const facet
*, __any_string
&,
658 messages_base::catalog
, int, int, const wchar_t*, size_t);
663 __messages_close(current_abi
, const facet
* f
, messages_base::catalog c
)
665 static_cast<const messages
<C
>*>(f
)->close(c
);
669 __messages_close
<char>(current_abi
, const facet
*, messages_base::catalog c
);
671 #ifdef _GLIBCXX_USE_WCHAR_T
673 __messages_close
<wchar_t>(current_abi
, const facet
*,
674 messages_base::catalog c
);
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
*);
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
);
700 return g
->get_time(beg
, end
, io
, err
, t
);
702 return g
->get_date(beg
, end
, io
, err
, t
);
704 return g
->get_weekday(beg
, end
, io
, err
, t
);
706 return g
->get_monthname(beg
, end
, io
, err
, t
);
708 return g
->get_year(beg
, end
, io
, err
, t
);
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);
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
);
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
)
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
*);
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
);
765 return m
->put(s
, intl
, io
, fill
, *digits
);
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
*);
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.
786 #if _GLIBCXX_USE_CXX11_ABI
787 locale::facet::_M_sso_shim(const locale::id
* which
) const
789 locale::facet::_M_cow_shim(const locale::id
* which
) const
792 using namespace __facet_shims
;
795 // If this is already a shim just use its underlying facet.
796 if (auto* p
= dynamic_cast<const __shim
*>(this))
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};
834 __throw_logic_error("cannot create shim for unknown locale::facet");
837 _GLIBCXX_END_NAMESPACE_VERSION