github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/cxx/ismpf.cc (about)

     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.h"
    37  #include "gmp-impl.h"
    38  
    39  using namespace std;
    40  
    41  
    42  // For g++ libstdc++ parsing see num_get<chartype,initer>::_M_extract_float
    43  // in include/bits/locale_facets.tcc.
    44  //
    45  // There are no plans to accept hex or octal floats, not unless the standard
    46  // C++ library does so.  Although such formats might be of use, it's
    47  // considered more important to be compatible with what the normal
    48  // operator>> does on "double"s etc.
    49  
    50  istream &
    51  operator>> (istream &i, mpf_ptr f)
    52  {
    53    int base;
    54    char c = 0;
    55    string s;
    56    bool ok = false;
    57  
    58    // C decimal point, as expected by mpf_set_str
    59    const char *lconv_point = GMP_DECIMAL_POINT;
    60  
    61    // C++ decimal point
    62  #if HAVE_STD__LOCALE
    63    const locale& loc = i.getloc();
    64    char point_char = use_facet< numpunct<char> >(loc).decimal_point();
    65  #else
    66    const char *point = lconv_point;
    67    char point_char = *point;
    68  #endif
    69  
    70    i.get(c); // start reading
    71  
    72    if (i.flags() & ios::skipws) // skip initial whitespace
    73      {
    74        // C++ isspace
    75  #if HAVE_STD__LOCALE
    76        const ctype<char>& ct = use_facet< ctype<char> >(loc);
    77  #define cxx_isspace(c)  (ct.is(ctype_base::space,(c)))
    78  #else
    79  #define cxx_isspace(c)  isspace(c)
    80  #endif
    81  
    82        while (cxx_isspace(c) && i.get(c))
    83          ;
    84      }
    85  
    86    if (c == '-' || c == '+') // sign
    87      {
    88        if (c == '-')
    89  	s = "-";
    90        i.get(c);
    91      }
    92  
    93    base = 10;
    94    __gmp_istream_set_digits(s, i, c, ok, base); // read the number
    95  
    96    // look for the C++ radix point, but put the C one in for mpf_set_str
    97    if (c == point_char)
    98      {
    99  #if HAVE_STD__LOCALE
   100        i.get(c);
   101  #else // lconv point can be multi-char
   102        for (;;)
   103          {
   104            i.get(c);
   105            point++;
   106            if (*point == '\0')
   107              break;
   108            if (c != *point)
   109              goto fail;
   110          }
   111  #endif
   112        s += lconv_point;
   113        __gmp_istream_set_digits(s, i, c, ok, base); // read the mantissa
   114      }
   115  
   116    if (ok && (c == 'e' || c == 'E')) // exponent
   117      {
   118        s += c;
   119        i.get(c);
   120        ok = false; // exponent is mandatory
   121  
   122        if (c == '-' || c == '+') // sign
   123  	{
   124  	  s += c;
   125  	  i.get(c);
   126  	}
   127  
   128        __gmp_istream_set_digits(s, i, c, ok, base); // read the exponent
   129      }
   130  
   131    if (i.good()) // last character read was non-numeric
   132      i.putback(c);
   133    else if (i.eof() && ok) // stopped just before eof
   134      i.clear(ios::eofbit);
   135  
   136    if (ok)
   137      ASSERT_NOCARRY (mpf_set_str(f, s.c_str(), base)); // extract the number
   138    else
   139      {
   140      fail:
   141        i.setstate(ios::failbit); // read failed
   142      }
   143  
   144    return i;
   145  }