1 // Wrapper for underlying C-language localization -*- C++ -*- 2 3 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 4 // Free Software Foundation, Inc. 5 // 6 // This file is part of the GNU ISO C++ Library. This library is free 7 // software; you can redistribute it and/or modify it under the 8 // terms of the GNU General Public License as published by the 9 // Free Software Foundation; either version 3, or (at your option) 10 // any later version. 11 12 // This library is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU General Public License for more details. 16 17 // Under Section 7 of GPL version 3, you are granted additional 18 // permissions described in the GCC Runtime Library Exception, version 19 // 3.1, as published by the Free Software Foundation. 20 21 // You should have received a copy of the GNU General Public License and 22 // a copy of the GCC Runtime Library Exception along with this program; 23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 // <http://www.gnu.org/licenses/>. 25 26 // 27 // ISO C++ 14882: 22.8 Standard locale categories. 28 // 29 30 // Written by Benjamin Kosnik <bkoz@redhat.com> 31 32 #include <cerrno> // For errno 33 #include <cmath> // For isinf, finite, finitef, fabs 34 #include <cstdlib> // For strof, strtold 35 #include <cstring> 36 #include <cstdio> 37 #include <locale> 38 #include <limits> 39 40 #ifdef _GLIBCXX_HAVE_IEEEFP_H 41 #include <ieeefp.h> 42 #endif 43 44 namespace std _GLIBCXX_VISIBILITY(default) 45 { 46 _GLIBCXX_BEGIN_NAMESPACE_VERSION 47 48 template<> 49 void 50 __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err, 51 const __c_locale&) throw() 52 { 53 // Assumes __s formatted for "C" locale. 54 char* __old = setlocale(LC_ALL, 0); 55 const size_t __len = strlen(__old) + 1; 56 char* __sav = new char[__len]; 57 memcpy(__sav, __old, __len); 58 setlocale(LC_ALL, "C"); 59 char* __sanity; 60 bool __overflow = false; 61 62 #if !__FLT_HAS_INFINITY__ 63 errno = 0; 64 #endif 65 66 #ifdef _GLIBCXX_HAVE_STRTOF 67 __v = strtof(__s, &__sanity); 68 #else 69 double __d = strtod(__s, &__sanity); 70 __v = static_cast<float>(__d); 71 #ifdef _GLIBCXX_HAVE_FINITEF 72 if (!finitef (__v)) 73 __overflow = true; 74 #elif defined (_GLIBCXX_HAVE_FINITE) 75 if (!finite (static_cast<double> (__v))) 76 __overflow = true; 77 #elif defined (_GLIBCXX_HAVE_ISINF) 78 if (isinf (static_cast<double> (__v))) 79 __overflow = true; 80 #else 81 if (fabs(__d) > numeric_limits<float>::max()) 82 __overflow = true; 83 #endif 84 #endif // _GLIBCXX_HAVE_STRTOF 85 86 // _GLIBCXX_RESOLVE_LIB_DEFECTS 87 // 23. Num_get overflow result. 88 if (__sanity == __s || *__sanity != '\0') 89 { 90 __v = 0.0f; 91 __err = ios_base::failbit; 92 } 93 else if (__overflow 94 #if __FLT_HAS_INFINITY__ 95 || __v == numeric_limits<float>::infinity() 96 || __v == -numeric_limits<float>::infinity() 97 #else 98 || ((__v > 1.0f || __v < -1.0f) && errno == ERANGE) 99 #endif 100 ) 101 { 102 if (__v > 0.0f) 103 __v = numeric_limits<float>::max(); 104 else 105 __v = -numeric_limits<float>::max(); 106 __err = ios_base::failbit; 107 } 108 109 setlocale(LC_ALL, __sav); 110 delete [] __sav; 111 } 112 113 template<> 114 void 115 __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err, 116 const __c_locale&) throw() 117 { 118 // Assumes __s formatted for "C" locale. 119 char* __old = setlocale(LC_ALL, 0); 120 const size_t __len = strlen(__old) + 1; 121 char* __sav = new char[__len]; 122 memcpy(__sav, __old, __len); 123 setlocale(LC_ALL, "C"); 124 char* __sanity; 125 126 #if !__DBL_HAS_INFINITY__ 127 errno = 0; 128 #endif 129 130 __v = strtod(__s, &__sanity); 131 132 // _GLIBCXX_RESOLVE_LIB_DEFECTS 133 // 23. Num_get overflow result. 134 if (__sanity == __s || *__sanity != '\0') 135 { 136 __v = 0.0; 137 __err = ios_base::failbit; 138 } 139 else if ( 140 #if __DBL_HAS_INFINITY__ 141 __v == numeric_limits<double>::infinity() 142 || __v == -numeric_limits<double>::infinity()) 143 #else 144 (__v > 1.0 || __v < -1.0) && errno == ERANGE) 145 #endif 146 { 147 if (__v > 0.0) 148 __v = numeric_limits<double>::max(); 149 else 150 __v = -numeric_limits<double>::max(); 151 __err = ios_base::failbit; 152 } 153 154 setlocale(LC_ALL, __sav); 155 delete [] __sav; 156 } 157 158 template<> 159 void 160 __convert_to_v(const char* __s, long double& __v, 161 ios_base::iostate& __err, const __c_locale&) throw() 162 { 163 // Assumes __s formatted for "C" locale. 164 char* __old = setlocale(LC_ALL, 0); 165 const size_t __len = strlen(__old) + 1; 166 char* __sav = new char[__len]; 167 memcpy(__sav, __old, __len); 168 setlocale(LC_ALL, "C"); 169 170 #if !__LDBL_HAS_INFINITY__ 171 errno = 0; 172 #endif 173 174 #if defined(_GLIBCXX_HAVE_STRTOLD) && !defined(_GLIBCXX_HAVE_BROKEN_STRTOLD) 175 char* __sanity; 176 __v = strtold(__s, &__sanity); 177 178 // _GLIBCXX_RESOLVE_LIB_DEFECTS 179 // 23. Num_get overflow result. 180 if (__sanity == __s || *__sanity != '\0') 181 #else 182 typedef char_traits<char>::int_type int_type; 183 int __p = sscanf(__s, "%Lf", &__v); 184 185 if (!__p || static_cast<int_type>(__p) == char_traits<char>::eof()) 186 #endif 187 { 188 __v = 0.0l; 189 __err = ios_base::failbit; 190 } 191 else if ( 192 #if __LDBL_HAS_INFINITY__ 193 __v == numeric_limits<long double>::infinity() 194 || __v == -numeric_limits<long double>::infinity()) 195 #else 196 (__v > 1.0l || __v < -1.0l) && errno == ERANGE) 197 #endif 198 { 199 if (__v > 0.0l) 200 __v = numeric_limits<long double>::max(); 201 else 202 __v = -numeric_limits<long double>::max(); 203 __err = ios_base::failbit; 204 } 205 206 setlocale(LC_ALL, __sav); 207 delete [] __sav; 208 } 209 210 void 211 locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s, 212 __c_locale) 213 { 214 // Currently, the generic model only supports the "C" locale. 215 // See http://gcc.gnu.org/ml/libstdc++/2003-02/msg00345.html 216 __cloc = 0; 217 if (strcmp(__s, "C")) 218 __throw_runtime_error(__N("locale::facet::_S_create_c_locale " 219 "name not valid")); 220 } 221 222 void 223 locale::facet::_S_destroy_c_locale(__c_locale& __cloc) 224 { __cloc = 0; } 225 226 __c_locale 227 locale::facet::_S_clone_c_locale(__c_locale&) throw() 228 { return __c_locale(); } 229 230 __c_locale 231 locale::facet::_S_lc_ctype_c_locale(__c_locale, const char*) 232 { return __c_locale(); } 233 234 _GLIBCXX_END_NAMESPACE_VERSION 235 } // namespace 236 237 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) 238 { 239 _GLIBCXX_BEGIN_NAMESPACE_VERSION 240 241 const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] = 242 { 243 "LC_CTYPE", 244 "LC_NUMERIC", 245 "LC_TIME", 246 "LC_COLLATE", 247 "LC_MONETARY", 248 "LC_MESSAGES" 249 }; 250 251 _GLIBCXX_END_NAMESPACE_VERSION 252 } // namespace 253 254 namespace std _GLIBCXX_VISIBILITY(default) 255 { 256 _GLIBCXX_BEGIN_NAMESPACE_VERSION 257 258 const char* const* const locale::_S_categories = __gnu_cxx::category_names; 259 260 _GLIBCXX_END_NAMESPACE_VERSION 261 } // namespace 262 263 // XXX GLIBCXX_ABI Deprecated 264 #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT 265 #define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \ 266 extern "C" void ldbl (void) __attribute__ ((alias (#dbl))) 267 _GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKPi, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKPi); 268 #endif // _GLIBCXX_LONG_DOUBLE_COMPAT 269