OSDN Git Service

libstdc++/5432
[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 <clocale>
29 #include <cstring>
30 #include <locale>
31 #include <vector>
32 #include <stdexcept>
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;
76     locale::facet::_S_create_c_locale(__cloc, __str.c_str());
77
78     // This is needed as presently "C" locales != required data in
79     // __timepunct, numpunct, and moneypunct.
80     __c_locale __cloc_c = NULL;
81     if (__str != "C" && __str != "POSIX")
82       __cloc_c = __cloc;
83
84     // Allocate facet container.
85     try
86       {  _M_facets = new __vec_facet(_S_num_facets, NULL); }
87     catch(...) 
88       {
89         delete _M_facets;
90         __throw_exception_again;
91       }
92
93     // Name all the categories.
94     for (size_t i = 0; i < _S_num_categories; ++i)
95       _M_names[i] = __str;
96
97     // Construct all standard facets and add them to _M_facets.
98     _M_init_facet(new std::collate<char>(__cloc));
99     _M_init_facet(new std::ctype<char>(__cloc));
100     _M_init_facet(new codecvt<char, char, mbstate_t>);
101     _M_init_facet(new moneypunct<char, false>(__cloc_c));
102     _M_init_facet(new moneypunct<char, true>(__cloc_c));
103     _M_init_facet(new money_get<char>);
104     _M_init_facet(new money_put<char>);
105     _M_init_facet(new numpunct<char>(__cloc_c));
106     _M_init_facet(new num_get<char>);
107     _M_init_facet(new num_put<char>);
108     _M_init_facet(new __timepunct<char>(__cloc_c, __str.c_str()));
109     _M_init_facet(new time_get<char>);
110     _M_init_facet(new time_put<char>);
111     _M_init_facet(new std::messages<char>(__cloc, __str.c_str()));
112     
113 #ifdef  _GLIBCPP_USE_WCHAR_T
114     _M_init_facet(new std::collate<wchar_t>(__cloc));
115     _M_init_facet(new std::ctype<wchar_t>(__cloc));
116     _M_init_facet(new codecvt<wchar_t, char, mbstate_t>);
117     _M_init_facet(new moneypunct<wchar_t, false>(__cloc_c));
118     _M_init_facet(new moneypunct<wchar_t, true>(__cloc_c));
119     _M_init_facet(new money_get<wchar_t>);
120     _M_init_facet(new money_put<wchar_t>);
121     _M_init_facet(new numpunct<wchar_t>(__cloc_c));
122     _M_init_facet(new num_get<wchar_t>);
123     _M_init_facet(new num_put<wchar_t>);
124     _M_init_facet(new __timepunct<wchar_t>(__cloc_c, __str.c_str()));
125     _M_init_facet(new time_get<wchar_t>);
126     _M_init_facet(new time_put<wchar_t>);
127     _M_init_facet(new std::messages<wchar_t>(__cloc, __str.c_str()));
128 #endif    
129     locale::facet::_S_destroy_c_locale(__cloc);
130   }
131   
132   void
133   locale::_Impl::
134   _M_replace_categories(const _Impl* __imp, category __cat)
135   {
136     const string __none("*");
137     category __mask;
138     for (unsigned int __ix = 0; __ix < _S_num_categories; ++__ix)
139       {
140         __mask = 1 << __ix;
141         if (__mask & __cat)
142           {
143             // Need to replace entry in _M_facets with other locale's info.
144             _M_replace_category(__imp, _S_facet_categories[__ix]);
145             // If both have names, go ahead and mangle.
146             if (_M_names[__ix] != __none && __imp->_M_names[__ix] != __none)
147               _M_names[__ix] = __imp->_M_names[__ix];
148           }
149       }
150   }
151
152   void
153   locale::_Impl::
154   _M_replace_category(const _Impl* __imp, const locale::id* const* __idpp)
155   {
156     for (; *__idpp; ++__idpp)
157       _M_replace_facet(__imp, *__idpp);
158   }
159   
160   void
161   locale::_Impl::
162   _M_replace_facet(const _Impl* __imp, const locale::id* __idp)
163   {
164     size_t __index = __idp->_M_index;
165     if (__index == 0 
166         || __imp->_M_facets->size() <= __index 
167         || (*(__imp->_M_facets))[__index] == 0)
168       __throw_runtime_error("no locale facet");
169         
170     _M_install_facet(__idp, (*(__imp->_M_facets))[__index]); 
171   }
172
173   void
174   locale::_Impl::
175   _M_install_facet(const locale::id* __idp, facet* __fp)
176   {
177     if (__fp)
178       {
179         size_t& __index = __idp->_M_index;
180         if (!__index)
181           __index = 1 + __exchange_and_add(&locale::id::_S_highwater, 1);
182         
183         if (__index >= _M_facets->size())
184           _M_facets->resize(__index + 1, 0);  // might throw
185
186         facet*& __fpr = (*_M_facets)[__index];
187         if (__fpr)
188           {
189             // Replacing an existing facet.
190             // Order matters, here:
191             __fp->_M_add_reference();
192             __fpr->_M_remove_reference();
193             __fpr = __fp;
194           }
195         else
196           {
197             // Installing a newly created facet into an empty
198             // _M_facets container, say a newly-constructed,
199             // swanky-fresh _Impl.
200             (*_M_facets)[__index] = __fp;
201           }
202       }
203   }
204 } // namespace std