/* operator>> -- C++-style input of mpf_t. Copyright 2001, 2003 Free Software Foundation, Inc. This file is part of the GNU MP Library. The GNU MP Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. The GNU MP Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ #include #include #include #include // for localeconv #include "gmp.h" #include "gmp-impl.h" using namespace std; // For g++ libstdc++ parsing see num_get::_M_extract_float // in include/bits/locale_facets.tcc. // // There are no plans to accept hex or octal floats, not unless the standard // C++ library does so. Although such formats might be of use, it's // considered more important to be compatible with what the normal // operator>> does on "double"s etc. istream & operator>> (istream &i, mpf_ptr f) { int base; char c = 0; string s; bool ok = false; // C decimal point, as expected by mpf_set_str const char *lconv_point = localeconv()->decimal_point; // C++ decimal point #if HAVE_STD__LOCALE const locale& loc = i.getloc(); char point_char = use_facet< numpunct >(loc).decimal_point(); #else const char *point = lconv_point; char point_char = *point; #endif i.get(c); // start reading if (i.flags() & ios::skipws) // skip initial whitespace { // C++ isspace #if HAVE_STD__LOCALE const ctype& ct = use_facet< ctype >(loc); #define cxx_isspace(c) (ct.is(ctype_base::space,(c))) #else #define cxx_isspace(c) isspace(c) #endif while (cxx_isspace(c) && i.get(c)) ; } if (c == '-' || c == '+') // sign { if (c == '-') s = "-"; i.get(c); } base = 10; __gmp_istream_set_digits(s, i, c, ok, base); // read the number // look for the C++ radix point, but put the C one in for mpf_set_str if (c == point_char) { #if HAVE_STD__LOCALE i.get(c); #else // lconv point can be multi-char for (;;) { i.get(c); point++; if (*point == '\0') break; if (c != *point) goto fail; } #endif s += lconv_point; __gmp_istream_set_digits(s, i, c, ok, base); // read the mantissa } if (ok && (c == 'e' || c == 'E')) // exponent { s += c; i.get(c); ok = false; // exponent is mandatory if (c == '-' || c == '+') // sign { s += c; i.get(c); } __gmp_istream_set_digits(s, i, c, ok, base); // read the exponent } if (i.good()) // last character read was non-numeric i.putback(c); else if (i.eof() && ok) // stopped just before eof i.clear(); if (ok) ASSERT_NOCARRY (mpf_set_str(f, s.c_str(), base)); // extract the number else { fail: i.setstate(ios::failbit); // read failed } return i; }