localename.cc

00001 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 00002 // Free Software Foundation, Inc. 00003 // 00004 // This file is part of the GNU ISO C++ Library. This library is free 00005 // software; you can redistribute it and/or modify it under the 00006 // terms of the GNU General Public License as published by the 00007 // Free Software Foundation; either version 2, or (at your option) 00008 // any later version. 00009 00010 // This library is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 00015 // You should have received a copy of the GNU General Public License along 00016 // with this library; see the file COPYING. If not, write to the Free 00017 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 00018 // USA. 00019 00020 // As a special exception, you may use this file as part of a free software 00021 // library without restriction. Specifically, if other files instantiate 00022 // templates or use macros or inline functions from this file, or you compile 00023 // this file and link it with other files to produce an executable, this 00024 // file does not by itself cause the resulting executable to be covered by 00025 // the GNU General Public License. This exception does not however 00026 // invalidate any other reasons why the executable file might be covered by 00027 // the GNU General Public License. 00028 00029 #include <clocale> 00030 #include <cstring> 00031 #include <locale> 00032 00033 namespace std 00034 { 00035 using namespace __gnu_cxx; 00036 00037 locale::locale(const char* __s) : _M_impl(0) 00038 { 00039 if (__s) 00040 { 00041 _S_initialize(); 00042 if (std::strcmp(__s, "C") == 0 || std::strcmp(__s, "POSIX") == 0) 00043 (_M_impl = _S_classic)->_M_add_reference(); 00044 else if (std::strcmp(__s, "") != 0) 00045 _M_impl = new _Impl(__s, 1); 00046 else 00047 { 00048 // Get it from the environment. 00049 char* __env = std::getenv("LC_ALL"); 00050 // If LC_ALL is set we are done. 00051 if (__env && std::strcmp(__env, "") != 0) 00052 { 00053 if (std::strcmp(__env, "C") == 0 00054 || std::strcmp(__env, "POSIX") == 0) 00055 (_M_impl = _S_classic)->_M_add_reference(); 00056 else 00057 _M_impl = new _Impl(__env, 1); 00058 } 00059 else 00060 { 00061 // LANG may set a default different from "C". 00062 string __res; 00063 char* __env = std::getenv("LANG"); 00064 if (!__env || std::strcmp(__env, "") == 0 00065 || std::strcmp(__env, "C") == 0 00066 || std::strcmp(__env, "POSIX") == 0) 00067 __res = "C"; 00068 else 00069 __res = __env; 00070 00071 // Scan the categories looking for the first one 00072 // different from LANG. 00073 size_t __i = 0; 00074 if (__res == "C") 00075 for (; __i < _S_categories_size; ++__i) 00076 { 00077 __env = std::getenv(_S_categories[__i]); 00078 if (__env && std::strcmp(__env, "") != 0 00079 && std::strcmp(__env, "C") != 0 00080 && std::strcmp(__env, "POSIX") != 0) 00081 break; 00082 } 00083 else 00084 for (; __i < _S_categories_size; ++__i) 00085 { 00086 __env = std::getenv(_S_categories[__i]); 00087 if (__env && std::strcmp(__env, "") != 0 00088 && __res != __env) 00089 break; 00090 } 00091 00092 // If one is found, build the complete string of 00093 // the form LC_CTYPE=xxx;LC_NUMERIC=yyy; and so on... 00094 if (__i < _S_categories_size) 00095 { 00096 string __str; 00097 __str.reserve(128); 00098 for (size_t __j = 0; __j < __i; ++__j) 00099 { 00100 __str += _S_categories[__j]; 00101 __str += '='; 00102 __str += __res; 00103 __str += ';'; 00104 } 00105 __str += _S_categories[__i]; 00106 __str += '='; 00107 __str += __env; 00108 __str += ';'; 00109 __i++; 00110 for (; __i < _S_categories_size; ++__i) 00111 { 00112 __env = std::getenv(_S_categories[__i]); 00113 if (!__env || std::strcmp(__env, "") == 0) 00114 { 00115 __str += _S_categories[__i]; 00116 __str += '='; 00117 __str += __res; 00118 __str += ';'; 00119 } 00120 else if (std::strcmp(__env, "C") == 0 00121 || std::strcmp(__env, "POSIX") == 0) 00122 { 00123 __str += _S_categories[__i]; 00124 __str += "=C;"; 00125 } 00126 else 00127 { 00128 __str += _S_categories[__i]; 00129 __str += '='; 00130 __str += __env; 00131 __str += ';'; 00132 } 00133 } 00134 __str.erase(__str.end() - 1); 00135 _M_impl = new _Impl(__str.c_str(), 1); 00136 } 00137 // ... otherwise either an additional instance of 00138 // the "C" locale or LANG. 00139 else if (__res == "C") 00140 (_M_impl = _S_classic)->_M_add_reference(); 00141 else 00142 _M_impl = new _Impl(__res.c_str(), 1); 00143 } 00144 } 00145 } 00146 else 00147 __throw_runtime_error(__N("locale::locale NULL not valid")); 00148 } 00149 00150 locale::locale(const locale& __base, const char* __s, category __cat) 00151 : _M_impl(0) 00152 { 00153 // NB: There are complicated, yet more efficient ways to do 00154 // this. Building up locales on a per-category way is tedious, so 00155 // let's do it this way until people complain. 00156 locale __add(__s); 00157 _M_coalesce(__base, __add, __cat); 00158 } 00159 00160 locale::locale(const locale& __base, const locale& __add, category __cat) 00161 : _M_impl(0) 00162 { _M_coalesce(__base, __add, __cat); } 00163 00164 void 00165 locale::_M_coalesce(const locale& __base, const locale& __add, 00166 category __cat) 00167 { 00168 __cat = _S_normalize_category(__cat); 00169 _M_impl = new _Impl(*__base._M_impl, 1); 00170 00171 try 00172 { _M_impl->_M_replace_categories(__add._M_impl, __cat); } 00173 catch (...) 00174 { 00175 _M_impl->_M_remove_reference(); 00176 __throw_exception_again; 00177 } 00178 } 00179 00180 // Construct named _Impl. 00181 locale::_Impl:: 00182 _Impl(const char* __s, size_t __refs) 00183 : _M_refcount(__refs), _M_facets(0), _M_facets_size(_GLIBCXX_NUM_FACETS), 00184 _M_caches(0), _M_names(0) 00185 { 00186 // Initialize the underlying locale model, which also checks to 00187 // see if the given name is valid. 00188 __c_locale __cloc; 00189 locale::facet::_S_create_c_locale(__cloc, __s); 00190 00191 try 00192 { 00193 _M_facets = new const facet*[_M_facets_size]; 00194 for (size_t __i = 0; __i < _M_facets_size; ++__i) 00195 _M_facets[__i] = 0; 00196 _M_caches = new const facet*[_M_facets_size]; 00197 for (size_t __j = 0; __j < _M_facets_size; ++__j) 00198 _M_caches[__j] = 0; 00199 _M_names = new char*[_S_categories_size]; 00200 for (size_t __k = 0; __k < _S_categories_size; ++__k) 00201 _M_names[__k] = 0; 00202 00203 // Name the categories. 00204 const size_t __len = std::strlen(__s); 00205 if (!std::strchr(__s, ';')) 00206 { 00207 _M_names[0] = new char[__len + 1]; 00208 std::memcpy(_M_names[0], __s, __len + 1); 00209 } 00210 else 00211 { 00212 const char* __beg = __s; 00213 for (size_t __i = 0; __i < _S_categories_size; ++__i) 00214 { 00215 __beg = std::strchr(__beg, '=') + 1; 00216 const char* __end = std::strchr(__beg, ';'); 00217 if (!__end) 00218 __end = __s + __len; 00219 _M_names[__i] = new char[__end - __beg + 1]; 00220 std::memcpy(_M_names[__i], __beg, __end - __beg); 00221 _M_names[__i][__end - __beg] = '\0'; 00222 } 00223 } 00224 00225 // Construct all standard facets and add them to _M_facets. 00226 _M_init_facet(new std::ctype<char>(__cloc, 0, false)); 00227 _M_init_facet(new codecvt<char, char, mbstate_t>(__cloc)); 00228 _M_init_facet(new numpunct<char>(__cloc)); 00229 _M_init_facet(new num_get<char>); 00230 _M_init_facet(new num_put<char>); 00231 _M_init_facet(new std::collate<char>(__cloc)); 00232 _M_init_facet(new moneypunct<char, false>(__cloc, __s)); 00233 _M_init_facet(new moneypunct<char, true>(__cloc, __s)); 00234 _M_init_facet(new money_get<char>); 00235 _M_init_facet(new money_put<char>); 00236 _M_init_facet(new __timepunct<char>(__cloc, __s)); 00237 _M_init_facet(new time_get<char>); 00238 _M_init_facet(new time_put<char>); 00239 _M_init_facet(new std::messages<char>(__cloc, __s)); 00240 00241 #ifdef _GLIBCXX_USE_WCHAR_T 00242 _M_init_facet(new std::ctype<wchar_t>(__cloc)); 00243 _M_init_facet(new codecvt<wchar_t, char, mbstate_t>(__cloc)); 00244 _M_init_facet(new numpunct<wchar_t>(__cloc)); 00245 _M_init_facet(new num_get<wchar_t>); 00246 _M_init_facet(new num_put<wchar_t>); 00247 _M_init_facet(new std::collate<wchar_t>(__cloc)); 00248 _M_init_facet(new moneypunct<wchar_t, false>(__cloc, __s)); 00249 _M_init_facet(new moneypunct<wchar_t, true>(__cloc, __s)); 00250 _M_init_facet(new money_get<wchar_t>); 00251 _M_init_facet(new money_put<wchar_t>); 00252 _M_init_facet(new __timepunct<wchar_t>(__cloc, __s)); 00253 _M_init_facet(new time_get<wchar_t>); 00254 _M_init_facet(new time_put<wchar_t>); 00255 _M_init_facet(new std::messages<wchar_t>(__cloc, __s)); 00256 #endif 00257 locale::facet::_S_destroy_c_locale(__cloc); 00258 } 00259 catch(...) 00260 { 00261 locale::facet::_S_destroy_c_locale(__cloc); 00262 this->~_Impl(); 00263 __throw_exception_again; 00264 } 00265 } 00266 00267 void 00268 locale::_Impl:: 00269 _M_replace_categories(const _Impl* __imp, category __cat) 00270 { 00271 category __mask = 1; 00272 const bool __have_names = _M_names[0] && __imp->_M_names[0]; 00273 for (size_t __ix = 0; __ix < _S_categories_size; ++__ix, __mask <<= 1) 00274 { 00275 if (__mask & __cat) 00276 { 00277 // Need to replace entry in _M_facets with other locale's info. 00278 _M_replace_category(__imp, _S_facet_categories[__ix]); 00279 // If both have names, go ahead and mangle. 00280 if (__have_names) 00281 { 00282 if (!_M_names[1]) 00283 { 00284 // A full set of _M_names must be prepared, all identical 00285 // to _M_names[0] to begin with. Then, below, a few will 00286 // be replaced by the corresponding __imp->_M_names. I.e., 00287 // not a "simple" locale anymore (see locale::operator==). 00288 const size_t __len = std::strlen(_M_names[0]) + 1; 00289 for (size_t __i = 1; __i < _S_categories_size; ++__i) 00290 { 00291 _M_names[__i] = new char[__len]; 00292 std::memcpy(_M_names[__i], _M_names[0], __len); 00293 } 00294 } 00295 char* __src = __imp->_M_names[__ix] ? __imp->_M_names[__ix] 00296 : __imp->_M_names[0]; 00297 const size_t __len = std::strlen(__src) + 1; 00298 char* __new = new char[__len]; 00299 std::memcpy(__new, __src, __len); 00300 delete [] _M_names[__ix]; 00301 _M_names[__ix] = __new; 00302 } 00303 } 00304 } 00305 } 00306 } // namespace std

Generated on Wed Jun 9 11:18:40 2004 for libstdc++-v3 Source by doxygen 1.3.7