[Numpy-svn] r6278 - branches/fix_float_format/numpy/core/src
numpy-svn at scipy.org
numpy-svn at scipy.org
Tue Dec 30 15:37:18 EST 2008
Author: ptvirtan
Date: 2008-12-30 14:37:05 -0600 (Tue, 30 Dec 2008)
New Revision: 6278
Modified:
branches/fix_float_format/numpy/core/src/arraytypes.inc.src
branches/fix_float_format/numpy/core/src/npy_format.c
Log:
Implement NumPyOS_ascii_ftof, and use it instead of fscanf to make fromfile locale-independent
Modified: branches/fix_float_format/numpy/core/src/arraytypes.inc.src
===================================================================
--- branches/fix_float_format/numpy/core/src/arraytypes.inc.src 2008-12-30 20:36:07 UTC (rev 6277)
+++ branches/fix_float_format/numpy/core/src/arraytypes.inc.src 2008-12-30 20:37:05 UTC (rev 6278)
@@ -897,17 +897,30 @@
*/
/**begin repeat
-
-#fname=SHORT,USHORT,INT,UINT,LONG,ULONG,LONGLONG,ULONGLONG,FLOAT,DOUBLE,LONGDOUBLE#
-#type=short,ushort,int,uint,long,ulong,longlong,ulonglong,float,double,longdouble#
-#format="hd","hu","d","u","ld","lu",LONGLONG_FMT,ULONGLONG_FMT,"f","lf","Lf"#
+#fname=SHORT,USHORT,INT,UINT,LONG,ULONG,LONGLONG,ULONGLONG#
+#type=short,ushort,int,uint,long,ulong,longlong,ulonglong#
+#format="hd","hu","d","u","ld","lu",LONGLONG_FMT,ULONGLONG_FMT#
*/
static int
@fname at _scan (FILE *fp, @type@ *ip, void *NPY_UNUSED(ignore), PyArray_Descr *NPY_UNUSED(ignored))
{
return fscanf(fp, "%"@format@, ip);
}
+/**end repeat**/
+/**begin repeat
+#fname=FLOAT,DOUBLE,LONGDOUBLE#
+#type=float,double,longdouble#
+*/
+static int
+ at fname@_scan (FILE *fp, @type@ *ip, void *NPY_UNUSED(ignore), PyArray_Descr *NPY_UNUSED(ignored))
+{
+ double result;
+ int ret;
+ ret = NumPyOS_ascii_ftolf(fp, &result);
+ *ip = (@type@) result;
+ return ret;
+}
/**end repeat**/
/**begin repeat
Modified: branches/fix_float_format/numpy/core/src/npy_format.c
===================================================================
--- branches/fix_float_format/numpy/core/src/npy_format.c 2008-12-30 20:36:07 UTC (rev 6277)
+++ branches/fix_float_format/numpy/core/src/npy_format.c 2008-12-30 20:37:05 UTC (rev 6278)
@@ -1,4 +1,5 @@
#include <locale.h>
+#include <stdio.h>
/* From the C99 standard, section 7.19.6:
The exponent always contains at least two digits, and only as many more digits
@@ -280,3 +281,166 @@
#else
_ASCII_FORMAT(long double, l, double)
#endif
+
+
+/* NumPyOS_ascii_isspace:
+ *
+ * Same as isspace under C locale
+ */
+static int
+NumPyOS_ascii_isspace(char c)
+{
+ return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t'
+ || c == '\v';
+}
+
+
+/*
+ * NumPyOS_ascii_ftolf:
+ * * fp: FILE pointer
+ * * value: Place to store the value read
+ *
+ * Similar to PyOS_ascii_strtod, except that it reads input from a file.
+ *
+ * Similarly to fscanf, this function always consumes leading whitespace,
+ * and any text that could be the leading part in valid input.
+ *
+ * Return value: similar to fscanf.
+ * * 0 if no number read,
+ * * 1 if a number read,
+ * * EOF if end-of-file met before reading anything.
+ */
+
+static int
+NumPyOS_ascii_ftolf(FILE *fp, double *value)
+{
+ char buffer[FLOAT_FORMATBUFLEN+1];
+ char *endp;
+ char *p;
+ int c;
+ int ok;
+
+ /*
+ * Pass on to PyOS_ascii_strtod the leftmost matching part in regexp
+ *
+ * \s*[+-]? ( [0-9]*\.[0-9]+([eE][+-]?[0-9]+)
+ * | nan ( \([:alphanum:_]*\) )?
+ * | inf(inity)?
+ * )
+ *
+ * case-insensitively.
+ *
+ * The "do { ... } while (0)" wrapping in macros ensures that they behave
+ * properly eg. in "if ... else" structures.
+ */
+
+#define END_MATCH() \
+ goto buffer_filled
+
+#define NEXT_CHAR() \
+ do { \
+ if (c == EOF || endp >= buffer + FLOAT_FORMATBUFLEN) \
+ END_MATCH(); \
+ *endp++ = (char)c; \
+ c = getc(fp); \
+ } while (0)
+
+#define MATCH_ALPHA_STRING_NOCASE(string) \
+ do { \
+ for (p=(string); *p!='\0' && (c==*p || c+('a'-'A')==*p); ++p) \
+ NEXT_CHAR(); \
+ if (*p != '\0') END_MATCH(); \
+ } while (0)
+
+#define MATCH_ONE_OR_NONE(condition) \
+ do { if (condition) NEXT_CHAR(); } while (0)
+
+#define MATCH_ONE_OR_MORE(condition) \
+ do { \
+ ok = 0; \
+ while (condition) { NEXT_CHAR(); ok = 1; } \
+ if (!ok) END_MATCH(); \
+ } while (0)
+
+#define MATCH_ZERO_OR_MORE(condition) \
+ while (condition) { NEXT_CHAR(); }
+
+#define IS_NUMBER (c >= '0' && c <= '9')
+
+#define IS_ALPHA ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
+
+#define IS_ALPHANUM (IS_NUMBER || IS_ALPHA)
+
+ /* 1. emulate fscanf EOF handling */
+ c = getc(fp);
+ if (c == EOF)
+ return EOF;
+
+ /* 2. consume leading whitespace unconditionally */
+ while (NumPyOS_ascii_isspace(c)) {
+ c = getc(fp);
+ }
+
+ /* 3. start reading matching input to buffer */
+ endp = buffer;
+
+ /* 4.1 sign (optional) */
+ MATCH_ONE_OR_NONE(c == '+' || c == '-');
+
+ /* 4.2 nan, inf, infinity; [case-insensitive] */
+ if (c == 'n' || c == 'N') {
+ NEXT_CHAR();
+ MATCH_ALPHA_STRING_NOCASE("an");
+
+ /* accept nan([:alphanum:_]*), similarly to strtod */
+ if (c == '(') {
+ NEXT_CHAR();
+ MATCH_ZERO_OR_MORE(IS_ALPHANUM || c == '_');
+ if (c == ')') NEXT_CHAR();
+ }
+ END_MATCH();
+ } else if (c == 'i' || c == 'I') {
+ NEXT_CHAR();
+ MATCH_ALPHA_STRING_NOCASE("nfinity");
+ END_MATCH();
+ }
+
+ /* 4.3 mantissa */
+ MATCH_ZERO_OR_MORE(IS_NUMBER);
+
+ if (c == '.') {
+ NEXT_CHAR();
+ MATCH_ONE_OR_MORE(IS_NUMBER);
+ }
+
+ /* 4.4 exponent */
+ if (c == 'e' || c == 'E') {
+ NEXT_CHAR();
+ MATCH_ONE_OR_NONE(c == '+' || c == '-');
+ MATCH_ONE_OR_MORE(IS_NUMBER);
+ }
+
+ END_MATCH();
+
+buffer_filled:
+
+ ungetc(c, fp);
+ *endp = '\0';
+
+ /* 5. try to convert buffer. */
+
+ *value = PyOS_ascii_strtod(buffer, &p);
+
+ return (buffer == p) ? 0 : 1; /* if something was read */
+}
+
+#undef END_MATCH
+#undef NEXT_CHAR
+#undef MATCH_ALPHA_STRING_NOCASE
+#undef MATCH_ONE_OR_NONE
+#undef MATCH_ONE_OR_MORE
+#undef MATCH_ZERO_OR_MORE
+#undef IS_NUMBER
+#undef IS_ALPHA
+#undef IS_ALPHANUM
+
More information about the Numpy-svn
mailing list