1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * Copyright (c) 1999
3*c2c66affSColin Finck  * Silicon Graphics Computer Systems, Inc.
4*c2c66affSColin Finck  *
5*c2c66affSColin Finck  * Copyright (c) 1999
6*c2c66affSColin Finck  * Boris Fomitchev
7*c2c66affSColin Finck  *
8*c2c66affSColin Finck  * This material is provided "as is", with absolutely no warranty expressed
9*c2c66affSColin Finck  * or implied. Any use is at your own risk.
10*c2c66affSColin Finck  *
11*c2c66affSColin Finck  * Permission to use or copy this software for any purpose is hereby granted
12*c2c66affSColin Finck  * without fee, provided the above notices are retained on all copies.
13*c2c66affSColin Finck  * Permission to modify the code and to distribute modified code is granted,
14*c2c66affSColin Finck  * provided the above notices are retained, and a notice that the code was
15*c2c66affSColin Finck  * modified is included with the above copyright notice.
16*c2c66affSColin Finck  *
17*c2c66affSColin Finck  */
18*c2c66affSColin Finck #include "stlport_prefix.h"
19*c2c66affSColin Finck 
20*c2c66affSColin Finck #include <typeinfo>
21*c2c66affSColin Finck 
22*c2c66affSColin Finck #include "message_facets.h"
23*c2c66affSColin Finck #include "acquire_release.h"
24*c2c66affSColin Finck 
25*c2c66affSColin Finck _STLP_BEGIN_NAMESPACE
26*c2c66affSColin Finck 
27*c2c66affSColin Finck _STLP_MOVE_TO_PRIV_NAMESPACE
28*c2c66affSColin Finck 
insert(nl_catd_type key,const locale & L)29*c2c66affSColin Finck void _Catalog_locale_map::insert(nl_catd_type key, const locale& L) {
30*c2c66affSColin Finck   _STLP_TRY {
31*c2c66affSColin Finck #if !defined (_STLP_NO_TYPEINFO) && !defined (_STLP_NO_RTTI)
32*c2c66affSColin Finck     // Don't bother to do anything unless we're using a non-default ctype facet
33*c2c66affSColin Finck #  ifdef _STLP_NO_WCHAR_T
34*c2c66affSColin Finck     typedef char _Char;
35*c2c66affSColin Finck #  else
36*c2c66affSColin Finck     typedef wchar_t _Char;
37*c2c66affSColin Finck #  endif
38*c2c66affSColin Finck 
39*c2c66affSColin Finck     typedef ctype<_Char> wctype;
40*c2c66affSColin Finck     wctype const& wct = use_facet<wctype>(L);
41*c2c66affSColin Finck     if (typeid(wct) != typeid(wctype)) {
42*c2c66affSColin Finck #endif
43*c2c66affSColin Finck       if (!M)
44*c2c66affSColin Finck         M = new map_type;
45*c2c66affSColin Finck 
46*c2c66affSColin Finck       M->insert(map_type::value_type(key, L));
47*c2c66affSColin Finck #if !defined (_STLP_NO_TYPEINFO) && !defined (_STLP_NO_RTTI)
48*c2c66affSColin Finck     }
49*c2c66affSColin Finck #endif
50*c2c66affSColin Finck   }
51*c2c66affSColin Finck   _STLP_CATCH_ALL {}
52*c2c66affSColin Finck }
53*c2c66affSColin Finck 
erase(nl_catd_type key)54*c2c66affSColin Finck void _Catalog_locale_map::erase(nl_catd_type key) {
55*c2c66affSColin Finck   if (M)
56*c2c66affSColin Finck     M->erase(key);
57*c2c66affSColin Finck }
58*c2c66affSColin Finck 
lookup(nl_catd_type key) const59*c2c66affSColin Finck locale _Catalog_locale_map::lookup(nl_catd_type key) const {
60*c2c66affSColin Finck   if (M) {
61*c2c66affSColin Finck     map_type::const_iterator i = M->find(key);
62*c2c66affSColin Finck     return i != M->end() ? (*i).second : locale::classic();
63*c2c66affSColin Finck   }
64*c2c66affSColin Finck   else
65*c2c66affSColin Finck     return locale::classic();
66*c2c66affSColin Finck }
67*c2c66affSColin Finck 
68*c2c66affSColin Finck 
69*c2c66affSColin Finck #if defined (_STLP_USE_NL_CATD_MAPPING)
70*c2c66affSColin Finck _STLP_VOLATILE __stl_atomic_t _Catalog_nl_catd_map::_count = 0;
71*c2c66affSColin Finck 
insert(nl_catd_type cat)72*c2c66affSColin Finck messages_base::catalog _Catalog_nl_catd_map::insert(nl_catd_type cat) {
73*c2c66affSColin Finck   messages_base::catalog &res = Mr[cat];
74*c2c66affSColin Finck   if ( res == 0 ) {
75*c2c66affSColin Finck #if defined (_STLP_ATOMIC_INCREMENT)
76*c2c66affSColin Finck     res = __STATIC_CAST(int, _STLP_ATOMIC_INCREMENT(&_count));
77*c2c66affSColin Finck #else
78*c2c66affSColin Finck     static _STLP_STATIC_MUTEX _Count_lock _STLP_MUTEX_INITIALIZER;
79*c2c66affSColin Finck     {
80*c2c66affSColin Finck       _STLP_auto_lock sentry(_Count_lock);
81*c2c66affSColin Finck       res = __STATIC_CAST(int, ++_count);
82*c2c66affSColin Finck     }
83*c2c66affSColin Finck #endif
84*c2c66affSColin Finck     M[res] = cat;
85*c2c66affSColin Finck   }
86*c2c66affSColin Finck   return res;
87*c2c66affSColin Finck }
88*c2c66affSColin Finck 
erase(messages_base::catalog cat)89*c2c66affSColin Finck void _Catalog_nl_catd_map::erase(messages_base::catalog cat) {
90*c2c66affSColin Finck   map_type::iterator mit(M.find(cat));
91*c2c66affSColin Finck   if (mit != M.end()) {
92*c2c66affSColin Finck     Mr.erase((*mit).second);
93*c2c66affSColin Finck     M.erase(mit);
94*c2c66affSColin Finck   }
95*c2c66affSColin Finck }
96*c2c66affSColin Finck #endif
97*c2c66affSColin Finck 
98*c2c66affSColin Finck //----------------------------------------------------------------------
99*c2c66affSColin Finck //
_Messages(bool is_wide,const char * name)100*c2c66affSColin Finck _Messages::_Messages(bool is_wide, const char *name) :
101*c2c66affSColin Finck   _M_message_obj(0), _M_map(0) {
102*c2c66affSColin Finck   if (!name)
103*c2c66affSColin Finck     locale::_M_throw_on_null_name();
104*c2c66affSColin Finck 
105*c2c66affSColin Finck   int __err_code;
106*c2c66affSColin Finck   char buf[_Locale_MAX_SIMPLE_NAME];
107*c2c66affSColin Finck   _M_message_obj = _STLP_PRIV __acquire_messages(name, buf, 0, &__err_code);
108*c2c66affSColin Finck   if (!_M_message_obj)
109*c2c66affSColin Finck     locale::_M_throw_on_creation_failure(__err_code, name, "messages");
110*c2c66affSColin Finck 
111*c2c66affSColin Finck   if (is_wide)
112*c2c66affSColin Finck     _M_map = new _Catalog_locale_map;
113*c2c66affSColin Finck }
114*c2c66affSColin Finck 
_Messages(bool is_wide,_Locale_messages * msg)115*c2c66affSColin Finck _Messages::_Messages(bool is_wide, _Locale_messages* msg) :
116*c2c66affSColin Finck   _M_message_obj(msg), _M_map(is_wide ? new _Catalog_locale_map() : 0)
117*c2c66affSColin Finck {}
118*c2c66affSColin Finck 
~_Messages()119*c2c66affSColin Finck _Messages::~_Messages() {
120*c2c66affSColin Finck   __release_messages(_M_message_obj);
121*c2c66affSColin Finck   delete _M_map;
122*c2c66affSColin Finck }
123*c2c66affSColin Finck 
do_open(const string & filename,const locale & L) const124*c2c66affSColin Finck _Messages::catalog _Messages::do_open(const string& filename, const locale& L) const {
125*c2c66affSColin Finck   nl_catd_type result = _M_message_obj ? _Locale_catopen(_M_message_obj, filename.c_str())
126*c2c66affSColin Finck     : (nl_catd_type)(-1);
127*c2c66affSColin Finck 
128*c2c66affSColin Finck   if ( result != (nl_catd_type)(-1) ) {
129*c2c66affSColin Finck     if ( _M_map != 0 ) {
130*c2c66affSColin Finck       _M_map->insert(result, L);
131*c2c66affSColin Finck     }
132*c2c66affSColin Finck     return _STLP_MUTABLE(_Messages_impl, _M_cat).insert( result );
133*c2c66affSColin Finck   }
134*c2c66affSColin Finck 
135*c2c66affSColin Finck   return -1;
136*c2c66affSColin Finck }
137*c2c66affSColin Finck 
do_get(catalog cat,int set,int p_id,const string & dfault) const138*c2c66affSColin Finck string _Messages::do_get(catalog cat,
139*c2c66affSColin Finck                          int set, int p_id, const string& dfault) const {
140*c2c66affSColin Finck   return _M_message_obj != 0 && cat >= 0
141*c2c66affSColin Finck     ? string(_Locale_catgets(_M_message_obj, _STLP_MUTABLE(_Messages_impl, _M_cat)[cat],
142*c2c66affSColin Finck                              set, p_id, dfault.c_str()))
143*c2c66affSColin Finck     : dfault;
144*c2c66affSColin Finck }
145*c2c66affSColin Finck 
146*c2c66affSColin Finck #if !defined (_STLP_NO_WCHAR_T)
147*c2c66affSColin Finck 
148*c2c66affSColin Finck wstring
do_get(catalog thecat,int set,int p_id,const wstring & dfault) const149*c2c66affSColin Finck _Messages::do_get(catalog thecat,
150*c2c66affSColin Finck                   int set, int p_id, const wstring& dfault) const {
151*c2c66affSColin Finck   typedef ctype<wchar_t> wctype;
152*c2c66affSColin Finck   const wctype& ct = use_facet<wctype>(_M_map->lookup(_STLP_MUTABLE(_Messages_impl, _M_cat)[thecat]));
153*c2c66affSColin Finck 
154*c2c66affSColin Finck   const char* str = _Locale_catgets(_M_message_obj, _STLP_MUTABLE(_Messages_impl, _M_cat)[thecat], set, p_id, "");
155*c2c66affSColin Finck 
156*c2c66affSColin Finck   // Verify that the lookup failed; an empty string might represent success.
157*c2c66affSColin Finck   if (!str)
158*c2c66affSColin Finck     return dfault;
159*c2c66affSColin Finck   else if (str[0] == '\0') {
160*c2c66affSColin Finck     const char* str2 = _Locale_catgets(_M_message_obj, _STLP_MUTABLE(_Messages_impl, _M_cat)[thecat], set, p_id, "*");
161*c2c66affSColin Finck     if (!str2 || ((str2[0] == '*') && (str2[1] == '\0')))
162*c2c66affSColin Finck       return dfault;
163*c2c66affSColin Finck   }
164*c2c66affSColin Finck 
165*c2c66affSColin Finck   // str is correct.  Now we must widen it to get a wstring.
166*c2c66affSColin Finck   size_t n = strlen(str);
167*c2c66affSColin Finck 
168*c2c66affSColin Finck   // NOT PORTABLE.  What we're doing relies on internal details of the
169*c2c66affSColin Finck   // string implementation.  (Contiguity of string elements.)
170*c2c66affSColin Finck   wstring result(n, wchar_t(0));
171*c2c66affSColin Finck   ct.widen(str, str + n, &*result.begin());
172*c2c66affSColin Finck   return result;
173*c2c66affSColin Finck }
174*c2c66affSColin Finck 
175*c2c66affSColin Finck #endif
176*c2c66affSColin Finck 
do_close(catalog thecat) const177*c2c66affSColin Finck void _Messages::do_close(catalog thecat) const {
178*c2c66affSColin Finck   if (_M_message_obj)
179*c2c66affSColin Finck     _Locale_catclose(_M_message_obj, _STLP_MUTABLE(_Messages_impl, _M_cat)[thecat]);
180*c2c66affSColin Finck   if (_M_map) _M_map->erase(_STLP_MUTABLE(_Messages_impl, _M_cat)[thecat]);
181*c2c66affSColin Finck   _STLP_MUTABLE(_Messages_impl, _M_cat).erase( thecat );
182*c2c66affSColin Finck }
183*c2c66affSColin Finck 
184*c2c66affSColin Finck _STLP_MOVE_TO_STD_NAMESPACE
185*c2c66affSColin Finck 
186*c2c66affSColin Finck //----------------------------------------------------------------------
187*c2c66affSColin Finck // messages<char>
messages(size_t refs)188*c2c66affSColin Finck messages<char>::messages(size_t refs)
189*c2c66affSColin Finck   : locale::facet(refs) {}
190*c2c66affSColin Finck 
messages_byname(const char * name,size_t refs)191*c2c66affSColin Finck messages_byname<char>::messages_byname(const char *name, size_t refs)
192*c2c66affSColin Finck   : messages<char>(refs), _M_impl(new _STLP_PRIV _Messages(false, name)) {}
193*c2c66affSColin Finck 
messages_byname(_Locale_messages * msg)194*c2c66affSColin Finck messages_byname<char>::messages_byname(_Locale_messages* msg)
195*c2c66affSColin Finck   : messages<char>(0), _M_impl(new _STLP_PRIV _Messages(false, msg)) {}
196*c2c66affSColin Finck 
~messages_byname()197*c2c66affSColin Finck messages_byname<char>::~messages_byname()
198*c2c66affSColin Finck { delete _M_impl; }
199*c2c66affSColin Finck 
200*c2c66affSColin Finck messages_byname<char>::catalog
do_open(const string & filename,const locale & l) const201*c2c66affSColin Finck messages_byname<char>::do_open(const string& filename, const locale& l) const
202*c2c66affSColin Finck { return _M_impl->do_open(filename, l); }
203*c2c66affSColin Finck 
204*c2c66affSColin Finck string
do_get(catalog cat,int set,int p_id,const string & dfault) const205*c2c66affSColin Finck messages_byname<char>::do_get(catalog cat, int set, int p_id,
206*c2c66affSColin Finck                               const string& dfault) const
207*c2c66affSColin Finck { return _M_impl->do_get(cat, set, p_id, dfault); }
208*c2c66affSColin Finck 
do_close(catalog cat) const209*c2c66affSColin Finck void messages_byname<char>::do_close(catalog cat) const
210*c2c66affSColin Finck { _M_impl->do_close(cat); }
211*c2c66affSColin Finck 
212*c2c66affSColin Finck #if !defined (_STLP_NO_WCHAR_T)
213*c2c66affSColin Finck 
214*c2c66affSColin Finck //----------------------------------------------------------------------
215*c2c66affSColin Finck // messages<wchar_t>
216*c2c66affSColin Finck 
messages(size_t refs)217*c2c66affSColin Finck messages<wchar_t>::messages(size_t refs)
218*c2c66affSColin Finck   : locale::facet(refs) {}
219*c2c66affSColin Finck 
messages_byname(const char * name,size_t refs)220*c2c66affSColin Finck messages_byname<wchar_t>::messages_byname(const char *name, size_t refs)
221*c2c66affSColin Finck   : messages<wchar_t>(refs), _M_impl(new _STLP_PRIV _Messages(true, name)) {}
222*c2c66affSColin Finck 
messages_byname(_Locale_messages * msg)223*c2c66affSColin Finck messages_byname<wchar_t>::messages_byname(_Locale_messages* msg)
224*c2c66affSColin Finck   : messages<wchar_t>(0), _M_impl(new _STLP_PRIV _Messages(true, msg)) {}
225*c2c66affSColin Finck 
~messages_byname()226*c2c66affSColin Finck messages_byname<wchar_t>::~messages_byname()
227*c2c66affSColin Finck { delete _M_impl; }
228*c2c66affSColin Finck 
229*c2c66affSColin Finck messages_byname<wchar_t>::catalog
do_open(const string & filename,const locale & L) const230*c2c66affSColin Finck messages_byname<wchar_t>::do_open(const string& filename, const locale& L) const
231*c2c66affSColin Finck { return _M_impl->do_open(filename, L); }
232*c2c66affSColin Finck 
233*c2c66affSColin Finck wstring
do_get(catalog thecat,int set,int p_id,const wstring & dfault) const234*c2c66affSColin Finck messages_byname<wchar_t>::do_get(catalog thecat,
235*c2c66affSColin Finck                                  int set, int p_id, const wstring& dfault) const
236*c2c66affSColin Finck { return _M_impl->do_get(thecat, set, p_id, dfault); }
237*c2c66affSColin Finck 
do_close(catalog cat) const238*c2c66affSColin Finck void messages_byname<wchar_t>::do_close(catalog cat) const
239*c2c66affSColin Finck { _M_impl->do_close(cat); }
240*c2c66affSColin Finck 
241*c2c66affSColin Finck #endif
242*c2c66affSColin Finck 
243*c2c66affSColin Finck _STLP_END_NAMESPACE
244*c2c66affSColin Finck 
245*c2c66affSColin Finck // Local Variables:
246*c2c66affSColin Finck // mode:C++
247*c2c66affSColin Finck // End:
248