Home | History | Annotate | Download | only in src
      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