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