1 // Locale support -*- C++ -*- 2 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. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 // 26 // ISO C++ 14882: 22.1 Locales 27 // 28 29 // This file defines classes that behave like the standard predefined locale 30 // facets (collate, money_get etc.) except that they forward all virtual 31 // functions to another facet which uses a different std::string ABI, 32 // converting between string types as needed. 33 // When a user replaces one of the relevant facets the corresponding shim in 34 // this file is used so that the replacement facet can be used (via the shim) 35 // in code that uses the other std::string ABI from the replacing code. 36 37 #ifndef _GLIBCXX_USE_CXX11_ABI 38 # define _GLIBCXX_USE_CXX11_ABI 1 39 #endif 40 #include <locale> 41 42 #if ! _GLIBCXX_USE_DUAL_ABI 43 # error This file should not be compiled for this configuration. 44 #endif 45 46 namespace std _GLIBCXX_VISIBILITY(default) 47 { 48 _GLIBCXX_BEGIN_NAMESPACE_VERSION 49 50 // Base class of facet shims, holds a reference to the underlying facet 51 // that the shim forwards to. 52 class locale::facet::__shim 53 { 54 public: 55 const facet* _M_get() const { return _M_facet; } 56 57 __shim(const __shim&) = delete; 58 __shim& operator=(const __shim&) = delete; 59 60 protected: 61 explicit 62 __shim(const facet* __f) : _M_facet(__f) { __f->_M_add_reference(); } 63 64 ~__shim() { _M_facet->_M_remove_reference(); } 65 66 private: 67 const facet* _M_facet; 68 }; 69 70 namespace __facet_shims 71 { 72 namespace // unnamed 73 { 74 template<typename C> 75 void __destroy_string(void* p) 76 { 77 static_cast<std::basic_string<C>*>(p)->~basic_string(); 78 } 79 } // namespace 80 81 // Manages a buffer of uninitialized memory that can store a std::string 82 // or std::wstring, using either ABI, and convert to the other ABI. 83 class __any_string 84 { 85 struct __attribute__((may_alias)) __str_rep 86 { 87 union { 88 const void* _M_p; 89 char* _M_pc; 90 #ifdef _GLIBCXX_USE_WCHAR_T 91 wchar_t* _M_pwc; 92 #endif 93 }; 94 size_t _M_len; 95 char _M_unused[16]; 96 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 101 }; 102 union { 103 __str_rep _M_str; 104 char _M_bytes[sizeof(__str_rep)]; 105 }; 106 using __dtor_func = void(*)(void*); 107 __dtor_func _M_dtor = nullptr; 108 109 #if _GLIBCXX_USE_CXX11_ABI 110 // SSO strings overlay the entire __str_rep structure. 111 static_assert(sizeof(std::string) == sizeof(__str_rep), 112 "std::string changed size!"); 113 #else 114 // COW strings overlay just the pointer, the length is stored manually. 115 static_assert(sizeof(std::string) == sizeof(__str_rep::_M_p), 116 "std::string changed size!"); 117 #endif 118 # ifdef _GLIBCXX_USE_WCHAR_T 119 static_assert(sizeof(std::wstring) == sizeof(std::string), 120 "std::wstring and std::string are different sizes!"); 121 # endif 122 123 public: 124 __any_string() = default; 125 ~__any_string() { if (_M_dtor) _M_dtor(_M_bytes); } 126 127 __any_string(const __any_string&) = delete; 128 __any_string& operator=(const __any_string&) = delete; 129 130 // Store a string (and its length if needed) in the buffer and 131 // set _M_dtor to the function that runs the right destructor. 132 template<typename C> 133 __any_string& 134 operator=(const basic_string<C>& s) 135 { 136 if (_M_dtor) 137 _M_dtor(_M_bytes); 138 ::new(_M_bytes) basic_string<C>(s); 139 #if ! _GLIBCXX_USE_CXX11_ABI 140 _M_str._M_len = s.length(); 141 #endif 142 _M_dtor = __destroy_string<C>; 143 return *this; 144 } 145 146 // Create a new string with a copy of the characters in the stored string. 147 // The returned object will match the caller's string ABI, even when the 148 // stored string doesn't. 149 template<typename C> 150 _GLIBCXX_DEFAULT_ABI_TAG 151 operator basic_string<C>() const 152 { 153 if (!_M_dtor) 154 __throw_logic_error("uninitialized __any_string"); 155 return basic_string<C>(static_cast<const C*>(_M_str), _M_str._M_len); 156 } 157 }; 158 159 // This file is compiled twice, with and without this macro defined. 160 // Define tag types to distinguish between the two cases and to allow 161 // overloading on the tag. 162 using current_abi = __bool_constant<_GLIBCXX_USE_CXX11_ABI>; 163 using other_abi = __bool_constant<!_GLIBCXX_USE_CXX11_ABI>; 164 165 using facet = locale::facet; 166 167 // Declare the functions that shims defined in this file will call to 168 // perform work in the context of the other ABI. 169 // These will be defined when this file is recompiled for the other ABI 170 // (at which point what is now "current_abi" will become "other_abi"). 171 172 template<typename C> 173 void 174 __numpunct_fill_cache(other_abi, const facet*, __numpunct_cache<C>*); 175 176 template<typename C> 177 int 178 __collate_compare(other_abi, const facet*, const C*, const C*, 179 const C*, const C*); 180 181 template<typename C> 182 void 183 __collate_transform(other_abi, const facet*, __any_string&, 184 const C*, const C*); 185 186 template<typename C> 187 time_base::dateorder 188 __time_get_dateorder(other_abi, const facet* f); 189 190 template<typename C> 191 istreambuf_iterator<C> 192 __time_get(other_abi, const facet* f, 193 istreambuf_iterator<C> beg, istreambuf_iterator<C> end, 194 ios_base& io, ios_base::iostate& err, tm* t, char which); 195 196 template<typename C, bool Intl> 197 void 198 __moneypunct_fill_cache(other_abi, const facet*, 199 __moneypunct_cache<C, Intl>*); 200 201 template<typename C> 202 istreambuf_iterator<C> 203 __money_get(other_abi, const facet*, 204 istreambuf_iterator<C>, istreambuf_iterator<C>, 205 bool, ios_base&, ios_base::iostate&, 206 long double*, __any_string*); 207 208 template<typename C> 209 ostreambuf_iterator<C> 210 __money_put(other_abi, const facet*, ostreambuf_iterator<C>, bool, 211 ios_base&, C, long double, const __any_string*); 212 213 template<typename C> 214 messages_base::catalog 215 __messages_open(other_abi, const facet*, const char*, size_t, 216 const locale&); 217 218 template<typename C> 219 void 220 __messages_get(other_abi, const facet*, __any_string&, 221 messages_base::catalog, int, int, const C*, size_t); 222 223 template<typename C> 224 void 225 __messages_close(other_abi, const facet*, messages_base::catalog); 226 227 namespace // unnamed 228 { 229 struct __shim_accessor : facet 230 { 231 using facet::__shim; // Redeclare protected member as public. 232 }; 233 using __shim = __shim_accessor::__shim; 234 235 template<typename _CharT> 236 struct numpunct_shim : std::numpunct<_CharT>, __shim 237 { 238 typedef typename numpunct<_CharT>::__cache_type __cache_type; 239 240 // f must point to a type derived from numpunct<C>[abi:other] 241 numpunct_shim(const facet* f, __cache_type* c = new __cache_type) 242 : std::numpunct<_CharT>(c), __shim(f), _M_cache(c) 243 { 244 __numpunct_fill_cache(other_abi{}, f, c); 245 } 246 247 ~numpunct_shim() 248 { 249 // Stop GNU locale's ~numpunct() from freeing the cached string. 250 _M_cache->_M_grouping_size = 0; 251 } 252 253 // No need to override any virtual functions, the base definitions 254 // will return the cached data. 255 256 __cache_type* _M_cache; 257 }; 258 259 template<typename _CharT> 260 struct collate_shim : std::collate<_CharT>, __shim 261 { 262 typedef basic_string<_CharT> string_type; 263 264 // f must point to a type derived from collate<C>[abi:other] 265 collate_shim(const facet* f) : __shim(f) { } 266 267 virtual int 268 do_compare(const _CharT* lo1, const _CharT* hi1, 269 const _CharT* lo2, const _CharT* hi2) const 270 { 271 return __collate_compare(other_abi{}, _M_get(), 272 lo1, hi1, lo2, hi2); 273 } 274 275 virtual string_type 276 do_transform(const _CharT* lo, const _CharT* hi) const 277 { 278 __any_string st; 279 __collate_transform(other_abi{}, _M_get(), st, lo, hi); 280 return st; 281 } 282 }; 283 284 template<typename _CharT> 285 struct time_get_shim : std::time_get<_CharT>, __shim 286 { 287 typedef typename std::time_get<_CharT>::iter_type iter_type; 288 typedef typename std::time_get<_CharT>::char_type char_type; 289 290 // f must point to a type derived from time_get<C>[abi:other] 291 time_get_shim(const facet* f) : __shim(f) { } 292 293 virtual time_base::dateorder 294 do_date_order() const 295 { return __time_get_dateorder<_CharT>(other_abi{}, _M_get()); } 296 297 virtual iter_type 298 do_get_time(iter_type beg, iter_type end, ios_base& io, 299 ios_base::iostate& err, tm* t) const 300 { 301 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t, 302 't'); 303 } 304 305 virtual iter_type 306 do_get_date(iter_type beg, iter_type end, ios_base& io, 307 ios_base::iostate& err, tm* t) const 308 { 309 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t, 310 'd'); 311 } 312 313 virtual iter_type 314 do_get_weekday(iter_type beg, iter_type end, ios_base& io, 315 ios_base::iostate& err, tm* t) const 316 { 317 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t, 318 'w'); 319 } 320 321 virtual iter_type 322 do_get_monthname(iter_type beg, iter_type end, ios_base& io, 323 ios_base::iostate& err, tm* t) const 324 { 325 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t, 326 'm'); 327 } 328 329 virtual iter_type 330 do_get_year(iter_type beg, iter_type end, ios_base& io, 331 ios_base::iostate& err, tm* t) const 332 { 333 return __time_get(other_abi{}, _M_get(), beg, end, io, err, t, 334 'y'); 335 } 336 }; 337 338 template<typename _CharT, bool _Intl> 339 struct moneypunct_shim : std::moneypunct<_CharT, _Intl>, __shim 340 { 341 typedef typename moneypunct<_CharT, _Intl>::__cache_type __cache_type; 342 343 // f must point to a type derived from moneypunct<C>[abi:other] 344 moneypunct_shim(const facet* f, __cache_type* c = new __cache_type) 345 : std::moneypunct<_CharT, _Intl>(c), __shim(f), _M_cache(c) 346 { 347 __moneypunct_fill_cache(other_abi{}, f, c); 348 } 349 350 ~moneypunct_shim() 351 { 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; 357 } 358 359 // No need to override any virtual functions, the base definitions 360 // will return the cached data. 361 362 __cache_type* _M_cache; 363 }; 364 365 template<typename _CharT> 366 struct money_get_shim : std::money_get<_CharT>, __shim 367 { 368 typedef typename std::money_get<_CharT>::iter_type iter_type; 369 typedef typename std::money_get<_CharT>::char_type char_type; 370 typedef typename std::money_get<_CharT>::string_type string_type; 371 372 // f must point to a type derived from money_get<C>[abi:other] 373 money_get_shim(const facet* f) : __shim(f) { } 374 375 virtual iter_type 376 do_get(iter_type s, iter_type end, bool intl, ios_base& io, 377 ios_base::iostate& err, long double& units) const 378 { 379 ios_base::iostate err2 = ios_base::goodbit; 380 long double units2; 381 s = __money_get(other_abi{}, _M_get(), s, end, intl, io, err2, 382 &units2, nullptr); 383 if (err2 == ios_base::goodbit) 384 units = units2; 385 else 386 err = err2; 387 return s; 388 } 389 390 virtual iter_type 391 do_get(iter_type s, iter_type end, bool intl, ios_base& io, 392 ios_base::iostate& err, string_type& digits) const 393 { 394 __any_string st; 395 ios_base::iostate err2 = ios_base::goodbit; 396 s = __money_get(other_abi{}, _M_get(), s, end, intl, io, err2, 397 nullptr, &st); 398 if (err2 == ios_base::goodbit) 399 digits = st; 400 else 401 err = err2; 402 return s; 403 } 404 }; 405 406 template<typename _CharT> 407 struct money_put_shim : std::money_put<_CharT>, __shim 408 { 409 typedef typename std::money_put<_CharT>::iter_type iter_type; 410 typedef typename std::money_put<_CharT>::char_type char_type; 411 typedef typename std::money_put<_CharT>::string_type string_type; 412 413 // f must point to a type derived from money_put<C>[abi:other] 414 money_put_shim(const facet* f) : __shim(f) { } 415 416 virtual iter_type 417 do_put(iter_type s, bool intl, ios_base& io, 418 char_type fill, long double units) const 419 { 420 return __money_put(other_abi{}, _M_get(), s, intl, io, fill, units, 421 nullptr); 422 } 423 424 virtual iter_type 425 do_put(iter_type s, bool intl, ios_base& io, 426 char_type fill, const string_type& digits) const 427 { 428 __any_string st; 429 st = digits; 430 return __money_put(other_abi{}, _M_get(), s, intl, io, fill, 0.L, 431 &st); 432 } 433 }; 434 435 template<typename _CharT> 436 struct messages_shim : std::messages<_CharT>, __shim 437 { 438 typedef messages_base::catalog catalog; 439 typedef basic_string<_CharT> string_type; 440 441 // f must point to a type derived from messages<C>[abi:other] 442 messages_shim(const facet* f) : __shim(f) { } 443 444 virtual catalog 445 do_open(const basic_string<char>& s, const locale& l) const 446 { 447 return __messages_open<_CharT>(other_abi{}, _M_get(), 448 s.c_str(), s.size(), l); 449 } 450 451 virtual string_type 452 do_get(catalog c, int set, int msgid, const string_type& dfault) const 453 { 454 __any_string st; 455 __messages_get(other_abi{}, _M_get(), st, c, set, msgid, 456 dfault.c_str(), dfault.size()); 457 return st; 458 } 459 460 virtual void 461 do_close(catalog c) const 462 { 463 __messages_close<_CharT>(other_abi{}, _M_get(), c); 464 } 465 }; 466 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 483 484 template<typename C> 485 inline size_t 486 __copy(const C*& dest, const basic_string<C>& s) 487 { 488 auto len = s.length(); 489 C* p = new C[len+1]; 490 s.copy(p, len); 491 p[len] = '\0'; 492 dest = p; 493 return len; 494 } 495 496 } // namespace 497 498 // Now define and instantiate the functions that will be called by the 499 // shim facets defined when this file is recompiled for the other ABI. 500 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) 507 { 508 auto* m = static_cast<const numpunct<C>*>(f); 509 510 c->_M_decimal_point = m->decimal_point(); 511 c->_M_thousands_sep = m->thousands_sep(); 512 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; 519 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()); 523 } 524 525 template void 526 __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<char>*); 527 528 #ifdef _GLIBCXX_USE_WCHAR_T 529 template void 530 __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<wchar_t>*); 531 #endif 532 533 template<typename C> 534 int 535 __collate_compare(current_abi, const facet* f, const C* lo1, const C* hi1, 536 const C* lo2, const C* hi2) 537 { 538 return static_cast<const collate<C>*>(f)->compare(lo1, hi1, lo2, hi2); 539 } 540 541 template int 542 __collate_compare(current_abi, const facet*, const char*, const char*, 543 const char*, const char*); 544 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 550 551 template<typename C> 552 void 553 __collate_transform(current_abi, const facet* f, __any_string& st, 554 const C* __lo, const C* __hi) 555 { 556 auto* c = static_cast<const collate<C>*>(f); 557 st = c->transform(__lo, __hi); 558 } 559 560 template void 561 __collate_transform(current_abi, const facet*, __any_string&, 562 const char*, const char*); 563 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 569 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) 577 { 578 auto* m = static_cast<const moneypunct<C, Intl>*>(f); 579 580 c->_M_decimal_point = m->decimal_point(); 581 c->_M_thousands_sep = m->thousands_sep(); 582 c->_M_frac_digits = m->frac_digits(); 583 584 c->_M_grouping = nullptr; 585 c->_M_curr_symbol = nullptr; 586 c->_M_positive_sign = nullptr; 587 c->_M_negative_sign = nullptr; 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; 591 592 c->_M_grouping_size = __copy(c->_M_grouping, m->grouping()); 593 c->_M_curr_symbol_size = __copy(c->_M_curr_symbol, m->curr_symbol()); 594 c->_M_positive_sign_size 595 = __copy(c->_M_positive_sign, m->positive_sign()); 596 c->_M_negative_sign_size 597 = __copy(c->_M_negative_sign, m->negative_sign()); 598 599 c->_M_pos_format = m->pos_format(); 600 c->_M_neg_format = m->neg_format(); 601 } 602 603 template void 604 __moneypunct_fill_cache(current_abi, const facet*, 605 __moneypunct_cache<char, true>*); 606 607 template void 608 __moneypunct_fill_cache(current_abi, const facet*, 609 __moneypunct_cache<char, false>*); 610 611 #ifdef _GLIBCXX_USE_WCHAR_T 612 template void 613 __moneypunct_fill_cache(current_abi, const facet*, 614 __moneypunct_cache<wchar_t, true>*); 615 616 template void 617 __moneypunct_fill_cache(current_abi, const facet*, 618 __moneypunct_cache<wchar_t, false>*); 619 #endif 620 621 template<typename C> 622 messages_base::catalog 623 __messages_open(current_abi, const facet* f, const char* s, size_t n, 624 const locale& l) 625 { 626 auto* m = static_cast<const messages<C>*>(f); 627 string str(s, n); 628 return m->open(str, l); 629 } 630 631 template messages_base::catalog 632 __messages_open<char>(current_abi, const facet*, const char*, size_t, 633 const locale&); 634 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 640 641 template<typename C> 642 void 643 __messages_get(current_abi, const facet* f, __any_string& st, 644 messages_base::catalog c, int set, int msgid, 645 const C* s, size_t n) 646 { 647 auto* m = static_cast<const messages<C>*>(f); 648 st = m->get(c, set, msgid, basic_string<C>(s, n)); 649 } 650 651 template void 652 __messages_get(current_abi, const facet*, __any_string&, 653 messages_base::catalog, int, int, const char*, size_t); 654 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 660 661 template<typename C> 662 void 663 __messages_close(current_abi, const facet* f, messages_base::catalog c) 664 { 665 static_cast<const messages<C>*>(f)->close(c); 666 } 667 668 template void 669 __messages_close<char>(current_abi, const facet*, messages_base::catalog c); 670 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 676 677 template<typename C> 678 time_base::dateorder 679 __time_get_dateorder(current_abi, const facet* f) 680 { return static_cast<const time_get<C>*>(f)->date_order(); } 681 682 template time_base::dateorder 683 __time_get_dateorder<char>(current_abi, const facet*); 684 685 #ifdef _GLIBCXX_USE_WCHAR_T 686 template time_base::dateorder 687 __time_get_dateorder<wchar_t>(current_abi, const facet*); 688 #endif 689 690 template<typename C> 691 istreambuf_iterator<C> 692 __time_get(current_abi, const facet* f, 693 istreambuf_iterator<C> beg, istreambuf_iterator<C> end, 694 ios_base& io, ios_base::iostate& err, tm* t, char which) 695 { 696 auto* g = static_cast<const time_get<C>*>(f); 697 switch(which) 698 { 699 case 't': 700 return g->get_time(beg, end, io, err, t); 701 case 'd': 702 return g->get_date(beg, end, io, err, t); 703 case 'w': 704 return g->get_weekday(beg, end, io, err, t); 705 case 'm': 706 return g->get_monthname(beg, end, io, err, t); 707 case 'y': 708 return g->get_year(beg, end, io, err, t); 709 default: 710 __builtin_unreachable(); 711 } 712 } 713 714 template istreambuf_iterator<char> 715 __time_get(current_abi, const facet*, 716 istreambuf_iterator<char>, istreambuf_iterator<char>, 717 ios_base&, ios_base::iostate&, tm*, char); 718 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 725 726 template<typename C> 727 istreambuf_iterator<C> 728 __money_get(current_abi, const facet* f, 729 istreambuf_iterator<C> s, istreambuf_iterator<C> end, 730 bool intl, ios_base& str, ios_base::iostate& err, 731 long double* units, __any_string* digits) 732 { 733 auto* m = static_cast<const money_get<C>*>(f); 734 if (units) 735 return m->get(s, end, intl, str, err, *units); 736 basic_string<C> digits2; 737 s = m->get(s, end, intl, str, err, digits2); 738 if (err == ios_base::goodbit) 739 *digits = digits2; 740 return s; 741 } 742 743 template istreambuf_iterator<char> 744 __money_get(current_abi, const facet*, 745 istreambuf_iterator<char>, istreambuf_iterator<char>, 746 bool, ios_base&, ios_base::iostate&, 747 long double*, __any_string*); 748 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 756 757 template<typename C> 758 ostreambuf_iterator<C> 759 __money_put(current_abi, const facet* f, ostreambuf_iterator<C> s, 760 bool intl, ios_base& io, C fill, long double units, 761 const __any_string* digits) 762 { 763 auto* m = static_cast<const money_put<C>*>(f); 764 if (digits) 765 return m->put(s, intl, io, fill, *digits); 766 else 767 return m->put(s, intl, io, fill, units); 768 } 769 770 template ostreambuf_iterator<char> 771 __money_put(current_abi, const facet*, ostreambuf_iterator<char>, 772 bool, ios_base&, char, long double, const __any_string*); 773 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 779 780 } // namespace __facet_shims 781 782 // Create a new shim facet of type WHICH that forwards calls to F. 783 // F is the replacement facet provided by the user, WHICH is the ID of 784 // F's "other ABI twin" which we are replacing with a shim. 785 const locale::facet* 786 #if _GLIBCXX_USE_CXX11_ABI 787 locale::facet::_M_sso_shim(const locale::id* which) const 788 #else 789 locale::facet::_M_cow_shim(const locale::id* which) const 790 #endif 791 { 792 using namespace __facet_shims; 793 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 799 800 if (which == &numpunct<char>::id) 801 return new numpunct_shim<char>{this}; 802 if (which == &std::collate<char>::id) 803 return new collate_shim<char>{this}; 804 if (which == &time_get<char>::id) 805 return new time_get_shim<char>{this}; 806 if (which == &money_get<char>::id) 807 return new money_get_shim<char>{this}; 808 if (which == &money_put<char>::id) 809 return new money_put_shim<char>{this}; 810 if (which == &moneypunct<char, true>::id) 811 return new moneypunct_shim<char, true>{this}; 812 if (which == &moneypunct<char, false>::id) 813 return new moneypunct_shim<char, false>{this}; 814 if (which == &std::messages<char>::id) 815 return new messages_shim<char>{this}; 816 #ifdef _GLIBCXX_USE_WCHAR_T 817 if (which == &numpunct<wchar_t>::id) 818 return new numpunct_shim<wchar_t>{this}; 819 if (which == &std::collate<wchar_t>::id) 820 return new collate_shim<wchar_t>{this}; 821 if (which == &time_get<wchar_t>::id) 822 return new time_get_shim<wchar_t>{this}; 823 if (which == &money_get<wchar_t>::id) 824 return new money_get_shim<wchar_t>{this}; 825 if (which == &money_put<wchar_t>::id) 826 return new money_put_shim<wchar_t>{this}; 827 if (which == &moneypunct<wchar_t, true>::id) 828 return new moneypunct_shim<wchar_t, true>{this}; 829 if (which == &moneypunct<wchar_t, false>::id) 830 return new moneypunct_shim<wchar_t, false>{this}; 831 if (which == &std::messages<wchar_t>::id) 832 return new messages_shim<wchar_t>{this}; 833 #endif 834 __throw_logic_error("cannot create shim for unknown locale::facet"); 835 } 836 837 _GLIBCXX_END_NAMESPACE_VERSION 838 } // namespace std 839