1  // Locale support -*- C++ -*-
       2  
       3  // Copyright (C) 1997-2023 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  /** @file bits/locale_classes.h
      26   *  This is an internal header file, included by other library headers.
      27   *  Do not attempt to use it directly. @headername{locale}
      28   */
      29  
      30  //
      31  // ISO C++ 14882: 22.1  Locales
      32  //
      33  
      34  #ifndef _LOCALE_CLASSES_H
      35  #define _LOCALE_CLASSES_H 1
      36  
      37  #pragma GCC system_header
      38  
      39  #include <bits/localefwd.h>
      40  #include <string>
      41  #include <ext/atomicity.h>
      42  
      43  namespace std _GLIBCXX_VISIBILITY(default)
      44  {
      45  _GLIBCXX_BEGIN_NAMESPACE_VERSION
      46  
      47    // 22.1.1 Class locale
      48    /**
      49     *  @brief  Container class for localization functionality.
      50     *  @ingroup locales
      51     *
      52     *  The locale class is first a class wrapper for C library locales.  It is
      53     *  also an extensible container for user-defined localization.  A locale is
      54     *  a collection of facets that implement various localization features such
      55     *  as money, time, and number printing.
      56     *
      57     *  Constructing C++ locales does not change the C library locale.
      58     *
      59     *  This library supports efficient construction and copying of locales
      60     *  through a reference counting implementation of the locale class.
      61    */
      62    class locale
      63    {
      64    public:
      65      // Types:
      66      /// Definition of locale::category.
      67      typedef int	category;
      68  
      69      // Forward decls and friends:
      70      class facet;
      71      class id;
      72      class _Impl;
      73  
      74      friend class facet;
      75      friend class _Impl;
      76  
      77      template<typename _Facet>
      78        friend bool
      79        has_facet(const locale&) throw();
      80  
      81      template<typename _Facet>
      82        friend const _Facet&
      83        use_facet(const locale&);
      84  
      85      template<typename _Facet>
      86        friend const _Facet*
      87        __try_use_facet(const locale&) _GLIBCXX_NOTHROW;
      88  
      89      template<typename _Cache>
      90        friend struct __use_cache;
      91  
      92      ///@{
      93      /**
      94       *  @brief  Category values.
      95       *
      96       *  The standard category values are none, ctype, numeric, collate, time,
      97       *  monetary, and messages.  They form a bitmask that supports union and
      98       *  intersection.  The category all is the union of these values.
      99       *
     100       *  NB: Order must match _S_facet_categories definition in locale.cc
     101      */
     102      static const category none		= 0;
     103      static const category ctype		= 1L << 0;
     104      static const category numeric	= 1L << 1;
     105      static const category collate	= 1L << 2;
     106      static const category time		= 1L << 3;
     107      static const category monetary	= 1L << 4;
     108      static const category messages	= 1L << 5;
     109      static const category all		= (ctype | numeric | collate |
     110  					   time  | monetary | messages);
     111      ///@}
     112  
     113      // Construct/copy/destroy:
     114  
     115      /**
     116       *  @brief  Default constructor.
     117       *
     118       *  Constructs a copy of the global locale.  If no locale has been
     119       *  explicitly set, this is the C locale.
     120      */
     121      locale() throw();
     122  
     123      /**
     124       *  @brief  Copy constructor.
     125       *
     126       *  Constructs a copy of @a other.
     127       *
     128       *  @param  __other  The locale to copy.
     129      */
     130      locale(const locale& __other) throw();
     131  
     132      /**
     133       *  @brief  Named locale constructor.
     134       *
     135       *  Constructs a copy of the named C library locale.
     136       *
     137       *  @param  __s  Name of the locale to construct.
     138       *  @throw  std::runtime_error if __s is null or an undefined locale.
     139      */
     140      explicit
     141      locale(const char* __s);
     142  
     143      /**
     144       *  @brief  Construct locale with facets from another locale.
     145       *
     146       *  Constructs a copy of the locale @a base.  The facets specified by @a
     147       *  cat are replaced with those from the locale named by @a s.  If base is
     148       *  named, this locale instance will also be named.
     149       *
     150       *  @param  __base  The locale to copy.
     151       *  @param  __s  Name of the locale to use facets from.
     152       *  @param  __cat  Set of categories defining the facets to use from __s.
     153       *  @throw  std::runtime_error if __s is null or an undefined locale.
     154      */
     155      locale(const locale& __base, const char* __s, category __cat);
     156  
     157  #if __cplusplus >= 201103L
     158      /**
     159       *  @brief  Named locale constructor.
     160       *
     161       *  Constructs a copy of the named C library locale.
     162       *
     163       *  @param  __s  Name of the locale to construct.
     164       *  @throw  std::runtime_error if __s is an undefined locale.
     165      */
     166      explicit
     167      locale(const std::string& __s) : locale(__s.c_str()) { }
     168  
     169      /**
     170       *  @brief  Construct locale with facets from another locale.
     171       *
     172       *  Constructs a copy of the locale @a base.  The facets specified by @a
     173       *  cat are replaced with those from the locale named by @a s.  If base is
     174       *  named, this locale instance will also be named.
     175       *
     176       *  @param  __base  The locale to copy.
     177       *  @param  __s  Name of the locale to use facets from.
     178       *  @param  __cat  Set of categories defining the facets to use from __s.
     179       *  @throw  std::runtime_error if __s is an undefined locale.
     180      */
     181      locale(const locale& __base, const std::string& __s, category __cat)
     182      : locale(__base, __s.c_str(), __cat) { }
     183  #endif
     184  
     185      /**
     186       *  @brief  Construct locale with facets from another locale.
     187       *
     188       *  Constructs a copy of the locale @a base.  The facets specified by @a
     189       *  cat are replaced with those from the locale @a add.  If @a base and @a
     190       *  add are named, this locale instance will also be named.
     191       *
     192       *  @param  __base  The locale to copy.
     193       *  @param  __add  The locale to use facets from.
     194       *  @param  __cat  Set of categories defining the facets to use from add.
     195      */
     196      locale(const locale& __base, const locale& __add, category __cat);
     197  
     198      /**
     199       *  @brief  Construct locale with another facet.
     200       *
     201       *  Constructs a copy of the locale @a __other.  The facet @a __f
     202       *  is added to @a __other, replacing an existing facet of type
     203       *  Facet if there is one.  If @a __f is null, this locale is a
     204       *  copy of @a __other.
     205       *
     206       *  @param  __other  The locale to copy.
     207       *  @param  __f  The facet to add in.
     208      */
     209      template<typename _Facet>
     210        locale(const locale& __other, _Facet* __f);
     211  
     212      /// Locale destructor.
     213      ~locale() throw();
     214  
     215      /**
     216       *  @brief  Assignment operator.
     217       *
     218       *  Set this locale to be a copy of @a other.
     219       *
     220       *  @param  __other  The locale to copy.
     221       *  @return  A reference to this locale.
     222      */
     223      const locale&
     224      operator=(const locale& __other) throw();
     225  
     226      /**
     227       *  @brief  Construct locale with another facet.
     228       *
     229       *  Constructs and returns a new copy of this locale.  Adds or replaces an
     230       *  existing facet of type Facet from the locale @a other into the new
     231       *  locale.
     232       *
     233       *  @tparam  _Facet  The facet type to copy from other
     234       *  @param  __other  The locale to copy from.
     235       *  @return  Newly constructed locale.
     236       *  @throw  std::runtime_error if __other has no facet of type _Facet.
     237      */
     238      template<typename _Facet>
     239        locale
     240        combine(const locale& __other) const;
     241  
     242      // Locale operations:
     243      /**
     244       *  @brief  Return locale name.
     245       *  @return  Locale name or "*" if unnamed.
     246      */
     247      _GLIBCXX_DEFAULT_ABI_TAG
     248      string
     249      name() const;
     250  
     251      /**
     252       *  @brief  Locale equality.
     253       *
     254       *  @param  __other  The locale to compare against.
     255       *  @return  True if other and this refer to the same locale instance, are
     256       *		 copies, or have the same name.  False otherwise.
     257      */
     258      bool
     259      operator==(const locale& __other) const throw();
     260  
     261  #if __cpp_impl_three_way_comparison < 201907L
     262      /**
     263       *  @brief  Locale inequality.
     264       *
     265       *  @param  __other  The locale to compare against.
     266       *  @return  ! (*this == __other)
     267      */
     268      bool
     269      operator!=(const locale& __other) const throw()
     270      { return !(this->operator==(__other)); }
     271  #endif
     272  
     273      /**
     274       *  @brief  Compare two strings according to collate.
     275       *
     276       *  Template operator to compare two strings using the compare function of
     277       *  the collate facet in this locale.  One use is to provide the locale to
     278       *  the sort function.  For example, a vector v of strings could be sorted
     279       *  according to locale loc by doing:
     280       *  @code
     281       *  std::sort(v.begin(), v.end(), loc);
     282       *  @endcode
     283       *
     284       *  @param  __s1  First string to compare.
     285       *  @param  __s2  Second string to compare.
     286       *  @return  True if collate<_Char> facet compares __s1 < __s2, else false.
     287      */
     288      template<typename _Char, typename _Traits, typename _Alloc>
     289        bool
     290        operator()(const basic_string<_Char, _Traits, _Alloc>& __s1,
     291  		 const basic_string<_Char, _Traits, _Alloc>& __s2) const;
     292  
     293      // Global locale objects:
     294      /**
     295       *  @brief  Set global locale
     296       *
     297       *  This function sets the global locale to the argument and returns a
     298       *  copy of the previous global locale.  If the argument has a name, it
     299       *  will also call std::setlocale(LC_ALL, loc.name()).
     300       *
     301       *  @param  __loc  The new locale to make global.
     302       *  @return  Copy of the old global locale.
     303      */
     304      static locale
     305      global(const locale& __loc);
     306  
     307      /**
     308       *  @brief  Return reference to the C locale.
     309      */
     310      static const locale&
     311      classic();
     312  
     313    private:
     314      // The (shared) implementation
     315      _Impl*		_M_impl;
     316  
     317      // The "C" reference locale
     318      static _Impl*       _S_classic;
     319  
     320      // Current global locale
     321      static _Impl*	_S_global;
     322  
     323      // Names of underlying locale categories.
     324      // NB: locale::global() has to know how to modify all the
     325      // underlying categories, not just the ones required by the C++
     326      // standard.
     327      static const char* const* const _S_categories;
     328  
     329      // Number of standard categories. For C++, these categories are
     330      // collate, ctype, monetary, numeric, time, and messages. These
     331      // directly correspond to ISO C99 macros LC_COLLATE, LC_CTYPE,
     332      // LC_MONETARY, LC_NUMERIC, and LC_TIME. In addition, POSIX (IEEE
     333      // 1003.1-2001) specifies LC_MESSAGES.
     334      // In addition to the standard categories, the underlying
     335      // operating system is allowed to define extra LC_*
     336      // macros. For GNU systems, the following are also valid:
     337      // LC_PAPER, LC_NAME, LC_ADDRESS, LC_TELEPHONE, LC_MEASUREMENT,
     338      // and LC_IDENTIFICATION.
     339      enum { _S_categories_size = 6 + _GLIBCXX_NUM_CATEGORIES };
     340  
     341  #ifdef __GTHREADS
     342      static __gthread_once_t _S_once;
     343  #endif
     344  
     345      explicit
     346      locale(_Impl*) throw();
     347  
     348      static void
     349      _S_initialize();
     350  
     351      static void
     352      _S_initialize_once() throw();
     353  
     354      static category
     355      _S_normalize_category(category);
     356  
     357      void
     358      _M_coalesce(const locale& __base, const locale& __add, category __cat);
     359  
     360  #if _GLIBCXX_USE_CXX11_ABI
     361      static const id* const _S_twinned_facets[];
     362  #endif
     363    };
     364  
     365  
     366    // 22.1.1.1.2  Class locale::facet
     367    /**
     368     *  @brief  Localization functionality base class.
     369     *  @ingroup locales
     370     *
     371     *  The facet class is the base class for a localization feature, such as
     372     *  money, time, and number printing.  It provides common support for facets
     373     *  and reference management.
     374     *
     375     *  Facets may not be copied or assigned.
     376    */
     377    class locale::facet
     378    {
     379    private:
     380      friend class locale;
     381      friend class locale::_Impl;
     382  
     383      mutable _Atomic_word		_M_refcount;
     384  
     385      // Contains data from the underlying "C" library for the classic locale.
     386      static __c_locale                   _S_c_locale;
     387  
     388      // String literal for the name of the classic locale.
     389      static const char			_S_c_name[2];
     390  
     391  #ifdef __GTHREADS
     392      static __gthread_once_t		_S_once;
     393  #endif
     394  
     395      static void
     396      _S_initialize_once();
     397  
     398    protected:
     399      /**
     400       *  @brief  Facet constructor.
     401       *
     402       *  This is the constructor provided by the standard.  If refs is 0, the
     403       *  facet is destroyed when the last referencing locale is destroyed.
     404       *  Otherwise the facet will never be destroyed.
     405       *
     406       *  @param __refs  The initial value for reference count.
     407      */
     408      explicit
     409      facet(size_t __refs = 0) throw() : _M_refcount(__refs ? 1 : 0)
     410      { }
     411  
     412      /// Facet destructor.
     413      virtual
     414      ~facet();
     415  
     416      static void
     417      _S_create_c_locale(__c_locale& __cloc, const char* __s,
     418  		       __c_locale __old = 0);
     419  
     420      static __c_locale
     421      _S_clone_c_locale(__c_locale& __cloc) throw();
     422  
     423      static void
     424      _S_destroy_c_locale(__c_locale& __cloc);
     425  
     426      static __c_locale
     427      _S_lc_ctype_c_locale(__c_locale __cloc, const char* __s);
     428  
     429      // Returns data from the underlying "C" library data for the
     430      // classic locale.
     431      static __c_locale
     432      _S_get_c_locale();
     433  
     434      _GLIBCXX_CONST static const char*
     435      _S_get_c_name() throw();
     436  
     437  #if __cplusplus < 201103L
     438    private:
     439      facet(const facet&);  // Not defined.
     440  
     441      facet&
     442      operator=(const facet&);  // Not defined.
     443  #else
     444      facet(const facet&) = delete;
     445  
     446      facet&
     447      operator=(const facet&) = delete;
     448  #endif
     449  
     450    private:
     451      void
     452      _M_add_reference() const throw()
     453      { __gnu_cxx::__atomic_add_dispatch(&_M_refcount, 1); }
     454  
     455      void
     456      _M_remove_reference() const throw()
     457      {
     458        // Be race-detector-friendly.  For more info see bits/c++config.
     459        _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_refcount);
     460        if (__gnu_cxx::__exchange_and_add_dispatch(&_M_refcount, -1) == 1)
     461  	{
     462            _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_refcount);
     463  	  __try
     464  	    { delete this; }
     465  	  __catch(...)
     466  	    { }
     467  	}
     468      }
     469  
     470      const facet* _M_sso_shim(const id*) const;
     471      const facet* _M_cow_shim(const id*) const;
     472  
     473    protected:
     474      class __shim; // For internal use only.
     475    };
     476  
     477  
     478    // 22.1.1.1.3 Class locale::id
     479    /**
     480     *  @brief  Facet ID class.
     481     *  @ingroup locales
     482     *
     483     *  The ID class provides facets with an index used to identify them.
     484     *  Every facet class must define a public static member locale::id, or be
     485     *  derived from a facet that provides this member, otherwise the facet
     486     *  cannot be used in a locale.  The locale::id ensures that each class
     487     *  type gets a unique identifier.
     488    */
     489    class locale::id
     490    {
     491    private:
     492      friend class locale;
     493      friend class locale::_Impl;
     494  
     495      template<typename _Facet>
     496        friend const _Facet&
     497        use_facet(const locale&);
     498  
     499      template<typename _Facet>
     500        friend bool
     501        has_facet(const locale&) throw();
     502  
     503      template<typename _Facet>
     504        friend const _Facet*
     505        __try_use_facet(const locale&) _GLIBCXX_NOTHROW;
     506  
     507      // NB: There is no accessor for _M_index because it may be used
     508      // before the constructor is run; the effect of calling a member
     509      // function (even an inline) would be undefined.
     510      mutable size_t		_M_index;
     511  
     512      // Last id number assigned.
     513      static _Atomic_word		_S_refcount;
     514  
     515      void
     516      operator=(const id&);  // Not defined.
     517  
     518      id(const id&);  // Not defined.
     519  
     520    public:
     521      // NB: This class is always a static data member, and thus can be
     522      // counted on to be zero-initialized.
     523      /// Constructor.
     524      id() { }
     525  
     526      size_t
     527      _M_id() const throw();
     528    };
     529  
     530  
     531    // Implementation object for locale.
     532    class locale::_Impl
     533    {
     534    public:
     535      // Friends.
     536      friend class locale;
     537      friend class locale::facet;
     538  
     539      template<typename _Facet>
     540        friend bool
     541        has_facet(const locale&) throw();
     542  
     543      template<typename _Facet>
     544        friend const _Facet&
     545        use_facet(const locale&);
     546  
     547      template<typename _Facet>
     548        friend const _Facet*
     549        __try_use_facet(const locale&) _GLIBCXX_NOTHROW;
     550  
     551      template<typename _Cache>
     552        friend struct __use_cache;
     553  
     554    private:
     555      // Data Members.
     556      _Atomic_word			_M_refcount;
     557      const facet**			_M_facets;
     558      size_t				_M_facets_size;
     559      const facet**			_M_caches;
     560      char**				_M_names;
     561      static const locale::id* const	_S_id_ctype[];
     562      static const locale::id* const	_S_id_numeric[];
     563      static const locale::id* const	_S_id_collate[];
     564      static const locale::id* const	_S_id_time[];
     565      static const locale::id* const	_S_id_monetary[];
     566      static const locale::id* const	_S_id_messages[];
     567      static const locale::id* const* const _S_facet_categories[];
     568  
     569      void
     570      _M_add_reference() throw()
     571      { __gnu_cxx::__atomic_add_dispatch(&_M_refcount, 1); }
     572  
     573      void
     574      _M_remove_reference() throw()
     575      {
     576        // Be race-detector-friendly.  For more info see bits/c++config.
     577        _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_refcount);
     578        if (__gnu_cxx::__exchange_and_add_dispatch(&_M_refcount, -1) == 1)
     579  	{
     580            _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_refcount);
     581  	  __try
     582  	    { delete this; }
     583  	  __catch(...)
     584  	    { }
     585  	}
     586      }
     587  
     588      _Impl(const _Impl&, size_t);
     589      _Impl(const char*, size_t);
     590      _Impl(size_t) throw();
     591  
     592     ~_Impl() throw();
     593  
     594      _Impl(const _Impl&);  // Not defined.
     595  
     596      void
     597      operator=(const _Impl&);  // Not defined.
     598  
     599      bool
     600      _M_check_same_name()
     601      {
     602        bool __ret = true;
     603        if (_M_names[1])
     604  	// We must actually compare all the _M_names: can be all equal!
     605  	for (size_t __i = 0; __ret && __i < _S_categories_size - 1; ++__i)
     606  	  __ret = __builtin_strcmp(_M_names[__i], _M_names[__i + 1]) == 0;
     607        return __ret;
     608      }
     609  
     610      void
     611      _M_replace_categories(const _Impl*, category);
     612  
     613      void
     614      _M_replace_category(const _Impl*, const locale::id* const*);
     615  
     616      void
     617      _M_replace_facet(const _Impl*, const locale::id*);
     618  
     619      void
     620      _M_install_facet(const locale::id*, const facet*);
     621  
     622      template<typename _Facet>
     623        void
     624        _M_init_facet(_Facet* __facet)
     625        { _M_install_facet(&_Facet::id, __facet); }
     626  
     627      template<typename _Facet>
     628        void
     629        _M_init_facet_unchecked(_Facet* __facet)
     630        {
     631  	__facet->_M_add_reference();
     632  	_M_facets[_Facet::id._M_id()] = __facet;
     633        }
     634  
     635      void
     636      _M_install_cache(const facet*, size_t);
     637  
     638      void _M_init_extra(facet**);
     639      void _M_init_extra(void*, void*, const char*, const char*);
     640  
     641  #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
     642      void _M_init_extra_ldbl128(bool);
     643  #endif
     644    };
     645  
     646  
     647    /**
     648     *  @brief  Facet for localized string comparison.
     649     *
     650     *  This facet encapsulates the code to compare strings in a localized
     651     *  manner.
     652     *
     653     *  The collate template uses protected virtual functions to provide
     654     *  the actual results.  The public accessors forward the call to
     655     *  the virtual functions.  These virtual functions are hooks for
     656     *  developers to implement the behavior they require from the
     657     *  collate facet.
     658    */
     659    template<typename _CharT>
     660      class _GLIBCXX_NAMESPACE_CXX11 collate : public locale::facet
     661      {
     662      public:
     663        // Types:
     664        ///@{
     665        /// Public typedefs
     666        typedef _CharT			char_type;
     667        typedef basic_string<_CharT>	string_type;
     668        ///@}
     669  
     670      protected:
     671        // Underlying "C" library locale information saved from
     672        // initialization, needed by collate_byname as well.
     673        __c_locale			_M_c_locale_collate;
     674  
     675      public:
     676        /// Numpunct facet id.
     677        static locale::id			id;
     678  
     679        /**
     680         *  @brief  Constructor performs initialization.
     681         *
     682         *  This is the constructor provided by the standard.
     683         *
     684         *  @param __refs  Passed to the base facet class.
     685        */
     686        explicit
     687        collate(size_t __refs = 0)
     688        : facet(__refs), _M_c_locale_collate(_S_get_c_locale())
     689        { }
     690  
     691        /**
     692         *  @brief  Internal constructor. Not for general use.
     693         *
     694         *  This is a constructor for use by the library itself to set up new
     695         *  locales.
     696         *
     697         *  @param __cloc  The C locale.
     698         *  @param __refs  Passed to the base facet class.
     699        */
     700        explicit
     701        collate(__c_locale __cloc, size_t __refs = 0)
     702        : facet(__refs), _M_c_locale_collate(_S_clone_c_locale(__cloc))
     703        { }
     704  
     705        /**
     706         *  @brief  Compare two strings.
     707         *
     708         *  This function compares two strings and returns the result by calling
     709         *  collate::do_compare().
     710         *
     711         *  @param __lo1  Start of string 1.
     712         *  @param __hi1  End of string 1.
     713         *  @param __lo2  Start of string 2.
     714         *  @param __hi2  End of string 2.
     715         *  @return  1 if string1 > string2, -1 if string1 < string2, else 0.
     716        */
     717        int
     718        compare(const _CharT* __lo1, const _CharT* __hi1,
     719  	      const _CharT* __lo2, const _CharT* __hi2) const
     720        { return this->do_compare(__lo1, __hi1, __lo2, __hi2); }
     721  
     722        /**
     723         *  @brief  Transform string to comparable form.
     724         *
     725         *  This function is a wrapper for strxfrm functionality.  It takes the
     726         *  input string and returns a modified string that can be directly
     727         *  compared to other transformed strings.  In the C locale, this
     728         *  function just returns a copy of the input string.  In some other
     729         *  locales, it may replace two chars with one, change a char for
     730         *  another, etc.  It does so by returning collate::do_transform().
     731         *
     732         *  @param __lo  Start of string.
     733         *  @param __hi  End of string.
     734         *  @return  Transformed string_type.
     735        */
     736        string_type
     737        transform(const _CharT* __lo, const _CharT* __hi) const
     738        { return this->do_transform(__lo, __hi); }
     739  
     740        /**
     741         *  @brief  Return hash of a string.
     742         *
     743         *  This function computes and returns a hash on the input string.  It
     744         *  does so by returning collate::do_hash().
     745         *
     746         *  @param __lo  Start of string.
     747         *  @param __hi  End of string.
     748         *  @return  Hash value.
     749        */
     750        long
     751        hash(const _CharT* __lo, const _CharT* __hi) const
     752        { return this->do_hash(__lo, __hi); }
     753  
     754        // Used to abstract out _CharT bits in virtual member functions, below.
     755        int
     756        _M_compare(const _CharT*, const _CharT*) const throw();
     757  
     758        size_t
     759        _M_transform(_CharT*, const _CharT*, size_t) const throw();
     760  
     761    protected:
     762        /// Destructor.
     763        virtual
     764        ~collate()
     765        { _S_destroy_c_locale(_M_c_locale_collate); }
     766  
     767        /**
     768         *  @brief  Compare two strings.
     769         *
     770         *  This function is a hook for derived classes to change the value
     771         *  returned.  @see compare().
     772         *
     773         *  @param __lo1  Start of string 1.
     774         *  @param __hi1  End of string 1.
     775         *  @param __lo2  Start of string 2.
     776         *  @param __hi2  End of string 2.
     777         *  @return  1 if string1 > string2, -1 if string1 < string2, else 0.
     778        */
     779        virtual int
     780        do_compare(const _CharT* __lo1, const _CharT* __hi1,
     781  		 const _CharT* __lo2, const _CharT* __hi2) const;
     782  
     783        /**
     784         *  @brief  Transform string to comparable form.
     785         *
     786         *  This function is a hook for derived classes to change the value
     787         *  returned.
     788         *
     789         *  @param __lo  Start.
     790         *  @param __hi  End.
     791         *  @return  transformed string.
     792        */
     793        virtual string_type
     794        do_transform(const _CharT* __lo, const _CharT* __hi) const;
     795  
     796        /**
     797         *  @brief  Return hash of a string.
     798         *
     799         *  This function computes and returns a hash on the input string.  This
     800         *  function is a hook for derived classes to change the value returned.
     801         *
     802         *  @param __lo  Start of string.
     803         *  @param __hi  End of string.
     804         *  @return  Hash value.
     805        */
     806        virtual long
     807        do_hash(const _CharT* __lo, const _CharT* __hi) const;
     808      };
     809  
     810    template<typename _CharT>
     811      locale::id collate<_CharT>::id;
     812  
     813    // Specializations.
     814    template<>
     815      int
     816      collate<char>::_M_compare(const char*, const char*) const throw();
     817  
     818    template<>
     819      size_t
     820      collate<char>::_M_transform(char*, const char*, size_t) const throw();
     821  
     822  #ifdef _GLIBCXX_USE_WCHAR_T
     823    template<>
     824      int
     825      collate<wchar_t>::_M_compare(const wchar_t*, const wchar_t*) const throw();
     826  
     827    template<>
     828      size_t
     829      collate<wchar_t>::_M_transform(wchar_t*, const wchar_t*, size_t) const throw();
     830  #endif
     831  
     832    /// class collate_byname [22.2.4.2].
     833    template<typename _CharT>
     834      class _GLIBCXX_NAMESPACE_CXX11 collate_byname : public collate<_CharT>
     835      {
     836      public:
     837        ///@{
     838        /// Public typedefs
     839        typedef _CharT               char_type;
     840        typedef basic_string<_CharT> string_type;
     841        ///@}
     842  
     843        explicit
     844        collate_byname(const char* __s, size_t __refs = 0)
     845        : collate<_CharT>(__refs)
     846        {
     847  	if (__builtin_strcmp(__s, "C") != 0
     848  	    && __builtin_strcmp(__s, "POSIX") != 0)
     849  	  {
     850  	    this->_S_destroy_c_locale(this->_M_c_locale_collate);
     851  	    this->_S_create_c_locale(this->_M_c_locale_collate, __s);
     852  	  }
     853        }
     854  
     855  #if __cplusplus >= 201103L
     856        explicit
     857        collate_byname(const string& __s, size_t __refs = 0)
     858        : collate_byname(__s.c_str(), __refs) { }
     859  #endif
     860  
     861      protected:
     862        virtual
     863        ~collate_byname() { }
     864      };
     865  
     866  _GLIBCXX_END_NAMESPACE_VERSION
     867  } // namespace
     868  
     869  # include <bits/locale_classes.tcc>
     870  
     871  #endif