xref: /openbsd-src/gnu/lib/libstdc++/libstdc++/include/bits/locale_classes.h (revision 534d6ef73a061b07292185cee5cb8230994f382b)
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 
50 namespace 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
_S_initialize()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
_M_add_reference()227     _M_add_reference() throw()
228     { __atomic_add(&_M_references, 1); }
229 
230     inline void
_M_remove_reference()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
_M_check_same_name()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
_M_init_facet(_Facet * __facet)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*
_M_get_cache(size_t __index)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
_M_install_cache(__locale_cache_base * __cache,int __id)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>
locale(const locale & __other,_Facet * __f)302     locale::locale(const locale& __other, _Facet* __f)
303     {
304       _M_impl = new _Impl(*__other._M_impl, 1);
305 
306       char* _M_tmp_names[_S_categories_size + _S_extra_categories_size];
307       size_t __i = 0;
308       try
309 	{
310 	  for (; __i < _S_categories_size
311 		       + _S_extra_categories_size; ++__i)
312 	    {
313 	      _M_tmp_names[__i] = new char[2];
314 	      strlcpy(_M_tmp_names[__i], "*", 2);
315 	    }
316 	  _M_impl->_M_install_facet(&_Facet::id, __f);
317 	}
318       catch(...)
319 	{
320 	  _M_impl->_M_remove_reference();
321 	  for (size_t __j = 0; __j < __i; ++__j)
322 	    delete [] _M_tmp_names[__j];
323 	  __throw_exception_again;
324 	}
325 
326       for (size_t __k = 0; __k < _S_categories_size
327 	                         + _S_extra_categories_size; ++__k)
328 	{
329 	  delete [] _M_impl->_M_names[__k];
330 	  _M_impl->_M_names[__k] = _M_tmp_names[__k];
331 	}
332     }
333 
334 
335   // 22.1.1.1.2  Class locale::facet
336   class locale::facet
337   {
338   private:
339     friend class locale;
340     friend class locale::_Impl;
341 
342     _Atomic_word 			_M_references;
343 
344   protected:
345     // Contains data from the underlying "C" library for the classic locale.
346     static __c_locale		     	_S_c_locale;
347 
348     // String literal for the name of the classic locale.
349     static char				_S_c_name[2];
350 
351     explicit
352     facet(size_t __refs = 0) throw();
353 
354     virtual
355     ~facet();
356 
357     static void
358     _S_create_c_locale(__c_locale& __cloc, const char* __s,
359 		       __c_locale __old = 0);
360 
361     static __c_locale
362     _S_clone_c_locale(__c_locale& __cloc);
363 
364     static void
365     _S_destroy_c_locale(__c_locale& __cloc);
366 
367   private:
368     void
369     _M_add_reference() throw();
370 
371     void
372     _M_remove_reference() throw();
373 
374     facet(const facet&);  // Not defined.
375 
376     void
377     operator=(const facet&);  // Not defined.
378   };
379 
380 
381   // 22.1.1.1.3 Class locale::id
382   class locale::id
383   {
384   private:
385     friend class locale;
386     friend class locale::_Impl;
387     template<typename _Facet>
388       friend const _Facet&
389       use_facet(const locale&);
390     template<typename _Facet>
391       friend bool
392       has_facet(const locale&) throw ();
393 
394     // NB: There is no accessor for _M_index because it may be used
395     // before the constructor is run; the effect of calling a member
396     // function (even an inline) would be undefined.
397     mutable size_t 		_M_index;
398 
399     // Last id number assigned.
400     static _Atomic_word 	_S_highwater;
401 
402     void
403     operator=(const id&);  // Not defined.
404 
405     id(const id&);  // Not defined.
406 
407   public:
408     // NB: This class is always a static data member, and thus can be
409     // counted on to be zero-initialized.
410     id();
411 
412     inline size_t
_M_id()413     _M_id() const
414     {
415       if (!_M_index)
416 	_M_index = 1 + __exchange_and_add(&_S_highwater, 1);
417       return _M_index - 1;
418     }
419   };
420 } // namespace std
421 
422 #endif
423