OSDN Git Service

2001-09-09 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 #include <bits/std_clocale.h>
29 #include <bits/std_locale.h>
30 #include <bits/std_cstring.h>
31 #include <bits/std_vector.h>
32 #include <bits/std_stdexcept.h>
33
34 namespace std
35 {
36   locale::_Impl::
37   ~_Impl() throw()
38   {
39     __vec_facet::iterator it = _M_facets->begin();
40     for (; it != _M_facets->end(); ++it)
41       if (*it)
42         (*it)->_M_remove_reference();
43     delete _M_facets;
44   }
45
46   // Clone existing _Impl object.
47   locale::_Impl::
48   _Impl(const _Impl& __imp, size_t __refs)
49   : _M_references(__refs), _M_facets(0) // XXX
50   {
51     try
52       {  _M_facets = new __vec_facet(*(__imp._M_facets)); }
53     catch(...) 
54       {
55         delete _M_facets;
56         __throw_exception_again;
57       }
58
59     for (size_t i = 0; i < _S_num_categories; ++i)
60       _M_names[i] = __imp._M_names[i];
61
62     __vec_facet::iterator __it = _M_facets->begin();
63     for (; __it != _M_facets->end(); ++__it)
64       if (*__it)
65         (*__it)->_M_add_reference();
66   }
67
68   // Construct named _Impl, including the standard "C" locale.
69   locale::_Impl::
70   _Impl(string __str, size_t __refs)
71   : _M_references(__refs), _M_facets(0)
72   {
73     // Initialize the underlying locale model, which also checks to
74     // see if the given name is valid.
75     __c_locale __cloc = NULL;
76     if (__str != "C" && __str != "POSIX")
77       locale::facet::_S_create_c_locale(__cloc, __str.c_str());
78
79     // Allocate facet container.
80     try
81       {  _M_facets = new __vec_facet(_S_num_facets, NULL); }
82     catch(...) 
83       {
84         delete _M_facets;
85         __throw_exception_again;
86       }
87
88     // Name all the categories.
89     for (size_t i = 0; i < _S_num_categories; ++i)
90       _M_names[i] = __str;
91
92     // Construct all standard facets and add them to _M_facets.
93     // XXX Eventually, all should use __clocale ctor like numpunct
94     // XXX how to deal cleanly, consistently with null ("C") __cloc?
95     _M_init_facet(new std::collate<char>(__cloc));
96     _M_init_facet(new std::ctype<char>);
97     _M_init_facet(new codecvt<char, char, mbstate_t>);
98     _M_init_facet(new moneypunct<char, false>(__cloc));
99     _M_init_facet(new moneypunct<char, true>(__cloc));
100     _M_init_facet(new money_get<char>);
101     _M_init_facet(new money_put<char>);
102     _M_init_facet(new numpunct<char>(__cloc));
103     _M_init_facet(new num_get<char>);
104     _M_init_facet(new num_put<char>);
105     _M_init_facet(new time_get<char>);
106     _M_init_facet(new time_put<char>);
107     _M_init_facet(new std::messages<char>(__cloc, __str.c_str()));
108     
109 #ifdef  _GLIBCPP_USE_WCHAR_T
110     _M_init_facet(new std::collate<wchar_t>(__cloc));
111     _M_init_facet(new std::ctype<wchar_t>);
112     _M_init_facet(new codecvt<wchar_t, char, mbstate_t>);
113     _M_init_facet(new moneypunct<wchar_t, false>(__cloc));
114     _M_init_facet(new moneypunct<wchar_t, true>(__cloc));
115     _M_init_facet(new money_get<wchar_t>);
116     _M_init_facet(new money_put<wchar_t>);
117     _M_init_facet(new numpunct<wchar_t>(__cloc));
118     _M_init_facet(new num_get<wchar_t>);
119     _M_init_facet(new num_put<wchar_t>);
120     _M_init_facet(new time_get<wchar_t>);
121     _M_init_facet(new time_put<wchar_t>);
122     _M_init_facet(new std::messages<wchar_t>(__cloc, __str.c_str()));
123 #endif    
124     locale::facet::_S_destroy_c_locale(__cloc);
125   }
126   
127   void
128   locale::_Impl::
129   _M_replace_categories(const _Impl* __imp, category __cat)
130   {
131     const string __none("*");
132     category __mask;
133     for (unsigned int __ix = 0; __ix < _S_num_categories; ++__ix)
134       {
135         __mask = 1 << __ix;
136         if (__mask & __cat)
137           {
138             // Need to replace entry in _M_facets with other locale's info.
139             _M_replace_category(__imp, _S_facet_categories[__ix]);
140             // If both have names, go ahead and mangle.
141             if (_M_names[__ix] != __none && __imp->_M_names[__ix] != __none)
142               _M_names[__ix] = __imp->_M_names[__ix];
143           }
144       }
145   }
146
147   void
148   locale::_Impl::
149   _M_replace_category(const _Impl* __imp, const locale::id* const* __idpp)
150   {
151     for (; *__idpp; ++__idpp)
152       _M_replace_facet(__imp, *__idpp);
153   }
154   
155   void
156   locale::_Impl::
157   _M_replace_facet(const _Impl* __imp, const locale::id* __idp)
158   {
159     size_t __index = __idp->_M_index;
160     if (__index == 0 
161         || __imp->_M_facets->size() <= __index 
162         || (*(__imp->_M_facets))[__index] == 0)
163       __throw_runtime_error("no locale facet");
164         
165     _M_install_facet(__idp, (*(__imp->_M_facets))[__index]); 
166   }
167
168   void
169   locale::_Impl::
170   _M_install_facet(const locale::id* __idp, facet* __fp)
171   {
172     if (__fp)
173       {
174         size_t& __index = __idp->_M_index;
175         if (!__index)
176           __index = ++locale::id::_S_highwater;  // XXX MT
177         
178         if (__index >= _M_facets->size())
179           _M_facets->resize(__index + 1, 0);  // might throw
180
181         facet*& __fpr = (*_M_facets)[__index];
182         if (__fpr)
183           {
184             // Replacing an existing facet.
185             // Order matters, here:
186             __fp->_M_add_reference();
187             __fpr->_M_remove_reference();
188             __fpr = __fp;
189           }
190         else
191           {
192             // Installing a newly created facet into an empty
193             // _M_facets container, say a newly-constructed,
194             // swanky-fresh _Impl.
195             (*_M_facets)[__index] = __fp;
196           }
197       }
198   }
199 } // namespace std