From 11da511c784eca003deb90c23570f0873954e0de Mon Sep 17 00:00:00 2001 From: Duncan Wilkie Date: Sat, 18 Nov 2023 06:11:09 -0600 Subject: Initial commit. --- gmp-6.3.0/mpz/set_str.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 gmp-6.3.0/mpz/set_str.c (limited to 'gmp-6.3.0/mpz/set_str.c') diff --git a/gmp-6.3.0/mpz/set_str.c b/gmp-6.3.0/mpz/set_str.c new file mode 100644 index 0000000..26c102b --- /dev/null +++ b/gmp-6.3.0/mpz/set_str.c @@ -0,0 +1,144 @@ +/* mpz_set_str(mp_dest, string, base) -- Convert the \0-terminated + string STRING in base BASE to multiple precision integer in + MP_DEST. Allow white space in the string. If BASE == 0 determine + the base in the C standard way, i.e. 0xhh...h means base 16, + 0oo...o means base 8, otherwise assume base 10. + +Copyright 1991, 1993, 1994, 1996-1998, 2000-2003, 2005, 2011-2013 Free Software +Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + +or + + * the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any + later version. + +or both in parallel, as here. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received copies of the GNU General Public License and the +GNU Lesser General Public License along with the GNU MP Library. If not, +see https://www.gnu.org/licenses/. */ + +#include +#include +#include "gmp-impl.h" +#include "longlong.h" + +#define digit_value_tab __gmp_digit_value_tab + +int +mpz_set_str (mpz_ptr x, const char *str, int base) +{ + size_t str_size; + char *s, *begs; + size_t i; + mp_size_t xsize; + int c; + int negative; + const unsigned char *digit_value; + TMP_DECL; + + digit_value = digit_value_tab; + if (base > 36) + { + /* For bases > 36, use the collating sequence + 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz. */ + digit_value += 208; + if (UNLIKELY (base > 62)) + return -1; /* too large base */ + } + + /* Skip whitespace. */ + do + c = (unsigned char) *str++; + while (isspace (c)); + + negative = 0; + if (c == '-') + { + negative = 1; + c = (unsigned char) *str++; + } + + if (digit_value[c] >= (base == 0 ? 10 : base)) + return -1; /* error if no valid digits */ + + /* If BASE is 0, try to find out the base by looking at the initial + characters. */ + if (base == 0) + { + base = 10; + if (c == '0') + { + base = 8; + c = (unsigned char) *str++; + if (c == 'x' || c == 'X') + { + base = 16; + c = (unsigned char) *str++; + } + else if (c == 'b' || c == 'B') + { + base = 2; + c = (unsigned char) *str++; + } + } + } + + /* Skip leading zeros and white space. */ + while (c == '0' || isspace (c)) + c = (unsigned char) *str++; + /* Make sure the string does not become empty, mpn_set_str would fail. */ + if (c == 0) + { + SIZ (x) = 0; + return 0; + } + + TMP_MARK; + str_size = strlen (str - 1); + s = begs = (char *) TMP_ALLOC (str_size + 1); + + /* Remove spaces from the string and convert the result from ASCII to a + byte array. */ + for (i = 0; i < str_size; i++) + { + if (!isspace (c)) + { + int dig = digit_value[c]; + if (UNLIKELY (dig >= base)) + { + TMP_FREE; + return -1; + } + *s++ = dig; + } + c = (unsigned char) *str++; + } + + str_size = s - begs; + + LIMBS_PER_DIGIT_IN_BASE (xsize, str_size, base); + MPZ_NEWALLOC (x, xsize); + + /* Convert the byte array in base BASE to our bignum format. */ + xsize = mpn_set_str (PTR (x), (unsigned char *) begs, str_size, base); + SIZ (x) = negative ? -xsize : xsize; + + TMP_FREE; + return 0; +} -- cgit v1.2.3