summaryrefslogtreecommitdiff
path: root/src/inp_str.c
diff options
context:
space:
mode:
authorthevenyp <thevenyp@211d60ee-9f03-0410-a15a-8952a2c7a4e4>2009-03-24 10:33:14 +0000
committerthevenyp <thevenyp@211d60ee-9f03-0410-a15a-8952a2c7a4e4>2009-03-24 10:33:14 +0000
commit0c3c05bc497748320de8987579a35da2af0059da (patch)
tree6392b80d263c1f87a55162154cb7a0982e27dd12 /src/inp_str.c
parent9b77de617d32192cde723557445c76864a1e00b0 (diff)
downloadmpc-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.c203
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;
}