static apr_status_t apr_json_decode_number()

in json/apr_json_decode.c [547:676]


static apr_status_t apr_json_decode_number(apr_json_scanner_t * self, apr_json_value_t * retval)
{
    apr_status_t status = APR_SUCCESS;
    int treat_as_float = 0, exp_occurred = 0;
    const char *p = self->p, *e = self->e;

    if (p >= e)
        return APR_EOF;

    {
        unsigned char c = *(unsigned char *)p;
        if (c == '-') {
            p++;
            if (p >= e)
                return APR_EOF;
            c = *(unsigned char *)p;
        }
        if (!isdigit(c)) {
            status = APR_BADCH;
            goto out;
        }
        p++;
    }

    if (!treat_as_float) {
        while (p < e) {
            unsigned char c = *(unsigned char *)p;
            if (c == 'e' || c == 'E') {
                p++;
                if (p >= e)
                    return APR_EOF;
                c = *(unsigned char *)p;
                if (c == '-') {
                    p++;
                    if (p >= e)
                        return APR_EOF;
                    c = *(unsigned char *)p;
                }
                if (!isdigit(c)) {
                    status = APR_BADCH;
                    goto out;
                }
                treat_as_float = 1;
                exp_occurred = 1;
                break;
            }
            else if (c == '.') {
                p++;
                treat_as_float = 1;
                break;
            }
            else if (!isdigit(c))
                break;
            p++;
        }
    }
    else {
        while (p < e) {
            unsigned char c = *(unsigned char *)p;
            if (c == 'e' || c == 'E') {
                p++;
                if (p >= e)
                    return APR_EOF;
                c = *(unsigned char *)p;
                if (c == '-') {
                    p++;
                    if (p >= e)
                        return APR_EOF;
                    c = *(unsigned char *)p;
                }
                if (!isdigit(c)) {
                    status = APR_BADCH;
                    goto out;
                }
                exp_occurred = 1;
                break;
            }
            else if (!isdigit(c))
                break;
            p++;
        }
    }

    if (treat_as_float) {
        if (!exp_occurred) {
            while (p < e) {
                unsigned char c = *(unsigned char *)p;
                if (c == 'e' || c == 'E') {
                    p++;
                    if (p >= e)
                        return APR_EOF;
                    c = *(unsigned char *)p;
                    if (c == '-') {
                        p++;
                        if (p >= e)
                            return APR_EOF;
                        c = *(unsigned char *)p;
                    }
                    if (!isdigit(c)) {
                        status = APR_BADCH;
                        goto out;
                    }
                    exp_occurred = 1;
                    break;
                }
                else if (!isdigit(c))
                    break;
                p++;
            }
        }
        if (exp_occurred) {
            if (p >= e || !isdigit(*(unsigned char *)p))
                return APR_EOF;
            while (++p < e && isdigit(*(unsigned char *)p));
        }
    }

    if (treat_as_float) {
        retval->type = APR_JSON_DOUBLE;
        retval->value.dnumber = strtod(self->p, NULL);
    }
    else {
        retval->type = APR_JSON_LONG;
        retval->value.lnumber = strtol(self->p, NULL, 10);
    }

out:
    self->p = p;
    return status;
}