]> git.proxmox.com Git - mirror_qemu.git/blobdiff - qjson.c
virtio-net: correctly drop truncated packets
[mirror_qemu.git] / qjson.c
diff --git a/qjson.c b/qjson.c
index 83a6b4f7c1df228a41253aecc1c71e16e61c27eb..e478802a461f6b5556732d8a07b5066780c1c524 100644 (file)
--- a/qjson.c
+++ b/qjson.c
 /*
- * QObject JSON integration
+ * QEMU JSON writer
  *
- * Copyright IBM, Corp. 2009
+ * Copyright Alexander Graf
  *
  * Authors:
- *  Anthony Liguori   <aliguori@us.ibm.com>
+ *  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.
  *
  */
 
-#include "qapi/qmp/json-lexer.h"
-#include "qapi/qmp/json-parser.h"
-#include "qapi/qmp/json-streamer.h"
-#include "qapi/qmp/qjson.h"
-#include "qapi/qmp/qint.h"
-#include "qapi/qmp/qlist.h"
-#include "qapi/qmp/qbool.h"
-#include "qapi/qmp/qfloat.h"
-#include "qapi/qmp/qdict.h"
+#include <qapi/qmp/qstring.h>
+#include <stdbool.h>
+#include <glib.h>
+#include <qjson.h>
+#include <qemu/module.h>
+#include <qom/object.h>
 
-typedef struct JSONParsingState
-{
-    JSONMessageParser parser;
-    va_list *ap;
-    QObject *result;
-} JSONParsingState;
+struct QJSON {
+    Object obj;
+    QString *str;
+    bool omit_comma;
+};
 
-static void parse_json(JSONMessageParser *parser, QList *tokens)
-{
-    JSONParsingState *s = container_of(parser, JSONParsingState, parser);
-    s->result = json_parser_parse(tokens, s->ap);
-}
+#define QJSON(obj) OBJECT_CHECK(QJSON, (obj), TYPE_QJSON)
 
-QObject *qobject_from_jsonv(const char *string, va_list *ap)
+static void json_emit_element(QJSON *json, const char *name)
 {
-    JSONParsingState state = {};
-
-    state.ap = ap;
-
-    json_message_parser_init(&state.parser, parse_json);
-    json_message_parser_feed(&state.parser, string, strlen(string));
-    json_message_parser_flush(&state.parser);
-    json_message_parser_destroy(&state.parser);
+    /* Check whether we need to print a , before an element */
+    if (json->omit_comma) {
+        json->omit_comma = false;
+    } else {
+        qstring_append(json->str, ", ");
+    }
 
-    return state.result;
+    if (name) {
+        qstring_append(json->str, "\"");
+        qstring_append(json->str, name);
+        qstring_append(json->str, "\" : ");
+    }
 }
 
-QObject *qobject_from_json(const char *string)
+void json_start_object(QJSON *json, const char *name)
 {
-    return qobject_from_jsonv(string, NULL);
+    json_emit_element(json, name);
+    qstring_append(json->str, "{ ");
+    json->omit_comma = true;
 }
 
-/*
- * IMPORTANT: This function aborts on error, thus it must not
- * be used with untrusted arguments.
- */
-QObject *qobject_from_jsonf(const char *string, ...)
+void json_end_object(QJSON *json)
 {
-    QObject *obj;
-    va_list ap;
-
-    va_start(ap, string);
-    obj = qobject_from_jsonv(string, &ap);
-    va_end(ap);
-
-    assert(obj != NULL);
-    return obj;
+    qstring_append(json->str, " }");
+    json->omit_comma = false;
 }
 
-typedef struct ToJsonIterState
+void json_start_array(QJSON *json, const char *name)
 {
-    int indent;
-    int pretty;
-    int count;
-    QString *str;
-} ToJsonIterState;
-
-static void to_json(const QObject *obj, QString *str, int pretty, int indent);
+    json_emit_element(json, name);
+    qstring_append(json->str, "[ ");
+    json->omit_comma = true;
+}
 
