/*
 * Core Definitions for QAPI/QMP Command Registry
 *
 * Copyright IBM, Corp. 2011
 *
 * Authors:
 *  Anthony Liguori   <aliguori@us.ibm.com>
 *
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
 * See the COPYING.LIB file in the top-level directory.
 *
 */

#include "qmp-output-visitor.h"
#include "qemu-queue.h"
#include "qemu-common.h"
#include "qemu-objects.h"
#include "qerror.h"

typedef struct QStackEntry
{
    QObject *value;
    bool is_list_head;
    QTAILQ_ENTRY(QStackEntry) node;
} QStackEntry;

typedef QTAILQ_HEAD(QStack, QStackEntry) QStack;

struct QmpOutputVisitor
{
    Visitor visitor;
    QStack stack;
};

#define qmp_output_add(qov, name, value) \
    qmp_output_add_obj(qov, name, QOBJECT(value))
#define qmp_output_push(qov, value) qmp_output_push_obj(qov, QOBJECT(value))

static QmpOutputVisitor *to_qov(Visitor *v)
{
    return container_of(v, QmpOutputVisitor, visitor);
}

static void qmp_output_push_obj(QmpOutputVisitor *qov, QObject *value)
{
    QStackEntry *e = g_malloc0(sizeof(*e));

    e->value = value;
    if (qobject_type(e->value) == QTYPE_QLIST) {
        e->is_list_head = true;
    }
    QTAILQ_INSERT_HEAD(&qov->stack, e, node);
}

static QObject *qmp_output_pop(QmpOutputVisitor *qov)
{
    QStackEntry *e = QTAILQ_FIRST(&qov->stack);
    QObject *value;
    QTAILQ_REMOVE(&qov->stack, e, node);
    value = e->value;
    g_free(e);
    return value;
}

static QObject *qmp_output_first(QmpOutputVisitor *qov)
{
    QStackEntry *e = QTAILQ_LAST(&qov->stack, QStack);
    return e->value;
}

static QObject *qmp_output_last(QmpOutputVisitor *qov)
{
    QStackEntry *e = QTAILQ_FIRST(&qov->stack);
    return e->value;
}

static void qmp_output_add_obj(QmpOutputVisitor *qov, const char *name,
                               QObject *value)
{
    QObject *cur;

    if (QTAILQ_EMPTY(&qov->stack)) {
        qmp_output_push_obj(qov, value);
        return;
    }

    cur = qmp_output_last(qov);

    switch (qobject_type(cur)) {
    case QTYPE_QDICT:
        qdict_put_obj(qobject_to_qdict(cur), name, value);
        break;
    case QTYPE_QLIST:
        qlist_append_obj(qobject_to_qlist(cur), value);
        break;
    default:
        qobject_decref(qmp_output_pop(qov));
        qmp_output_push_obj(qov, value);
        break;
    }
}

static void qmp_output_start_struct(Visitor *v, void **obj, const char *kind,
                                    const char *name, size_t unused,
                                    Error **errp)
{
    QmpOutputVisitor *qov = to_qov(v);
    QDict *dict = qdict_new();

    qmp_output_add(qov, name, dict);
    qmp_output_push(qov, dict);
}

static void qmp_output_end_struct(Visitor *v, Error **errp)
{
    QmpOutputVisitor *qov = to_qov(v);
    qmp_output_pop(qov);
}

static void qmp_output_start_list(Visitor *v, const char *name, Error **errp)
{
    QmpOutputVisitor *qov = to_qov(v);
    QList *list = qlist_new();

    qmp_output_add(qov, name, list);
    qmp_output_push(qov, list);
}

static GenericList *qmp_output_next_list(Visitor *v, GenericList **listp,
                                         Error **errp)
{
    GenericList *list = *listp;
    QmpOutputVisitor *qov = to_qov(v);
    QStackEntry *e = QTAILQ_FIRST(&qov->stack);

    assert(e);
    if (e->is_list_head) {
        e->is_list_head = false;
        return list;
    }

    return list ? list->next : NULL;
}

static void qmp_output_end_list(Visitor *v, Error **errp)
{
    QmpOutputVisitor *qov = to_qov(v);
    qmp_output_pop(qov);
}

static void qmp_output_type_int(Visitor *v, int64_t *obj, const char *name,
                                Error **errp)
{
    QmpOutputVisitor *qov = to_qov(v);
    qmp_output_add(qov, name, qint_from_int(*obj));
}

static void qmp_output_type_bool(Visitor *v, bool *obj, const char *name,
                                 Error **errp)
{
    QmpOutputVisitor *qov = to_qov(v);
    qmp_output_add(qov, name, qbool_from_int(*obj));
}

static void qmp_output_type_str(Visitor *v, char **obj, const char *name,
                                Error **errp)
{
    QmpOutputVisitor *qov = to_qov(v);
    if (*obj) {
        qmp_output_add(qov, name, qstring_from_str(*obj));
    } else {
        qmp_output_add(qov, name, qstring_from_str(""));
    }
}

static void qmp_output_type_number(Visitor *v, double *obj, const char *name,
                                   Error **errp)
{
    QmpOutputVisitor *qov = to_qov(v);
    qmp_output_add(qov, name, qfloat_from_double(*obj));
}

static void qmp_output_type_enum(Visitor *v, int *obj, const char *strings[],
                                 const char *kind, const char *name,
                                 Error **errp)
{
    int i = 0;
    int value = *obj;
    char *enum_str;

    assert(strings);
    while (strings[i++] != NULL);
    if (value >= i - 1) {
        error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
        return;
    }

    enum_str = (char *)strings[value];
    qmp_output_type_str(v, &enum_str, name, errp);
}

QObject *qmp_output_get_qobject(QmpOutputVisitor *qov)
{
    QObject *obj = qmp_output_first(qov);
    if (obj) {
        qobject_incref(obj);
    }
    return obj;
}

Visitor *qmp_output_get_visitor(QmpOutputVisitor *v)
{
    return &v->visitor;
}

void qmp_output_visitor_cleanup(QmpOutputVisitor *v)
{
    QStackEntry *e, *tmp;

    QTAILQ_FOREACH_SAFE(e, &v->stack, node, tmp) {
        QTAILQ_REMOVE(&v->stack, e, node);
        if (e->value) {
            qobject_decref(e->value);
        }
        g_free(e);
    }

    g_free(v);
}

QmpOutputVisitor *qmp_output_visitor_new(void)
{
    QmpOutputVisitor *v;

    v = g_malloc0(sizeof(*v));

    v->visitor.start_struct = qmp_output_start_struct;
    v->visitor.end_struct = qmp_output_end_struct;
    v->visitor.start_list = qmp_output_start_list;
    v->visitor.next_list = qmp_output_next_list;
    v->visitor.end_list = qmp_output_end_list;
    v->visitor.type_enum = qmp_output_type_enum;
    v->visitor.type_int = qmp_output_type_int;
    v->visitor.type_bool = qmp_output_type_bool;
    v->visitor.type_str = qmp_output_type_str;
    v->visitor.type_number = qmp_output_type_number;

    QTAILQ_INIT(&v->stack);

    return v;
}
