/*
 * Core Definitions for QAPI/QMP Command Registry
 *
 * Copyright (C) 2012-2016 Red Hat, Inc.
 * 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 "qemu/osdep.h"
#include "qapi/qobject-output-visitor.h"
#include "qapi/visitor-impl.h"
#include "qemu/queue.h"
#include "qemu-common.h"
#include "qapi/qmp/qbool.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qlist.h"
#include "qapi/qmp/qnull.h"
#include "qapi/qmp/qnum.h"
#include "qapi/qmp/qstring.h"

typedef struct QStackEntry {
    QObject *value;
    void *qapi; /* sanity check that caller uses same pointer */
    QSLIST_ENTRY(QStackEntry) node;
} QStackEntry;

struct QObjectOutputVisitor {
    Visitor visitor;
    QSLIST_HEAD(, QStackEntry) stack; /* Stack of unfinished containers */
    QObject *root; /* Root of the output visit */
    QObject **result; /* User's storage location for result */
};

#define qobject_output_add(qov, name, value) \
    qobject_output_add_obj(qov, name, QOBJECT(value))
#define qobject_output_push(qov, value, qapi) \
    qobject_output_push_obj(qov, QOBJECT(value), qapi)

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

/* Push @value onto the stack of current QObjects being built */
static void qobject_output_push_obj(QObjectOutputVisitor *qov, QObject *value,
                                    void *qapi)
{
    QStackEntry *e = g_malloc0(sizeof(*e));

    assert(qov->root);
    assert(value);
    e->value = value;
    e->qapi = qapi;
    QSLIST_INSERT_HEAD(&qov->stack, e, node);
}

/* Pop a value off the stack of QObjects being built, and return it. */
static QObject *qobject_output_pop(QObjectOutputVisitor *qov, void *qapi)
{
    QStackEntry *e = QSLIST_FIRST(&qov->stack);
    QObject *value;

    assert(e);
    assert(e->qapi == qapi);
    QSLIST_REMOVE_HEAD(&qov->stack, node);
    value = e->value;
    assert(value);
    g_free(e);
    return value;
}

/* Add @value to the current QObject being built.
 * If the stack is visiting a dictionary or list, @value is now owned
 * by that container. Otherwise, @value is now the root.  */
static void qobject_output_add_obj(QObjectOutputVisitor *qov, const char *name,
                                   QObject *value)
{
    QStackEntry *e = QSLIST_FIRST(&qov->stack);
    QObject *cur = e ? e->value : NULL;

    if (!cur) {
        /* Don't allow reuse of visitor on more than one root */
        assert(!qov->root);
        qov->root = value;
    } else {
        switch (qobject_type(cur)) {
        case QTYPE_QDICT:
            assert(name);
            qdict_put_obj(qobject_to(QDict, cur), name, value);
            break;
        case QTYPE_QLIST:
            assert(!name);
            qlist_append_obj(qobject_to(QList, cur), value);
            break;
        default:
            g_assert_not_reached();
        }
    }
}

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

    qobject_output_add(qov, name, dict);
    qobject_output_push(qov, dict, obj);
}

static void qobject_output_end_struct(Visitor *v, void **obj)
{
    QObjectOutputVisitor *qov = to_qov(v);
    QObject *value = qobject_output_pop(qov, obj);
    assert(qobject_type(value) == QTYPE_QDICT);
}

static void qobject_output_start_list(Visitor *v, const char *name,
                                      GenericList **listp, size_t size,
                                      Error **errp)
{
    QObjectOutputVisitor *qov = to_qov(v);
    QList *list = qlist_new();

    qobject_output_add(qov, name, list);
    qobject_output_push(qov, list, listp);
}

static GenericList *qobject_output_next_list(Visitor *v, GenericList *tail,
                                             size_t size)
{
    return tail->next;
}

static void qobject_output_end_list(Visitor *v, void **obj)
{
    QObjectOutputVisitor *qov = to_qov(v);
    QObject *value = qobject_output_pop(qov, obj);
    assert(qobject_type(value) == QTYPE_QLIST);
}

static void qobject_output_type_int64(Visitor *v, const char *name,
                                      int64_t *obj, Error **errp)
{
    QObjectOutputVisitor *qov = to_qov(v);
    qobject_output_add(qov, name, qnum_from_int(*obj));
}

static void qobject_output_type_uint64(Visitor *v, const char *name,
                                       uint64_t *obj, Error **errp)
{
    QObjectOutputVisitor *qov = to_qov(v);
    qobject_output_add(qov, name, qnum_from_uint(*obj));
}

static void qobject_output_type_bool(Visitor *v, const char *name, bool *obj,
                                     Error **errp)
{
    QObjectOutputVisitor *qov = to_qov(v);
    qobject_output_add(qov, name, qbool_from_bool(*obj));
}

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

static void qobject_output_type_number(Visitor *v, const char *name,
                                       double *obj, Error **errp)
{
    QObjectOutputVisitor *qov = to_qov(v);
    qobject_output_add(qov, name, qnum_from_double(*obj));
}

static void qobject_output_type_any(Visitor *v, const char *name,
                                    QObject **obj, Error **errp)
{
    QObjectOutputVisitor *qov = to_qov(v);

    qobject_output_add_obj(qov, name, qobject_ref(*obj));
}

static void qobject_output_type_null(Visitor *v, const char *name,
                                     QNull **obj, Error **errp)
{
    QObjectOutputVisitor *qov = to_qov(v);
    qobject_output_add(qov, name, qnull());
}

/* Finish building, and return the root object.
 * The root object is never null. The caller becomes the object's
 * owner, and should use qobject_unref() when done with it.  */
static void qobject_output_complete(Visitor *v, void *opaque)
{
    QObjectOutputVisitor *qov = to_qov(v);

    /* A visit must have occurred, with each start paired with end.  */
    assert(qov->root && QSLIST_EMPTY(&qov->stack));
    assert(opaque == qov->result);

    *qov->result = qobject_ref(qov->root);
    qov->result = NULL;
}

static void qobject_output_free(Visitor *v)
{
    QObjectOutputVisitor *qov = to_qov(v);
    QStackEntry *e;

    while (!QSLIST_EMPTY(&qov->stack)) {
        e = QSLIST_FIRST(&qov->stack);
        QSLIST_REMOVE_HEAD(&qov->stack, node);
        g_free(e);
    }

    qobject_unref(qov->root);
    g_free(qov);
}

Visitor *qobject_output_visitor_new(QObject **result)
{
    QObjectOutputVisitor *v;

    v = g_malloc0(sizeof(*v));

    v->visitor.type = VISITOR_OUTPUT;
    v->visitor.start_struct = qobject_output_start_struct;
    v->visitor.end_struct = qobject_output_end_struct;
    v->visitor.start_list = qobject_output_start_list;
    v->visitor.next_list = qobject_output_next_list;
    v->visitor.end_list = qobject_output_end_list;
    v->visitor.type_int64 = qobject_output_type_int64;
    v->visitor.type_uint64 = qobject_output_type_uint64;
    v->visitor.type_bool = qobject_output_type_bool;
    v->visitor.type_str = qobject_output_type_str;
    v->visitor.type_number = qobject_output_type_number;
    v->visitor.type_any = qobject_output_type_any;
    v->visitor.type_null = qobject_output_type_null;
    v->visitor.complete = qobject_output_complete;
    v->visitor.free = qobject_output_free;

    *result = NULL;
    v->result = result;

    return &v->visitor;
}
