localename.cc revision 97403
1// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
2// Free Software Foundation, Inc.
3//
4// This file is part of the GNU ISO C++ Library.  This library is free
5// software; you can redistribute it and/or modify it under the
6// terms of the GNU General Public License as published by the
7// Free Software Foundation; either version 2, or (at your option)
8// any later version.
9
10// This library is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13// GNU General Public License for more details.
14
15// You should have received a copy of the GNU General Public License along
16// with this library; see the file COPYING.  If not, write to the Free
17// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18// USA.
19
20// As a special exception, you may use this file as part of a free software
21// library without restriction.  Specifically, if other files instantiate
22// templates or use macros or inline functions from this file, or you compile
23// this file and link it with other files to produce an executable, this
24// file does not by itself cause the resulting executable to be covered by
25// the GNU General Public License.  This exception does not however
26// invalidate any other reasons why the executable file might be covered by
27// the GNU General Public License.
28
29#include <clocale>
30#include <cstring>
31#include <locale>
32
33namespace std
34{
35  // Defined in globals.cc.
36  extern std::ctype<char>			ctype_c;
37  extern std::collate<char> 			collate_c;
38  extern numpunct<char> 			numpunct_c;
39  extern num_get<char> 				num_get_c;
40  extern num_put<char> 				num_put_c;
41  extern codecvt<char, char, mbstate_t>		codecvt_c;
42  extern moneypunct<char, false> 		moneypunct_fc;
43  extern moneypunct<char, true> 		moneypunct_tc;
44  extern money_get<char> 			money_get_c;
45  extern money_put<char> 			money_put_c;
46  extern __timepunct<char> 			timepunct_c;
47  extern time_get<char> 			time_get_c;
48  extern time_put<char> 			time_put_c;
49  extern std::messages<char> 			messages_c;
50#ifdef  _GLIBCPP_USE_WCHAR_T
51  extern std::ctype<wchar_t>			ctype_w;
52  extern std::collate<wchar_t> 			collate_w;
53  extern numpunct<wchar_t> 			numpunct_w;
54  extern num_get<wchar_t> 			num_get_w;
55  extern num_put<wchar_t> 			num_put_w;
56  extern codecvt<wchar_t, char, mbstate_t>	codecvt_w;
57  extern moneypunct<wchar_t, false> 		moneypunct_fw;
58  extern moneypunct<wchar_t, true> 		moneypunct_tw;
59  extern money_get<wchar_t> 			money_get_w;
60  extern money_put<wchar_t> 			money_put_w;
61  extern __timepunct<wchar_t> 			timepunct_w;
62  extern time_get<wchar_t> 			time_get_w;
63  extern time_put<wchar_t> 			time_put_w;
64  extern std::messages<wchar_t> 		messages_w;
65#endif
66
67  locale::_Impl::
68  ~_Impl() throw()
69  {
70    for (size_t __i = 0; __i < _M_facets_size; ++__i)
71      if (_M_facets[__i])
72	_M_facets[__i]->_M_remove_reference();
73    delete [] _M_facets;
74  }
75
76  // Clone existing _Impl object.
77  locale::_Impl::
78  _Impl(const _Impl& __imp, size_t __refs)
79  : _M_references(__refs), _M_facets_size(__imp._M_facets_size) // XXX
80  {
81    try
82      {
83	_M_facets = new facet*[_M_facets_size];
84	for (size_t __i = 0; __i < _M_facets_size; ++__i)
85	  _M_facets[__i] = 0;
86      }
87    catch(...)
88      {
89	delete [] _M_facets;
90	__throw_exception_again;
91      }
92    for (size_t __i = 0; __i < _M_facets_size; ++__i)
93      {
94	_M_facets[__i] = __imp._M_facets[__i];
95	if (_M_facets[__i])
96	  _M_facets[__i]->_M_add_reference();
97      }
98    for (size_t __i = 0; __i < _S_num_categories; ++__i)
99      _M_names[__i] = __imp._M_names[__i];
100  }
101
102  // Construct named _Impl.
103  locale::_Impl::
104  _Impl(const char* __s, size_t __refs)
105  : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS) // XXX
106  {
107    // Initialize the underlying locale model, which also checks
108    // to see if the given name is valid.
109    __c_locale __cloc;
110    locale::facet::_S_create_c_locale(__cloc, __s);
111
112    try
113      {
114	_M_facets = new facet*[_M_facets_size];
115	for (size_t __i = 0; __i < _M_facets_size; ++__i)
116	  _M_facets[__i] = 0;
117      }
118    catch(...)
119      {
120	delete [] _M_facets;
121	__throw_exception_again;
122      }
123
124    // Name all the categories.
125    for (size_t i = 0; i < _S_num_categories; ++i)
126      _M_names[i] = __s;
127
128    // Construct all standard facets and add them to _M_facets.
129    _M_init_facet(new std::ctype<char>(__cloc));
130    _M_init_facet(new codecvt<char, char, mbstate_t>);
131    _M_init_facet(new numpunct<char>(__cloc));
132    _M_init_facet(new num_get<char>);
133    _M_init_facet(new num_put<char>);
134    _M_init_facet(new std::collate<char>(__cloc));
135    _M_init_facet(new moneypunct<char, false>(__cloc));
136    _M_init_facet(new moneypunct<char, true>(__cloc));
137    _M_init_facet(new money_get<char>);
138    _M_init_facet(new money_put<char>);
139    _M_init_facet(new __timepunct<char>(__cloc, __s));
140    _M_init_facet(new time_get<char>);
141    _M_init_facet(new time_put<char>);
142    _M_init_facet(new std::messages<char>(__cloc, __s));
143
144#ifdef  _GLIBCPP_USE_WCHAR_T
145    _M_init_facet(new std::ctype<wchar_t>(__cloc));
146    _M_init_facet(new codecvt<wchar_t, char, mbstate_t>);
147    _M_init_facet(new numpunct<wchar_t>(__cloc));
148    _M_init_facet(new num_get<wchar_t>);
149    _M_init_facet(new num_put<wchar_t>);
150    _M_init_facet(new std::collate<wchar_t>(__cloc));
151    _M_init_facet(new moneypunct<wchar_t, false>(__cloc));
152    _M_init_facet(new moneypunct<wchar_t, true>(__cloc));
153    _M_init_facet(new money_get<wchar_t>);
154    _M_init_facet(new money_put<wchar_t>);
155    _M_init_facet(new __timepunct<wchar_t>(__cloc, __s));
156    _M_init_facet(new time_get<wchar_t>);
157    _M_init_facet(new time_put<wchar_t>);
158    _M_init_facet(new std::messages<wchar_t>(__cloc, __s));
159#endif
160    locale::facet::_S_destroy_c_locale(__cloc);
161  }
162
163  // Construct "C" _Impl.
164  locale::_Impl::
165  _Impl(facet** __f, size_t __refs, bool)
166  : _M_references(__refs), _M_facets(__f), _M_facets_size(_GLIBCPP_NUM_FACETS)
167  {
168    // Name all the categories.
169    for (size_t i = 0; i < _S_num_categories; ++i)
170      _M_names[i] = "C";
171
172    // This is needed as presently the C++ version of "C" locales
173    // != data in the underlying locale model for __timepunct,
174    // numpunct, and moneypunct. Also, the "C" locales must be
175    // constructed in a way such that they are pre-allocated.
176    _M_init_facet(new (&ctype_c) std::ctype<char>);
177    _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>);
178    _M_init_facet(new (&numpunct_c) numpunct<char>);
179    _M_init_facet(new (&num_get_c) num_get<char>);
180    _M_init_facet(new (&num_put_c) num_put<char>);
181    _M_init_facet(new (&collate_c) std::collate<char>);
182    _M_init_facet(new (&moneypunct_fc) moneypunct<char, false>);
183    _M_init_facet(new (&moneypunct_tc) moneypunct<char, true>);
184    _M_init_facet(new (&money_get_c) money_get<char>);
185    _M_init_facet(new (&money_put_c) money_put<char>);
186    _M_init_facet(new (&timepunct_c) __timepunct<char>);
187    _M_init_facet(new (&time_get_c) time_get<char>);
188    _M_init_facet(new (&time_put_c) time_put<char>);
189    _M_init_facet(new (&messages_c) std::messages<char>);
190#ifdef  _GLIBCPP_USE_WCHAR_T
191    _M_init_facet(new (&ctype_w) std::ctype<wchar_t>);
192    _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>);
193    _M_init_facet(new (&numpunct_w) numpunct<wchar_t>);
194    _M_init_facet(new (&num_get_w) num_get<wchar_t>);
195    _M_init_facet(new (&num_put_w) num_put<wchar_t>);
196    _M_init_facet(new (&collate_w) std::collate<wchar_t>);
197    _M_init_facet(new (&moneypunct_fw) moneypunct<wchar_t, false>);
198    _M_init_facet(new (&moneypunct_tw) moneypunct<wchar_t, true>);
199    _M_init_facet(new (&money_get_w) money_get<wchar_t>);
200    _M_init_facet(new (&money_put_w) money_put<wchar_t>);
201    _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>);
202    _M_init_facet(new (&time_get_w) time_get<wchar_t>);
203    _M_init_facet(new (&time_put_w) time_put<wchar_t>);
204    _M_init_facet(new (&messages_w) std::messages<wchar_t>);
205#endif
206  }
207
208  void
209  locale::_Impl::
210  _M_replace_categories(const _Impl* __imp, category __cat)
211  {
212    category __mask;
213    for (unsigned int __ix = 0; __ix < _S_num_categories; ++__ix)
214      {
215	__mask = 1 << __ix;
216	if (__mask & __cat)
217	  {
218	    // Need to replace entry in _M_facets with other locale's info.
219	    _M_replace_category(__imp, _S_facet_categories[__ix]);
220	    // If both have names, go ahead and mangle.
221	    if (strcmp(_M_names[__ix], "*") != 0
222		&& strcmp(__imp->_M_names[__ix], "*") != 0)
223	      _M_names[__ix] = __imp->_M_names[__ix];
224	  }
225      }
226  }
227
228  void
229  locale::_Impl::
230  _M_replace_category(const _Impl* __imp, const locale::id* const* __idpp)
231  {
232    for (; *__idpp; ++__idpp)
233      _M_replace_facet(__imp, *__idpp);
234  }
235
236  void
237  locale::_Impl::
238  _M_replace_facet(const _Impl* __imp, const locale::id* __idp)
239  {
240    size_t __index = __idp->_M_id();
241    if ((__index > (__imp->_M_facets_size - 1)) || !__imp->_M_facets[__index])
242      __throw_runtime_error("no locale facet");
243    _M_install_facet(__idp, __imp->_M_facets[__index]);
244  }
245
246  void
247  locale::_Impl::
248  _M_install_facet(const locale::id* __idp, facet* __fp)
249  {
250    if (__fp)
251      {
252	size_t __index = __idp->_M_id();
253	if (__index > _M_facets_size - 1)
254	  {
255	    facet** __old = _M_facets;
256	    facet** __new;
257	    const size_t __new_size = __index + 4;
258	    try
259	      { __new = new facet*[__new_size]; }
260	    catch(...)
261	      {
262		delete [] __new;
263		__throw_exception_again;
264	      }
265	    for (size_t __i = 0; __i < _M_facets_size; ++__i)
266	      __new[__i] = _M_facets[__i];
267	    for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
268	      __new[__i2] = 0;
269
270	    _M_facets_size = __new_size;
271	    _M_facets = __new;
272	    delete [] __old;
273	  }
274
275	facet*& __fpr = _M_facets[__index];
276	if (__fpr)
277	  {
278	    // Replacing an existing facet. Order matters.
279	    __fp->_M_add_reference();
280	    __fpr->_M_remove_reference();
281	    __fpr = __fp;
282	  }
283	else
284	  {
285	    // Installing a newly created facet into an empty
286	    // _M_facets container, say a newly-constructed,
287	    // swanky-fresh _Impl.
288	    _M_facets[__index] = __fp;
289	  }
290      }
291  }
292} // namespace std
293