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 #include <cstddef> 40 41 #ifdef _GLIBCXX_HAVE_IEEEFP_H 42 #include <ieeefp.h> 43 #endif 44 45 _GLIBCXX_BEGIN_NAMESPACE(std) 46 47 template<> 48 void 49 __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err, 50 const __c_locale&) throw() 51 { 52 // Assumes __s formatted for "C" locale. 53 char* __old = setlocale(LC_ALL, NULL); 54 const size_t __len = strlen(__old) + 1; 55 char* __sav = new char[__len]; 56 memcpy(__sav, __old, __len); 57 setlocale(LC_ALL, "C"); 58 char* __sanity; 59 bool __overflow = false; 60 61 #if !__FLT_HAS_INFINITY__ 62 errno = 0; 63 #endif 64 65 #ifdef _GLIBCXX_HAVE_STRTOF 66 __v = strtof(__s, &__sanity); 67 #else 68 double __d = strtod(__s, &__sanity); 69 __v = static_cast<float>(__d); 70 #ifdef _GLIBCXX_HAVE_FINITEF 71 if (!finitef (__v)) 72 __overflow = true; 73 #elif defined (_GLIBCXX_HAVE_FINITE) 74 if (!finite (static_cast<double> (__v))) 75 __overflow = true; 76 #elif defined (_GLIBCXX_HAVE_ISINF) 77 if (isinf (static_cast<double> (__v))) 78 __overflow = true; 79 #else 80 if (fabs(__d) > numeric_limits<float>::max()) 81 __overflow = true; 82 #endif 83 #endif // _GLIBCXX_HAVE_STRTOF 84 85 // _GLIBCXX_RESOLVE_LIB_DEFECTS 86 // 23. Num_get overflow result. 87 if (__sanity == __s || *__sanity != '\0') 88 { 89 __v = 0.0f; 90 __err = ios_base::failbit; 91 } 92 else if (__overflow 93 #if __FLT_HAS_INFINITY__ 94 || __v == numeric_limits<float>::infinity() 95 || __v == -numeric_limits<float>::infinity() 96 #else 97 || ((__v > 1.0f || __v < -1.0f) && errno == ERANGE) 98 #endif 99 ) 100 { 101 if (__v > 0.0f) 102 __v = numeric_limits<float>::max(); 103 else 104 __v = -numeric_limits<float>::max(); 105 __err = ios_base::failbit; 106 } 107 108 setlocale(LC_ALL, __sav); 109 delete [] __sav; 110 } 111 112 template<> 113 void 114 __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err, 115 const __c_locale&) throw() 116 { 117 // Assumes __s formatted for "C" locale. 118 char* __old = setlocale(LC_ALL, NULL); 119 const size_t __len = strlen(__old) + 1; 120 char* __sav = new char[__len]; 121 memcpy(__sav, __old, __len); 122 setlocale(LC_ALL, "C"); 123 char* __sanity; 124 125 #if !__DBL_HAS_INFINITY__ 126 errno = 0; 127 #endif 128 129 __v = strtod(__s, &__sanity); 130 131 // _GLIBCXX_RESOLVE_LIB_DEFECTS 132 // 23. Num_get overflow result. 133 if (__sanity == __s || *__sanity != '\0') 134 { 135 __v = 0.0; 136 __err = ios_base::failbit; 137 } 138 else if ( 139 #if __DBL_HAS_INFINITY__ 140 __v == numeric_limits<double>::infinity() 141 || __v == -numeric_limits<double>::infinity()) 142 #else 143 (__v > 1.0 || __v < -1.0) && errno == ERANGE) 144 #endif 145 { 146 if (__v > 0.0) 147 __v = numeric_limits<double>::max(); 148 else 149 __v = -numeric_limits<double>::max(); 150 __err = ios_base::failbit; 151 } 152 153 setlocale(LC_ALL, __sav); 154 delete [] __sav; 155 } 156 157 template<> 158 void 159 __convert_to_v(const char* __s, long double& __v, 160 ios_base::iostate& __err, const __c_locale&) throw() 161 { 162 // Assumes __s formatted for "C" locale. 163 char* __old = setlocale(LC_ALL, NULL); 164 const size_t __len = strlen(__old) + 1; 165 char* __sav = new char[__len]; 166 memcpy(__sav, __old, __len); 167 setlocale(LC_ALL, "C"); 168 169 #if !__LDBL_HAS_INFINITY__ 170 errno = 0; 171 #endif 172 173 #if defined(_GLIBCXX_HAVE_STRTOLD) && !defined(_GLIBCXX_HAVE_BROKEN_STRTOLD) 174 char* __sanity; 175 __v = strtold(__s, &__sanity); 176 177 // _GLIBCXX_RESOLVE_LIB_DEFECTS 178 // 23. Num_get overflow result. 179 if (__sanity == __s || *__sanity != '\0') 180 #else 181 typedef char_traits<char>::int_type int_type; 182 int __p = sscanf(__s, "%Lf", &__v); 183 184 if (!__p || static_cast<int_type>(__p) == char_traits<char>::eof()) 185 #endif 186 { 187 __v = 0.0l; 188 __err = ios_base::failbit; 189 } 190 else if ( 191 #if __LDBL_HAS_INFINITY__ 192 __v == numeric_limits<long double>::infinity() 193 || __v == -numeric_limits<long double>::infinity()) 194 #else 195 (__v > 1.0l || __v < -1.0l) && errno == ERANGE) 196 #endif 197 { 198 if (__v > 0.0l) 199 __v = numeric_limits<long double>::max(); 200 else 201 __v = -numeric_limits<long double>::max(); 202 __err = ios_base::failbit; 203 } 204 205 setlocale(LC_ALL, __sav); 206 delete [] __sav; 207 } 208 209 void 210 locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s, 211 __c_locale) 212 { 213 // Currently, the generic model only supports the "C" locale. 214 // See http://gcc.gnu.org/ml/libstdc++/2003-02/msg00345.html 215 __cloc = NULL; 216 if (strcmp(__s, "C")) 217 __throw_runtime_error(__N("locale::facet::_S_create_c_locale " 218 "name not valid")); 219 } 220 221 void 222 locale::facet::_S_destroy_c_locale(__c_locale& __cloc) 223 { __cloc = NULL; } 224 225 __c_locale 226 locale::facet::_S_clone_c_locale(__c_locale&) throw() 227 { return __c_locale(); } 228 229 __c_locale 230 locale::facet::_S_lc_ctype_c_locale(__c_locale, const char*) 231 { return __c_locale(); } 232 233 _GLIBCXX_END_NAMESPACE 234 235 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) 236 237 const char* const category_names[6 + _GLIBCXX_NUM_CATEGORIES] = 238 { 239 "LC_CTYPE", 240 "LC_NUMERIC", 241 "LC_TIME", 242 "LC_COLLATE", 243 "LC_MONETARY", 244 "LC_MESSAGES" 245 }; 246 247 _GLIBCXX_END_NAMESPACE 248 249 _GLIBCXX_BEGIN_NAMESPACE(std) 250 251 const char* const* const locale::_S_categories = __gnu_cxx::category_names; 252 253 _GLIBCXX_END_NAMESPACE 254 255 // XXX GLIBCXX_ABI Deprecated 256 #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT 257 #define _GLIBCXX_LDBL_COMPAT(dbl, ldbl) \ 258 extern "C" void ldbl (void) __attribute__ ((alias (#dbl))) 259 _GLIBCXX_LDBL_COMPAT(_ZSt14__convert_to_vIdEvPKcRT_RSt12_Ios_IostateRKPi, _ZSt14__convert_to_vIeEvPKcRT_RSt12_Ios_IostateRKPi); 260 #endif // _GLIBCXX_LONG_DOUBLE_COMPAT 261