Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // Locale support -*- C++ -*-
  2.  
  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.
  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.   // Base class of facet shims, holds a reference to the underlying facet
  49.   // that the shim forwards to.
  50.   class locale::facet::__shim
  51.   {
  52.   public:
  53.     const facet* _M_get() const { return _M_facet; }
  54.  
  55.     __shim(const __shim&) = delete;
  56.     __shim& operator=(const __shim&) = delete;
  57.  
  58.   protected:
  59.     explicit
  60.     __shim(const facet* __f) : _M_facet(__f) { __f->_M_add_reference(); }
  61.  
  62.     ~__shim() { _M_facet->_M_remove_reference(); }
  63.  
  64.   private:
  65.     const facet* _M_facet;
  66.   };
  67.  
  68. namespace __facet_shims
  69. {
  70. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  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.     template<typename _CharT>
  230.       struct numpunct_shim : std::numpunct<_CharT>, facet::__shim
  231.       {
  232.         typedef typename numpunct<_CharT>::__cache_type __cache_type;
  233.  
  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)
  237.         {
  238.           __numpunct_fill_cache(other_abi{}, f, c);
  239.         }
  240.  
  241.         ~numpunct_shim()
  242.         {
  243.           // Stop GNU locale's ~numpunct() from freeing the cached string.
  244.           _M_cache->_M_grouping_size = 0;
  245.         }
  246.  
  247.         // No need to override any virtual functions, the base definitions
  248.         // will return the cached data.
  249.  
  250.         __cache_type* _M_cache;
  251.       };
  252.  
  253.     template<typename _CharT>
  254.       struct collate_shim : std::collate<_CharT>, facet::__shim
  255.       {
  256.         typedef basic_string<_CharT>    string_type;
  257.  
  258.         // f must point to a type derived from collate<C>[abi:other]
  259.         collate_shim(const facet* f) : __shim(f) { }
  260.  
  261.         virtual int
  262.         do_compare(const _CharT* lo1, const _CharT* hi1,
  263.                    const _CharT* lo2, const _CharT* hi2) const
  264.         {
  265.           return __collate_compare(other_abi{}, _M_get(),
  266.                                    lo1, hi1, lo2, hi2);
  267.         }
  268.  
  269.         virtual string_type
  270.         do_transform(const _CharT* lo, const _CharT* hi) const
  271.         {
  272.           __any_string st;
  273.           __collate_transform(other_abi{}, _M_get(), st, lo, hi);
  274.           return st;
  275.         }
  276.       };
  277.  
  278.     template<typename _CharT>
  279.       struct time_get_shim : std::time_get<_CharT>, facet::__shim
  280.       {
  281.         typedef typename std::time_get<_CharT>::iter_type iter_type;
  282.         typedef typename std::time_get<_CharT>::char_type char_type;
  283.  
  284.         // f must point to a type derived from time_get<C>[abi:other]
  285.         time_get_shim(const facet* f) : __shim(f) { }
  286.  
  287.         virtual time_base::dateorder
  288.         do_date_order() const
  289.         { return __time_get_dateorder<_CharT>(other_abi{}, _M_get()); }
  290.  
  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
  294.         {
  295.           return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
  296.                             't');
  297.         }
  298.  
  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
  302.         {
  303.           return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
  304.                             'd');
  305.         }
  306.  
  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
  310.         {
  311.           return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
  312.                             'w');
  313.         }
  314.  
  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
  318.         {
  319.           return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
  320.                             'm');
  321.         }
  322.  
  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
  326.         {
  327.           return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
  328.                             'y');
  329.         }
  330.       };
  331.  
  332.     template<typename _CharT, bool _Intl>
  333.       struct moneypunct_shim : std::moneypunct<_CharT, _Intl>, facet::__shim
  334.       {
  335.         typedef typename moneypunct<_CharT, _Intl>::__cache_type __cache_type;
  336.  
  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)
  340.         {
  341.           __moneypunct_fill_cache(other_abi{}, f, c);
  342.         }
  343.  
  344.         ~moneypunct_shim()
  345.         {
  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;
  351.         }
  352.  
  353.         // No need to override any virtual functions, the base definitions
  354.         // will return the cached data.
  355.  
  356.         __cache_type* _M_cache;
  357.       };
  358.  
  359.     template<typename _CharT>
  360.       struct money_get_shim : std::money_get<_CharT>, facet::__shim
  361.       {
  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;
  365.  
  366.         // f must point to a type derived from money_get<C>[abi:other]
  367.         money_get_shim(const facet* f) : __shim(f) { }
  368.  
  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
  372.         {
  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;
  382.         }
  383.  
  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
  387.         {
  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;
  397.         }
  398.       };
  399.  
  400.     template<typename _CharT>
  401.       struct money_put_shim : std::money_put<_CharT>, facet::__shim
  402.       {
  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;
  406.  
  407.         // f must point to a type derived from money_put<C>[abi:other]
  408.         money_put_shim(const facet* f) : __shim(f) { }
  409.  
  410.         virtual iter_type
  411.         do_put(iter_type s, bool intl, ios_base& io,
  412.                char_type fill, long double units) const
  413.         {
  414.           return __money_put(other_abi{}, _M_get(), s, intl, io, fill, units,
  415.                              nullptr);
  416.         }
  417.  
  418.         virtual iter_type
  419.         do_put(iter_type s, bool intl, ios_base& io,
  420.                char_type fill, const string_type& digits) const
  421.         {
  422.           __any_string st;
  423.           st = digits;
  424.           return __money_put(other_abi{}, _M_get(), s, intl, io, fill, 0.L,
  425.                              &st);
  426.         }
  427.       };
  428.  
  429.     template<typename _CharT>
  430.       struct messages_shim : std::messages<_CharT>, facet::__shim
  431.       {
  432.         typedef messages_base::catalog  catalog;
  433.         typedef basic_string<_CharT>    string_type;
  434.  
  435.         // f must point to a type derived from messages<C>[abi:other]
  436.         messages_shim(const facet* f) : __shim(f) { }
  437.  
  438.         virtual catalog
  439.         do_open(const basic_string<char>& s, const locale& l) const
  440.         {
  441.           return __messages_open<_CharT>(other_abi{}, _M_get(),
  442.                                          s.c_str(), s.size(), l);
  443.         }
  444.  
  445.         virtual string_type
  446.         do_get(catalog c, int set, int msgid, const string_type& dfault) const
  447.         {
  448.           __any_string st;
  449.           __messages_get(other_abi{}, _M_get(), st, c, set, msgid,
  450.                          dfault.c_str(), dfault.size());
  451.           return st;
  452.         }
  453.  
  454.         virtual void
  455.         do_close(catalog c) const
  456.         {
  457.           __messages_close<_CharT>(other_abi{}, _M_get(), c);
  458.         }
  459.       };
  460.  
  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
  477.  
  478.     template<typename C>
  479.       inline size_t
  480.       __copy(const C*& dest, const basic_string<C>& s)
  481.       {
  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;
  488.       }
  489.  
  490.   } // namespace
  491.  
  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.
  494.  
  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)
  501.     {
  502.       auto* m = static_cast<const numpunct<C>*>(f);
  503.  
  504.       c->_M_decimal_point = m->decimal_point();
  505.       c->_M_thousands_sep = m->thousands_sep();
  506.  
  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;
  513.  
  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());
  517.     }
  518.  
  519.   template void
  520.   __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<char>*);
  521.  
  522. #ifdef _GLIBCXX_USE_WCHAR_T
  523.   template void
  524.   __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<wchar_t>*);
  525. #endif
  526.  
  527.   template<typename C>
  528.     int
  529.     __collate_compare(current_abi, const facet* f, const C* lo1, const C* hi1,
  530.                       const C* lo2, const C* hi2)
  531.     {
  532.       return static_cast<const collate<C>*>(f)->compare(lo1, hi1, lo2, hi2);
  533.     }
  534.  
  535.   template int
  536.   __collate_compare(current_abi, const facet*, const char*, const char*,
  537.                     const char*, const char*);
  538.  
  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
  544.  
  545.   template<typename C>
  546.     void
  547.     __collate_transform(current_abi, const facet* f, __any_string& st,
  548.                         const C* __lo, const C* __hi)
  549.     {
  550.       auto* c = static_cast<const collate<C>*>(f);
  551.       st = c->transform(__lo, __hi);
  552.     }
  553.  
  554.   template void
  555.   __collate_transform(current_abi, const facet*, __any_string&,
  556.                       const char*, const char*);
  557.  
  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
  563.  
  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)
  571.     {
  572.       auto* m = static_cast<const moneypunct<C, Intl>*>(f);
  573.  
  574.       c->_M_decimal_point = m->decimal_point();
  575.       c->_M_thousands_sep = m->thousands_sep();
  576.       c->_M_frac_digits = m->frac_digits();
  577.  
  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;
  585.  
  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());
  592.  
  593.       c->_M_pos_format = m->pos_format();
  594.       c->_M_neg_format = m->neg_format();
  595.     }
  596.  
  597.   template void
  598.   __moneypunct_fill_cache(current_abi, const facet*,
  599.                           __moneypunct_cache<char, true>*);
  600.  
  601.   template void
  602.   __moneypunct_fill_cache(current_abi, const facet*,
  603.                           __moneypunct_cache<char, false>*);
  604.  
  605. #ifdef _GLIBCXX_USE_WCHAR_T
  606.   template void
  607.   __moneypunct_fill_cache(current_abi, const facet*,
  608.                           __moneypunct_cache<wchar_t, true>*);
  609.  
  610.   template void
  611.   __moneypunct_fill_cache(current_abi, const facet*,
  612.                           __moneypunct_cache<wchar_t, false>*);
  613. #endif
  614.  
  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)
  619.     {
  620.       auto* m = static_cast<const messages<C>*>(f);
  621.       string str(s, n);
  622.       return m->open(str, l);
  623.     }
  624.  
  625.   template messages_base::catalog
  626.   __messages_open<char>(current_abi, const facet*, const char*, size_t,
  627.                         const locale&);
  628.  
  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
  634.  
  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)
  640.     {
  641.       auto* m = static_cast<const messages<C>*>(f);
  642.       st = m->get(c, set, msgid, basic_string<C>(s, n));
  643.     }
  644.  
  645.   template void
  646.   __messages_get(current_abi, const facet*, __any_string&,
  647.                  messages_base::catalog, int, int, const char*, size_t);
  648.  
  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
  654.  
  655.   template<typename C>
  656.     void
  657.     __messages_close(current_abi, const facet* f, messages_base::catalog c)
  658.     {
  659.       static_cast<const messages<C>*>(f)->close(c);
  660.     }
  661.  
  662.   template void
  663.   __messages_close<char>(current_abi, const facet*, messages_base::catalog c);
  664.  
  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
  670.  
  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(); }
  675.  
  676.   template time_base::dateorder
  677.   __time_get_dateorder<char>(current_abi, const facet*);
  678.  
  679. #ifdef _GLIBCXX_USE_WCHAR_T
  680.   template time_base::dateorder
  681.   __time_get_dateorder<wchar_t>(current_abi, const facet*);
  682. #endif
  683.  
  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)
  689.     {
  690.       auto* g = static_cast<const time_get<C>*>(f);
  691.       switch(which)
  692.       {
  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();
  705.       }
  706.     }
  707.  
  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);
  712.  
  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
  719.  
  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)
  726.     {
  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;
  735.     }
  736.  
  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*);
  742.  
  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
  750.  
  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)
  756.     {
  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);
  762.     }
  763.  
  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*);
  767.  
  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
  773.  
  774. _GLIBCXX_END_NAMESPACE_VERSION
  775. } // namespace __facet_shims
  776.  
  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
  787.   {
  788.     using namespace __facet_shims;
  789.  
  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
  795.  
  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");
  831.   }
  832.  
  833. _GLIBCXX_END_NAMESPACE_VERSION
  834. } // namespace std
  835.