NPY_NO_EXPORT PyArray_Descr* _descriptor_from_pep3118_format(char *s) { char *buf, *p; int in_name = 0; PyObject *descr; PyObject *str; PyObject *_numpy_internal; if (s == NULL) { return PyArray_DescrNewFromType(NPY_BYTE); } /* Strip whitespace, except from field names */ buf = (char*)malloc(strlen(s) + 1); p = buf; while (*s != '\0') { if (*s == ':') { in_name = !in_name; *p = *s; } else if (in_name || !NumPyOS_ascii_isspace(*s)) { *p = *s; } ++p; ++s; } *p = '\0'; str = PyUString_FromStringAndSize(buf, strlen(buf)); free(buf); if (str == NULL) { return NULL; } /* Convert */ _numpy_internal = PyImport_ImportModule("numpy.core._internal"); if (_numpy_internal == NULL) { Py_DECREF(str); return NULL; } descr = PyObject_CallMethod( _numpy_internal, "_dtype_from_pep3118", "O", str); Py_DECREF(str); Py_DECREF(_numpy_internal); if (descr == NULL) { PyErr_Format(PyExc_ValueError, "'%s' is not a valid PEP 3118 buffer format string", buf); return NULL; } if (!PyArray_DescrCheck(descr)) { PyErr_Format(PyExc_RuntimeError, "internal error: numpy.core._internal._dtype_from_pep3118 " "did not return a valid dtype, got %s", buf); return NULL; } return (PyArray_Descr*)descr; }
/* * 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. */ NPY_NO_EXPORT 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(); } /* 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(NumPyOS_ascii_isalnum(c) || 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(NumPyOS_ascii_isdigit(c)); if (c == '.') { NEXT_CHAR(); MATCH_ONE_OR_MORE(NumPyOS_ascii_isdigit(c)); } /* 4.4 exponent */ if (c == 'e' || c == 'E') { NEXT_CHAR(); MATCH_ONE_OR_NONE(c == '+' || c == '-'); MATCH_ONE_OR_MORE(NumPyOS_ascii_isdigit(c)); } END_MATCH(); buffer_filled: ungetc(c, fp); *endp = '\0'; /* 5. try to convert buffer. */ *value = NumPyOS_ascii_strtod(buffer, &p); /* return 1 if something read, else 0 */ return (buffer == p) ? 0 : 1; }
/* * NumPyOS_ascii_strtod: * * Work around bugs in PyOS_ascii_strtod */ NPY_NO_EXPORT double NumPyOS_ascii_strtod(const char *s, char** endptr) { struct lconv *locale_data = localeconv(); const char *decimal_point = locale_data->decimal_point; size_t decimal_point_len = strlen(decimal_point); char buffer[FLOAT_FORMATBUFLEN+1]; const char *p; char *q; size_t n; double result; while (NumPyOS_ascii_isspace(*s)) { ++s; } /* * ##1 * * Recognize POSIX inf/nan representations on all platforms. */ p = s; result = 1.0; if (*p == '-') { result = -1.0; ++p; } else if (*p == '+') { ++p; } if (NumPyOS_ascii_strncasecmp(p, "nan", 3) == 0) { p += 3; if (*p == '(') { ++p; while (NumPyOS_ascii_isalnum(*p) || *p == '_') { ++p; } if (*p == ')') { ++p; } } if (endptr != NULL) { *endptr = (char*)p; } return NPY_NAN; } else if (NumPyOS_ascii_strncasecmp(p, "inf", 3) == 0) { p += 3; if (NumPyOS_ascii_strncasecmp(p, "inity", 5) == 0) { p += 5; } if (endptr != NULL) { *endptr = (char*)p; } return result*NPY_INFINITY; } /* End of ##1 */ /* * ## 2 * * At least Python versions <= 2.5.2 and <= 2.6.1 * * Fails to do best-efforts parsing of strings of the form "1<DP>234" * where <DP> is the decimal point under the foreign locale. */ if (decimal_point[0] != '.' || decimal_point[1] != 0) { p = s; if (*p == '+' || *p == '-') { ++p; } while (*p >= '0' && *p <= '9') { ++p; } if (strncmp(p, decimal_point, decimal_point_len) == 0) { n = (size_t)(p - s); if (n > FLOAT_FORMATBUFLEN) { n = FLOAT_FORMATBUFLEN; } memcpy(buffer, s, n); buffer[n] = '\0'; result = NumPyOS_ascii_strtod_plain(buffer, &q); if (endptr != NULL) { *endptr = (char*)(s + (q - buffer)); } return result; } } /* End of ##2 */ return NumPyOS_ascii_strtod_plain(s, endptr); }