michael@0: /* michael@0: * Copyright (c) 1999 michael@0: * Silicon Graphics Computer Systems, Inc. michael@0: * michael@0: * Copyright (c) 1999 michael@0: * Boris Fomitchev michael@0: * michael@0: * This material is provided "as is", with absolutely no warranty expressed michael@0: * or implied. Any use is at your own risk. michael@0: * michael@0: * Permission to use or copy this software for any purpose is hereby granted michael@0: * without fee, provided the above notices are retained on all copies. michael@0: * Permission to modify the code and to distribute modified code is granted, michael@0: * provided the above notices are retained, and a notice that the code was michael@0: * modified is included with the above copyright notice. michael@0: * michael@0: */ michael@0: #include "stlport_prefix.h" michael@0: michael@0: #include michael@0: michael@0: #include "message_facets.h" michael@0: #include "acquire_release.h" michael@0: michael@0: _STLP_BEGIN_NAMESPACE michael@0: michael@0: _STLP_MOVE_TO_PRIV_NAMESPACE michael@0: michael@0: void _Catalog_locale_map::insert(nl_catd_type key, const locale& L) { michael@0: _STLP_TRY { michael@0: #if !defined (_STLP_NO_TYPEINFO) && !defined (_STLP_NO_RTTI) michael@0: // Don't bother to do anything unless we're using a non-default ctype facet michael@0: # ifdef _STLP_NO_WCHAR_T michael@0: typedef char _Char; michael@0: # else michael@0: typedef wchar_t _Char; michael@0: # endif michael@0: michael@0: typedef ctype<_Char> wctype; michael@0: wctype const& wct = use_facet(L); michael@0: if (typeid(wct) != typeid(wctype)) { michael@0: #endif michael@0: if (!M) michael@0: M = new map_type; michael@0: michael@0: M->insert(map_type::value_type(key, L)); michael@0: #if !defined (_STLP_NO_TYPEINFO) && !defined (_STLP_NO_RTTI) michael@0: } michael@0: #endif michael@0: } michael@0: _STLP_CATCH_ALL {} michael@0: } michael@0: michael@0: void _Catalog_locale_map::erase(nl_catd_type key) { michael@0: if (M) michael@0: M->erase(key); michael@0: } michael@0: michael@0: locale _Catalog_locale_map::lookup(nl_catd_type key) const { michael@0: if (M) { michael@0: map_type::const_iterator i = M->find(key); michael@0: return i != M->end() ? (*i).second : locale::classic(); michael@0: } michael@0: else michael@0: return locale::classic(); michael@0: } michael@0: michael@0: michael@0: #if defined (_STLP_USE_NL_CATD_MAPPING) michael@0: _STLP_VOLATILE __stl_atomic_t _Catalog_nl_catd_map::_count = 0; michael@0: michael@0: messages_base::catalog _Catalog_nl_catd_map::insert(nl_catd_type cat) { michael@0: messages_base::catalog &res = Mr[cat]; michael@0: if ( res == 0 ) { michael@0: #if defined (_STLP_ATOMIC_INCREMENT) michael@0: res = __STATIC_CAST(int, _STLP_ATOMIC_INCREMENT(&_count)); michael@0: #else michael@0: static _STLP_STATIC_MUTEX _Count_lock _STLP_MUTEX_INITIALIZER; michael@0: { michael@0: _STLP_auto_lock sentry(_Count_lock); michael@0: res = __STATIC_CAST(int, ++_count); michael@0: } michael@0: #endif michael@0: M[res] = cat; michael@0: } michael@0: return res; michael@0: } michael@0: michael@0: void _Catalog_nl_catd_map::erase(messages_base::catalog cat) { michael@0: map_type::iterator mit(M.find(cat)); michael@0: if (mit != M.end()) { michael@0: Mr.erase((*mit).second); michael@0: M.erase(mit); michael@0: } michael@0: } michael@0: #endif michael@0: michael@0: //---------------------------------------------------------------------- michael@0: // michael@0: _Messages::_Messages(bool is_wide, const char *name) : michael@0: _M_message_obj(0), _M_map(0) { michael@0: if (!name) michael@0: locale::_M_throw_on_null_name(); michael@0: michael@0: int __err_code; michael@0: char buf[_Locale_MAX_SIMPLE_NAME]; michael@0: _M_message_obj = _STLP_PRIV __acquire_messages(name, buf, 0, &__err_code); michael@0: if (!_M_message_obj) michael@0: locale::_M_throw_on_creation_failure(__err_code, name, "messages"); michael@0: michael@0: if (is_wide) michael@0: _M_map = new _Catalog_locale_map; michael@0: } michael@0: michael@0: _Messages::_Messages(bool is_wide, _Locale_messages* msg) : michael@0: _M_message_obj(msg), _M_map(is_wide ? new _Catalog_locale_map() : 0) michael@0: {} michael@0: michael@0: _Messages::~_Messages() { michael@0: __release_messages(_M_message_obj); michael@0: delete _M_map; michael@0: } michael@0: michael@0: _Messages::catalog _Messages::do_open(const string& filename, const locale& L) const { michael@0: nl_catd_type result = _M_message_obj ? _Locale_catopen(_M_message_obj, filename.c_str()) michael@0: : (nl_catd_type)(-1); michael@0: michael@0: if ( result != (nl_catd_type)(-1) ) { michael@0: if ( _M_map != 0 ) { michael@0: _M_map->insert(result, L); michael@0: } michael@0: return _STLP_MUTABLE(_Messages_impl, _M_cat).insert( result ); michael@0: } michael@0: michael@0: return -1; michael@0: } michael@0: michael@0: string _Messages::do_get(catalog cat, michael@0: int set, int p_id, const string& dfault) const { michael@0: return _M_message_obj != 0 && cat >= 0 michael@0: ? string(_Locale_catgets(_M_message_obj, _STLP_MUTABLE(_Messages_impl, _M_cat)[cat], michael@0: set, p_id, dfault.c_str())) michael@0: : dfault; michael@0: } michael@0: michael@0: #if !defined (_STLP_NO_WCHAR_T) michael@0: michael@0: wstring michael@0: _Messages::do_get(catalog thecat, michael@0: int set, int p_id, const wstring& dfault) const { michael@0: typedef ctype wctype; michael@0: const wctype& ct = use_facet(_M_map->lookup(_STLP_MUTABLE(_Messages_impl, _M_cat)[thecat])); michael@0: michael@0: const char* str = _Locale_catgets(_M_message_obj, _STLP_MUTABLE(_Messages_impl, _M_cat)[thecat], set, p_id, ""); michael@0: michael@0: // Verify that the lookup failed; an empty string might represent success. michael@0: if (!str) michael@0: return dfault; michael@0: else if (str[0] == '\0') { michael@0: const char* str2 = _Locale_catgets(_M_message_obj, _STLP_MUTABLE(_Messages_impl, _M_cat)[thecat], set, p_id, "*"); michael@0: if (!str2 || ((str2[0] == '*') && (str2[1] == '\0'))) michael@0: return dfault; michael@0: } michael@0: michael@0: // str is correct. Now we must widen it to get a wstring. michael@0: size_t n = strlen(str); michael@0: michael@0: // NOT PORTABLE. What we're doing relies on internal details of the michael@0: // string implementation. (Contiguity of string elements.) michael@0: wstring result(n, wchar_t(0)); michael@0: ct.widen(str, str + n, &*result.begin()); michael@0: return result; michael@0: } michael@0: michael@0: #endif michael@0: michael@0: void _Messages::do_close(catalog thecat) const { michael@0: if (_M_message_obj) michael@0: _Locale_catclose(_M_message_obj, _STLP_MUTABLE(_Messages_impl, _M_cat)[thecat]); michael@0: if (_M_map) _M_map->erase(_STLP_MUTABLE(_Messages_impl, _M_cat)[thecat]); michael@0: _STLP_MUTABLE(_Messages_impl, _M_cat).erase( thecat ); michael@0: } michael@0: michael@0: _STLP_MOVE_TO_STD_NAMESPACE michael@0: michael@0: //---------------------------------------------------------------------- michael@0: // messages michael@0: messages::messages(size_t refs) michael@0: : locale::facet(refs) {} michael@0: michael@0: messages_byname::messages_byname(const char *name, size_t refs) michael@0: : messages(refs), _M_impl(new _STLP_PRIV _Messages(false, name)) {} michael@0: michael@0: messages_byname::messages_byname(_Locale_messages* msg) michael@0: : messages(0), _M_impl(new _STLP_PRIV _Messages(false, msg)) {} michael@0: michael@0: messages_byname::~messages_byname() michael@0: { delete _M_impl; } michael@0: michael@0: messages_byname::catalog michael@0: messages_byname::do_open(const string& filename, const locale& l) const michael@0: { return _M_impl->do_open(filename, l); } michael@0: michael@0: string michael@0: messages_byname::do_get(catalog cat, int set, int p_id, michael@0: const string& dfault) const michael@0: { return _M_impl->do_get(cat, set, p_id, dfault); } michael@0: michael@0: void messages_byname::do_close(catalog cat) const michael@0: { _M_impl->do_close(cat); } michael@0: michael@0: #if !defined (_STLP_NO_WCHAR_T) michael@0: michael@0: //---------------------------------------------------------------------- michael@0: // messages michael@0: michael@0: messages::messages(size_t refs) michael@0: : locale::facet(refs) {} michael@0: michael@0: messages_byname::messages_byname(const char *name, size_t refs) michael@0: : messages(refs), _M_impl(new _STLP_PRIV _Messages(true, name)) {} michael@0: michael@0: messages_byname::messages_byname(_Locale_messages* msg) michael@0: : messages(0), _M_impl(new _STLP_PRIV _Messages(true, msg)) {} michael@0: michael@0: messages_byname::~messages_byname() michael@0: { delete _M_impl; } michael@0: michael@0: messages_byname::catalog michael@0: messages_byname::do_open(const string& filename, const locale& L) const michael@0: { return _M_impl->do_open(filename, L); } michael@0: michael@0: wstring michael@0: messages_byname::do_get(catalog thecat, michael@0: int set, int p_id, const wstring& dfault) const michael@0: { return _M_impl->do_get(thecat, set, p_id, dfault); } michael@0: michael@0: void messages_byname::do_close(catalog cat) const michael@0: { _M_impl->do_close(cat); } michael@0: michael@0: #endif michael@0: michael@0: _STLP_END_NAMESPACE michael@0: michael@0: // Local Variables: michael@0: // mode:C++ michael@0: // End: