locale_classes.h revision 117397
1// Locale support -*- C++ -*-
2
3// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
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 _CPP_BITS_LOCALE_CLASSES_H
41#define _CPP_BITS_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
50namespace std
51{
52  class __locale_cache_base;
53  template<typename _Facet> class __locale_cache;
54
55  // 22.1.1 Class locale
56  class locale
57  {
58  public:
59    // Types:
60    typedef unsigned int 	category;
61
62    // Forward decls and friends:
63    class facet;
64    class id;
65    class _Impl;
66
67    friend class facet;
68    friend class _Impl;
69
70    template<typename _Facet>
71      friend const _Facet&
72      use_facet(const locale&);
73
74    template<typename _Facet>
75      friend bool
76      has_facet(const locale&) throw();
77
78    template<typename _Facet>
79      friend const __locale_cache<_Facet>&
80      __use_cache(const locale&);
81
82    // Category values:
83    // NB: Order must match _S_facet_categories definition in locale.cc
84    static const category none		= 0;
85    static const category ctype 	= 1L << 0;
86    static const category numeric 	= 1L << 1;
87    static const category collate  	= 1L << 2;
88    static const category time 		= 1L << 3;
89    static const category monetary 	= 1L << 4;
90    static const category messages 	= 1L << 5;
91    static const category all 		= (ctype | numeric | collate |
92				 	   time  | monetary | messages);
93
94    // Construct/copy/destroy:
95    locale() throw();
96
97    locale(const locale& __other) throw();
98
99    explicit
100    locale(const char* __s);
101
102    locale(const locale& __base, const char* __s, category __cat);
103
104    locale(const locale& __base, const locale& __add, category __cat);
105
106    template<typename _Facet>
107      locale(const locale& __other, _Facet* __f);
108
109    ~locale() throw();
110
111    const locale&
112    operator=(const locale& __other) throw();
113
114    template<typename _Facet>
115      locale
116      combine(const locale& __other) const;
117
118    // Locale operations:
119    string
120    name() const;
121
122    bool
123    operator==(const locale& __other) const throw ();
124
125    inline bool
126    operator!=(const locale& __other) const throw ()
127    { return !(this->operator==(__other));  }
128
129    template<typename _Char, typename _Traits, typename _Alloc>
130      bool
131      operator()(const basic_string<_Char, _Traits, _Alloc>& __s1,
132		 const basic_string<_Char, _Traits, _Alloc>& __s2) const;
133
134    // Global locale objects:
135    static locale
136    global(const locale&);
137
138    static const locale&
139    classic();
140
141  private:
142    // The (shared) implementation
143    _Impl* 		_M_impl;
144
145    // The "C" reference locale
146    static _Impl* 	_S_classic;
147
148    // Current global locale
149    static _Impl* 	_S_global;
150
151    // Number of standard categories. For C++, these categories are
152    // collate, ctype, monetary, numeric, time, and messages. These
153    // directly correspond to ISO C99 macros LC_COLLATE, LC_CTYPE,
154    // LC_MONETARY, LC_NUMERIC, and LC_TIME. In addition, POSIX (IEEE
155    // 1003.1-2001) specifies LC_MESSAGES.
156    static const size_t	_S_categories_size = 6;
157
158    // In addition to the standard categories, the underlying
159    // operating system is allowed to define extra LC_*
160    // macros. For GNU systems, the following are also valid:
161    // LC_PAPER, LC_NAME, LC_ADDRESS, LC_TELEPHONE, LC_MEASUREMENT,
162    // and LC_IDENTIFICATION.
163    static const size_t	_S_extra_categories_size = _GLIBCPP_NUM_CATEGORIES;
164
165    // Names of underlying locale categories.
166    // NB: locale::global() has to know how to modify all the
167    // underlying categories, not just the ones required by the C++
168    // standard.
169    static const char* 	_S_categories[_S_categories_size
170				      + _S_extra_categories_size];
171
172    explicit
173    locale(_Impl*) throw();
174
175    static inline void
176    _S_initialize()
177    {
178      if (!_S_classic)
179	classic();
180    }
181
182    static category
183    _S_normalize_category(category);
184
185    void
186    _M_coalesce(const locale& __base, const locale& __add, category __cat);
187  };
188
189
190  // Implementation object for locale
191  class locale::_Impl
192  {
193  public:
194    // Friends.
195    friend class locale;
196    friend class locale::facet;
197
198    template<typename _Facet>
199      friend const _Facet&
200      use_facet(const locale&);
201
202    template<typename _Facet>
203      friend bool
204      has_facet(const locale&) throw();
205
206    template<typename _Facet>
207      friend const __locale_cache<_Facet>&
208      __use_cache(const locale&);
209
210  private:
211    // Data Members.
212    _Atomic_word			_M_references;
213    facet** 				_M_facets;
214    size_t 				_M_facets_size;
215
216    char* 				_M_names[_S_categories_size
217						 + _S_extra_categories_size];
218    static const locale::id* const 	_S_id_ctype[];
219    static const locale::id* const 	_S_id_numeric[];
220    static const locale::id* const 	_S_id_collate[];
221    static const locale::id* const 	_S_id_time[];
222    static const locale::id* const 	_S_id_monetary[];
223    static const locale::id* const 	_S_id_messages[];
224    static const locale::id* const* const _S_facet_categories[];
225
226    inline void
227    _M_add_reference() throw()
228    { __atomic_add(&_M_references, 1); }
229
230    inline void
231    _M_remove_reference() throw()
232    {
233      if (__exchange_and_add(&_M_references, -1) == 1)
234	{
235	  try
236	    { delete this; }
237	  catch(...)
238	    { }
239	}
240    }
241
242    _Impl(const _Impl&, size_t);
243    _Impl(const char*, size_t);
244    _Impl(facet**, size_t, bool);
245
246   ~_Impl() throw();
247
248    _Impl(const _Impl&);  // Not defined.
249
250    void
251    operator=(const _Impl&);  // Not defined.
252
253    inline bool
254    _M_check_same_name()
255    {
256      bool __ret = true;
257      for (size_t __i = 0;
258	   __ret && __i < _S_categories_size + _S_extra_categories_size - 1;
259	   ++__i)
260	__ret &= (strcmp(_M_names[__i], _M_names[__i + 1]) == 0);
261      return __ret;
262    }
263
264    void
265    _M_replace_categories(const _Impl*, category);
266
267    void
268    _M_replace_category(const _Impl*, const locale::id* const*);
269
270    void
271    _M_replace_facet(const _Impl*, const locale::id*);
272
273    void
274    _M_install_facet(const locale::id*, facet*);
275
276    template<typename _Facet>
277      inline void
278      _M_init_facet(_Facet* __facet)
279      { _M_install_facet(&_Facet::id, __facet);  }
280
281    // Retrieve the cache at __index.  0 is returned if the cache is
282    // missing.  Cache is actually located at __index +
283    // _M_facets_size.  __index must be < _M_facets_size.
284    inline __locale_cache_base*
285      _M_get_cache(size_t __index)
286      {
287	return (__locale_cache_base*)_M_facets[__index + _M_facets_size];
288      }
289
290    // Save the supplied cache at __id.  Assumes _M_get_cache has been
291    // called.
292    void
293    _M_install_cache(__locale_cache_base* __cache, int __id)
294    {
295      _M_facets[__id + _M_facets_size] =
296	reinterpret_cast<locale::facet*>(__cache);
297    }
298
299  };
300
301  template<typename _Facet>
302    locale::locale(const locale& __other, _Facet* __f)
303    {
304      _M_impl = new _Impl(*__other._M_impl, 1);
305      _M_impl->_M_install_facet(&_Facet::id, __f);
306      for (size_t __i = 0;
307	   __i < _S_categories_size + _S_extra_categories_size; ++__i)
308	{
309	  delete [] _M_impl->_M_names[__i];
310	  char* __new = new char[2];
311	  strcpy(__new, "*");
312	  _M_impl->_M_names[__i] = __new;
313	}
314    }
315
316
317  // 22.1.1.1.2  Class locale::facet
318  class locale::facet
319  {
320  private:
321    friend class locale;
322    friend class locale::_Impl;
323
324    _Atomic_word 			_M_references;
325
326  protected:
327    // Contains data from the underlying "C" library for the classic locale.
328    static __c_locale		     	_S_c_locale;
329
330    // String literal for the name of the classic locale.
331    static char				_S_c_name[2];
332
333    explicit
334    facet(size_t __refs = 0) throw();
335
336    virtual
337    ~facet();
338
339    static void
340    _S_create_c_locale(__c_locale& __cloc, const char* __s,
341		       __c_locale __old = 0);
342
343    static __c_locale
344    _S_clone_c_locale(__c_locale& __cloc);
345
346    static void
347    _S_destroy_c_locale(__c_locale& __cloc);
348
349  private:
350    void
351    _M_add_reference() throw();
352
353    void
354    _M_remove_reference() throw();
355
356    facet(const facet&);  // Not defined.
357
358    void
359    operator=(const facet&);  // Not defined.
360  };
361
362
363  // 22.1.1.1.3 Class locale::id
364  class locale::id
365  {
366  private:
367    friend class locale;
368    friend class locale::_Impl;
369    template<typename _Facet>
370      friend const _Facet&
371      use_facet(const locale&);
372    template<typename _Facet>
373      friend bool
374      has_facet(const locale&) throw ();
375
376    // NB: There is no accessor for _M_index because it may be used
377    // before the constructor is run; the effect of calling a member
378    // function (even an inline) would be undefined.
379    mutable size_t 		_M_index;
380
381    // Last id number assigned.
382    static _Atomic_word 	_S_highwater;
383
384    void
385    operator=(const id&);  // Not defined.
386
387    id(const id&);  // Not defined.
388
389  public:
390    // NB: This class is always a static data member, and thus can be
391    // counted on to be zero-initialized.
392    id();
393
394    inline size_t
395    _M_id() const
396    {
397      if (!_M_index)
398	_M_index = 1 + __exchange_and_add(&_S_highwater, 1);
399      return _M_index - 1;
400    }
401  };
402} // namespace std
403
404#endif
405