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