Example #1
0
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;
}
Example #2
0
/*
 * 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;
}
Example #3
0
/*
 * 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);
}