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