1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/build/stlport/src/locale.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,446 @@ 1.4 +/* 1.5 + * Copyright (c) 1999 1.6 + * Silicon Graphics Computer Systems, Inc. 1.7 + * 1.8 + * Copyright (c) 1999 1.9 + * Boris Fomitchev 1.10 + * 1.11 + * This material is provided "as is", with absolutely no warranty expressed 1.12 + * or implied. Any use is at your own risk. 1.13 + * 1.14 + * Permission to use or copy this software for any purpose is hereby granted 1.15 + * without fee, provided the above notices are retained on all copies. 1.16 + * Permission to modify the code and to distribute modified code is granted, 1.17 + * provided the above notices are retained, and a notice that the code was 1.18 + * modified is included with the above copyright notice. 1.19 + * 1.20 + */ 1.21 + 1.22 +#include "stlport_prefix.h" 1.23 + 1.24 +#include <locale> 1.25 +#include <stdexcept> 1.26 + 1.27 +#include "c_locale.h" 1.28 +#include "locale_impl.h" 1.29 + 1.30 +_STLP_BEGIN_NAMESPACE 1.31 + 1.32 +#define _NAMELESS "*" 1.33 +static const char _Nameless[] = _NAMELESS; 1.34 + 1.35 +static inline bool is_C_locale_name (const char* name) 1.36 +{ return ((name[0] == 'C') && (name[1] == 0)); } 1.37 + 1.38 +locale* _Stl_get_classic_locale(); 1.39 +locale* _Stl_get_global_locale(); 1.40 + 1.41 +#if defined (_STLP_USE_MSVC6_MEM_T_BUG_WORKAROUND) || \ 1.42 + defined (_STLP_SIGNAL_RUNTIME_COMPATIBILITY) || defined (_STLP_CHECK_RUNTIME_COMPATIBILITY) 1.43 +# define locale _STLP_NO_MEM_T_NAME(loc) 1.44 +#endif 1.45 + 1.46 +locale::facet::~facet() {} 1.47 + 1.48 +#if !defined (_STLP_MEMBER_TEMPLATES) || defined (_STLP_INLINE_MEMBER_TEMPLATES) 1.49 +// members that fail to be templates 1.50 +bool locale::operator()(const string& __x, 1.51 + const string& __y) const 1.52 +{ return __locale_do_operator_call(*this, __x, __y); } 1.53 + 1.54 +# if !defined (_STLP_NO_WCHAR_T) 1.55 +bool locale::operator()(const wstring& __x, 1.56 + const wstring& __y) const 1.57 +{ return __locale_do_operator_call(*this, __x, __y); } 1.58 +# endif 1.59 +#endif 1.60 + 1.61 +void _STLP_CALL locale::_M_throw_on_null_name() 1.62 +{ _STLP_THROW(runtime_error("Invalid null locale name")); } 1.63 + 1.64 +void _STLP_CALL locale::_M_throw_on_combine_error(const string& name) { 1.65 + string what = "Unable to find facet"; 1.66 + what += " in "; 1.67 + what += name.empty() ? "system" : name.c_str(); 1.68 + what += " locale"; 1.69 + _STLP_THROW(runtime_error(what.c_str())); 1.70 +} 1.71 + 1.72 +void _STLP_CALL locale::_M_throw_on_creation_failure(int __err_code, 1.73 + const char* name, const char* facet) { 1.74 + string what; 1.75 + switch (__err_code) { 1.76 + case _STLP_LOC_UNSUPPORTED_FACET_CATEGORY: 1.77 + what = "No platform localization support for "; 1.78 + what += facet; 1.79 + what += " facet category, unable to create facet for "; 1.80 + what += name[0] == 0 ? "system" : name; 1.81 + what += " locale"; 1.82 + break; 1.83 + case _STLP_LOC_NO_PLATFORM_SUPPORT: 1.84 + what = "No platform localization support, unable to create "; 1.85 + what += name[0] == 0 ? "system" : name; 1.86 + what += " locale"; 1.87 + break; 1.88 + default: 1.89 + case _STLP_LOC_UNKNOWN_NAME: 1.90 + what = "Unable to create facet "; 1.91 + what += facet; 1.92 + what += " from name '"; 1.93 + what += name; 1.94 + what += "'"; 1.95 + break; 1.96 + case _STLP_LOC_NO_MEMORY: 1.97 + _STLP_THROW_BAD_ALLOC; 1.98 + break; 1.99 + } 1.100 + 1.101 + _STLP_THROW(runtime_error(what.c_str())); 1.102 +} 1.103 + 1.104 +// Takes a reference to a locale::id, assign a numeric index if not already 1.105 +// affected and returns it. The returned index is always positive. 1.106 +static const locale::id& _Stl_loc_get_index(locale::id& id) { 1.107 + if (id._M_index == 0) { 1.108 +#if defined (_STLP_ATOMIC_INCREMENT) && !defined (_STLP_WIN95_LIKE) 1.109 + static _STLP_VOLATILE __stl_atomic_t _S_index = __STATIC_CAST(__stl_atomic_t, locale::id::_S_max); 1.110 + id._M_index = _STLP_ATOMIC_INCREMENT(&_S_index); 1.111 +#else 1.112 + static _STLP_STATIC_MUTEX _Index_lock _STLP_MUTEX_INITIALIZER; 1.113 + _STLP_auto_lock sentry(_Index_lock); 1.114 + size_t new_index = locale::id::_S_max++; 1.115 + id._M_index = new_index; 1.116 +#endif 1.117 + } 1.118 + return id; 1.119 +} 1.120 + 1.121 +// Default constructor: create a copy of the global locale. 1.122 +locale::locale() _STLP_NOTHROW 1.123 + : _M_impl(_get_Locale_impl(_Stl_get_global_locale()->_M_impl)) 1.124 +{} 1.125 + 1.126 +// Copy constructor 1.127 +locale::locale(const locale& L) _STLP_NOTHROW 1.128 + : _M_impl( _get_Locale_impl( L._M_impl ) ) 1.129 +{} 1.130 + 1.131 +void locale::_M_insert(facet* f, locale::id& n) { 1.132 + if (f) 1.133 + _M_impl->insert(f, _Stl_loc_get_index(n)); 1.134 +} 1.135 + 1.136 +locale::locale( _Locale_impl* impl ) : 1.137 + _M_impl( _get_Locale_impl( impl ) ) 1.138 +{} 1.139 + 1.140 +// Create a locale from a name. 1.141 +locale::locale(const char* name) 1.142 + : _M_impl(0) { 1.143 + if (!name) 1.144 + _M_throw_on_null_name(); 1.145 + 1.146 + if (is_C_locale_name(name)) { 1.147 + _M_impl = _get_Locale_impl( locale::classic()._M_impl ); 1.148 + return; 1.149 + } 1.150 + 1.151 + _Locale_impl* impl = 0; 1.152 + _STLP_TRY { 1.153 + impl = new _Locale_impl(locale::id::_S_max, name); 1.154 + 1.155 + // Insert categories one at a time. 1.156 + _Locale_name_hint *hint = 0; 1.157 + const char* ctype_name = name; 1.158 + char ctype_buf[_Locale_MAX_SIMPLE_NAME]; 1.159 + const char* numeric_name = name; 1.160 + char numeric_buf[_Locale_MAX_SIMPLE_NAME]; 1.161 + const char* time_name = name; 1.162 + char time_buf[_Locale_MAX_SIMPLE_NAME]; 1.163 + const char* collate_name = name; 1.164 + char collate_buf[_Locale_MAX_SIMPLE_NAME]; 1.165 + const char* monetary_name = name; 1.166 + char monetary_buf[_Locale_MAX_SIMPLE_NAME]; 1.167 + const char* messages_name = name; 1.168 + char messages_buf[_Locale_MAX_SIMPLE_NAME]; 1.169 + hint = impl->insert_ctype_facets(ctype_name, ctype_buf, hint); 1.170 + hint = impl->insert_numeric_facets(numeric_name, numeric_buf, hint); 1.171 + hint = impl->insert_time_facets(time_name, time_buf, hint); 1.172 + hint = impl->insert_collate_facets(collate_name, collate_buf, hint); 1.173 + hint = impl->insert_monetary_facets(monetary_name, monetary_buf, hint); 1.174 + impl->insert_messages_facets(messages_name, messages_buf, hint); 1.175 + 1.176 + // Try to use a normalize locale name in order to have the == operator 1.177 + // to behave correctly: 1.178 + if (strcmp(ctype_name, numeric_name) == 0 && 1.179 + strcmp(ctype_name, time_name) == 0 && 1.180 + strcmp(ctype_name, collate_name) == 0 && 1.181 + strcmp(ctype_name, monetary_name) == 0 && 1.182 + strcmp(ctype_name, messages_name) == 0) { 1.183 + impl->name = ctype_name; 1.184 + } 1.185 + // else we keep current name. 1.186 + 1.187 + // reassign impl 1.188 + _M_impl = _get_Locale_impl( impl ); 1.189 + } 1.190 + _STLP_UNWIND(delete impl); 1.191 +} 1.192 + 1.193 +static void _Stl_loc_combine_names_aux(_Locale_impl* L, 1.194 + const char* name, 1.195 + const char* ctype_name, const char* time_name, const char* numeric_name, 1.196 + const char* collate_name, const char* monetary_name, const char* messages_name, 1.197 + locale::category c) { 1.198 + // This function is only called when names has been validated so using _Locale_extract_*_name 1.199 + // can't fail. 1.200 + int __err_code; 1.201 + char buf[_Locale_MAX_SIMPLE_NAME]; 1.202 + L->name = string("LC_CTYPE=") + _Locale_extract_ctype_name((c & locale::ctype) ? ctype_name : name, buf, 0, &__err_code) + ";"; 1.203 + L->name += string("LC_TIME=") + _Locale_extract_time_name((c & locale::time) ? time_name : name, buf, 0, &__err_code) + ";"; 1.204 + L->name += string("LC_NUMERIC=") + _Locale_extract_numeric_name((c & locale::numeric) ? numeric_name : name, buf, 0, &__err_code) + ";"; 1.205 + L->name += string("LC_COLLATE=") + _Locale_extract_collate_name((c & locale::collate) ? collate_name : name, buf, 0, &__err_code) + ";"; 1.206 + L->name += string("LC_MONETARY=") + _Locale_extract_monetary_name((c & locale::monetary) ? monetary_name : name, buf, 0, &__err_code) + ";"; 1.207 + L->name += string("LC_MESSAGES=") + _Locale_extract_messages_name((c & locale::messages) ? messages_name : name, buf, 0, &__err_code); 1.208 +} 1.209 + 1.210 +// Give L a name where all facets except those in category c 1.211 +// are taken from name1, and those in category c are taken from name2. 1.212 +static void _Stl_loc_combine_names(_Locale_impl* L, 1.213 + const char* name1, const char* name2, 1.214 + locale::category c) { 1.215 + if ((c & locale::all) == 0 || strcmp(name1, name1) == 0) 1.216 + L->name = name1; 1.217 + else if ((c & locale::all) == locale::all) 1.218 + L->name = name2; 1.219 + else { 1.220 + _Stl_loc_combine_names_aux(L, name1, name2, name2, name2, name2, name2, name2, c); 1.221 + } 1.222 +} 1.223 + 1.224 +static void _Stl_loc_combine_names(_Locale_impl* L, 1.225 + const char* name, 1.226 + const char* ctype_name, const char* time_name, const char* numeric_name, 1.227 + const char* collate_name, const char* monetary_name, const char* messages_name, 1.228 + locale::category c) { 1.229 + if ((c & locale::all) == 0 || (strcmp(name, ctype_name) == 0 && 1.230 + strcmp(name, time_name) == 0 && 1.231 + strcmp(name, numeric_name) == 0 && 1.232 + strcmp(name, collate_name) == 0 && 1.233 + strcmp(name, monetary_name) == 0 && 1.234 + strcmp(name, messages_name) == 0)) 1.235 + L->name = name; 1.236 + else if ((c & locale::all) == locale::all && strcmp(ctype_name, time_name) == 0 && 1.237 + strcmp(ctype_name, numeric_name) == 0 && 1.238 + strcmp(ctype_name, collate_name) == 0 && 1.239 + strcmp(ctype_name, monetary_name) == 0 && 1.240 + strcmp(ctype_name, messages_name) == 0) 1.241 + L->name = ctype_name; 1.242 + else { 1.243 + _Stl_loc_combine_names_aux(L, name, ctype_name, time_name, numeric_name, collate_name, monetary_name, messages_name, c); 1.244 + } 1.245 +} 1.246 + 1.247 + 1.248 +// Create a locale that's a copy of L, except that all of the facets 1.249 +// in category c are instead constructed by name. 1.250 +locale::locale(const locale& L, const char* name, locale::category c) 1.251 + : _M_impl(0) { 1.252 + if (!name) 1.253 + _M_throw_on_null_name(); 1.254 + 1.255 + if (!::strcmp(_Nameless, name)) 1.256 + _STLP_THROW(runtime_error("Invalid locale name '" _NAMELESS "'")); 1.257 + 1.258 + _Locale_impl* impl = 0; 1.259 + 1.260 + _STLP_TRY { 1.261 + impl = new _Locale_impl(*L._M_impl); 1.262 + 1.263 + _Locale_name_hint *hint = 0; 1.264 + const char* ctype_name = name; 1.265 + char ctype_buf[_Locale_MAX_SIMPLE_NAME]; 1.266 + const char* numeric_name = name; 1.267 + char numeric_buf[_Locale_MAX_SIMPLE_NAME]; 1.268 + const char* time_name = name; 1.269 + char time_buf[_Locale_MAX_SIMPLE_NAME]; 1.270 + const char* collate_name = name; 1.271 + char collate_buf[_Locale_MAX_SIMPLE_NAME]; 1.272 + const char* monetary_name = name; 1.273 + char monetary_buf[_Locale_MAX_SIMPLE_NAME]; 1.274 + const char* messages_name = name; 1.275 + char messages_buf[_Locale_MAX_SIMPLE_NAME]; 1.276 + if (c & locale::ctype) 1.277 + hint = impl->insert_ctype_facets(ctype_name, ctype_buf, hint); 1.278 + if (c & locale::numeric) 1.279 + hint = impl->insert_numeric_facets(numeric_name, numeric_buf, hint); 1.280 + if (c & locale::time) 1.281 + hint = impl->insert_time_facets(time_name, time_buf, hint); 1.282 + if (c & locale::collate) 1.283 + hint = impl->insert_collate_facets(collate_name, collate_buf, hint); 1.284 + if (c & locale::monetary) 1.285 + hint = impl->insert_monetary_facets(monetary_name, monetary_buf,hint); 1.286 + if (c & locale::messages) 1.287 + impl->insert_messages_facets(messages_name, messages_buf, hint); 1.288 + 1.289 + _Stl_loc_combine_names(impl, L._M_impl->name.c_str(), 1.290 + ctype_name, time_name, numeric_name, 1.291 + collate_name, monetary_name, messages_name, c); 1.292 + _M_impl = _get_Locale_impl( impl ); 1.293 + } 1.294 + _STLP_UNWIND(delete impl) 1.295 +} 1.296 + 1.297 +// Contruct a new locale where all facets that aren't in category c 1.298 +// come from L1, and all those that are in category c come from L2. 1.299 +locale::locale(const locale& L1, const locale& L2, category c) 1.300 + : _M_impl(0) { 1.301 + _Locale_impl* impl = new _Locale_impl(*L1._M_impl); 1.302 + 1.303 + _Locale_impl* i2 = L2._M_impl; 1.304 + 1.305 + if (L1.name() != _Nameless && L2.name() != _Nameless) 1.306 + _Stl_loc_combine_names(impl, L1._M_impl->name.c_str(), L2._M_impl->name.c_str(), c); 1.307 + else { 1.308 + impl->name = _Nameless; 1.309 + } 1.310 + 1.311 + if (c & collate) { 1.312 + impl->insert( i2, _STLP_STD::collate<char>::id); 1.313 +# ifndef _STLP_NO_WCHAR_T 1.314 + impl->insert( i2, _STLP_STD::collate<wchar_t>::id); 1.315 +# endif 1.316 + } 1.317 + if (c & ctype) { 1.318 + impl->insert( i2, _STLP_STD::ctype<char>::id); 1.319 + impl->insert( i2, _STLP_STD::codecvt<char, char, mbstate_t>::id); 1.320 +# ifndef _STLP_NO_WCHAR_T 1.321 + impl->insert( i2, _STLP_STD::ctype<wchar_t>::id); 1.322 + impl->insert( i2, _STLP_STD::codecvt<wchar_t, char, mbstate_t>::id); 1.323 +# endif 1.324 + } 1.325 + if (c & monetary) { 1.326 + impl->insert( i2, _STLP_STD::moneypunct<char, true>::id); 1.327 + impl->insert( i2, _STLP_STD::moneypunct<char, false>::id); 1.328 + impl->insert( i2, _STLP_STD::money_get<char, istreambuf_iterator<char, char_traits<char> > >::id); 1.329 + impl->insert( i2, _STLP_STD::money_put<char, ostreambuf_iterator<char, char_traits<char> > >::id); 1.330 +# ifndef _STLP_NO_WCHAR_T 1.331 + impl->insert( i2, _STLP_STD::moneypunct<wchar_t, true>::id); 1.332 + impl->insert( i2, _STLP_STD::moneypunct<wchar_t, false>::id); 1.333 + impl->insert( i2, _STLP_STD::money_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id); 1.334 + impl->insert( i2, _STLP_STD::money_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id); 1.335 +# endif 1.336 + } 1.337 + if (c & numeric) { 1.338 + impl->insert( i2, _STLP_STD::numpunct<char>::id); 1.339 + impl->insert( i2, _STLP_STD::num_get<char, istreambuf_iterator<char, char_traits<char> > >::id); 1.340 + impl->insert( i2, _STLP_STD::num_put<char, ostreambuf_iterator<char, char_traits<char> > >::id); 1.341 +# ifndef _STLP_NO_WCHAR_T 1.342 + impl->insert( i2, _STLP_STD::numpunct<wchar_t>::id); 1.343 + impl->insert( i2, _STLP_STD::num_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id); 1.344 + impl->insert( i2, _STLP_STD::num_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id); 1.345 +# endif 1.346 + } 1.347 + if (c & time) { 1.348 + impl->insert( i2, _STLP_STD::time_get<char, istreambuf_iterator<char, char_traits<char> > >::id); 1.349 + impl->insert( i2, _STLP_STD::time_put<char, ostreambuf_iterator<char, char_traits<char> > >::id); 1.350 +# ifndef _STLP_NO_WCHAR_T 1.351 + impl->insert( i2, _STLP_STD::time_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id); 1.352 + impl->insert( i2, _STLP_STD::time_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id); 1.353 +# endif 1.354 + } 1.355 + if (c & messages) { 1.356 + impl->insert( i2, _STLP_STD::messages<char>::id); 1.357 +# ifndef _STLP_NO_WCHAR_T 1.358 + impl->insert( i2, _STLP_STD::messages<wchar_t>::id); 1.359 +# endif 1.360 + } 1.361 + _M_impl = _get_Locale_impl( impl ); 1.362 +} 1.363 + 1.364 +// Destructor. 1.365 +locale::~locale() _STLP_NOTHROW { 1.366 + if (_M_impl) 1.367 + _release_Locale_impl(_M_impl); 1.368 +} 1.369 + 1.370 +// Assignment operator. Much like the copy constructor: just a bit of 1.371 +// pointer twiddling. 1.372 +const locale& locale::operator=(const locale& L) _STLP_NOTHROW { 1.373 + if (this->_M_impl != L._M_impl) { 1.374 + if (this->_M_impl) 1.375 + _release_Locale_impl(this->_M_impl); 1.376 + this->_M_impl = _get_Locale_impl(L._M_impl); 1.377 + } 1.378 + return *this; 1.379 +} 1.380 + 1.381 +locale::facet* locale::_M_get_facet(const locale::id& n) const { 1.382 + return n._M_index < _M_impl->size() ? _M_impl->facets_vec[n._M_index] : 0; 1.383 +} 1.384 + 1.385 +locale::facet* locale::_M_use_facet(const locale::id& n) const { 1.386 + locale::facet* f = (n._M_index < _M_impl->size() ? _M_impl->facets_vec[n._M_index] : 0); 1.387 + if (!f) 1.388 + _M_impl->_M_throw_bad_cast(); 1.389 + return f; 1.390 +} 1.391 + 1.392 +string locale::name() const { 1.393 + return _M_impl->name; 1.394 +} 1.395 + 1.396 +// Compare two locales for equality. 1.397 +bool locale::operator==(const locale& L) const { 1.398 + return this->_M_impl == L._M_impl || 1.399 + (this->name() == L.name() && this->name() != _Nameless); 1.400 +} 1.401 + 1.402 +bool locale::operator!=(const locale& L) const { 1.403 + return !(*this == L); 1.404 +} 1.405 + 1.406 +// static data members. 1.407 + 1.408 +const locale& _STLP_CALL locale::classic() { 1.409 + return *_Stl_get_classic_locale(); 1.410 +} 1.411 + 1.412 +#if !defined (_STLP_USE_MSVC6_MEM_T_BUG_WORKAROUND) 1.413 +locale _STLP_CALL locale::global(const locale& L) { 1.414 +#else 1.415 +_Locale_impl* _STLP_CALL locale::global(const locale& L) { 1.416 +#endif 1.417 + locale old(_Stl_get_global_locale()->_M_impl); 1.418 + if (_Stl_get_global_locale()->_M_impl != L._M_impl) { 1.419 + _release_Locale_impl(_Stl_get_global_locale()->_M_impl); 1.420 + // this assign should be atomic, should be fixed here: 1.421 + _Stl_get_global_locale()->_M_impl = _get_Locale_impl(L._M_impl); 1.422 + 1.423 + // Set the global C locale, if appropriate. 1.424 +#if !defined(_STLP_NO_LOCALE_SUPPORT) 1.425 + if (L.name() != _Nameless) 1.426 + setlocale(LC_ALL, L.name().c_str()); 1.427 +#endif 1.428 + } 1.429 + 1.430 +#if !defined (_STLP_USE_MSVC6_MEM_T_BUG_WORKAROUND) 1.431 + return old; 1.432 +#else 1.433 + return old._M_impl; 1.434 +#endif 1.435 +} 1.436 + 1.437 +#if !defined (_STLP_STATIC_CONST_INIT_BUG) && !defined (_STLP_NO_STATIC_CONST_DEFINITION) 1.438 +const locale::category locale::none; 1.439 +const locale::category locale::collate; 1.440 +const locale::category locale::ctype; 1.441 +const locale::category locale::monetary; 1.442 +const locale::category locale::numeric; 1.443 +const locale::category locale::time; 1.444 +const locale::category locale::messages; 1.445 +const locale::category locale::all; 1.446 +#endif 1.447 + 1.448 +_STLP_END_NAMESPACE 1.449 +