OSDN Git Service

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