ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

locale.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1999
00003  * Silicon Graphics Computer Systems, Inc.
00004  *
00005  * Copyright (c) 1999
00006  * Boris Fomitchev
00007  *
00008  * This material is provided "as is", with absolutely no warranty expressed
00009  * or implied. Any use is at your own risk.
00010  *
00011  * Permission to use or copy this software for any purpose is hereby granted
00012  * without fee, provided the above notices are retained on all copies.
00013  * Permission to modify the code and to distribute modified code is granted,
00014  * provided the above notices are retained, and a notice that the code was
00015  * modified is included with the above copyright notice.
00016  *
00017  */
00018 
00019 #include "stlport_prefix.h"
00020 
00021 #include <locale>
00022 #include <stdexcept>
00023 
00024 #include "c_locale.h"
00025 #include "locale_impl.h"
00026 
00027 _STLP_BEGIN_NAMESPACE
00028 
00029 static const string _Nameless("*");
00030 
00031 static inline bool is_C_locale_name (const char* name)
00032 { return ((name[0] == 'C') && (name[1] == 0)); }
00033 
00034 locale* _Stl_get_classic_locale();
00035 locale* _Stl_get_global_locale();
00036 
00037 #if defined (_STLP_USE_MSVC6_MEM_T_BUG_WORKAROUND) || \
00038     defined (_STLP_SIGNAL_RUNTIME_COMPATIBILITY) || defined (_STLP_CHECK_RUNTIME_COMPATIBILITY)
00039 #  define locale _STLP_NO_MEM_T_NAME(loc)
00040 #endif
00041 
00042 locale::facet::~facet() {}
00043 
00044 #if !defined (_STLP_MEMBER_TEMPLATES) || defined (_STLP_INLINE_MEMBER_TEMPLATES)
00045 // members that fail to be templates
00046 bool locale::operator()(const string& __x,
00047                         const string& __y) const
00048 { return __locale_do_operator_call(*this, __x, __y); }
00049 
00050 #  if !defined (_STLP_NO_WCHAR_T)
00051 bool locale::operator()(const wstring& __x,
00052                         const wstring& __y) const
00053 { return __locale_do_operator_call(*this, __x, __y); }
00054 #  endif
00055 #endif
00056 
00057 void _STLP_CALL locale::_M_throw_on_null_name()
00058 { _STLP_THROW(runtime_error("Invalid null locale name")); }
00059 
00060 void _STLP_CALL locale::_M_throw_on_combine_error(const string& name) {
00061   string what = "Unable to find facet";
00062   what += " in ";
00063   what += name.empty() ? "system" : name.c_str();
00064   what += " locale";
00065   _STLP_THROW(runtime_error(what.c_str()));
00066 }
00067 
00068 void _STLP_CALL locale::_M_throw_on_creation_failure(int __err_code,
00069                                                      const char* name, const char* facet) {
00070   string what;
00071   switch (__err_code) {
00072     case _STLP_LOC_UNSUPPORTED_FACET_CATEGORY:
00073       what = "No platform localization support for ";
00074       what += facet;
00075       what += " facet category, unable to create facet for ";
00076       what += name[0] == 0 ? "system" : name;
00077       what += " locale";
00078       break;
00079     case _STLP_LOC_NO_PLATFORM_SUPPORT:
00080       what = "No platform localization support, unable to create ";
00081       what += name[0] == 0 ? "system" : name;
00082       what += " locale";
00083       break;
00084     default:
00085     case _STLP_LOC_UNKNOWN_NAME:
00086       what = "Unable to create facet ";
00087       what += facet;
00088       what += " from name '";
00089       what += name;
00090       what += "'";
00091       break;
00092     case _STLP_LOC_NO_MEMORY:
00093       _STLP_THROW_BAD_ALLOC;
00094       break;
00095   }
00096 
00097   _STLP_THROW(runtime_error(what.c_str()));
00098 }
00099 
00100 // Takes a reference to a locale::id, assign a numeric index if not already
00101 // affected and returns it. The returned index is always positive.
00102 static const locale::id& _Stl_loc_get_index(locale::id& id) {
00103   if (id._M_index == 0) {
00104 #if defined (_STLP_ATOMIC_INCREMENT) && !defined (_STLP_WIN95_LIKE)
00105     static _STLP_VOLATILE __stl_atomic_t _S_index = __STATIC_CAST(__stl_atomic_t, locale::id::_S_max);
00106     id._M_index = _STLP_ATOMIC_INCREMENT(&_S_index);
00107 #else
00108     static _STLP_STATIC_MUTEX _Index_lock _STLP_MUTEX_INITIALIZER;
00109     _STLP_auto_lock sentry(_Index_lock);
00110     size_t new_index = locale::id::_S_max++;
00111     id._M_index = new_index;
00112 #endif
00113   }
00114   return id;
00115 }
00116 
00117 // Default constructor: create a copy of the global locale.
00118 locale::locale() _STLP_NOTHROW
00119   : _M_impl(_get_Locale_impl(_Stl_get_global_locale()->_M_impl))
00120 {}
00121 
00122 // Copy constructor
00123 locale::locale(const locale& L) _STLP_NOTHROW
00124   : _M_impl( _get_Locale_impl( L._M_impl ) )
00125 {}
00126 
00127 void locale::_M_insert(facet* f, locale::id& n) {
00128   if (f)
00129     _M_impl->insert(f, _Stl_loc_get_index(n));
00130 }
00131 
00132 locale::locale( _Locale_impl* impl ) :
00133   _M_impl( _get_Locale_impl( impl ) )
00134 {}
00135 
00136 // Create a locale from a name.
00137 locale::locale(const char* name)
00138   : _M_impl(0) {
00139   if (!name)
00140     _M_throw_on_null_name();
00141 
00142   if (is_C_locale_name(name)) {
00143     _M_impl = _get_Locale_impl( locale::classic()._M_impl );
00144     return;
00145   }
00146 
00147   _Locale_impl* impl = 0;
00148   _STLP_TRY {
00149     impl = new _Locale_impl(locale::id::_S_max, name);
00150 
00151     // Insert categories one at a time.
00152     _Locale_name_hint *hint = 0;
00153     const char* ctype_name = name;
00154     char ctype_buf[_Locale_MAX_SIMPLE_NAME];
00155     const char* numeric_name = name;
00156     char numeric_buf[_Locale_MAX_SIMPLE_NAME];
00157     const char* time_name = name;
00158     char time_buf[_Locale_MAX_SIMPLE_NAME];
00159     const char* collate_name = name;
00160     char collate_buf[_Locale_MAX_SIMPLE_NAME];
00161     const char* monetary_name = name;
00162     char monetary_buf[_Locale_MAX_SIMPLE_NAME];
00163     const char* messages_name = name;
00164     char messages_buf[_Locale_MAX_SIMPLE_NAME];
00165     hint = impl->insert_ctype_facets(ctype_name, ctype_buf, hint);
00166     hint = impl->insert_numeric_facets(numeric_name, numeric_buf, hint);
00167     hint = impl->insert_time_facets(time_name, time_buf, hint);
00168     hint = impl->insert_collate_facets(collate_name, collate_buf, hint);
00169     hint = impl->insert_monetary_facets(monetary_name, monetary_buf, hint);
00170     impl->insert_messages_facets(messages_name, messages_buf, hint);
00171 
00172     // Try to use a normalize locale name in order to have the == operator
00173     // to behave correctly:
00174     if (strcmp(ctype_name, numeric_name) == 0 &&
00175         strcmp(ctype_name, time_name) == 0 &&
00176         strcmp(ctype_name, collate_name) == 0 &&
00177         strcmp(ctype_name, monetary_name) == 0 &&
00178         strcmp(ctype_name, messages_name) == 0) {
00179       impl->name = ctype_name;
00180     }
00181     // else we keep current name.
00182 
00183     // reassign impl
00184     _M_impl = _get_Locale_impl( impl );
00185   }
00186   _STLP_UNWIND(delete impl);
00187 }
00188 
00189 static void _Stl_loc_combine_names_aux(_Locale_impl* L,
00190                                        const char* name,
00191                                        const char* ctype_name, const char* time_name, const char* numeric_name,
00192                                        const char* collate_name, const char* monetary_name, const char* messages_name,
00193                                        locale::category c) {
00194   // This function is only called when names has been validated so using _Locale_extract_*_name
00195   // can't fail.
00196   int __err_code;
00197   char buf[_Locale_MAX_SIMPLE_NAME];
00198   L->name = string("LC_CTYPE=") + _Locale_extract_ctype_name((c & locale::ctype) ? ctype_name : name, buf, 0, &__err_code) + ";";
00199   L->name += string("LC_TIME=") + _Locale_extract_time_name((c & locale::time) ? time_name : name, buf, 0, &__err_code) + ";";
00200   L->name += string("LC_NUMERIC=") + _Locale_extract_numeric_name((c & locale::numeric) ? numeric_name : name, buf, 0, &__err_code) + ";";
00201   L->name += string("LC_COLLATE=") + _Locale_extract_collate_name((c & locale::collate) ? collate_name : name, buf, 0, &__err_code) + ";";
00202   L->name += string("LC_MONETARY=") + _Locale_extract_monetary_name((c & locale::monetary) ? monetary_name : name, buf, 0, &__err_code) + ";";
00203   L->name += string("LC_MESSAGES=") + _Locale_extract_messages_name((c & locale::messages) ? messages_name : name, buf, 0, &__err_code);
00204 }
00205 
00206 // Give L a name where all facets except those in category c
00207 // are taken from name1, and those in category c are taken from name2.
00208 static void _Stl_loc_combine_names(_Locale_impl* L,
00209                                    const char* name1, const char* name2,
00210                                    locale::category c) {
00211   if ((c & locale::all) == 0 || strcmp(name1, name2) == 0)
00212     L->name = name1;
00213   else if ((c & locale::all) == locale::all)
00214     L->name = name2;
00215   else {
00216     _Stl_loc_combine_names_aux(L, name1, name2, name2, name2, name2, name2, name2, c);
00217   }
00218 }
00219 
00220 static void _Stl_loc_combine_names(_Locale_impl* L,
00221                                    const char* name,
00222                                    const char* ctype_name, const char* time_name, const char* numeric_name,
00223                                    const char* collate_name, const char* monetary_name, const char* messages_name,
00224                                    locale::category c) {
00225   if ((c & locale::all) == 0 || (strcmp(name, ctype_name) == 0 &&
00226                                  strcmp(name, time_name) == 0 &&
00227                                  strcmp(name, numeric_name) == 0 &&
00228                                  strcmp(name, collate_name) == 0 &&
00229                                  strcmp(name, monetary_name) == 0 &&
00230                                  strcmp(name, messages_name) == 0))
00231     L->name = name;
00232   else if ((c & locale::all) == locale::all && strcmp(ctype_name, time_name) == 0 &&
00233                                                strcmp(ctype_name, numeric_name) == 0 &&
00234                                                strcmp(ctype_name, collate_name) == 0 &&
00235                                                strcmp(ctype_name, monetary_name) == 0 &&
00236                                                strcmp(ctype_name, messages_name) == 0)
00237     L->name = ctype_name;
00238   else {
00239     _Stl_loc_combine_names_aux(L, name, ctype_name, time_name, numeric_name, collate_name, monetary_name, messages_name, c);
00240   }
00241 }
00242 
00243 
00244 // Create a locale that's a copy of L, except that all of the facets
00245 // in category c are instead constructed by name.
00246 locale::locale(const locale& L, const char* name, locale::category c)
00247   : _M_impl(0) {
00248   if (!name)
00249     _M_throw_on_null_name();
00250 
00251   if (_Nameless == name)
00252     _STLP_THROW(runtime_error((string("Invalid locale name '") + _Nameless + "'").c_str()));
00253 
00254   _Locale_impl* impl = 0;
00255 
00256   _STLP_TRY {
00257     impl = new _Locale_impl(*L._M_impl);
00258 
00259     _Locale_name_hint *hint = 0;
00260     const char* ctype_name = name;
00261     char ctype_buf[_Locale_MAX_SIMPLE_NAME];
00262     const char* numeric_name = name;
00263     char numeric_buf[_Locale_MAX_SIMPLE_NAME];
00264     const char* time_name = name;
00265     char time_buf[_Locale_MAX_SIMPLE_NAME];
00266     const char* collate_name = name;
00267     char collate_buf[_Locale_MAX_SIMPLE_NAME];
00268     const char* monetary_name = name;
00269     char monetary_buf[_Locale_MAX_SIMPLE_NAME];
00270     const char* messages_name = name;
00271     char messages_buf[_Locale_MAX_SIMPLE_NAME];
00272     if (c & locale::ctype)
00273       hint = impl->insert_ctype_facets(ctype_name, ctype_buf, hint);
00274     if (c & locale::numeric)
00275       hint = impl->insert_numeric_facets(numeric_name, numeric_buf, hint);
00276     if (c & locale::time)
00277       hint = impl->insert_time_facets(time_name, time_buf, hint);
00278     if (c & locale::collate)
00279       hint = impl->insert_collate_facets(collate_name, collate_buf, hint);
00280     if (c & locale::monetary)
00281       hint = impl->insert_monetary_facets(monetary_name, monetary_buf,hint);
00282     if (c & locale::messages)
00283       impl->insert_messages_facets(messages_name, messages_buf, hint);
00284 
00285     _Stl_loc_combine_names(impl, L._M_impl->name.c_str(),
00286                            ctype_name, time_name, numeric_name,
00287                            collate_name, monetary_name, messages_name, c);
00288     _M_impl = _get_Locale_impl( impl );
00289   }
00290   _STLP_UNWIND(delete impl)
00291 }
00292 
00293 // Contruct a new locale where all facets that aren't in category c
00294 // come from L1, and all those that are in category c come from L2.
00295 locale::locale(const locale& L1, const locale& L2, category c)
00296   : _M_impl(0) {
00297   _Locale_impl* impl = new _Locale_impl(*L1._M_impl);
00298 
00299   _Locale_impl* i2 = L2._M_impl;
00300 
00301   if (L1.name() != _Nameless && L2.name() != _Nameless)
00302     _Stl_loc_combine_names(impl, L1._M_impl->name.c_str(), L2._M_impl->name.c_str(), c);
00303   else {
00304     impl->name = _Nameless;
00305   }
00306 
00307   if (c & collate) {
00308     impl->insert( i2, _STLP_STD::collate<char>::id);
00309 # ifndef _STLP_NO_WCHAR_T
00310     impl->insert( i2, _STLP_STD::collate<wchar_t>::id);
00311 # endif
00312   }
00313   if (c & ctype) {
00314     impl->insert( i2, _STLP_STD::ctype<char>::id);
00315     impl->insert( i2, _STLP_STD::codecvt<char, char, mbstate_t>::id);
00316 # ifndef _STLP_NO_WCHAR_T
00317     impl->insert( i2, _STLP_STD::ctype<wchar_t>::id);
00318     impl->insert( i2, _STLP_STD::codecvt<wchar_t, char, mbstate_t>::id);
00319 # endif
00320   }
00321   if (c & monetary) {
00322     impl->insert( i2, _STLP_STD::moneypunct<char, true>::id);
00323     impl->insert( i2, _STLP_STD::moneypunct<char, false>::id);
00324     impl->insert( i2, _STLP_STD::money_get<char, istreambuf_iterator<char, char_traits<char> > >::id);
00325     impl->insert( i2, _STLP_STD::money_put<char, ostreambuf_iterator<char, char_traits<char> > >::id);
00326 # ifndef _STLP_NO_WCHAR_T
00327     impl->insert( i2, _STLP_STD::moneypunct<wchar_t, true>::id);
00328     impl->insert( i2, _STLP_STD::moneypunct<wchar_t, false>::id);
00329     impl->insert( i2, _STLP_STD::money_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id);
00330     impl->insert( i2, _STLP_STD::money_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id);
00331 # endif
00332   }
00333   if (c & numeric) {
00334     impl->insert( i2, _STLP_STD::numpunct<char>::id);
00335     impl->insert( i2, _STLP_STD::num_get<char, istreambuf_iterator<char, char_traits<char> > >::id);
00336     impl->insert( i2, _STLP_STD::num_put<char, ostreambuf_iterator<char, char_traits<char> > >::id);
00337 # ifndef _STLP_NO_WCHAR_T
00338     impl->insert( i2, _STLP_STD::numpunct<wchar_t>::id);
00339     impl->insert( i2, _STLP_STD::num_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id);
00340     impl->insert( i2, _STLP_STD::num_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id);
00341 # endif
00342   }
00343   if (c & time) {
00344     impl->insert( i2, _STLP_STD::time_get<char, istreambuf_iterator<char, char_traits<char> > >::id);
00345     impl->insert( i2, _STLP_STD::time_put<char, ostreambuf_iterator<char, char_traits<char> > >::id);
00346 # ifndef _STLP_NO_WCHAR_T
00347     impl->insert( i2, _STLP_STD::time_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id);
00348     impl->insert( i2, _STLP_STD::time_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id);
00349 # endif
00350   }
00351   if (c & messages) {
00352     impl->insert( i2, _STLP_STD::messages<char>::id);
00353 # ifndef _STLP_NO_WCHAR_T
00354     impl->insert( i2, _STLP_STD::messages<wchar_t>::id);
00355 # endif
00356   }
00357   _M_impl = _get_Locale_impl( impl );
00358 }
00359 
00360 // Destructor.
00361 locale::~locale() _STLP_NOTHROW {
00362   if (_M_impl)
00363     _release_Locale_impl(_M_impl);
00364 }
00365 
00366 // Assignment operator.  Much like the copy constructor: just a bit of
00367 // pointer twiddling.
00368 const locale& locale::operator=(const locale& L) _STLP_NOTHROW {
00369   if (this->_M_impl != L._M_impl) {
00370     if (this->_M_impl)
00371       _release_Locale_impl(this->_M_impl);
00372     this->_M_impl = _get_Locale_impl(L._M_impl);
00373   }
00374   return *this;
00375 }
00376 
00377 locale::facet* locale::_M_get_facet(const locale::id& n) const {
00378   return n._M_index < _M_impl->size() ? _M_impl->facets_vec[n._M_index] : 0;
00379 }
00380 
00381 locale::facet* locale::_M_use_facet(const locale::id& n) const {
00382   locale::facet* f = (n._M_index < _M_impl->size() ? _M_impl->facets_vec[n._M_index] : 0);
00383   if (!f)
00384     _M_impl->_M_throw_bad_cast();
00385   return f;
00386 }
00387 
00388 string locale::name() const {
00389   return _M_impl->name;
00390 }
00391 
00392 // Compare two locales for equality.
00393 bool locale::operator==(const locale& L) const {
00394   return this->_M_impl == L._M_impl ||
00395          (this->name() == L.name() && this->name() != _Nameless);
00396 }
00397 
00398 bool locale::operator!=(const locale& L) const {
00399   return !(*this == L);
00400 }
00401 
00402 // static data members.
00403 
00404 const locale& _STLP_CALL locale::classic() {
00405   return *_Stl_get_classic_locale();
00406 }
00407 
00408 #if !defined (_STLP_USE_MSVC6_MEM_T_BUG_WORKAROUND)
00409 locale _STLP_CALL locale::global(const locale& L) {
00410 #else
00411 _Locale_impl* _STLP_CALL locale::global(const locale& L) {
00412 #endif
00413   locale old(_Stl_get_global_locale()->_M_impl);
00414   if (_Stl_get_global_locale()->_M_impl != L._M_impl) {
00415     _release_Locale_impl(_Stl_get_global_locale()->_M_impl);
00416     // this assign should be atomic, should be fixed here:
00417     _Stl_get_global_locale()->_M_impl = _get_Locale_impl(L._M_impl);
00418 
00419     // Set the global C locale, if appropriate.
00420 #if !defined(_STLP_NO_LOCALE_SUPPORT)
00421     if (L.name() != _Nameless)
00422       setlocale(LC_ALL, L.name().c_str());
00423 #endif
00424   }
00425 
00426 #if !defined (_STLP_USE_MSVC6_MEM_T_BUG_WORKAROUND)
00427   return old;
00428 #else
00429   return old._M_impl;
00430 #endif
00431 }
00432 
00433 #if !defined (_STLP_STATIC_CONST_INIT_BUG) && !defined (_STLP_NO_STATIC_CONST_DEFINITION)
00434 const locale::category locale::none;
00435 const locale::category locale::collate;
00436 const locale::category locale::ctype;
00437 const locale::category locale::monetary;
00438 const locale::category locale::numeric;
00439 const locale::category locale::time;
00440 const locale::category locale::messages;
00441 const locale::category locale::all;
00442 #endif
00443 
00444 _STLP_END_NAMESPACE
00445 

Generated on Sun May 27 2012 04:35:12 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.