diff options
author | enge <enge@211d60ee-9f03-0410-a15a-8952a2c7a4e4> | 2009-03-19 17:05:09 +0000 |
---|---|---|
committer | enge <enge@211d60ee-9f03-0410-a15a-8952a2c7a4e4> | 2009-03-19 17:05:09 +0000 |
commit | 4c14321905768e1a782384c38c49a9c66e3c1308 (patch) | |
tree | f27a1e4344bbd162916d9f2eab8f3fb5d8f49569 /src/inp_str.c | |
parent | 2e8fe025b2ac45daec5a2c1b0437b71b7e36c1a6 (diff) | |
download | mpc-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.c | 147 |
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; } |