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 the GNU Lesser General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or (at your 10 option) any later version. 11 12 The GNU MP Library is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 License for more details. 16 17 You should have received a copy of the GNU Lesser General Public License 18 along 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 28 using 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 39 istream & 40 operator>> (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