home *** CD-ROM | disk | FTP | other *** search
/ Beginning C++ Through Gam…rogramming (2nd Edition) / BCGP2E.ISO / bloodshed / devcpp-4.9.9.2_setup.exe / locale_classes.h < prev    next >
C/C++ Source or Header  |  2005-01-29  |  17KB  |  600 lines

  1. // Locale support -*- C++ -*-
  2.  
  3. // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
  4. // Free Software Foundation, Inc.
  5. //
  6. // This file is part of the GNU ISO C++ Library.  This library is free
  7. // software; you can redistribute it and/or modify it under the
  8. // terms of the GNU General Public License as published by the
  9. // Free Software Foundation; either version 2, or (at your option)
  10. // any later version.
  11.  
  12. // This library is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. // GNU General Public License for more details.
  16.  
  17. // You should have received a copy of the GNU General Public License along
  18. // with this library; see the file COPYING.  If not, write to the Free
  19. // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  20. // USA.
  21.  
  22. // As a special exception, you may use this file as part of a free software
  23. // library without restriction.  Specifically, if other files instantiate
  24. // templates or use macros or inline functions from this file, or you compile
  25. // this file and link it with other files to produce an executable, this
  26. // file does not by itself cause the resulting executable to be covered by
  27. // the GNU General Public License.  This exception does not however
  28. // invalidate any other reasons why the executable file might be covered by
  29. // the GNU General Public License.
  30.  
  31. //
  32. // ISO C++ 14882: 22.1  Locales
  33. //
  34.  
  35. /** @file localefwd.h
  36.  *  This is an internal header file, included by other library headers.
  37.  *  You should not attempt to use it directly.
  38.  */
  39.  
  40. #ifndef _LOCALE_CLASSES_H
  41. #define _LOCALE_CLASSES_H 1
  42.  
  43. #pragma GCC system_header
  44.  
  45. #include <bits/localefwd.h>
  46. #include <cstring>        // For strcmp.
  47. #include <string>
  48. #include <bits/atomicity.h>
  49. #include <bits/gthr.h>
  50.  
  51. namespace std
  52. {
  53.   // 22.1.1 Class locale
  54.   /**
  55.    *  @brief  Container class for localization functionality.
  56.    *
  57.    *  The locale class is first a class wrapper for C library locales.  It is
  58.    *  also an extensible container for user-defined localization.  A locale is
  59.    *  a collection of facets that implement various localization features such
  60.    *  as money, time, and number printing.
  61.    *
  62.    *  Constructing C++ locales does not change the C library locale.
  63.    *
  64.    *  This library supports efficient construction and copying of locales
  65.    *  through a reference counting implementation of the locale class.
  66.   */
  67.   class locale
  68.   {
  69.   public:
  70.     // Types:
  71.     /// Definition of locale::category.
  72.     typedef int    category;
  73.  
  74.     // Forward decls and friends:
  75.     class facet;
  76.     class id;
  77.     class _Impl;
  78.  
  79.     friend class facet;
  80.     friend class _Impl;
  81.  
  82.     template<typename _Facet>
  83.       friend bool
  84.       has_facet(const locale&) throw();
  85.  
  86.     template<typename _Facet>
  87.       friend const _Facet&
  88.       use_facet(const locale&);
  89.  
  90.     template<typename _Cache>
  91.       friend struct __use_cache;
  92.  
  93.     //@{
  94.     /**
  95.      *  @brief  Category values.
  96.      *
  97.      *  The standard category values are none, ctype, numeric, collate, time,
  98.      *  monetary, and messages.  They form a bitmask that supports union and
  99.      *  intersection.  The category all is the union of these values.
  100.      *
  101.      *  @if maint
  102.      *  NB: Order must match _S_facet_categories definition in locale.cc
  103.      *  @endif
  104.     */
  105.     static const category none        = 0;
  106.     static const category ctype        = 1L << 0;
  107.     static const category numeric    = 1L << 1;
  108.     static const category collate    = 1L << 2;
  109.     static const category time        = 1L << 3;
  110.     static const category monetary    = 1L << 4;
  111.     static const category messages    = 1L << 5;
  112.     static const category all        = (ctype | numeric | collate |
  113.                        time  | monetary | messages);
  114.     //@}
  115.  
  116.     // Construct/copy/destroy:
  117.  
  118.     /**
  119.      *  @brief  Default constructor.
  120.      *
  121.      *  Constructs a copy of the global locale.  If no locale has been
  122.      *  explicitly set, this is the "C" locale.
  123.     */
  124.     locale() throw();
  125.  
  126.     /**
  127.      *  @brief  Copy constructor.
  128.      *
  129.      *  Constructs a copy of @a other.
  130.      *
  131.      *  @param  other  The locale to copy.
  132.     */
  133.     locale(const locale& __other) throw();
  134.  
  135.     /**
  136.      *  @brief  Named locale constructor.
  137.      *
  138.      *  Constructs a copy of the named C library locale.
  139.      *
  140.      *  @param  s  Name of the locale to construct.
  141.      *  @throw  std::runtime_error if s is null or an undefined locale.
  142.     */
  143.     explicit
  144.     locale(const char* __s);
  145.  
  146.     /**
  147.      *  @brief  Construct locale with facets from another locale.
  148.      *
  149.      *  Constructs a copy of the locale @a base.  The facets specified by @a
  150.      *  cat are replaced with those from the locale named by @a s.  If base is
  151.      *  named, this locale instance will also be named.
  152.      *
  153.      *  @param  base  The locale to copy.
  154.      *  @param  s  Name of the locale to use facets from.
  155.      *  @param  cat  Set of categories defining the facets to use from s.
  156.      *  @throw  std::runtime_error if s is null or an undefined locale.
  157.     */
  158.     locale(const locale& __base, const char* __s, category __cat);
  159.  
  160.     /**
  161.      *  @brief  Construct locale with facets from another locale.
  162.      *
  163.      *  Constructs a copy of the locale @a base.  The facets specified by @a
  164.      *  cat are replaced with those from the locale @a add.  If @a base and @a
  165.      *  add are named, this locale instance will also be named.
  166.      *
  167.      *  @param  base  The locale to copy.
  168.      *  @param  add  The locale to use facets from.
  169.      *  @param  cat  Set of categories defining the facets to use from add.
  170.     */
  171.     locale(const locale& __base, const locale& __add, category __cat);
  172.  
  173.     /**
  174.      *  @brief  Construct locale with another facet.
  175.      *
  176.      *  Constructs a copy of the locale @a other.  The facet @f is added to
  177.      *  @other, replacing an existing facet of type Facet if there is one.  If
  178.      *  @f is null, this locale is a copy of @a other.
  179.      *
  180.      *  @param  other  The locale to copy.
  181.      *  @param  f  The facet to add in.
  182.     */
  183.     template<typename _Facet>
  184.       locale(const locale& __other, _Facet* __f);
  185.  
  186.     /// Locale destructor.
  187.     ~locale() throw();
  188.  
  189.     /**
  190.      *  @brief  Assignment operator.
  191.      *
  192.      *  Set this locale to be a copy of @a other.
  193.      *
  194.      *  @param  other  The locale to copy.
  195.      *  @return  A reference to this locale.
  196.     */
  197.     const locale&
  198.     operator=(const locale& __other) throw();
  199.  
  200.     /**
  201.      *  @brief  Construct locale with another facet.
  202.      *
  203.      *  Constructs and returns a new copy of this locale.  Adds or replaces an
  204.      *  existing facet of type Facet from the locale @a other into the new
  205.      *  locale.
  206.      *
  207.      *  @param  Facet  The facet type to copy from other
  208.      *  @param  other  The locale to copy from.
  209.      *  @return  Newly constructed locale.
  210.      *  @throw  std::runtime_error if other has no facet of type Facet.
  211.     */
  212.     template<typename _Facet>
  213.       locale
  214.       combine(const locale& __other) const;
  215.  
  216.     // Locale operations:
  217.     /**
  218.      *  @brief  Return locale name.
  219.      *  @return  Locale name or "*" if unnamed.
  220.     */
  221.     string
  222.     name() const;
  223.  
  224.     /**
  225.      *  @brief  Locale equality.
  226.      *
  227.      *  @param  other  The locale to compare against.
  228.      *  @return  True if other and this refer to the same locale instance, are
  229.      *         copies, or have the same name.  False otherwise.
  230.     */
  231.     bool
  232.     operator==(const locale& __other) const throw ();
  233.  
  234.     /**
  235.      *  @brief  Locale inequality.
  236.      *
  237.      *  @param  other  The locale to compare against.
  238.      *  @return  ! (*this == other)
  239.     */
  240.     inline bool
  241.     operator!=(const locale& __other) const throw ()
  242.     { return !(this->operator==(__other));  }
  243.  
  244.     /**
  245.      *  @brief  Compare two strings according to collate.
  246.      *
  247.      *  Template operator to compare two strings using the compare function of
  248.      *  the collate facet in this locale.  One use is to provide the locale to
  249.      *  the sort function.  For example, a vector v of strings could be sorted
  250.      *  according to locale loc by doing:
  251.      *  @code
  252.      *  std::sort(v.begin(), v.end(), loc);
  253.      *  @endcode
  254.      *
  255.      *  @param  s1  First string to compare.
  256.      *  @param  s2  Second string to compare.
  257.      *  @return  True if collate<Char> facet compares s1 < s2, else false.
  258.     */
  259.     template<typename _Char, typename _Traits, typename _Alloc>
  260.       bool
  261.       operator()(const basic_string<_Char, _Traits, _Alloc>& __s1,
  262.          const basic_string<_Char, _Traits, _Alloc>& __s2) const;
  263.  
  264.     // Global locale objects:
  265.     /**
  266.      *  @brief  Set global locale
  267.      *
  268.      *  This function sets the global locale to the argument and returns a
  269.      *  copy of the previous global locale.  If the argument has a name, it
  270.      *  will also call std::setlocale(LC_ALL, loc.name()).
  271.      *
  272.      *  @param  locale  The new locale to make global.
  273.      *  @return  Copy of the old global locale.
  274.     */
  275.     static locale
  276.     global(const locale&);
  277.  
  278.     /**
  279.      *  @brief  Return reference to the "C" locale.
  280.     */
  281.     static const locale&
  282.     classic();
  283.  
  284.   private:
  285.     // The (shared) implementation
  286.     _Impl*        _M_impl;
  287.  
  288.     // The "C" reference locale
  289.     static _Impl*       _S_classic;
  290.  
  291.     // Current global locale
  292.     static _Impl*    _S_global;
  293.  
  294.     // Names of underlying locale categories.
  295.     // NB: locale::global() has to know how to modify all the
  296.     // underlying categories, not just the ones required by the C++
  297.     // standard.
  298.     static const char* const* const _S_categories;
  299.  
  300.     // Number of standard categories. For C++, these categories are
  301.     // collate, ctype, monetary, numeric, time, and messages. These
  302.     // directly correspond to ISO C99 macros LC_COLLATE, LC_CTYPE,
  303.     // LC_MONETARY, LC_NUMERIC, and LC_TIME. In addition, POSIX (IEEE
  304.     // 1003.1-2001) specifies LC_MESSAGES.
  305.     // In addition to the standard categories, the underlying
  306.     // operating system is allowed to define extra LC_*
  307.     // macros. For GNU systems, the following are also valid:
  308.     // LC_PAPER, LC_NAME, LC_ADDRESS, LC_TELEPHONE, LC_MEASUREMENT,
  309.     // and LC_IDENTIFICATION.
  310.     static const size_t _S_categories_size = 6 + _GLIBCXX_NUM_CATEGORIES;
  311.  
  312. #ifdef __GTHREADS
  313.     static __gthread_once_t _S_once;
  314. #endif
  315.  
  316.     explicit
  317.     locale(_Impl*) throw();
  318.  
  319.     static void
  320.     _S_initialize();
  321.  
  322.     static void
  323.     _S_initialize_once();
  324.  
  325.     static category
  326.     _S_normalize_category(category);
  327.  
  328.     void
  329.     _M_coalesce(const locale& __base, const locale& __add, category __cat);
  330.   };
  331.  
  332.  
  333.   // 22.1.1.1.2  Class locale::facet
  334.   /**
  335.    *  @brief  Localization functionality base class.
  336.    *
  337.    *  The facet class is the base class for a localization feature, such as
  338.    *  money, time, and number printing.  It provides common support for facets
  339.    *  and reference management.
  340.    *
  341.    *  Facets may not be copied or assigned.
  342.   */
  343.   class locale::facet
  344.   {
  345.   private:
  346.     friend class locale;
  347.     friend class locale::_Impl;
  348.  
  349.     mutable _Atomic_word        _M_refcount;
  350.  
  351.     // Contains data from the underlying "C" library for the classic locale.
  352.     static __c_locale                   _S_c_locale;
  353.  
  354.     // String literal for the name of the classic locale.
  355.     static const char            _S_c_name[2];
  356.  
  357. #ifdef __GTHREADS
  358.     static __gthread_once_t        _S_once;
  359. #endif
  360.  
  361.     static void
  362.     _S_initialize_once();
  363.  
  364.   protected:
  365.     /**
  366.      *  @brief  Facet constructor.
  367.      *
  368.      *  This is the constructor provided by the standard.  If refs is 0, the
  369.      *  facet is destroyed when the last referencing locale is destroyed.
  370.      *  Otherwise the facet will never be destroyed.
  371.      *
  372.      *  @param refs  The initial value for reference count.
  373.     */
  374.     explicit
  375.     facet(size_t __refs = 0) throw() : _M_refcount(__refs ? 1 : 0)
  376.     { }
  377.  
  378.     /// Facet destructor.
  379.     virtual
  380.     ~facet();
  381.  
  382.     static void
  383.     _S_create_c_locale(__c_locale& __cloc, const char* __s,
  384.                __c_locale __old = 0);
  385.  
  386.     static __c_locale
  387.     _S_clone_c_locale(__c_locale& __cloc);
  388.  
  389.     static void
  390.     _S_destroy_c_locale(__c_locale& __cloc);
  391.  
  392.     // Returns data from the underlying "C" library data for the
  393.     // classic locale.
  394.     static __c_locale
  395.     _S_get_c_locale();
  396.  
  397.     static const char*
  398.     _S_get_c_name();
  399.  
  400.   private:
  401.     inline void
  402.     _M_add_reference() const throw()
  403.     { __gnu_cxx::__atomic_add(&_M_refcount, 1); }
  404.  
  405.     inline void
  406.     _M_remove_reference() const throw()
  407.     {
  408.       if (__gnu_cxx::__exchange_and_add(&_M_refcount, -1) == 1)
  409.     {
  410.       try
  411.         { delete this; }
  412.       catch (...)
  413.         { }
  414.     }
  415.     }
  416.  
  417.     facet(const facet&);  // Not defined.
  418.  
  419.     facet&
  420.     operator=(const facet&);  // Not defined.
  421.   };
  422.  
  423.  
  424.   // 22.1.1.1.3 Class locale::id
  425.   /**
  426.    *  @brief  Facet ID class.
  427.    *
  428.    *  The ID class provides facets with an index used to identify them.
  429.    *  Every facet class must define a public static member locale::id, or be
  430.    *  derived from a facet that provides this member, otherwise the facet
  431.    *  cannot be used in a locale.  The locale::id ensures that each class
  432.    *  type gets a unique identifier.
  433.   */
  434.   class locale::id
  435.   {
  436.   private:
  437.     friend class locale;
  438.     friend class locale::_Impl;
  439.  
  440.     template<typename _Facet>
  441.       friend const _Facet&
  442.       use_facet(const locale&);
  443.  
  444.     template<typename _Facet>
  445.       friend bool
  446.       has_facet(const locale&) throw ();
  447.  
  448.     // NB: There is no accessor for _M_index because it may be used
  449.     // before the constructor is run; the effect of calling a member
  450.     // function (even an inline) would be undefined.
  451.     mutable size_t        _M_index;
  452.  
  453.     // Last id number assigned.
  454.     static _Atomic_word        _S_refcount;
  455.  
  456.     void
  457.     operator=(const id&);  // Not defined.
  458.  
  459.     id(const id&);  // Not defined.
  460.  
  461.   public:
  462.     // NB: This class is always a static data member, and thus can be
  463.     // counted on to be zero-initialized.
  464.     /// Constructor.
  465.     id() { }
  466.  
  467.     size_t
  468.     _M_id() const;
  469.   };
  470.  
  471.  
  472.   // Implementation object for locale.
  473.   class locale::_Impl
  474.   {
  475.   public:
  476.     // Friends.
  477.     friend class locale;
  478.     friend class locale::facet;
  479.  
  480.     template<typename _Facet>
  481.       friend bool
  482.       has_facet(const locale&) throw();
  483.  
  484.     template<typename _Facet>
  485.       friend const _Facet&
  486.       use_facet(const locale&);
  487.  
  488.     template<typename _Cache>
  489.       friend struct __use_cache;
  490.  
  491.   private:
  492.     // Data Members.
  493.     _Atomic_word            _M_refcount;
  494.     const facet**            _M_facets;
  495.     size_t                _M_facets_size;
  496.     const facet**            _M_caches;
  497.     char**                _M_names;
  498.     static const locale::id* const    _S_id_ctype[];
  499.     static const locale::id* const    _S_id_numeric[];
  500.     static const locale::id* const    _S_id_collate[];
  501.     static const locale::id* const    _S_id_time[];
  502.     static const locale::id* const    _S_id_monetary[];
  503.     static const locale::id* const    _S_id_messages[];
  504.     static const locale::id* const* const _S_facet_categories[];
  505.  
  506.     inline void
  507.     _M_add_reference() throw()
  508.     { __gnu_cxx::__atomic_add(&_M_refcount, 1); }
  509.  
  510.     inline void
  511.     _M_remove_reference() throw()
  512.     {
  513.       if (__gnu_cxx::__exchange_and_add(&_M_refcount, -1) == 1)
  514.     {
  515.       try
  516.         { delete this; }
  517.       catch(...)
  518.         { }
  519.     }
  520.     }
  521.  
  522.     _Impl(const _Impl&, size_t);
  523.     _Impl(const char*, size_t);
  524.     _Impl(size_t) throw();
  525.  
  526.    ~_Impl() throw();
  527.  
  528.     _Impl(const _Impl&);  // Not defined.
  529.  
  530.     void
  531.     operator=(const _Impl&);  // Not defined.
  532.  
  533.     inline bool
  534.     _M_check_same_name()
  535.     {
  536.       bool __ret = true;
  537.       for (size_t __i = 0; __ret && __i < _S_categories_size - 1; ++__i)
  538.     __ret = std::strcmp(_M_names[__i], _M_names[__i + 1]) == 0;
  539.       return __ret;
  540.     }
  541.  
  542.     void
  543.     _M_replace_categories(const _Impl*, category);
  544.  
  545.     void
  546.     _M_replace_category(const _Impl*, const locale::id* const*);
  547.  
  548.     void
  549.     _M_replace_facet(const _Impl*, const locale::id*);
  550.  
  551.     void
  552.     _M_install_facet(const locale::id*, const facet*);
  553.  
  554.     template<typename _Facet>
  555.       inline void
  556.       _M_init_facet(_Facet* __facet)
  557.       { _M_install_facet(&_Facet::id, __facet); }
  558.  
  559.     void
  560.     _M_install_cache(const facet* __cache, size_t __index) throw()
  561.     {
  562.       __cache->_M_add_reference();
  563.       _M_caches[__index] = __cache;
  564.     }
  565.   };
  566.  
  567.   template<typename _Facet>
  568.     locale::locale(const locale& __other, _Facet* __f)
  569.     {
  570.       _M_impl = new _Impl(*__other._M_impl, 1);
  571.  
  572.       char* _M_tmp_names[_S_categories_size];
  573.       size_t __i = 0;
  574.       try
  575.     {
  576.       for (; __i < _S_categories_size; ++__i)
  577.         {
  578.           _M_tmp_names[__i] = new char[2];
  579.           std::strcpy(_M_tmp_names[__i], "*");
  580.         }
  581.       _M_impl->_M_install_facet(&_Facet::id, __f);
  582.     }
  583.       catch(...)
  584.     {
  585.       _M_impl->_M_remove_reference();
  586.       for (size_t __j = 0; __j < __i; ++__j)
  587.         delete [] _M_tmp_names[__j];
  588.       __throw_exception_again;
  589.     }
  590.  
  591.       for (size_t __k = 0; __k < _S_categories_size; ++__k)
  592.     {
  593.       delete [] _M_impl->_M_names[__k];
  594.       _M_impl->_M_names[__k] = _M_tmp_names[__k];
  595.     }
  596.     }
  597. } // namespace std
  598.  
  599. #endif
  600.