OSDN Git Service

libstdc++/5432
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / src / localename.cc
index 7d6f259..816f758 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
 // invalidate any other reasons why the executable file might be covered by
 // the GNU General Public License.
 
+#include <clocale>
+#include <cstring>
+#include <locale>
+#include <vector>
+#include <stdexcept>
 
-#include <bits/std_clocale.h>
-#include <bits/std_locale.h>
-#include <bits/std_cstring.h>
-#include <bits/std_cassert.h>
-#include <bits/std_vector.h>
-#include <bits/std_stdexcept.h>
-
-namespace std {
-
+namespace std
+{
   locale::_Impl::
   ~_Impl() throw()
   {
-    std::vector<facet*>::iterator it = _M_facets->begin();
+    __vec_facet::iterator it = _M_facets->begin();
     for (; it != _M_facets->end(); ++it)
-      (*it)->_M_remove_reference();
+      if (*it)
+       (*it)->_M_remove_reference();
     delete _M_facets;
-    delete _M_category_names;
   }
 
+  // Clone existing _Impl object.
   locale::_Impl::
-  _Impl(const _Impl& __other, size_t __refs)
-  : _M_references(__refs - 1), _M_facets(0), _M_category_names(0), 
-    _M_has_name(__other._M_has_name), _M_name(__other._M_name)
+  _Impl(const _Impl& __imp, size_t __refs)
+  : _M_references(__refs), _M_facets(0) // XXX
   {
     try
-      {  _M_facets = new __vec_facet(*(__other._M_facets)); }
+      {  _M_facets = new __vec_facet(*(__imp._M_facets)); }
     catch(...) 
       {
        delete _M_facets;
-       throw;
+       __throw_exception_again;
       }
 
-    try 
-      {        _M_category_names = new __vec_string(*(__other._M_category_names)); }
-    catch(...) 
-      {
-       delete _M_category_names;
-       throw;
-      }
+    for (size_t i = 0; i < _S_num_categories; ++i)
+      _M_names[i] = __imp._M_names[i];
 
-    std::vector<facet*>::iterator __it = _M_facets->begin();
+    __vec_facet::iterator __it = _M_facets->begin();
     for (; __it != _M_facets->end(); ++__it)
-      (*__it)->_M_add_reference();
+      if (*__it)
+       (*__it)->_M_add_reference();
   }
 
-  // This constructor is used to correctly initialize named locales,
-  // including the standard "C" locale.
+  // Construct named _Impl, including the standard "C" locale.
   locale::_Impl::
-  _Impl(size_t __numfacets, size_t __refs, bool __has_name = false, 
-       string __name = "*")
-  : _M_references(__refs - 1), _M_facets(0), _M_category_names(0), 
-    _M_has_name(__has_name), _M_name(__name)
-  { 
-    try
-      {  _M_facets = new __vec_facet(__numfacets, NULL); }
-    catch(...) 
-      {
-       delete _M_facets;
-       throw;
-      }
-
-    try 
-      {        _M_category_names = new __vec_string(_S_categories_num, _M_name); }
-    catch(...) 
-      {
-       delete _M_category_names;
-       throw;
-      }
-  }
-  
-  // Construct specific categories, leaving unselected ones alone
-  locale::_Impl::
-  _Impl(const _Impl& __other, const string& __name, category __cat, 
-       size_t __refs)
-    : _M_references(__refs - 1), _M_has_name(__other._M_name != "*")
+  _Impl(string __str, size_t __refs)
+  : _M_references(__refs), _M_facets(0)
   {
-    __cat = _S_normalize_category(__cat);  // might throw
-
-    try 
-      { _M_facets = new __vec_facet(*(__other._M_facets)); }
+    // Initialize the underlying locale model, which also checks to
+    // see if the given name is valid.
+    __c_locale __cloc;
+    locale::facet::_S_create_c_locale(__cloc, __str.c_str());
+
+    // This is needed as presently "C" locales != required data in
+    // __timepunct, numpunct, and moneypunct.
+    __c_locale __cloc_c = NULL;
+    if (__str != "C" && __str != "POSIX")
+      __cloc_c = __cloc;
+
+    // Allocate facet container.
+    try
+      {  _M_facets = new __vec_facet(_S_num_facets, NULL); }
     catch(...) 
       {
        delete _M_facets;
-       throw;
-      }
-
-    try 
-      {        _M_category_names = new __vec_string(*(__other._M_category_names)); }
-    catch(...) 
-      {
-       delete _M_category_names;
-       throw;
+       __throw_exception_again;
       }
 
-    static void(_Impl::* ctors[]) (const char*) = 
-    {
-      //  NB: Order must match the decl order in class locale.
-      &locale::_Impl::_M_construct_collate,
-      &locale::_Impl::_M_construct_ctype,
-      &locale::_Impl::_M_construct_monetary,
-      &locale::_Impl::_M_construct_numeric,
-      &locale::_Impl::_M_construct_time,
-      &locale::_Impl::_M_construct_messages,
-      0
-    };
+    // Name all the categories.
+    for (size_t i = 0; i < _S_num_categories; ++i)
+      _M_names[i] = __str;
+
+    // Construct all standard facets and add them to _M_facets.
+    _M_init_facet(new std::collate<char>(__cloc));
+    _M_init_facet(new std::ctype<char>(__cloc));
+    _M_init_facet(new codecvt<char, char, mbstate_t>);
+    _M_init_facet(new moneypunct<char, false>(__cloc_c));
+    _M_init_facet(new moneypunct<char, true>(__cloc_c));
+    _M_init_facet(new money_get<char>);
+    _M_init_facet(new money_put<char>);
+    _M_init_facet(new numpunct<char>(__cloc_c));
+    _M_init_facet(new num_get<char>);
+    _M_init_facet(new num_put<char>);
+    _M_init_facet(new __timepunct<char>(__cloc_c, __str.c_str()));
+    _M_init_facet(new time_get<char>);
+    _M_init_facet(new time_put<char>);
+    _M_init_facet(new std::messages<char>(__cloc, __str.c_str()));
     
-    __vec_facet::iterator __it = _M_facets->begin();
-    for (; __it != _M_facets->end(); ++__it)
-      (*__it)->_M_add_reference();
-
-    try 
-      {
-       unsigned mask = (locale::all & -(unsigned)locale::all);
-       for (unsigned ix = 0; (-mask & __cat) != 0; ++ix, (mask <<= 1))
-         {
-           if (!(mask & __cat))
-             continue;
-           
-           if (mask & __cat)
-             _M_replace_category(_S_classic, _S_facet_categories[ix]);
-           else
-             (this->*ctors[ix])(__name.c_str());
-         }
-      }
-    catch(...) 
-      {
-       __it = _M_facets->begin();
-       for (; __it != _M_facets->end(); ++__it)
-         (*__it)->_M_remove_reference();
-       throw;
-      }
-
-    // XXX May need to be adjusted
-    if (__cat == all)
-      _M_name = __name;
+#ifdef  _GLIBCPP_USE_WCHAR_T
+    _M_init_facet(new std::collate<wchar_t>(__cloc));
+    _M_init_facet(new std::ctype<wchar_t>(__cloc));
+    _M_init_facet(new codecvt<wchar_t, char, mbstate_t>);
+    _M_init_facet(new moneypunct<wchar_t, false>(__cloc_c));
+    _M_init_facet(new moneypunct<wchar_t, true>(__cloc_c));
+    _M_init_facet(new money_get<wchar_t>);
+    _M_init_facet(new money_put<wchar_t>);
+    _M_init_facet(new numpunct<wchar_t>(__cloc_c));
+    _M_init_facet(new num_get<wchar_t>);
+    _M_init_facet(new num_put<wchar_t>);
+    _M_init_facet(new __timepunct<wchar_t>(__cloc_c, __str.c_str()));
+    _M_init_facet(new time_get<wchar_t>);
+    _M_init_facet(new time_put<wchar_t>);
+    _M_init_facet(new std::messages<wchar_t>(__cloc, __str.c_str()));
+#endif   
+    locale::facet::_S_destroy_c_locale(__cloc);
   }
   
   void
   locale::_Impl::
-  _M_replace_categories(const _Impl* __other, category __cat)
+  _M_replace_categories(const _Impl* __imp, category __cat)
   {
-    assert((__cat & locale::all) && !(__cat & ~locale::all));
-    
-    unsigned int __mask = locale::all & -static_cast<unsigned int>(locale::all);
-    for (unsigned int __ix = 0; (-__mask & __cat) != 0; ++__ix, (__mask <<= 1))
+    const string __none("*");
+    category __mask;
+    for (unsigned int __ix = 0; __ix < _S_num_categories; ++__ix)
       {
+       __mask = 1 << __ix;
        if (__mask & __cat)
          {
-           _M_replace_category(__other, _S_facet_categories[__ix]);
-           (*_M_category_names)[__ix] = (*(__other->_M_category_names))[__ix];
+           // Need to replace entry in _M_facets with other locale's info.
+           _M_replace_category(__imp, _S_facet_categories[__ix]);
+           // If both have names, go ahead and mangle.
+           if (_M_names[__ix] != __none && __imp->_M_names[__ix] != __none)
+             _M_names[__ix] = __imp->_M_names[__ix];
          }
       }
   }
 
   void
   locale::_Impl::
-  _M_replace_category(const _Impl* __other, const locale::id* const* __idpp)
+  _M_replace_category(const _Impl* __imp, const locale::id* const* __idpp)
   {
     for (; *__idpp; ++__idpp)
-      _M_replace_facet(__other, *__idpp);
+      _M_replace_facet(__imp, *__idpp);
   }
   
   void
   locale::_Impl::
-  _M_replace_facet(const _Impl* __other, const locale::id* __idp)
+  _M_replace_facet(const _Impl* __imp, const locale::id* __idp)
   {
     size_t __index = __idp->_M_index;
     if (__index == 0 
-       || __other->_M_facets->size() <= __index 
-       || (*(__other->_M_facets))[__index] == 0)
-      throw runtime_error("no locale facet");
+       || __imp->_M_facets->size() <= __index 
+       || (*(__imp->_M_facets))[__index] == 0)
+      __throw_runtime_error("no locale facet");
        
-    _M_install_facet(__idp, (*(__other->_M_facets))[__index]); 
+    _M_install_facet(__idp, (*(__imp->_M_facets))[__index]); 
   }
 
   void
   locale::_Impl::
   _M_install_facet(const locale::id* __idp, facet* __fp)
   {
-    if (__fp == 0)
-      return;
-
-    size_t& __index = __idp->_M_index;
-    if (!__index)
-      __index = ++locale::id::_S_highwater;  // XXX MT
-
-    if (__index >= _M_facets->size())
-      _M_facets->resize(__index + 1, 0);  // might throw
-    facet*& __fpr = (*_M_facets)[__index];
-    // Order matters, here:
-    __fp->_M_add_reference();
-    if (__fpr) 
-      __fpr->_M_remove_reference();
-    __fpr = __fp;
-  }
-  void 
-  locale::_Impl::_M_construct_collate(const char* __name)
-  {
-    _M_facet_init(new collate_byname<char>(__name, 0));
-    _M_facet_init(new collate_byname<wchar_t>(__name, 0));
-  }
-
-  void 
-  locale::_Impl::_M_construct_ctype(const char* __name)
-  {
-    _M_facet_init(new ctype_byname<char>(__name, 0));
-    _M_facet_init(new ctype_byname<wchar_t>(__name, 0));
-    _M_facet_init(new codecvt_byname<char, char, mbstate_t>(__name));
-    _M_facet_init(new codecvt_byname<wchar_t, char, mbstate_t>(__name));
-  }
-    
-  void 
-  locale::_Impl::_M_construct_monetary(const char* __name)
-  {
-    _M_facet_init(new moneypunct_byname<char, false>(__name, 0));
-    _M_facet_init(new moneypunct_byname<wchar_t, false>(__name, 0));
-    _M_facet_init(new moneypunct_byname<char, true >(__name, 0));
-    _M_facet_init(new moneypunct_byname<wchar_t, true >(__name, 0));
-
-    _M_replace_facet(locale::_S_classic, &money_get<char>::id);
-    _M_replace_facet(locale::_S_classic, &money_get<wchar_t>::id);
-    _M_replace_facet(locale::_S_classic, &money_put<char>::id);
-    _M_replace_facet(locale::_S_classic, &money_put<wchar_t>::id);
-  }
-    
-  void 
-  locale::_Impl::_M_construct_numeric(const char* __name)
-  {
-    _M_facet_init(new numpunct_byname<char>(__name, 0));
-    _M_facet_init(new numpunct_byname<wchar_t>(__name, 0));
+    if (__fp)
+      {
+       size_t& __index = __idp->_M_index;
+       if (!__index)
+         __index = 1 + __exchange_and_add(&locale::id::_S_highwater, 1);
+       
+       if (__index >= _M_facets->size())
+         _M_facets->resize(__index + 1, 0);  // might throw
 
-    _M_replace_facet(locale::_S_classic, &num_get<char>::id);
-    _M_replace_facet(locale::_S_classic, &num_get<wchar_t>::id);
-    _M_replace_facet(locale::_S_classic, &num_put<char>::id);
-    _M_replace_facet(locale::_S_classic, &num_put<wchar_t>::id);
-  }
-    
-  void 
-  locale::_Impl::_M_construct_time(const char* __name)
-  {
-    _M_facet_init(new time_get_byname<char>(__name, 0));
-    _M_facet_init(new time_get_byname<wchar_t>(__name, 0));
-    _M_facet_init(new time_put_byname<char>(__name, 0));
-    _M_facet_init(new time_put_byname<wchar_t>(__name, 0));
-  }
-    
-  void 
-  locale::_Impl::_M_construct_messages(const char* __name)
-  {
-    _M_facet_init(new messages_byname<char>(__name, 0));
-    _M_facet_init(new messages_byname<wchar_t>(__name, 0));
+       facet*& __fpr = (*_M_facets)[__index];
+       if (__fpr)
+         {
+           // Replacing an existing facet.
+           // Order matters, here:
+           __fp->_M_add_reference();
+           __fpr->_M_remove_reference();
+           __fpr = __fp;
+         }
+       else
+         {
+           // Installing a newly created facet into an empty
+           // _M_facets container, say a newly-constructed,
+           // swanky-fresh _Impl.
+           (*_M_facets)[__index] = __fp;
+         }
+      }
   }
-}
-
-
-
+} // namespace std