locale_classes.h

00001 // Locale support -*- C++ -*-
00002 
00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
00004 // Free Software Foundation, Inc.
00005 //
00006 // This file is part of the GNU ISO C++ Library.  This library is free
00007 // software; you can redistribute it and/or modify it under the
00008 // terms of the GNU General Public License as published by the
00009 // Free Software Foundation; either version 2, or (at your option)
00010 // any later version.
00011 
00012 // This library is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 
00017 // You should have received a copy of the GNU General Public License along
00018 // with this library; see the file COPYING.  If not, write to the Free
00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00020 // USA.
00021 
00022 // As a special exception, you may use this file as part of a free software
00023 // library without restriction.  Specifically, if other files instantiate
00024 // templates or use macros or inline functions from this file, or you compile
00025 // this file and link it with other files to produce an executable, this
00026 // file does not by itself cause the resulting executable to be covered by
00027 // the GNU General Public License.  This exception does not however
00028 // invalidate any other reasons why the executable file might be covered by
00029 // the GNU General Public License.
00030 
00031 //
00032 // ISO C++ 14882: 22.1  Locales
00033 //
00034 
00035 /** @file localefwd.h
00036  *  This is an internal header file, included by other library headers.
00037  *  You should not attempt to use it directly.
00038  */
00039 
00040 #ifndef _CPP_BITS_LOCALE_CLASSES_H
00041 #define _CPP_BITS_LOCALE_CLASSES_H  1
00042 
00043 #pragma GCC system_header
00044 
00045 #include <bits/localefwd.h>
00046 #include <cstring>      // For strcmp.
00047 #include <string>
00048 #include <bits/atomicity.h>
00049 
00050 namespace std
00051 {
00052   class __locale_cache_base;
00053   template<typename _Facet> class __locale_cache;
00054 
00055   // 22.1.1 Class locale
00056   class locale
00057   {
00058   public:
00059     // Types:
00060     typedef unsigned int    category;
00061 
00062     // Forward decls and friends:
00063     class facet;
00064     class id;
00065     class _Impl;
00066 
00067     friend class facet;
00068     friend class _Impl;
00069 
00070     template<typename _Facet>
00071       friend const _Facet& 
00072       use_facet(const locale&);
00073     
00074     template<typename _Facet>
00075       friend bool 
00076       has_facet(const locale&) throw();
00077  
00078     template<typename _Facet>
00079       friend const __locale_cache<_Facet>&
00080       __use_cache(const locale&);
00081 
00082     // Category values:
00083     // NB: Order must match _S_facet_categories definition in locale.cc
00084     static const category none      = 0;
00085     static const category ctype     = 1L << 0;
00086     static const category numeric   = 1L << 1;
00087     static const category collate   = 1L << 2;
00088     static const category time      = 1L << 3;
00089     static const category monetary  = 1L << 4;
00090     static const category messages  = 1L << 5;
00091     static const category all       = (ctype | numeric | collate |
00092                        time  | monetary | messages);
00093 
00094     // Construct/copy/destroy:
00095     locale() throw();
00096 
00097     locale(const locale& __other) throw();
00098 
00099     explicit  
00100     locale(const char* __s);
00101 
00102     locale(const locale& __base, const char* __s, category __cat);
00103 
00104     locale(const locale& __base, const locale& __add, category __cat);
00105 
00106     template<typename _Facet>
00107       locale(const locale& __other, _Facet* __f);
00108 
00109     ~locale() throw();
00110 
00111     const locale&  
00112     operator=(const locale& __other) throw();
00113 
00114     template<typename _Facet>
00115       locale  
00116       combine(const locale& __other) const;
00117 
00118     // Locale operations:
00119     string 
00120     name() const;
00121 
00122     bool 
00123     operator==(const locale& __other) const throw ();
00124 
00125     inline bool  
00126     operator!=(const locale& __other) const throw ()
00127     { return !(this->operator==(__other));  }
00128 
00129     template<typename _Char, typename _Traits, typename _Alloc>
00130       bool  
00131       operator()(const basic_string<_Char, _Traits, _Alloc>& __s1,
00132          const basic_string<_Char, _Traits, _Alloc>& __s2) const;
00133 
00134     // Global locale objects:
00135     static locale 
00136     global(const locale&);
00137 
00138     static const locale& 
00139     classic();
00140 
00141   private:
00142     // The (shared) implementation
00143     _Impl*      _M_impl;  
00144 
00145     // The "C" reference locale
00146     static _Impl*   _S_classic; 
00147 
00148     // Current global locale
00149     static _Impl*   _S_global;  
00150 
00151     // Number of standard categories. For C++, these categories are
00152     // collate, ctype, monetary, numeric, time, and messages. These
00153     // directly correspond to ISO C99 macros LC_COLLATE, LC_CTYPE,
00154     // LC_MONETARY, LC_NUMERIC, and LC_TIME. In addition, POSIX (IEEE
00155     // 1003.1-2001) specifies LC_MESSAGES.
00156     static const size_t _S_categories_size = 6;
00157 
00158     // In addition to the standard categories, the underlying
00159     // operating system is allowed to define extra LC_*
00160     // macros. For GNU systems, the following are also valid:
00161     // LC_PAPER, LC_NAME, LC_ADDRESS, LC_TELEPHONE, LC_MEASUREMENT,
00162     // and LC_IDENTIFICATION.
00163     static const size_t _S_extra_categories_size = _GLIBCPP_NUM_CATEGORIES;
00164 
00165     // Names of underlying locale categories.  
00166     // NB: locale::global() has to know how to modify all the
00167     // underlying categories, not just the ones required by the C++
00168     // standard.
00169     static const char*  _S_categories[_S_categories_size 
00170                       + _S_extra_categories_size];
00171 
00172     explicit 
00173     locale(_Impl*) throw();
00174 
00175     static inline void  
00176     _S_initialize()
00177     { 
00178       if (!_S_classic) 
00179     classic();  
00180     }
00181 
00182     static category  
00183     _S_normalize_category(category);
00184 
00185     void
00186     _M_coalesce(const locale& __base, const locale& __add, category __cat);
00187   };
00188 
00189 
00190   // Implementation object for locale 
00191   class locale::_Impl
00192   {
00193   public:
00194     // Friends.
00195     friend class locale;
00196     friend class locale::facet;
00197 
00198     template<typename _Facet>
00199       friend const _Facet&  
00200       use_facet(const locale&);
00201 
00202     template<typename _Facet>
00203       friend bool  
00204       has_facet(const locale&) throw();
00205 
00206     template<typename _Facet>
00207       friend const __locale_cache<_Facet>&
00208       __use_cache(const locale&);
00209 
00210   private:
00211     // Data Members.
00212     _Atomic_word            _M_references;
00213     facet**                 _M_facets;
00214     size_t              _M_facets_size;
00215 
00216     char*               _M_names[_S_categories_size
00217                          + _S_extra_categories_size];
00218     static const locale::id* const  _S_id_ctype[];
00219     static const locale::id* const  _S_id_numeric[];
00220     static const locale::id* const  _S_id_collate[];
00221     static const locale::id* const  _S_id_time[];
00222     static const locale::id* const  _S_id_monetary[];
00223     static const locale::id* const  _S_id_messages[];
00224     static const locale::id* const* const _S_facet_categories[];
00225 
00226     inline void 
00227     _M_add_reference() throw()
00228     { __atomic_add(&_M_references, 1); }
00229 
00230     inline void 
00231     _M_remove_reference() throw()
00232     {
00233       if (__exchange_and_add(&_M_references, -1) == 1)
00234     {
00235       try 
00236         { delete this; } 
00237       catch(...) 
00238         { }
00239     }
00240     }
00241 
00242     _Impl(const _Impl&, size_t);
00243     _Impl(const char*, size_t);
00244     _Impl(facet**, size_t, bool);
00245 
00246    ~_Impl() throw();
00247 
00248     _Impl(const _Impl&);  // Not defined.
00249 
00250     void 
00251     operator=(const _Impl&);  // Not defined.
00252 
00253     inline bool
00254     _M_check_same_name()
00255     {
00256       bool __ret = true;
00257       for (size_t __i = 0; 
00258        __ret && __i < _S_categories_size + _S_extra_categories_size - 1; 
00259        ++__i)
00260     __ret &= (strcmp(_M_names[__i], _M_names[__i + 1]) == 0);
00261       return __ret;
00262     }
00263 
00264     void 
00265     _M_replace_categories(const _Impl*, category);
00266 
00267     void 
00268     _M_replace_category(const _Impl*, const locale::id* const*);
00269 
00270     void 
00271     _M_replace_facet(const _Impl*, const locale::id*);
00272 
00273     void 
00274     _M_install_facet(const locale::id*, facet*);
00275 
00276     template<typename _Facet>
00277       inline void 
00278       _M_init_facet(_Facet* __facet)
00279       { _M_install_facet(&_Facet::id, __facet);  }
00280 
00281     // Retrieve the cache at __index.  0 is returned if the cache is
00282     // missing.  Cache is actually located at __index +
00283     // _M_facets_size.  __index must be < _M_facets_size.
00284     inline __locale_cache_base*
00285       _M_get_cache(size_t __index)
00286       {
00287     return (__locale_cache_base*)_M_facets[__index + _M_facets_size];
00288       }
00289 
00290     // Save the supplied cache at __id.  Assumes _M_get_cache has been
00291     // called.
00292     void
00293     _M_install_cache(__locale_cache_base* __cache, int __id)
00294     {
00295       _M_facets[__id + _M_facets_size] = 
00296     reinterpret_cast<locale::facet*>(__cache);
00297     }
00298       
00299   };
00300 
00301   template<typename _Facet>
00302     locale::locale(const locale& __other, _Facet* __f)
00303     {
00304       _M_impl = new _Impl(*__other._M_impl, 1);
00305 
00306       char* _M_tmp_names[_S_categories_size + _S_extra_categories_size];
00307       size_t __i = 0;
00308       try
00309     {
00310       for (; __i < _S_categories_size
00311                + _S_extra_categories_size; ++__i)
00312         {
00313           _M_tmp_names[__i] = new char[2];
00314           strcpy(_M_tmp_names[__i], "*");
00315         }
00316       _M_impl->_M_install_facet(&_Facet::id, __f);
00317     }
00318       catch(...)
00319     {
00320       _M_impl->_M_remove_reference();
00321       for (size_t __j = 0; __j < __i; ++__j)
00322         delete [] _M_tmp_names[__j];      
00323       __throw_exception_again;
00324     }
00325 
00326       for (size_t __k = 0; __k < _S_categories_size
00327                              + _S_extra_categories_size; ++__k)
00328     {
00329       delete [] _M_impl->_M_names[__k];
00330       _M_impl->_M_names[__k] = _M_tmp_names[__k];
00331     }
00332     }
00333 
00334 
00335   // 22.1.1.1.2  Class locale::facet
00336   class locale::facet
00337   {
00338   private:
00339     friend class locale;
00340     friend class locale::_Impl;
00341 
00342     _Atomic_word            _M_references;
00343 
00344   protected:
00345     // Contains data from the underlying "C" library for the classic locale.
00346     static __c_locale               _S_c_locale;
00347 
00348     // String literal for the name of the classic locale.
00349     static char             _S_c_name[2];
00350     
00351     explicit 
00352     facet(size_t __refs = 0) throw();
00353 
00354     virtual 
00355     ~facet();
00356 
00357     static void
00358     _S_create_c_locale(__c_locale& __cloc, const char* __s, 
00359                __c_locale __old = 0);
00360 
00361     static __c_locale
00362     _S_clone_c_locale(__c_locale& __cloc);
00363 
00364     static void
00365     _S_destroy_c_locale(__c_locale& __cloc);
00366 
00367   private:
00368     void 
00369     _M_add_reference() throw();
00370 
00371     void 
00372     _M_remove_reference() throw();
00373 
00374     facet(const facet&);  // Not defined.
00375 
00376     void 
00377     operator=(const facet&);  // Not defined.
00378   };
00379 
00380 
00381   // 22.1.1.1.3 Class locale::id
00382   class locale::id
00383   {
00384   private:
00385     friend class locale;
00386     friend class locale::_Impl;
00387     template<typename _Facet>
00388       friend const _Facet&  
00389       use_facet(const locale&);
00390     template<typename _Facet>
00391       friend bool           
00392       has_facet(const locale&) throw ();
00393 
00394     // NB: There is no accessor for _M_index because it may be used
00395     // before the constructor is run; the effect of calling a member
00396     // function (even an inline) would be undefined.
00397     mutable size_t      _M_index;
00398 
00399     // Last id number assigned.
00400     static _Atomic_word     _S_highwater;   
00401 
00402     void 
00403     operator=(const id&);  // Not defined.
00404 
00405     id(const id&);  // Not defined.
00406 
00407   public:
00408     // NB: This class is always a static data member, and thus can be
00409     // counted on to be zero-initialized.
00410     id();
00411 
00412     inline size_t
00413     _M_id() const
00414     {
00415       if (!_M_index)
00416     _M_index = 1 + __exchange_and_add(&_S_highwater, 1);
00417       return _M_index - 1;
00418     }
00419   };
00420 } // namespace std
00421 
00422 #endif

Generated on Thu Feb 10 23:22:56 2005 for libstdc++-v3 Source by  doxygen 1.4.0