OLD | NEW |
| (Empty) |
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 | |
7 Copyright 1991, 1993, 1994, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005 | |
8 Free Software Foundation, Inc. | |
9 | |
10 This file is part of the GNU MP Library. | |
11 | |
12 The GNU MP Library is free software; you can redistribute it and/or modify | |
13 it under the terms of the GNU Lesser General Public License as published by | |
14 the Free Software Foundation; either version 3 of the License, or (at your | |
15 option) any later version. | |
16 | |
17 The GNU MP Library is distributed in the hope that it will be useful, but | |
18 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
19 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public | |
20 License for more details. | |
21 | |
22 You should have received a copy of the GNU Lesser General Public License | |
23 along 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 | |
30 extern const unsigned char __gmp_digit_value_tab[]; | |
31 #define digit_value_tab __gmp_digit_value_tab | |
32 | |
33 int | |
34 mpz_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 = (((mp_size_t) (str_size / __mp_bases[base].chars_per_bit_exactly)) | |
126 / GMP_NUMB_BITS + 2); | |
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 } | |
OLD | NEW |