aboutsummaryrefslogtreecommitdiff
path: root/migration/qjson.c
blob: cb479fe0eb66974b36d1556b92cd19338253cc19 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 * A simple JSON writer
 *
 * Copyright Alexander Graf
 *
 * Authors:
 *  Alexander Graf <agraf@suse.de>
 *
 * 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.
 *
 */

/*
 * Type QJSON lets you build JSON text.  Its interface mirrors (a
 * subset of) abstract JSON syntax.
 *
 * It does *not* detect incorrect use.  It happily produces invalid
 * JSON then.  This is what migration wants.
 *
 * QAPI output visitors also produce JSON text.  However, they do
 * assert their preconditions and invariants, and therefore abort on
 * incorrect use.
 */

#include "qemu/osdep.h"
#include "qapi/qmp/qstring.h"
#include "migration/qjson.h"
#include "qemu/module.h"
#include "qom/object.h"

struct QJSON {
    Object obj;
    QString *str;
    bool omit_comma;
};

#define QJSON(obj) OBJECT_CHECK(QJSON, (obj), TYPE_QJSON)

static void json_emit_element(QJSON *json, const char *name)
{
    /* Check whether we need to print a , before an element */
    if (json->omit_comma) {
        json->omit_comma = false;
    } else {
        qstring_append(json->str, ", ");
    }

    if (name) {
        qstring_append(json->str, "\"");
        qstring_append(json->str, name);
        qstring_append(json->str, "\" : ");
    }
}

void json_start_object(QJSON *json, const char *name)
{
    json_emit_element(json, name);
    qstring_append(json->str, "{ ");
    json->omit_comma = true;
}

void json_end_object(QJSON *json)
{
    qstring_append(json->str, " }");
    json->omit_comma = false;
}

void json_start_array(QJSON *json, const char *name)
{
    json_emit_element(json, name);
    qstring_append(json->str, "[ ");
    json->omit_comma = true;
}

void json_end_array(QJSON *json)
{
    qstring_append(json->str, " ]");
    json->omit_comma = false;
}

void json_prop_int(QJSON *json, const char *name, int64_t val)
{
    json_emit_element(json, name);
    qstring_append_int(json->str, val);
}

void json_prop_str(QJSON *json, const char *name, const char *str)
{
    json_emit_element(json, name);
    qstring_append_chr(json->str, '"');
    qstring_append(json->str, str);
    qstring_append_chr(json->str, '"');
}

const char *qjson_get_str(QJSON *json)
{
    return qstring_get_str(json->str);
}

QJSON *qjson_new(void)
{
    QJSON *json = QJSON(object_new(TYPE_QJSON));
    return json;
}

void qjson_finish(QJSON *json)
{
    json_end_object(json);
}

static void qjson_initfn(Object *obj)
{
    QJSON *json = QJSON(obj);

    json->str = qstring_from_str("{ ");
    json->omit_comma = true;
}

static void qjson_finalizefn(Object *obj)
{
    QJSON *json = QJSON(obj);

    qobject_decref(QOBJECT(json->str));
}

static const TypeInfo qjson_type_info = {
    .name = TYPE_QJSON,
    .parent = TYPE_OBJECT,
    .instance_size = sizeof(QJSON),
    .instance_init = qjson_initfn,
    .instance_finalize = qjson_finalizefn,
};

static void qjson_register_types(void)
{
    type_register_static(&qjson_type_info);
}

type_init(qjson_register_types)