source: trunk/third/gmp/mpz/inp_str.c @ 18191

Revision 18191, 3.8 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18190, which included commits to RCS files with non-trunk default branches.
Line 
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
8Copyright 1991, 1993, 1994, 1996, 1998, 2000, 2001, 2002 Free Software
9Foundation, Inc.
10
11This file is part of the GNU MP Library.
12
13The GNU MP Library is free software; you can redistribute it and/or modify
14it under the terms of the GNU Lesser General Public License as published by
15the Free Software Foundation; either version 2.1 of the License, or (at your
16option) any later version.
17
18The GNU MP Library is distributed in the hope that it will be useful, but
19WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
21License for more details.
22
23You should have received a copy of the GNU Lesser General Public License
24along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
25the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
26MA 02111-1307, USA. */
27
28#include <stdio.h>
29#include <ctype.h>
30#include "gmp.h"
31#include "gmp-impl.h"
32
33static int
34digit_value_in_base (int c, int base)
35{
36  int digit;
37
38  if (isdigit (c))
39    digit = c - '0';
40  else if (islower (c))
41    digit = c - 'a' + 10;
42  else if (isupper (c))
43    digit = c - 'A' + 10;
44  else
45    return -1;
46
47  if (digit < base)
48    return digit;
49  return -1;
50}
51
52size_t
53mpz_inp_str (mpz_ptr x, FILE *stream, int base)
54{
55  int c;
56  size_t nread;
57
58  if (stream == 0)
59    stream = stdin;
60
61  nread = 0;
62
63  /* Skip whitespace.  */
64  do
65    {
66      c = getc (stream);
67      nread++;
68    }
69  while (isspace (c));
70
71  return mpz_inp_str_nowhite (x, stream, base, c, nread);
72}
73
74/* shared by mpq_inp_str */
75size_t
76mpz_inp_str_nowhite (mpz_ptr x, FILE *stream, int base, int c, size_t nread)
77{
78  char *str;
79  size_t alloc_size, str_size;
80  int negative;
81  mp_size_t xsize;
82
83  negative = 0;
84  if (c == '-')
85    {
86      negative = 1;
87      c = getc (stream);
88      nread++;
89    }
90
91  if (digit_value_in_base (c, base == 0 ? 10 : base) < 0)
92    return 0;                   /* error if no digits */
93
94  /* If BASE is 0, try to find out the base by looking at the initial
95     characters.  */
96  if (base == 0)
97    {
98      base = 10;
99      if (c == '0')
100        {
101          base = 8;
102          c = getc (stream);
103          nread++;
104          if (c == 'x' || c == 'X')
105            {
106              base = 16;
107              c = getc (stream);
108              nread++;
109            }
110          else if (c == 'b' || c == 'B')
111            {
112              base = 2;
113              c = getc (stream);
114              nread++;
115            }
116        }
117    }
118
119  /* Skip leading zeros.  */
120  while (c == '0')
121    {
122      c = getc (stream);
123      nread++;
124    }
125
126  alloc_size = 100;
127  str = (char *) (*__gmp_allocate_func) (alloc_size);
128  str_size = 0;
129
130  for (;;)
131    {
132      int dig;
133      if (str_size >= alloc_size)
134        {
135          size_t old_alloc_size = alloc_size;
136          alloc_size = alloc_size * 3 / 2;
137          str = (char *) (*__gmp_reallocate_func) (str, old_alloc_size, alloc_size);
138        }
139      dig = digit_value_in_base (c, base);
140      if (dig < 0)
141        break;
142      str[str_size++] = dig;
143      c = getc (stream);
144    }
145  nread += str_size;
146
147  ungetc (c, stream);
148  nread--;
149
150  /* Make sure the string is not empty, mpn_set_str would fail.  */
151  if (str_size == 0)
152    {
153      x->_mp_size = 0;
154    }
155  else
156    {
157      xsize = (((mp_size_t)
158                (str_size / __mp_bases[base].chars_per_bit_exactly))
159               / GMP_NUMB_BITS + 2);
160      if (x->_mp_alloc < xsize)
161        _mpz_realloc (x, xsize);
162
163      /* Convert the byte array in base BASE to our bignum format.  */
164      xsize = mpn_set_str (x->_mp_d, (unsigned char *) str, str_size, base);
165      x->_mp_size = negative ? -xsize : xsize;
166    }
167  (*__gmp_free_func) (str, alloc_size);
168  return nread;
169}
Note: See TracBrowser for help on using the repository browser.