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 00038 locale::locale(const char* __s) : _M_impl(0) 00039 { 00040 if (__s) 00041 { 00042 _S_initialize(); 00043 if (std::strcmp(__s, "C") == 0 || std::strcmp(__s, "POSIX") == 0) 00044 (_M_impl = _S_classic)->_M_add_reference(); 00045 else if (std::strcmp(__s, "") != 0) 00046 _M_impl = new _Impl(__s, 1); 00047 else 00048 { 00049 // Get it from the environment. 00050 char* __env = std::getenv("LC_ALL"); 00051 // If LC_ALL is set we are done. 00052 if (__env && std::strcmp(__env, "") != 0) 00053 { 00054 if (std::strcmp(__env, "C") == 0 00055 || std::strcmp(__env, "POSIX") == 0) 00056 (_M_impl = _S_classic)->_M_add_reference(); 00057 else 00058 _M_impl = new _Impl(__env, 1); 00059 } 00060 else 00061 { 00062 // LANG may set a default different from "C". 00063 string __res; 00064 char* __env = std::getenv("LANG"); 00065 if (!__env || std::strcmp(__env, "") == 0 00066 || std::strcmp(__env, "C") == 0 00067 || std::strcmp(__env, "POSIX") == 0) 00068 __res = "C"; 00069 else 00070 __res = __env; 00071 00072 // Scan the categories looking for the first one 00073 // different from LANG. 00074 size_t __i = 0; 00075 if (__res == "C") 00076 for (; __i < _S_categories_size; ++__i) 00077 { 00078 __env = std::getenv(_S_categories[__i]); 00079 if (__env && std::strcmp(__env, "") != 0 00080 && std::strcmp(__env, "C") != 0 00081 && std::strcmp(__env, "POSIX") != 0) 00082 break; 00083 } 00084 else 00085 for (; __i < _S_categories_size; ++__i) 00086 { 00087 __env = std::getenv(_S_categories[__i]); 00088 if (__env && std::strcmp(__env, "") != 0 00089 && __res != __env) 00090 break; 00091 } 00092 00093 // If one is found, build the complete string of 00094 // the form LC_CTYPE=xxx;LC_NUMERIC=yyy; and so on... 00095 if (__i < _S_categories_size) 00096 { 00097 string __str; 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 all the categories. 00204 const size_t __len = std::strlen(__s); 00205 if (!std::strchr(__s, ';')) 00206 { 00207 for (size_t __i = 0; __i < _S_categories_size; ++__i) 00208 { 00209 _M_names[__i] = new char[__len + 1]; 00210 std::strcpy(_M_names[__i], __s); 00211 } 00212 } 00213 else 00214 { 00215 const char* __beg = __s; 00216 for (size_t __i = 0; __i < _S_categories_size; ++__i) 00217 { 00218 __beg = std::strchr(__beg, '=') + 1; 00219 const char* __end = std::strchr(__beg, ';'); 00220 if (!__end) 00221 __end = __s + __len; 00222 char* __new = new char[__end - __beg + 1]; 00223 std::memcpy(__new, __beg, __end - __beg); 00224 __new[__end - __beg] = '\0'; 00225 _M_names[__i] = __new; 00226 } 00227 } 00228 00229 // Construct all standard facets and add them to _M_facets. 00230 _M_init_facet(new std::ctype<char>(__cloc, 0, false)); 00231 _M_init_facet(new codecvt<char, char, mbstate_t>(__cloc)); 00232 _M_init_facet(new numpunct<char>(__cloc)); 00233 _M_init_facet(new num_get<char>); 00234 _M_init_facet(new num_put<char>); 00235 _M_init_facet(new std::collate<char>(__cloc)); 00236 _M_init_facet(new moneypunct<char, false>(__cloc, __s)); 00237 _M_init_facet(new moneypunct<char, true>(__cloc, __s)); 00238 _M_init_facet(new money_get<char>); 00239 _M_init_facet(new money_put<char>); 00240 _M_init_facet(new __timepunct<char>(__cloc, __s)); 00241 _M_init_facet(new time_get<char>); 00242 _M_init_facet(new time_put<char>); 00243 _M_init_facet(new std::messages<char>(__cloc, __s)); 00244 00245 #ifdef _GLIBCXX_USE_WCHAR_T 00246 _M_init_facet(new std::ctype<wchar_t>(__cloc)); 00247 _M_init_facet(new codecvt<wchar_t, char, mbstate_t>(__cloc)); 00248 _M_init_facet(new numpunct<wchar_t>(__cloc)); 00249 _M_init_facet(new num_get<wchar_t>); 00250 _M_init_facet(new num_put<wchar_t>); 00251 _M_init_facet(new std::collate<wchar_t>(__cloc)); 00252 _M_init_facet(new moneypunct<wchar_t, false>(__cloc, __s)); 00253 _M_init_facet(new moneypunct<wchar_t, true>(__cloc, __s)); 00254 _M_init_facet(new money_get<wchar_t>); 00255 _M_init_facet(new money_put<wchar_t>); 00256 _M_init_facet(new __timepunct<wchar_t>(__cloc, __s)); 00257 _M_init_facet(new time_get<wchar_t>); 00258 _M_init_facet(new time_put<wchar_t>); 00259 _M_init_facet(new std::messages<wchar_t>(__cloc, __s)); 00260 #endif 00261 locale::facet::_S_destroy_c_locale(__cloc); 00262 } 00263 catch(...) 00264 { 00265 locale::facet::_S_destroy_c_locale(__cloc); 00266 this->~_Impl(); 00267 __throw_exception_again; 00268 } 00269 } 00270 00271 void 00272 locale::_Impl:: 00273 _M_replace_categories(const _Impl* __imp, category __cat) 00274 { 00275 for (size_t __ix = 0; __ix < _S_categories_size; ++__ix) 00276 { 00277 const category __mask = 1 << __ix; 00278 if (__mask & __cat) 00279 { 00280 // Need to replace entry in _M_facets with other locale's info. 00281 _M_replace_category(__imp, _S_facet_categories[__ix]); 00282 // If both have names, go ahead and mangle. 00283 if (std::strcmp(_M_names[__ix], "*") != 0 00284 && std::strcmp(__imp->_M_names[__ix], "*") != 0) 00285 { 00286 char* __new = new char[std::strlen(__imp->_M_names[__ix]) + 1]; 00287 std::strcpy(__new, __imp->_M_names[__ix]); 00288 delete [] _M_names[__ix]; 00289 _M_names[__ix] = __new; 00290 } 00291 } 00292 } 00293 } 00294 } // namespace std

Generated on Tue Sep 7 10:05:09 2004 for libstdc++-v3 Source by doxygen 1.3.8