OSDN Git Service

2001-01-10 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / src / localename.cc
1 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library.  This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 2, or (at your option)
7 // any later version.
8
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING.  If not, write to the Free
16 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 // USA.
18
19 // As a special exception, you may use this file as part of a free software
20 // library without restriction.  Specifically, if other files instantiate
21 // templates or use macros or inline functions from this file, or you compile
22 // this file and link it with other files to produce an executable, this
23 // file does not by itself cause the resulting executable to be covered by
24 // the GNU General Public License.  This exception does not however
25 // invalidate any other reasons why the executable file might be covered by
26 // the GNU General Public License.
27
28
29 #include <bits/std_clocale.h>
30 #include <bits/std_locale.h>
31 #include <bits/std_cstring.h>
32 #include <bits/std_vector.h>
33 #include <bits/std_stdexcept.h>
34
35 namespace std {
36
37   locale::_Impl::
38   ~_Impl() throw()
39   {
40     std::vector<facet*>::iterator it = _M_facets->begin();
41     for (; it != _M_facets->end(); ++it)
42       (*it)->_M_remove_reference();
43     delete _M_facets;
44     delete _M_category_names;
45   }
46
47   locale::_Impl::
48   _Impl(const _Impl& __imp, size_t __refs)
49   : _M_references(__refs - 1), _M_facets(0), _M_category_names(0), 
50     _M_has_name(__imp._M_has_name), _M_name(__imp._M_name)
51   {
52     try
53       {  _M_facets = new __vec_facet(*(__imp._M_facets)); }
54     catch(...) 
55       {
56         delete _M_facets;
57         throw;
58       }
59
60     try 
61       { _M_category_names = new __vec_string(*(__imp._M_category_names)); }
62     catch(...) 
63       {
64         delete _M_category_names;
65         throw;
66       }
67
68     std::vector<facet*>::iterator __it = _M_facets->begin();
69     for (; __it != _M_facets->end(); ++__it)
70       (*__it)->_M_add_reference();
71   }
72
73   // This constructor is used to correctly initialize named locales,
74   // including the standard "C" locale.
75   locale::_Impl::
76   _Impl(size_t __num, size_t __refs, bool __has_name, string __str)
77   : _M_references(__refs - 1), _M_facets(0), _M_category_names(0), 
78     _M_has_name(__has_name), _M_name(__str)
79   {
80     try
81       {  _M_facets = new __vec_facet(__num, NULL); }
82     catch(...) 
83       {
84         delete _M_facets;
85         throw;
86       }
87
88     try 
89       { _M_category_names = new __vec_string(_S_categories_num, _M_name); }
90     catch(...) 
91       {
92         delete _M_category_names;
93         throw;
94       }
95   }
96   
97   // Construct specific categories, leaving unselected ones alone
98   locale::_Impl::
99   _Impl(const _Impl& __imp, const string& __str, category __cat, size_t __refs)
100   : _M_references(__refs - 1)
101   {
102     __cat = _S_normalize_category(__cat);  // might throw
103
104     try 
105       { _M_facets = new __vec_facet(*(__imp._M_facets)); }
106     catch(...) 
107       {
108         delete _M_facets;
109         throw;
110       }
111
112     try 
113       { _M_category_names = new __vec_string(*(__imp._M_category_names)); }
114     catch(...) 
115       {
116         delete _M_category_names;
117         throw;
118       }
119
120     static void(_Impl::* ctors[]) (const char*) = 
121     {
122       //  NB: Order must match the decl order in class locale.
123       &locale::_Impl::_M_construct_ctype,
124       &locale::_Impl::_M_construct_numeric,
125       &locale::_Impl::_M_construct_collate,
126       &locale::_Impl::_M_construct_time,
127       &locale::_Impl::_M_construct_monetary,
128       &locale::_Impl::_M_construct_messages,
129       0
130     };
131     
132     __vec_facet::iterator __it = _M_facets->begin();
133     for (; __it != _M_facets->end(); ++__it)
134       (*__it)->_M_add_reference();
135
136     try 
137       {
138         unsigned mask = (locale::all & -(unsigned)locale::all);
139         for (unsigned ix = 0; (-mask & __cat) != 0; ++ix, (mask <<= 1))
140           {
141             if (!(mask & __cat))
142               continue;
143             
144             if (mask & __cat)
145               _M_replace_category(_S_classic, _S_facet_categories[ix]);
146             else
147               (this->*ctors[ix])(__str.c_str());
148           }
149       }
150     catch(...) 
151       {
152         __it = _M_facets->begin();
153         for (; __it != _M_facets->end(); ++__it)
154           (*__it)->_M_remove_reference();
155         throw;
156       }
157
158     // XXX May need to be adjusted
159     if (__cat == all)
160       _M_name = __str;
161     _M_has_name = __str != "*";
162   }
163   
164   void
165   locale::_Impl::
166   _M_replace_categories(const _Impl* __imp, category __cat)
167   {
168     category  __mask = locale::all & -static_cast<unsigned int>(locale::all);
169     for (unsigned int __ix = 0; (-__mask & __cat) != 0; ++__ix, (__mask <<= 1))
170       {
171         if (__mask & __cat)
172           {
173             _M_replace_category(__imp, _S_facet_categories[__ix]);
174             (*_M_category_names)[__ix] = (*(__imp->_M_category_names))[__ix];
175           }
176       }
177   }
178
179   void
180   locale::_Impl::
181   _M_replace_category(const _Impl* __imp, const locale::id* const* __idpp)
182   {
183     for (; *__idpp; ++__idpp)
184       _M_replace_facet(__imp, *__idpp);
185   }
186   
187   void
188   locale::_Impl::
189   _M_replace_facet(const _Impl* __imp, const locale::id* __idp)
190   {
191     size_t __index = __idp->_M_index;
192     if (__index == 0 
193         || __imp->_M_facets->size() <= __index 
194         || (*(__imp->_M_facets))[__index] == 0)
195       throw runtime_error("no locale facet");
196         
197     _M_install_facet(__idp, (*(__imp->_M_facets))[__index]); 
198   }
199
200   void
201   locale::_Impl::
202   _M_install_facet(const locale::id* __idp, facet* __fp)
203   {
204     if (__fp == 0)
205       return;
206
207     size_t& __index = __idp->_M_index;
208     if (!__index)
209       __index = ++locale::id::_S_highwater;  // XXX MT
210
211     if (__index >= _M_facets->size())
212       _M_facets->resize(__index + 1, 0);  // might throw
213     facet*& __fpr = (*_M_facets)[__index];
214     // Order matters, here:
215     __fp->_M_add_reference();
216     if (__fpr) 
217       __fpr->_M_remove_reference();
218     __fpr = __fp;
219   }
220  
221   void 
222   locale::_Impl::_M_construct_collate(const char* __s)
223   {
224     _M_facet_init(new collate_byname<char>(__s, 0));
225 #ifdef _GLIBCPP_USE_WCHAR_T
226     _M_facet_init(new collate_byname<wchar_t>(__s, 0));
227 #endif 
228   }
229
230   void 
231   locale::_Impl::_M_construct_ctype(const char* __s)
232   {
233     _M_facet_init(new ctype_byname<char>(__s, 0));
234     _M_facet_init(new codecvt_byname<char, char, mbstate_t>(__s));
235 #ifdef _GLIBCPP_USE_WCHAR_T
236     _M_facet_init(new ctype_byname<wchar_t>(__s, 0));
237     _M_facet_init(new codecvt_byname<wchar_t, char, mbstate_t>(__s));
238 #endif 
239   }
240     
241   void 
242   locale::_Impl::_M_construct_monetary(const char* __s)
243   {
244     _M_replace_facet(locale::_S_classic, &money_get<char>::id);
245     _M_replace_facet(locale::_S_classic, &money_put<char>::id);
246     _M_facet_init(new moneypunct_byname<char, false>(__s, 0));
247     _M_facet_init(new moneypunct_byname<char, true >(__s, 0));
248 #ifdef _GLIBCPP_USE_WCHAR_T
249     _M_replace_facet(locale::_S_classic, &money_get<wchar_t>::id);
250     _M_replace_facet(locale::_S_classic, &money_put<wchar_t>::id);
251     _M_facet_init(new moneypunct_byname<wchar_t, false>(__s, 0));
252     _M_facet_init(new moneypunct_byname<wchar_t, true >(__s, 0));
253 #endif
254   }
255     
256   void 
257   locale::_Impl::_M_construct_numeric(const char* __s)
258   {
259     _M_replace_facet(locale::_S_classic, &num_get<char>::id);
260     _M_replace_facet(locale::_S_classic, &num_put<char>::id);
261     _M_facet_init(new numpunct_byname<char>(__s, 0));
262 #ifdef _GLIBCPP_USE_WCHAR_T
263     _M_replace_facet(locale::_S_classic, &num_get<wchar_t>::id);
264     _M_replace_facet(locale::_S_classic, &num_put<wchar_t>::id);
265     _M_facet_init(new numpunct_byname<wchar_t>(__s, 0));
266 #endif 
267   }
268     
269   void 
270   locale::_Impl::_M_construct_time(const char* __s)
271   {
272     _M_facet_init(new time_get_byname<char>(__s, 0));
273     _M_facet_init(new time_put_byname<char>(__s, 0));
274 #ifdef _GLIBCPP_USE_WCHAR_T
275     _M_facet_init(new time_get_byname<wchar_t>(__s, 0));
276     _M_facet_init(new time_put_byname<wchar_t>(__s, 0));
277 #endif 
278   }
279     
280   void 
281   locale::_Impl::_M_construct_messages(const char* __s)
282   {
283     _M_facet_init(new messages_byname<char>(__s, 0));
284 #ifdef _GLIBCPP_USE_WCHAR_T
285     _M_facet_init(new messages_byname<wchar_t>(__s, 0));
286 #endif 
287   }
288 }
289
290
291