enum json_type json_next()

in libvmaf/src/pdjson.c [681:785]


enum json_type json_next(json_stream *json)
{
    if (json->flags & JSON_FLAG_ERROR)
        return JSON_ERROR;
    if (json->next != 0) {
        enum json_type next = json->next;
        json->next = (enum json_type)0;
        return next;
    }
    if (json->ntokens > 0 && json->stack_top == (size_t)-1) {

        /* In the streaming mode leave any trailing whitespaces in the stream.
         * This allows the user to validate any desired separation between
         * values (such as newlines) using json_source_get/peek() with any
         * remaining whitespaces ignored as leading when we parse the next
         * value. */
        if (!(json->flags & JSON_FLAG_STREAMING)) {
            int c;

            do {
                c = json->source.peek(&json->source);
                if (json_isspace(c)) {
                    c = json->source.get(&json->source);
                }
            } while (json_isspace(c));

            if (c != EOF) {
                json_error(json, "expected end of text instead of byte '%c'", c);
                return JSON_ERROR;
            }
        }

        return JSON_DONE;
    }
    int c = next(json);
    if (json->stack_top == (size_t)-1) {
        if (c == EOF && (json->flags & JSON_FLAG_STREAMING))
            return JSON_DONE;

        return read_value(json, c);
    }
    if (json->stack[json->stack_top].type == JSON_ARRAY) {
        if (json->stack[json->stack_top].count == 0) {
            if (c == ']') {
                return pop(json, c, JSON_ARRAY);
            }
            json->stack[json->stack_top].count++;
            return read_value(json, c);
        } else if (c == ',') {
            json->stack[json->stack_top].count++;
            return read_value(json, next(json));
        } else if (c == ']') {
            return pop(json, c, JSON_ARRAY);
        } else {
            json_error(json, "unexpected byte '%c'", c);
            return JSON_ERROR;
        }
    } else if (json->stack[json->stack_top].type == JSON_OBJECT) {
        if (json->stack[json->stack_top].count == 0) {
            if (c == '}') {
                return pop(json, c, JSON_OBJECT);
            }

            /* No member name/value pairs yet. */
            enum json_type value = read_value(json, c);
            if (value != JSON_STRING) {
                if (value != JSON_ERROR)
                    json_error(json, "%s", "expected member name or '}'");
                return JSON_ERROR;
            } else {
                json->stack[json->stack_top].count++;
                return value;
            }
        } else if ((json->stack[json->stack_top].count % 2) == 0) {
            /* Expecting comma followed by member name. */
            if (c != ',' && c != '}') {
                json_error(json, "%s", "expected ',' or '}' after member value");
                return JSON_ERROR;
            } else if (c == '}') {
                return pop(json, c, JSON_OBJECT);
            } else {
                enum json_type value = read_value(json, next(json));
                if (value != JSON_STRING) {
                    if (value != JSON_ERROR)
                        json_error(json, "%s", "expected member name");
                    return JSON_ERROR;
                } else {
                    json->stack[json->stack_top].count++;
                    return value;
                }
            }
        } else if ((json->stack[json->stack_top].count % 2) == 1) {
            /* Expecting colon followed by value. */
            if (c != ':') {
                json_error(json, "%s", "expected ':' after member name");
                return JSON_ERROR;
            } else {
                json->stack[json->stack_top].count++;
                return read_value(json, next(json));
            }
        }
    }
    json_error(json, "%s", "invalid parser state");
    return JSON_ERROR;
}