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