summaryrefslogtreecommitdiff
path: root/src/inp_str.c
diff options
context:
space:
mode:
authorenge <enge@211d60ee-9f03-0410-a15a-8952a2c7a4e4>2009-03-19 17:05:09 +0000
committerenge <enge@211d60ee-9f03-0410-a15a-8952a2c7a4e4>2009-03-19 17:05:09 +0000
commit4c14321905768e1a782384c38c49a9c66e3c1308 (patch)
treef27a1e4344bbd162916d9f2eab8f3fb5d8f49569 /src/inp_str.c
parent2e8fe025b2ac45daec5a2c1b0437b71b7e36c1a6 (diff)
downloadmpc-4c14321905768e1a782384c38c49a9c66e3c1308.tar.gz
inp_str, out_str: totally rewritten according to the format of strtoc;
inp_str sets the number to nan+i*nan in case of an error git-svn-id: svn://scm.gforge.inria.fr/svn/mpc/trunk@483 211d60ee-9f03-0410-a15a-8952a2c7a4e4
Diffstat (limited to 'src/inp_str.c')
-rw-r--r--src/inp_str.c147
1 files changed, 93 insertions, 54 deletions
diff --git a/src/inp_str.c b/src/inp_str.c
index 31565f8..1b25fa0 100644
--- a/src/inp_str.c
+++ b/src/inp_str.c
@@ -1,6 +1,6 @@
/* mpc_inp_str -- Input a complex number from a given stream.
-Copyright (C) 2002, 2009 Andreas Enge, Paul Zimmermann, Philippe Th\'eveny
+Copyright (C) 2009 Andreas Enge
This file is part of the MPC Library.
@@ -21,60 +21,99 @@ MA 02111-1307, USA. */
#include <stdio.h>
#include <ctype.h>
+#include <string.h>
#include "mpc-impl.h"
-size_t
-mpc_inp_str (mpc_ptr rop, FILE *stream, int base, mpc_rnd_t rnd_mode)
-{
- size_t size, size_im;
- int c;
- int sign;
-
- if (stream == NULL)
- stream = stdin;
-
- /* input real part */
- size = mpfr_inp_str (MPC_RE(rop), stream, base, MPC_RND_RE(rnd_mode));
- if (size == 0) /* error while reading the real part */
- return 0;
-
- /* get 'i' or 'I' followed by '*' */
- do
- {
+static size_t
+skip_whitespace (FILE *stream) {
+ int c = getc (stream);
+ size_t size = 0;
+ while (c != EOF && isspace ((unsigned char) c)) {
c = getc (stream);
- size ++;
- }
- while (isspace (c));
-
- switch (c)
- {
- case '+':
- sign = 0;
- break;
- case '-':
- sign = 1;
- break;
- default:
- /* error */
- return 0;
- }
-
- c = getc (stream);
- size ++;
- if (c != 'I' && c != 'i')
- return 0; /* error */
-
- c = getc (stream);
- size ++;
- if (c != '*')
- return 0; /* error */
-
- size_im = mpfr_inp_str (MPC_IM(rop), stream, base, MPC_RND_IM(rnd_mode));
- if (size_im == 0) /* error while reading the imaginary part */
- return 0;
-
- if (sign)
- mpfr_setsign (MPC_IM (rop), MPC_IM (rop), sign, GMP_RNDN);
-
- return size + size_im;
+ size++;
+ }
+ if (c != EOF)
+ ungetc (c, stream);
+ return size;
+}
+
+
+static char *
+mpc_alloc_str (size_t len) {
+ void * (*allocfunc) (size_t);
+ mp_get_memory_functions (&allocfunc, NULL, NULL);
+ return (char *) ((*allocfunc) (len * sizeof (char)));
+}
+
+
+static char *
+mpc_realloc_str (char * str, size_t oldlen, size_t newlen) {
+ void * (*reallocfunc) (void *, size_t, size_t);
+ mp_get_memory_functions (NULL, &reallocfunc, NULL);
+ return (char *) ((*reallocfunc) (str, oldlen * sizeof (char),
+ newlen * sizeof (char)));
+}
+
+
+static void
+mpc_free_str_len (char *str, size_t len) {
+ void (*freefunc) (void *, size_t);
+ mp_get_memory_functions (NULL, NULL, &freefunc);
+ (*freefunc) (str, len * sizeof (char));
+}
+
+
+
+size_t
+mpc_inp_str (mpc_ptr rop, FILE *stream, int base, mpc_rnd_t rnd_mode) {
+ size_t size, nread;
+ int c;
+
+ if (stream == NULL)
+ stream = stdin;
+
+ size = skip_whitespace (stream);
+ c = getc (stream);
+ if (c != EOF) {
+ if (c != '(') {
+ /* real number without parentheses */
+ ungetc (c, stream);
+ nread = mpfr_inp_str (MPC_RE(rop), stream, base, MPC_RND_RE(rnd_mode));
+ if (nread != 0) {
+ size += nread;
+ mpfr_set_ui (MPC_IM(rop), 0ul, GMP_RNDN);
+ return size;
+ }
+ }
+ else {
+ /* Complex number in parentheses; read everything from '(' to ')'
+ into a string and have mpc_setstr do the work */
+ size_t strsize = 100;
+ char *str = mpc_alloc_str (strsize);
+ nread = 0;
+ while (c != EOF && c != ')') {
+ str [nread] = (char) c;
+ nread++;
+ if (nread == strsize) {
+ str = mpc_realloc_str (str, strsize, 2 * strsize);
+ strsize *= 2;
+ }
+ c = getc (stream);
+ }
+ if (c != EOF) {
+ str [nread] = ')';
+ nread++;
+ str = mpc_realloc_str (str, strsize, nread + 1);
+ str [nread] = '\0';
+ size += nread;
+ if (mpc_set_str (rop, str, base, rnd_mode) != -1)
+ return size;
+ }
+ mpc_free_str_len (str, strsize);
+ }
+ }
+
+ mpfr_set_nan (MPC_RE(rop));
+ mpfr_set_nan (MPC_IM(rop));
+ return 0;
}