diff options
author | thevenyp <thevenyp@211d60ee-9f03-0410-a15a-8952a2c7a4e4> | 2009-03-24 10:33:14 +0000 |
---|---|---|
committer | thevenyp <thevenyp@211d60ee-9f03-0410-a15a-8952a2c7a4e4> | 2009-03-24 10:33:14 +0000 |
commit | 0c3c05bc497748320de8987579a35da2af0059da (patch) | |
tree | 6392b80d263c1f87a55162154cb7a0982e27dd12 /src/inp_str.c | |
parent | 9b77de617d32192cde723557445c76864a1e00b0 (diff) | |
download | mpc-0c3c05bc497748320de8987579a35da2af0059da.tar.gz |
src/inp_str.c: Read sequence of adjacent alphanumerical char through new functions extract_suffix and extract_string
tests/inp_str.dat: adapt data to new behavior, STRING is now completely enclosed into quotes
tests/tio_str.c: read string remainder if needed.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpc/trunk@500 211d60ee-9f03-0410-a15a-8952a2c7a4e4
Diffstat (limited to 'src/inp_str.c')
-rw-r--r-- | src/inp_str.c | 203 |
1 files changed, 167 insertions, 36 deletions
diff --git a/src/inp_str.c b/src/inp_str.c index c748352..2d9d0f8 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) 2009 Andreas Enge +Copyright (C) 2009 Andreas Enge, Philippe Th\'eveny This file is part of the MPC Library. @@ -55,12 +55,125 @@ mpc_realloc_str (char * str, size_t oldlen, size_t newlen) { } +/* Extract from stream the longest string made up of alphanumeric char and + '_' (i.e. n-char-sequence). + The user must free the returned string. */ +static char * +extract_suffix (FILE *stream) +{ + int c; + size_t nread = 0; + size_t strsize = 100; + char *str = mpc_alloc_str (strsize); + + c = getc (stream); + while (isalnum ((unsigned char) c) || c == '_') { + str [nread] = (char) c; + nread++; + if (nread == strsize) { + str = mpc_realloc_str (str, strsize, 2 * strsize); + strsize *= 2; + } + c = getc (stream); + } + + str = mpc_realloc_str (str, strsize, nread + 1); + strsize = nread + 1; + str [nread] = '\0'; + + if (c != EOF) + ungetc (c, stream); + return str; +} + + +/* Extract from the stream the longest string of caracters which are not + whitespace with optional bracketed n-char_sequence after a NaN. + The user must free the returned string. + FIXME: The returned string is not always a valid floating-point number */ +static char * +extract_string (FILE *stream) +{ + int c; + size_t nread = 0; + size_t strsize = 100; + char *str = mpc_alloc_str (strsize); + + c = getc (stream); + while (c != EOF && c != '\n' + && !isspace ((unsigned char) c) + && c != '(' && c != ')') { + str [nread] = (char) c; + nread++; + if (nread == strsize) { + str = mpc_realloc_str (str, strsize, 2 * strsize); + strsize *= 2; + } + c = getc (stream); + } + + str = mpc_realloc_str (str, strsize, nread + 1); + strsize = nread + 1; + str [nread] = '\0'; + + if (nread == 0) + return str; + + if (c == '(') { + size_t n; + char *suffix; + + /* (n-char-sequence) only after a NaN */ + if ((nread != 3 + || tolower (str[0]) != 'n' + || tolower (str[1]) != 'a' + || tolower (str[2]) != 'n') + && (nread != 5 + || str[0] != '@' + || tolower (str[1]) != 'n' + || tolower (str[2]) != 'a' + || tolower (str[3]) != 'n' + || str[4] != '@')) { + ungetc (c, stream); + return str; + } + + suffix = extract_suffix (stream); + nread += strlen (suffix) + 1; + if (nread >= strsize) { + str = mpc_realloc_str (str, strsize, nread + 1); + strsize = nread + 1; + } + + n = sprintf (str, "%s(%s", str, suffix); + MPC_ASSERT (n == nread); + + c = getc (stream); + if (c == ')') { + str = mpc_realloc_str (str, strsize, nread + 2); + strsize = nread + 2; + str [nread] = c; + str [nread+1] = '\0'; + nread++; + } + else if (c != EOF) + ungetc (c, stream); + + mpc_free_str (suffix); + } + else if (c != EOF) + ungetc (c, stream); + + return str; +} + + int mpc_inp_str (mpc_ptr rop, FILE *stream, size_t *read, int base, mpc_rnd_t rnd_mode) { size_t white, nread = 0; int inex = -1; int c; - int par = 0; + char *str; if (stream == NULL) stream = stdin; @@ -68,47 +181,65 @@ mpc_inp_str (mpc_ptr rop, FILE *stream, size_t *read, int base, mpc_rnd_t rnd_mo white = skip_whitespace (stream); c = getc (stream); if (c != EOF) { - /* If c=='(', set par=1 and read everything up to ')' skipping one level - of nested pair of parentheses; otherwise, par=0 already and read - everything up to white space. Then have mpc_setstr do the work. */ - size_t strsize = 100; - char *str = mpc_alloc_str (strsize); - while (c != EOF && c != '\n' - && (par != 0 || !isspace ((unsigned char) c))) { - str [nread] = (char) c; + if (c == '(') { + char *real_str; + char *imag_str; + size_t n; + + nread++; /* the opening parenthesis */ + white = skip_whitespace (stream); + real_str = extract_string (stream); + nread += strlen(real_str); + + c = getc (stream); + if (!isspace ((unsigned int) c)) { + if (c != EOF) + ungetc (c, stream); + mpc_free_str (real_str); + goto error; + } + else + ungetc (c, stream); + + white += skip_whitespace (stream); + imag_str = extract_string (stream); + nread += strlen (imag_str); + + str = mpc_alloc_str (nread + 2); + n = sprintf (str, "(%s %s", real_str, imag_str); + MPC_ASSERT (n == nread + 1); + mpc_free_str (real_str); + mpc_free_str (imag_str); + + white += skip_whitespace (stream); + c = getc (stream); + if (c == ')') { + str = mpc_realloc_str (str, nread +2, nread + 3); + str [nread+1] = c; + str [nread+2] = '\0'; nread++; - if (nread == strsize) { - str = mpc_realloc_str (str, strsize, 2 * strsize); - strsize *= 2; - } - if (c == '(') { - par++; - if (par > 2) - break; - } - else if (c == ')') { - par--; - if (par < 0) - break; - } - c = getc (stream); - } - if (isspace ((unsigned char) c)) - ungetc (c, stream); - - str = mpc_realloc_str (str, strsize, nread + 1); - strsize = nread + 1; - str [nread] = '\0'; - inex = mpc_set_str (rop, str, base, rnd_mode); - - mpc_free_str (str); + } + else if (c != EOF) + ungetc (c, stream); + } + else { + if (c != EOF) + ungetc (c, stream); + str = extract_string (stream); + nread += strlen (str); + } + + inex = mpc_set_str (rop, str, base, rnd_mode); + + mpc_free_str (str); } + error: if (inex == -1) { mpfr_set_nan (MPC_RE(rop)); mpfr_set_nan (MPC_IM(rop)); } if (read != NULL) - *read = white + nread; + *read = white + nread; return inex; } |