github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/mpz/inp_str.c (about)

     1  /* mpz_inp_str(dest_integer, stream, base) -- Input a number in base
     2     BASE from stdio stream STREAM and store the result in DEST_INTEGER.
     3  
     4     OF THE FUNCTIONS IN THIS FILE, ONLY mpz_inp_str IS FOR EXTERNAL USE, THE
     5     REST ARE INTERNALS AND ARE ALMOST CERTAIN TO BE SUBJECT TO INCOMPATIBLE
     6     CHANGES OR DISAPPEAR COMPLETELY IN FUTURE GNU MP RELEASES.
     7  
     8  Copyright 1991, 1993, 1994, 1996, 1998, 2000-2003, 2011-2013 Free Software
     9  Foundation, Inc.
    10  
    11  This file is part of the GNU MP Library.
    12  
    13  The GNU MP Library is free software; you can redistribute it and/or modify
    14  it under the terms of either:
    15  
    16    * the GNU Lesser General Public License as published by the Free
    17      Software Foundation; either version 3 of the License, or (at your
    18      option) any later version.
    19  
    20  or
    21  
    22    * the GNU General Public License as published by the Free Software
    23      Foundation; either version 2 of the License, or (at your option) any
    24      later version.
    25  
    26  or both in parallel, as here.
    27  
    28  The GNU MP Library is distributed in the hope that it will be useful, but
    29  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    30  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    31  for more details.
    32  
    33  You should have received copies of the GNU General Public License and the
    34  GNU Lesser General Public License along with the GNU MP Library.  If not,
    35  see https://www.gnu.org/licenses/.  */
    36  
    37  #include <stdio.h>
    38  #include <ctype.h>
    39  #include "gmp.h"
    40  #include "gmp-impl.h"
    41  #include "longlong.h"
    42  
    43  #define digit_value_tab __gmp_digit_value_tab
    44  
    45  size_t
    46  mpz_inp_str (mpz_ptr x, FILE *stream, int base)
    47  {
    48    int c;
    49    size_t nread;
    50  
    51    if (stream == 0)
    52      stream = stdin;
    53  
    54    nread = 0;
    55  
    56    /* Skip whitespace.  */
    57    do
    58      {
    59        c = getc (stream);
    60        nread++;
    61      }
    62    while (isspace (c));
    63  
    64    return mpz_inp_str_nowhite (x, stream, base, c, nread);
    65  }
    66  
    67  /* shared by mpq_inp_str */
    68  size_t
    69  mpz_inp_str_nowhite (mpz_ptr x, FILE *stream, int base, int c, size_t nread)
    70  {
    71    char *str;
    72    size_t alloc_size, str_size;
    73    int negative;
    74    mp_size_t xsize;
    75    const unsigned char *digit_value;
    76  
    77    ASSERT_ALWAYS (EOF == -1);	/* FIXME: handle this by adding explicit */
    78  				/* comparisons of c and EOF before each  */
    79  				/* read of digit_value[].  */
    80  
    81    digit_value = digit_value_tab;
    82    if (base > 36)
    83      {
    84        /* For bases > 36, use the collating sequence
    85  	 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.  */
    86        digit_value += 208;
    87        if (base > 62)
    88  	return 0;		/* too large base */
    89      }
    90  
    91    negative = 0;
    92    if (c == '-')
    93      {
    94        negative = 1;
    95        c = getc (stream);
    96        nread++;
    97      }
    98  
    99    if (c == EOF || digit_value[c] >= (base == 0 ? 10 : base))
   100      return 0;			/* error if no digits */
   101  
   102    /* If BASE is 0, try to find out the base by looking at the initial
   103       characters.  */
   104    if (base == 0)
   105      {
   106        base = 10;
   107        if (c == '0')
   108  	{
   109  	  base = 8;
   110  	  c = getc (stream);
   111  	  nread++;
   112  	  if (c == 'x' || c == 'X')
   113  	    {
   114  	      base = 16;
   115  	      c = getc (stream);
   116  	      nread++;
   117  	    }
   118  	  else if (c == 'b' || c == 'B')
   119  	    {
   120  	      base = 2;
   121  	      c = getc (stream);
   122  	      nread++;
   123  	    }
   124  	}
   125      }
   126  
   127    /* Skip leading zeros.  */
   128    while (c == '0')
   129      {
   130        c = getc (stream);
   131        nread++;
   132      }
   133  
   134    alloc_size = 100;
   135    str = (char *) (*__gmp_allocate_func) (alloc_size);
   136    str_size = 0;
   137  
   138    while (c != EOF)
   139      {
   140        int dig;
   141        dig = digit_value[c];
   142        if (dig >= base)
   143  	break;
   144        if (str_size >= alloc_size)
   145  	{
   146  	  size_t old_alloc_size = alloc_size;
   147  	  alloc_size = alloc_size * 3 / 2;
   148  	  str = (char *) (*__gmp_reallocate_func) (str, old_alloc_size, alloc_size);
   149  	}
   150        str[str_size++] = dig;
   151        c = getc (stream);
   152      }
   153    nread += str_size;
   154  
   155    ungetc (c, stream);
   156    nread--;
   157  
   158    /* Make sure the string is not empty, mpn_set_str would fail.  */
   159    if (str_size == 0)
   160      {
   161        SIZ (x) = 0;
   162      }
   163    else
   164      {
   165        LIMBS_PER_DIGIT_IN_BASE (xsize, str_size, base);
   166        MPZ_REALLOC (x, xsize);
   167  
   168        /* Convert the byte array in base BASE to our bignum format.  */
   169        xsize = mpn_set_str (PTR (x), (unsigned char *) str, str_size, base);
   170        SIZ (x) = negative ? -xsize : xsize;
   171      }
   172    (*__gmp_free_func) (str, alloc_size);
   173    return nread;
   174  }