-static void to_json_dict_iter(const char *key, QObject *obj, void *opaque)
+void json_end_array(QJSON *json)
 {
-    ToJsonIterState *s = opaque;
-    QString *qkey;
-    int j;
-
-    if (s->count)
-        qstring_append(s->str, ", ");
-
-    if (s->pretty) {
-        qstring_append(s->str, "\n");
-        for (j = 0 ; j < s->indent ; j++)
-            qstring_append(s->str, "    ");
-    }
-
-    qkey = qstring_from_str(key);
-    to_json(QOBJECT(qkey), s->str, s->pretty, s->indent);
-    QDECREF(qkey);
-
-    qstring_append(s->str, ": ");
-    to_json(obj, s->str, s->pretty, s->indent);
-    s->count++;
+    qstring_append(json->str, " ]");
+    json->omit_comma = false;
 }
 
-static void to_json_list_iter(QObject *obj, void *opaque)
+void json_prop_int(QJSON *json, const char *name, int64_t val)
 {
-    ToJsonIterState *s = opaque;
-    int j;
-
-    if (s->count)
-        qstring_append(s->str, ", ");
-
-    if (s->pretty) {
-        qstring_append(s->str, "\n");
-        for (j = 0 ; j < s->indent ; j++)
-            qstring_append(s->str, "    ");
-    }
-
-    to_json(obj, s->str, s->pretty, s->indent);
-    s->count++;
+    json_emit_element(json, name);
+    qstring_append_int(json->str, val);
 }
 
