1 /* operator>> -- C++-style input of mpf_t. 2 3 Copyright 2001, 2003 Free Software Foundation, Inc. 4 5 This file is part of the GNU MP Library. 6 7 The GNU MP Library is free software; you can redistribute it and/or modify 8 it under the terms of either: 9 10 * the GNU Lesser General Public License as published by the Free 11 Software Foundation; either version 3 of the License, or (at your 12 option) any later version. 13 14 or 15 16 * the GNU General Public License as published by the Free Software 17 Foundation; either version 2 of the License, or (at your option) any 18 later version. 19 20 or both in parallel, as here. 21 22 The GNU MP Library is distributed in the hope that it will be useful, but 23 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 24 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 25 for more details. 26 27 You should have received copies of the GNU General Public License and the 28 GNU Lesser General Public License along with the GNU MP Library. If not, 29 see https://www.gnu.org/licenses/. */ 30 31 #include <cctype> 32 #include <iostream> 33 #include <string> 34 #include <clocale> // for localeconv 35 36 #include "gmp-impl.h" 37 38 using namespace std; 39 40 41 // For g++ libstdc++ parsing see num_get<chartype,initer>::_M_extract_float 42 // in include/bits/locale_facets.tcc. 43 // 44 // There are no plans to accept hex or octal floats, not unless the standard 45 // C++ library does so. Although such formats might be of use, it's 46 // considered more important to be compatible with what the normal 47 // operator>> does on "double"s etc. 48 49 istream & 50 operator>> (istream &i, mpf_ptr f) 51 { 52 int base; 53 char c = 0; 54 string s; 55 bool ok = false; 56 57 // C decimal point, as expected by mpf_set_str 58 const char *lconv_point = GMP_DECIMAL_POINT; 59 60 // C++ decimal point 61 #if HAVE_STD__LOCALE 62 const locale& loc = i.getloc(); 63 char point_char = use_facet< numpunct<char> >(loc).decimal_point(); 64 #else 65 const char *point = lconv_point; 66 char point_char = *point; 67 #endif 68 69 i.get(c); // start reading 70 71 if (i.flags() & ios::skipws) // skip initial whitespace 72 { 73 // C++ isspace 74 #if HAVE_STD__LOCALE 75 const ctype<char>& ct = use_facet< ctype<char> >(loc); 76 #define cxx_isspace(c) (ct.is(ctype_base::space,(c))) 77 #else 78 #define cxx_isspace(c) isspace(c) 79 #endif 80 81 while (cxx_isspace(c) && i.get(c)) 82 ; 83 } 84 85 if (c == '-' || c == '+') // sign 86 { 87 if (c == '-') 88 s = "-"; 89 i.get(c); 90 } 91 92 base = 10; 93 __gmp_istream_set_digits(s, i, c, ok, base); // read the number 94 95 // look for the C++ radix point, but put the C one in for mpf_set_str 96 if (c == point_char) 97 { 98 #if HAVE_STD__LOCALE 99 i.get(c); 100 #else // lconv point can be multi-char 101 for (;;) 102 { 103 i.get(c); 104 point++; 105 if (*point == '\0') 106 break; 107 if (c != *point) 108 goto fail; 109 } 110 #endif 111 s += lconv_point; 112 __gmp_istream_set_digits(s, i, c, ok, base); // read the mantissa 113 } 114 115 if (ok && (c == 'e' || c == 'E')) // exponent 116 { 117 s += c; 118 i.get(c); 119 ok = false; // exponent is mandatory 120 121 if (c == '-' || c == '+') // sign 122 { 123 s += c; 124 i.get(c); 125 } 126 127 __gmp_istream_set_digits(s, i, c, ok, base); // read the exponent 128 } 129 130 if (i.good()) // last character read was non-numeric 131 i.putback(c); 132 else if (i.eof() && ok) // stopped just before eof 133 i.clear(ios::eofbit); 134 135 if (ok) 136 ASSERT_NOCARRY (mpf_set_str(f, s.c_str(), base)); // extract the number 137 else 138 { 139 fail: 140 i.setstate(ios::failbit); // read failed 141 } 142 143 return i; 144 } 145