Home | History | Annotate | Line # | Download | only in mpz
      1      1.1  mrg /* mpz_set_str(mp_dest, string, base) -- Convert the \0-terminated
      2      1.1  mrg    string STRING in base BASE to multiple precision integer in
      3      1.1  mrg    MP_DEST.  Allow white space in the string.  If BASE == 0 determine
      4      1.1  mrg    the base in the C standard way, i.e.  0xhh...h means base 16,
      5      1.1  mrg    0oo...o means base 8, otherwise assume base 10.
      6      1.1  mrg 
      7  1.1.1.3  mrg Copyright 1991, 1993, 1994, 1996-1998, 2000-2003, 2005, 2011-2013 Free Software
      8  1.1.1.3  mrg Foundation, Inc.
      9      1.1  mrg 
     10      1.1  mrg This file is part of the GNU MP Library.
     11      1.1  mrg 
     12      1.1  mrg The GNU MP Library is free software; you can redistribute it and/or modify
     13  1.1.1.3  mrg it under the terms of either:
     14  1.1.1.3  mrg 
     15  1.1.1.3  mrg   * the GNU Lesser General Public License as published by the Free
     16  1.1.1.3  mrg     Software Foundation; either version 3 of the License, or (at your
     17  1.1.1.3  mrg     option) any later version.
     18  1.1.1.3  mrg 
     19  1.1.1.3  mrg or
     20  1.1.1.3  mrg 
     21  1.1.1.3  mrg   * the GNU General Public License as published by the Free Software
     22  1.1.1.3  mrg     Foundation; either version 2 of the License, or (at your option) any
     23  1.1.1.3  mrg     later version.
     24  1.1.1.3  mrg 
     25  1.1.1.3  mrg or both in parallel, as here.
     26      1.1  mrg 
     27      1.1  mrg The GNU MP Library is distributed in the hope that it will be useful, but
     28      1.1  mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     29  1.1.1.3  mrg or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     30  1.1.1.3  mrg for more details.
     31      1.1  mrg 
     32  1.1.1.3  mrg You should have received copies of the GNU General Public License and the
     33  1.1.1.3  mrg GNU Lesser General Public License along with the GNU MP Library.  If not,
     34  1.1.1.3  mrg see https://www.gnu.org/licenses/.  */
     35      1.1  mrg 
     36      1.1  mrg #include <string.h>
     37      1.1  mrg #include <ctype.h>
     38      1.1  mrg #include "gmp-impl.h"
     39  1.1.1.2  mrg #include "longlong.h"
     40      1.1  mrg 
     41      1.1  mrg #define digit_value_tab __gmp_digit_value_tab
     42      1.1  mrg 
     43      1.1  mrg int
     44      1.1  mrg mpz_set_str (mpz_ptr x, const char *str, int base)
     45      1.1  mrg {
     46      1.1  mrg   size_t str_size;
     47      1.1  mrg   char *s, *begs;
     48      1.1  mrg   size_t i;
     49      1.1  mrg   mp_size_t xsize;
     50      1.1  mrg   int c;
     51      1.1  mrg   int negative;
     52      1.1  mrg   const unsigned char *digit_value;
     53      1.1  mrg   TMP_DECL;
     54      1.1  mrg 
     55      1.1  mrg   digit_value = digit_value_tab;
     56      1.1  mrg   if (base > 36)
     57      1.1  mrg     {
     58      1.1  mrg       /* For bases > 36, use the collating sequence
     59      1.1  mrg 	 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.  */
     60  1.1.1.3  mrg       digit_value += 208;
     61  1.1.1.4  mrg       if (UNLIKELY (base > 62))
     62      1.1  mrg 	return -1;		/* too large base */
     63      1.1  mrg     }
     64      1.1  mrg 
     65      1.1  mrg   /* Skip whitespace.  */
     66      1.1  mrg   do
     67      1.1  mrg     c = (unsigned char) *str++;
     68      1.1  mrg   while (isspace (c));
     69      1.1  mrg 
     70      1.1  mrg   negative = 0;
     71      1.1  mrg   if (c == '-')
     72      1.1  mrg     {
     73      1.1  mrg       negative = 1;
     74      1.1  mrg       c = (unsigned char) *str++;
     75      1.1  mrg     }
     76      1.1  mrg 
     77      1.1  mrg   if (digit_value[c] >= (base == 0 ? 10 : base))
     78      1.1  mrg     return -1;			/* error if no valid digits */
     79      1.1  mrg 
     80      1.1  mrg   /* If BASE is 0, try to find out the base by looking at the initial
     81      1.1  mrg      characters.  */
     82      1.1  mrg   if (base == 0)
     83      1.1  mrg     {
     84      1.1  mrg       base = 10;
     85      1.1  mrg       if (c == '0')
     86      1.1  mrg 	{
     87      1.1  mrg 	  base = 8;
     88      1.1  mrg 	  c = (unsigned char) *str++;
     89      1.1  mrg 	  if (c == 'x' || c == 'X')
     90      1.1  mrg 	    {
     91      1.1  mrg 	      base = 16;
     92      1.1  mrg 	      c = (unsigned char) *str++;
     93      1.1  mrg 	    }
     94      1.1  mrg 	  else if (c == 'b' || c == 'B')
     95      1.1  mrg 	    {
     96      1.1  mrg 	      base = 2;
     97      1.1  mrg 	      c = (unsigned char) *str++;
     98      1.1  mrg 	    }
     99      1.1  mrg 	}
    100      1.1  mrg     }
    101      1.1  mrg 
    102      1.1  mrg   /* Skip leading zeros and white space.  */
    103      1.1  mrg   while (c == '0' || isspace (c))
    104      1.1  mrg     c = (unsigned char) *str++;
    105      1.1  mrg   /* Make sure the string does not become empty, mpn_set_str would fail.  */
    106      1.1  mrg   if (c == 0)
    107      1.1  mrg     {
    108  1.1.1.2  mrg       SIZ (x) = 0;
    109      1.1  mrg       return 0;
    110      1.1  mrg     }
    111      1.1  mrg 
    112      1.1  mrg   TMP_MARK;
    113      1.1  mrg   str_size = strlen (str - 1);
    114      1.1  mrg   s = begs = (char *) TMP_ALLOC (str_size + 1);
    115      1.1  mrg 
    116      1.1  mrg   /* Remove spaces from the string and convert the result from ASCII to a
    117      1.1  mrg      byte array.  */
    118      1.1  mrg   for (i = 0; i < str_size; i++)
    119      1.1  mrg     {
    120      1.1  mrg       if (!isspace (c))
    121      1.1  mrg 	{
    122      1.1  mrg 	  int dig = digit_value[c];
    123  1.1.1.4  mrg 	  if (UNLIKELY (dig >= base))
    124      1.1  mrg 	    {
    125      1.1  mrg 	      TMP_FREE;
    126      1.1  mrg 	      return -1;
    127      1.1  mrg 	    }
    128      1.1  mrg 	  *s++ = dig;
    129      1.1  mrg 	}
    130      1.1  mrg       c = (unsigned char) *str++;
    131      1.1  mrg     }
    132      1.1  mrg 
    133      1.1  mrg   str_size = s - begs;
    134      1.1  mrg 
    135  1.1.1.2  mrg   LIMBS_PER_DIGIT_IN_BASE (xsize, str_size, base);
    136  1.1.1.4  mrg   MPZ_NEWALLOC (x, xsize);
    137      1.1  mrg 
    138      1.1  mrg   /* Convert the byte array in base BASE to our bignum format.  */
    139  1.1.1.2  mrg   xsize = mpn_set_str (PTR (x), (unsigned char *) begs, str_size, base);
    140  1.1.1.2  mrg   SIZ (x) = negative ? -xsize : xsize;
    141      1.1  mrg 
    142      1.1  mrg   TMP_FREE;
    143      1.1  mrg   return 0;
    144      1.1  mrg }
    145