-static void to_json(const QObject *obj, QString *str, int pretty, int indent)
+void json_prop_str(QJSON *json, const char *name, const char *str)
 {
-    switch (qobject_type(obj)) {
-    case QTYPE_QINT: {
-        QInt *val = qobject_to_qint(obj);
-        char buffer[1024];
-
-        snprintf(buffer, sizeof(buffer), "%" PRId64, qint_get_int(val));
-        qstring_append(str, buffer);
-        break;
-    }
-    case QTYPE_QSTRING: {
-        QString *val = qobject_to_qstring(obj);
-        const char *ptr;
-
-        ptr = qstring_get_str(val);
-        qstring_append(str, "\"");
-        while (*ptr) {
-            if ((ptr[0] & 0xE0) == 0xE0 &&
-                (ptr[1] & 0x80) && (ptr[2] & 0x80)) {
-                uint16_t wchar;
-                char escape[7];
-
-                wchar  = (ptr[0] & 0x0F) << 12;
-                wchar |= (ptr[1] & 0x3F) << 6;
-                wchar |= (ptr[2] & 0x3F);
-                ptr += 2;
-
-                snprintf(escape, sizeof(escape), "\\u%04X", wchar);
-                qstring_append(str, escape);
-            } else if ((ptr[0] & 0xE0) == 0xC0 && (ptr[1] & 0x80)) {
-                uint16_t wchar;
-                char escape[7];
-
-                wchar  = (ptr[0] & 0x1F) << 6;
-                wchar |= (ptr[1] & 0x3F);
-                ptr++;
-
-                snprintf(escape, sizeof(escape), "\\u%04X", wchar);
-                qstring_append(str, escape);
-            } else switch (ptr[0]) {
-                case '\"':
-                    qstring_append(str, "\\\"");
-                    break;
-                case '\\':
-                    qstring_append(str, "\\\\");
-                    break;
-                case '\b':
-                    qstring_append(str, "\\b");
-                    break;
-                case '\f':
-                    qstring_append(str, "\\f");
-                    break;
-                case '\n':
-                    qstring_append(str, "\\n");
-                    break;
-                case '\r':
-                    qstring_append(str, "\\r");
-                    break;
-                case '\t':
-                    qstring_append(str, "\\t");
-                    break;
-                default: {
-                    if (ptr[0] <= 0x1F) {
-                        char escape[7];
-                        snprintf(escape, sizeof(escape), "\\u%04X", ptr[0]);
-                        qstring_append(str, escape);
-                    } else {
-                        char buf[2] = { ptr[0], 0 };
-                        qstring_append(str, buf);
-                    }
-                    break;
-                }
-                }
-            ptr++;
-        }
-        qstring_append(str, "\"");
-        break;
-    }
-    case QTYPE_QDICT: {
-        ToJsonIterState s;
-        QDict *val = qobject_to_qdict(obj);
-
-        s.count = 0;
-        s.str = str;
-        s.indent = indent + 1;
-        s.pretty = pretty;
-        qstring_append(str, "{");
-        qdict_iter(val, to_json_dict_iter, &s);
-        if (pretty) {
-            int j;
-            qstring_append(str, "\n");
-            for (j = 0 ; j < indent ; j++)
-                qstring_append(str, "    ");
-        }
-        qstring_append(str, "}");
-        break;
-    }
-    case QTYPE_QLIST: {
-        ToJsonIterState s;
-        QList *val = qobject_to_qlist(obj);
-
-        s.count = 0;
-        s.str = str;
-        s.indent = indent + 1;
-        s.pretty = pretty;
-        qstring_append(str, "[");
-        qlist_iter(val, (void *)to_json_list_iter, &s);
-        if (pretty) {
-            int j;
-            qstring_append(str, "\n");
-            for (j = 0 ; j < indent ; j++)
-                qstring_append(str, "    ");
-        }
-        qstring_append(str, "]");
-        break;
-    }
-    case QTYPE_QFLOAT: {
-        QFloat *val = qobject_to_qfloat(obj);
-        char buffer[1024];
-        int len;
-
-        len = snprintf(buffer, sizeof(buffer), "%f", qfloat_get_double(val));
-        while (len > 0 && buffer[len - 1] == '0') {
-            len--;
-        }
+    json_emit_element(json, name);
+    qstring_append_chr(json->str, '"');
+    qstring_append(json->str, str);
+    qstring_append_chr(json->str, '"');
+}
 
-        if (len && buffer[len - 1] == '.') {
-            buffer[len - 1] = 0;
-        } else {
-            buffer[len] = 0;
-        }
-        
-        qstring_append(str, buffer);
-        break;
-    }
-    case QTYPE_QBOOL: {
-        QBool *val = qobject_to_qbool(obj);
+const char *qjson_get_str(QJSON *json)
+{
+    return qstring_get_str(json->str);
+}
 
-        if (qbool_get_int(val)) {
-            qstring_append(str, "true");
-        } else {
-            qstring_append(str, "false");
-        }
-        break;
-    }
-    case QTYPE_QERROR:
-        /* XXX: should QError be emitted? */
-    case QTYPE_NONE:
-        break;
-    }
+QJSON *qjson_new(void)
+{
+    QJSON *json = QJSON(object_new(TYPE_QJSON));
+    return json;
 }
 
-QString *qobject_to_json(const QObject *obj)
+void qjson_finish(QJSON *json)
 {
-    QString *str = qstring_new();
+    json_end_object(json);
+}
 
-    to_json(obj, str, 0, 0);
+static void qjson_initfn(Object *obj)
+{
+    QJSON *json = QJSON(obj);
 
-    return str;
+    json->str = qstring_from_str("{ ");
+    json->omit_comma = true;
 }
 
-QString *qobject_to_json_pretty(const QObject *obj)
+static void qjson_finalizefn(Object *obj)
 {
-    QString *str = qstring_new();
+    QJSON *json = QJSON(obj);
+
+    qobject_decref(QOBJECT(json->str));
+}
 
-    to_json(obj, str, 1, 0);
+static const TypeInfo qjson_type_info = {
+    .name = TYPE_QJSON,
+    .parent = TYPE_OBJECT,
+    .instance_size = sizeof(QJSON),
+    .instance_init = qjson_initfn,
+    .instance_finalize = qjson_finalizefn,
+};
 
-    return str;
+static void qjson_register_types(void)
+{
+    type_register_static(&qjson_type_info);
 }
+
+type_init(qjson_register_types)