Remove incorrect cache_purge() calls in *_rmdir() (OLD API). These could
[dragonfly.git] / contrib / libstdc++3 / src / localename.cc
1 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
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
33 namespace __gnu_cxx
34 {
35   using namespace std;
36
37   // Defined in globals.cc.
38   extern locale::facet* facet_vec[_GLIBCPP_NUM_FACETS];
39   extern locale::facet* facet_cache_vec[2 * _GLIBCPP_NUM_FACETS];
40   extern char* facet_name[6 + _GLIBCPP_NUM_CATEGORIES];
41
42   extern std::ctype<char>                       ctype_c;
43   extern std::collate<char>                     collate_c;
44   extern numpunct<char>                         numpunct_c;
45   extern num_get<char>                          num_get_c;
46   extern num_put<char>                          num_put_c;
47   extern codecvt<char, char, mbstate_t>         codecvt_c;
48   extern moneypunct<char, false>                moneypunct_fc;
49   extern moneypunct<char, true>                 moneypunct_tc;
50   extern money_get<char>                        money_get_c;
51   extern money_put<char>                        money_put_c;
52   extern __timepunct<char>                      timepunct_c;
53   extern time_get<char>                         time_get_c;
54   extern time_put<char>                         time_put_c;
55   extern std::messages<char>                    messages_c;
56 #ifdef  _GLIBCPP_USE_WCHAR_T
57   extern std::ctype<wchar_t>                    ctype_w;
58   extern std::collate<wchar_t>                  collate_w;
59   extern numpunct<wchar_t>                      numpunct_w;
60   extern num_get<wchar_t>                       num_get_w;
61   extern num_put<wchar_t>                       num_put_w;
62   extern codecvt<wchar_t, char, mbstate_t>      codecvt_w;
63   extern moneypunct<wchar_t, false>             moneypunct_fw;
64   extern moneypunct<wchar_t, true>              moneypunct_tw;
65   extern money_get<wchar_t>                     money_get_w;
66   extern money_put<wchar_t>                     money_put_w;
67   extern __timepunct<wchar_t>                   timepunct_w;
68   extern time_get<wchar_t>                      time_get_w;
69   extern time_put<wchar_t>                      time_put_w;
70   extern std::messages<wchar_t>                 messages_w;
71 #endif
72
73   extern std::__locale_cache<numpunct<char> >   locale_cache_np_c;
74 #ifdef  _GLIBCPP_USE_WCHAR_T
75   extern std::__locale_cache<numpunct<wchar_t> >        locale_cache_np_w;
76 #endif
77 } // namespace __gnu_cxx
78
79 namespace std
80 {
81   using namespace __gnu_cxx;
82
83   locale::_Impl::
84   ~_Impl() throw()
85   {
86     // Clean up facets, then caches.  No cache refcounts for now.
87     for (size_t __i = 0; __i < _M_facets_size; ++__i)
88       if (_M_facets[__i])
89         _M_facets[__i]->_M_remove_reference();
90     for (size_t __i = _M_facets_size; __i < 2*_M_facets_size; ++__i)
91       if (_M_facets[__i])
92         delete (__locale_cache_base*)_M_facets[__i];
93     delete [] _M_facets;
94
95     for (size_t __i = 0; 
96          __i < _S_categories_size + _S_extra_categories_size; ++__i)
97       delete [] _M_names[__i];  
98   }
99
100   // Clone existing _Impl object.
101   locale::_Impl::
102   _Impl(const _Impl& __imp, size_t __refs)
103   : _M_references(__refs), _M_facets_size(__imp._M_facets_size) // XXX
104   {
105     try
106       { 
107         // Space for facets and matching caches
108         _M_facets = new facet*[2*_M_facets_size]; 
109         for (size_t __i = 0; __i < 2*_M_facets_size; ++__i)
110           _M_facets[__i] = 0;
111       }
112     catch(...) 
113       {
114         delete [] _M_facets;
115         __throw_exception_again;
116       }
117     for (size_t __i = 0; __i < _M_facets_size; ++__i)
118       {
119         _M_facets[__i] = __imp._M_facets[__i];
120         if (_M_facets[__i])
121           _M_facets[__i]->_M_add_reference();
122       }
123     for (size_t __i = 0; 
124          __i < _S_categories_size + _S_extra_categories_size; ++__i)
125       {
126         char* __new = new char[strlen(__imp._M_names[__i]) + 1];
127         strcpy(__new, __imp._M_names[__i]);
128         _M_names[__i] = __new;
129       }
130   }
131
132   // Construct named _Impl.
133   locale::_Impl::
134   _Impl(const char* __s, size_t __refs) 
135   : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS) 
136   {
137     // Initialize the underlying locale model, which also checks
138     // to see if the given name is valid.
139     __c_locale __cloc;
140     locale::facet::_S_create_c_locale(__cloc, __s);
141
142     try
143       {
144         // Space for facets and matching caches
145         _M_facets = new facet*[2*_M_facets_size]; 
146         for (size_t __i = 0; __i < 2*_M_facets_size; ++__i)
147           _M_facets[__i] = 0;
148       }
149     catch(...) 
150       {
151         delete [] _M_facets;
152         __throw_exception_again;
153       }
154
155     // Name all the categories.
156     size_t __len = strlen(__s);
157     if (!strchr(__s, ';'))
158       {
159         for (size_t __i = 0; 
160              __i < _S_categories_size + _S_extra_categories_size; ++__i)
161           {
162             _M_names[__i] = new char[__len + 1];
163             strcpy(_M_names[__i], __s);
164           }
165       }
166     else
167       {
168         const char* __beg = __s;
169         for (size_t __i = 0; 
170              __i < _S_categories_size + _S_extra_categories_size; ++__i)
171           {
172             __beg = strchr(__beg, '=') + 1;
173             const char* __end = strchr(__beg, ';');
174             if (!__end)
175               __end = __s + __len;
176             char* __new = new char[__end - __beg + 1];
177             memcpy(__new, __beg, __end - __beg);
178             __new[__end - __beg] = '\0';
179             _M_names[__i] = __new;
180           }
181       }
182
183     // Construct all standard facets and add them to _M_facets.  
184     _M_init_facet(new std::ctype<char>(__cloc, 0, false));
185     _M_init_facet(new codecvt<char, char, mbstate_t>);
186     _M_init_facet(new numpunct<char>(__cloc));
187     _M_init_facet(new num_get<char>);
188     _M_init_facet(new num_put<char>);
189     _M_init_facet(new std::collate<char>(__cloc));
190     _M_init_facet(new moneypunct<char, false>(__cloc, __s));
191     _M_init_facet(new moneypunct<char, true>(__cloc, __s));
192     _M_init_facet(new money_get<char>);
193     _M_init_facet(new money_put<char>);
194     _M_init_facet(new __timepunct<char>(__cloc, __s));
195     _M_init_facet(new time_get<char>);
196     _M_init_facet(new time_put<char>);
197     _M_init_facet(new std::messages<char>(__cloc, __s));
198         
199 #ifdef  _GLIBCPP_USE_WCHAR_T
200     _M_init_facet(new std::ctype<wchar_t>(__cloc));
201     _M_init_facet(new codecvt<wchar_t, char, mbstate_t>);
202     _M_init_facet(new numpunct<wchar_t>(__cloc));
203     _M_init_facet(new num_get<wchar_t>);
204     _M_init_facet(new num_put<wchar_t>);
205     _M_init_facet(new std::collate<wchar_t>(__cloc));
206     _M_init_facet(new moneypunct<wchar_t, false>(__cloc, __s));
207     _M_init_facet(new moneypunct<wchar_t, true>(__cloc, __s));
208     _M_init_facet(new money_get<wchar_t>);
209     _M_init_facet(new money_put<wchar_t>);
210     _M_init_facet(new __timepunct<wchar_t>(__cloc, __s));
211     _M_init_facet(new time_get<wchar_t>);
212     _M_init_facet(new time_put<wchar_t>);
213     _M_init_facet(new std::messages<wchar_t>(__cloc, __s));
214 #endif    
215     locale::facet::_S_destroy_c_locale(__cloc);
216   }
217
218   // Construct "C" _Impl.
219   locale::_Impl::
220   _Impl(facet**, size_t __refs, bool) 
221   : _M_references(__refs), _M_facets_size(_GLIBCPP_NUM_FACETS)
222   {
223     // Initialize the underlying locale model.
224     locale::facet::_S_c_name[0] = 'C';
225     locale::facet::_S_c_name[1] = '\0';
226     locale::facet::_S_create_c_locale(locale::facet::_S_c_locale, 
227                                       locale::facet::_S_c_name);
228
229     // Space for facets and matching caches
230     _M_facets = new(&facet_cache_vec) facet*[2*_M_facets_size];
231     for (size_t __i = 0; __i < 2*_M_facets_size; ++__i)
232       _M_facets[__i] = 0;
233
234     // Name all the categories.
235     for (size_t __i = 0; 
236          __i < _S_categories_size + _S_extra_categories_size; ++__i)
237       {
238         _M_names[__i]  = new (&facet_name[__i]) char[2];
239         strcpy(_M_names[__i], locale::facet::_S_c_name);
240       }
241
242     // This is needed as presently the C++ version of "C" locales
243     // != data in the underlying locale model for __timepunct,
244     // numpunct, and moneypunct. Also, the "C" locales must be
245     // constructed in a way such that they are pre-allocated.
246     // NB: Set locale::facets(ref) count to one so that each individual
247     // facet is not destroyed when the locale (and thus locale::_Impl) is
248     // destroyed.
249     _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1));
250     _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1));
251     _M_init_facet(new (&numpunct_c) numpunct<char>(1));
252     _M_init_facet(new (&num_get_c) num_get<char>(1));
253     _M_init_facet(new (&num_put_c) num_put<char>(1));
254     _M_init_facet(new (&collate_c) std::collate<char>(1));
255     _M_init_facet(new (&moneypunct_fc) moneypunct<char, false>(1));
256     _M_init_facet(new (&moneypunct_tc) moneypunct<char, true>(1));
257     _M_init_facet(new (&money_get_c) money_get<char>(1));
258     _M_init_facet(new (&money_put_c) money_put<char>(1));
259     _M_init_facet(new (&timepunct_c) __timepunct<char>(1));
260     _M_init_facet(new (&time_get_c) time_get<char>(1));
261     _M_init_facet(new (&time_put_c) time_put<char>(1));
262     _M_init_facet(new (&messages_c) std::messages<char>(1));    
263 #ifdef  _GLIBCPP_USE_WCHAR_T
264     _M_init_facet(new (&ctype_w) std::ctype<wchar_t>(1));
265     _M_init_facet(new (&codecvt_w) codecvt<wchar_t, char, mbstate_t>(1));
266     _M_init_facet(new (&numpunct_w) numpunct<wchar_t>(1));
267     _M_init_facet(new (&num_get_w) num_get<wchar_t>(1));
268     _M_init_facet(new (&num_put_w) num_put<wchar_t>(1));
269     _M_init_facet(new (&collate_w) std::collate<wchar_t>(1));
270     _M_init_facet(new (&moneypunct_fw) moneypunct<wchar_t, false>(1));
271     _M_init_facet(new (&moneypunct_tw) moneypunct<wchar_t, true>(1));
272     _M_init_facet(new (&money_get_w) money_get<wchar_t>(1));
273     _M_init_facet(new (&money_put_w) money_put<wchar_t>(1));
274     _M_init_facet(new (&timepunct_w) __timepunct<wchar_t>(1));
275     _M_init_facet(new (&time_get_w) time_get<wchar_t>(1));
276     _M_init_facet(new (&time_put_w) time_put<wchar_t>(1));
277     _M_init_facet(new (&messages_w) std::messages<wchar_t>(1));
278 #endif 
279
280     // Initialize the static locale caches for C locale.
281
282     locale ltmp(this);          // Doesn't bump refcount
283     _M_add_reference();         // Bump so destructor doesn't trash us
284
285     // These need to be built in static allocated memory.  There must
286     // be a better way to do this!
287     __locale_cache<numpunct<char> >* __lc =
288       new (&locale_cache_np_c) __locale_cache<numpunct<char> >(ltmp, true);
289     _M_facets[numpunct<char>::id._M_id() + _M_facets_size] =
290       reinterpret_cast<locale::facet*>(__lc);
291       
292 #ifdef  _GLIBCPP_USE_WCHAR_T
293     __locale_cache<numpunct<wchar_t> >* __wlc =
294       new (&locale_cache_np_w) __locale_cache<numpunct<wchar_t> >(ltmp, true);
295     _M_facets[numpunct<wchar_t>::id._M_id() + _M_facets_size] =
296       reinterpret_cast<locale::facet*>(__wlc);
297 #endif    
298   }
299   
300   void
301   locale::_Impl::
302   _M_replace_categories(const _Impl* __imp, category __cat)
303   {
304     category __mask;
305     for (size_t __ix = 0; __ix < _S_categories_size; ++__ix)
306       {
307         __mask = 1 << __ix;
308         if (__mask & __cat)
309           {
310             // Need to replace entry in _M_facets with other locale's info.
311             _M_replace_category(__imp, _S_facet_categories[__ix]);
312             // If both have names, go ahead and mangle.
313             if (strcmp(_M_names[__ix], "*") != 0 
314                 && strcmp(__imp->_M_names[__ix], "*") != 0)
315               {
316                 delete [] _M_names[__ix];
317                 char* __new = new char[strlen(__imp->_M_names[__ix]) + 1];
318                 strcpy(__new, __imp->_M_names[__ix]);
319                 _M_names[__ix] = __new;
320               }
321           }
322       }
323   }
324
325   void
326   locale::_Impl::
327   _M_replace_category(const _Impl* __imp, const locale::id* const* __idpp)
328   {
329     for (; *__idpp; ++__idpp)
330       _M_replace_facet(__imp, *__idpp);
331   }
332   
333   void
334   locale::_Impl::
335   _M_replace_facet(const _Impl* __imp, const locale::id* __idp)
336   {
337     size_t __index = __idp->_M_id();
338     if ((__index > (__imp->_M_facets_size - 1)) || !__imp->_M_facets[__index])
339       __throw_runtime_error("no locale facet");
340     _M_install_facet(__idp, __imp->_M_facets[__index]); 
341   }
342
343   void
344   locale::_Impl::
345   _M_install_facet(const locale::id* __idp, facet* __fp)
346   {
347     if (__fp)
348       {
349         size_t __index = __idp->_M_id();
350
351         // Check size of facet vector to ensure adequate room.
352         if (__index > _M_facets_size - 1)
353           {
354             facet** __old = _M_facets;
355             facet** __new;
356             const size_t __new_size = __index + 4;
357             __new = new facet*[2 * __new_size]; 
358             for (size_t __i = 0; __i < _M_facets_size; ++__i)
359               __new[__i] = _M_facets[__i];
360             for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
361               __new[__i2] = 0;
362             // Also copy caches and clear extra space
363             for (size_t __i = 0; __i < _M_facets_size; ++__i)
364               __new[__i + __new_size] = _M_facets[__i + _M_facets_size];
365             for (size_t __i2 = _M_facets_size; __i2 < __new_size; ++__i2)
366               __new[__i2 + __new_size] = 0;
367
368             _M_facets_size = __new_size;
369             _M_facets = __new;
370             delete [] __old;
371           }
372
373         __fp->_M_add_reference();
374         facet*& __fpr = _M_facets[__index];
375         if (__fpr)
376           {
377             // Replacing an existing facet. Order matters.
378             __fpr->_M_remove_reference();
379             __fpr = __fp;
380           }
381         else
382           {
383             // Installing a newly created facet into an empty
384             // _M_facets container, say a newly-constructed,
385             // swanky-fresh _Impl.
386             _M_facets[__index] = __fp;
387           }
388       }
389   }
390 } // namespace std