]> git.proxmox.com Git - mirror_qemu.git/commitdiff
qobject: Use GString instead of QString to accumulate JSON
authorMarkus Armbruster <armbru@redhat.com>
Fri, 11 Dec 2020 17:11:36 +0000 (18:11 +0100)
committerMarkus Armbruster <armbru@redhat.com>
Sat, 19 Dec 2020 09:38:43 +0000 (10:38 +0100)
QString supports modifying its string, but it's quite limited: you can
only append.  The remaining callers use it for building an initial
string, never for modifying it later.

Use of GString for building the initial string is actually more
convenient here.  Change qobject_to_json() & friends to do that.

Once all such uses are replaced this way, QString can become immutable.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20201211171152.146877-5-armbru@redhat.com>

include/qapi/qmp/qstring.h
qobject/qjson.c
qobject/qstring.c

index e2e356e5e775f2078635c8c07ef885138c3c380e..ae7698d6c705a5bc1e4bd8d9562ab15fa73451f5 100644 (file)
@@ -25,6 +25,7 @@ struct QString {
 QString *qstring_new(void);
 QString *qstring_from_str(const char *str);
 QString *qstring_from_substr(const char *str, size_t start, size_t end);
+QString *qstring_from_gstring(GString *gstr);
 size_t qstring_get_length(const QString *qstring);
 const char *qstring_get_str(const QString *qstring);
 const char *qstring_get_try_str(const QString *qstring);
index 523a4ab8defe0fdbfbc1d2de22cf6a111afd9a06..e7100a539c7259bcee68021a67c29474bb6bc547 100644 (file)
@@ -149,28 +149,23 @@ QDict *qdict_from_jsonf_nofail(const char *string, ...)
     return qdict;
 }
 
-static void json_pretty_newline(QString *str, bool pretty, int indent)
+static void json_pretty_newline(GString *accu, bool pretty, int indent)
 {
-    int i;
-
     if (pretty) {
-        qstring_append(str, "\n");
-        for (i = 0; i < indent; i++) {
-            qstring_append(str, "    ");
-        }
+        g_string_append_printf(accu, "\n%*s", indent * 4, "");
     }
 }
 
-static void to_json(const QObject *obj, QString *str, bool pretty, int indent)
+static void to_json(const QObject *obj, GString *accu, bool pretty, int indent)
 {
     switch (qobject_type(obj)) {
     case QTYPE_QNULL:
-        qstring_append(str, "null");
+        g_string_append(accu, "null");
         break;
     case QTYPE_QNUM: {
         QNum *val = qobject_to(QNum, obj);
         char *buffer = qnum_to_string(val);
-        qstring_append(str, buffer);
+        g_string_append(accu, buffer);
         g_free(buffer);
         break;
     }
@@ -178,35 +173,34 @@ static void to_json(const QObject *obj, QString *str, bool pretty, int indent)
         QString *val = qobject_to(QString, obj);
         const char *ptr;
         int cp;
-        char buf[16];
         char *end;
 
         ptr = qstring_get_str(val);
-        qstring_append(str, "\"");
+        g_string_append_c(accu, '"');
 
         for (; *ptr; ptr = end) {
             cp = mod_utf8_codepoint(ptr, 6, &end);
             switch (cp) {
             case '\"':
-                qstring_append(str, "\\\"");
+                g_string_append(accu, "\\\"");
                 break;
             case '\\':
-                qstring_append(str, "\\\\");
+                g_string_append(accu, "\\\\");
                 break;
             case '\b':
-                qstring_append(str, "\\b");
+                g_string_append(accu, "\\b");
                 break;
             case '\f':
-                qstring_append(str, "\\f");
+                g_string_append(accu, "\\f");
                 break;
             case '\n':
-                qstring_append(str, "\\n");
+                g_string_append(accu, "\\n");
                 break;
             case '\r':
-                qstring_append(str, "\\r");
+                g_string_append(accu, "\\r");
                 break;
             case '\t':
-                qstring_append(str, "\\t");
+                g_string_append(accu, "\\t");
                 break;
             default:
                 if (cp < 0) {
@@ -214,20 +208,18 @@ static void to_json(const QObject *obj, QString *str, bool pretty, int indent)
                 }
                 if (cp > 0xFFFF) {
                     /* beyond BMP; need a surrogate pair */
-                    snprintf(buf, sizeof(buf), "\\u%04X\\u%04X",
-                             0xD800 + ((cp - 0x10000) >> 10),
-                             0xDC00 + ((cp - 0x10000) & 0x3FF));
+                    g_string_append_printf(accu, "\\u%04X\\u%04X",
+                                           0xD800 + ((cp - 0x10000) >> 10),
+                                           0xDC00 + ((cp - 0x10000) & 0x3FF));
                 } else if (cp < 0x20 || cp >= 0x7F) {
-                    snprintf(buf, sizeof(buf), "\\u%04X", cp);
+                    g_string_append_printf(accu, "\\u%04X", cp);
                 } else {
-                    buf[0] = cp;
-                    buf[1] = 0;
+                    g_string_append_c(accu, cp);
                 }
-                qstring_append(str, buf);
             }
         };
 
-        qstring_append(str, "\"");
+        g_string_append_c(accu, '"');
         break;
     }
     case QTYPE_QDICT: {
@@ -237,25 +229,25 @@ static void to_json(const QObject *obj, QString *str, bool pretty, int indent)
         const QDictEntry *entry;
         QString *qkey;
 
-        qstring_append(str, "{");
+        g_string_append_c(accu, '{');
 
         for (entry = qdict_first(val);
              entry;
              entry = qdict_next(val, entry)) {
-            qstring_append(str, sep);
-            json_pretty_newline(str, pretty, indent + 1);
+            g_string_append(accu, sep);
+            json_pretty_newline(accu, pretty, indent + 1);
 
             qkey = qstring_from_str(qdict_entry_key(entry));
-            to_json(QOBJECT(qkey), str, pretty, indent + 1);
+            to_json(QOBJECT(qkey), accu, pretty, indent + 1);
             qobject_unref(qkey);
 
-            qstring_append(str, ": ");
-            to_json(qdict_entry_value(entry), str, pretty, indent + 1);
+            g_string_append(accu, ": ");
+            to_json(qdict_entry_value(entry), accu, pretty, indent + 1);
             sep = comma;
         }
 
-        json_pretty_newline(str, pretty, indent);
-        qstring_append(str, "}");
+        json_pretty_newline(accu, pretty, indent);
+        g_string_append_c(accu, '}');
         break;
     }
     case QTYPE_QLIST: {
@@ -264,26 +256,26 @@ static void to_json(const QObject *obj, QString *str, bool pretty, int indent)
         const char *sep = "";
         QListEntry *entry;
 
-        qstring_append(str, "[");
+        g_string_append_c(accu, '[');
 
         QLIST_FOREACH_ENTRY(val, entry) {
-            qstring_append(str, sep);
-            json_pretty_newline(str, pretty, indent + 1);
-            to_json(qlist_entry_obj(entry), str, pretty, indent + 1);
+            g_string_append(accu, sep);
+            json_pretty_newline(accu, pretty, indent + 1);
+            to_json(qlist_entry_obj(entry), accu, pretty, indent + 1);
             sep = comma;
         }
 
-        json_pretty_newline(str, pretty, indent);
-        qstring_append(str, "]");
+        json_pretty_newline(accu, pretty, indent);
+        g_string_append_c(accu, ']');
         break;
     }
     case QTYPE_QBOOL: {
         QBool *val = qobject_to(QBool, obj);
 
         if (qbool_get_bool(val)) {
-            qstring_append(str, "true");
+            g_string_append(accu, "true");
         } else {
-            qstring_append(str, "false");
+            g_string_append(accu, "false");
         }
         break;
     }
@@ -294,11 +286,10 @@ static void to_json(const QObject *obj, QString *str, bool pretty, int indent)
 
 QString *qobject_to_json_pretty(const QObject *obj, bool pretty)
 {
-    QString *str = qstring_new();
-
-    to_json(obj, str, pretty, 0);
+    GString *accu = g_string_new(NULL);
 
-    return str;
+    to_json(obj, accu, pretty, 0);
+    return qstring_from_gstring(accu);
 }
 
 QString *qobject_to_json(const QObject *obj)
index b66a2c35f22b61dc5e9df3c42b36f52db13a43f3..af7c18ca73864e50b00b1a86f6b3ee7bd9d00d66 100644 (file)
@@ -66,6 +66,25 @@ QString *qstring_from_str(const char *str)
     return qstring_from_substr(str, 0, strlen(str));
 }
 
+/**
+ * qstring_from_gstring(): Convert a GString to a QString
+ *
+ * Return strong reference.
+ */
+
+QString *qstring_from_gstring(GString *gstr)
+{
+    QString *qstring;
+
+    qstring = g_malloc(sizeof(*qstring));
+    qobject_init(QOBJECT(qstring), QTYPE_QSTRING);
+    qstring->length = gstr->len;
+    qstring->capacity = gstr->allocated_len;
+    qstring->string = g_string_free(gstr, false);
+    return qstring;
+}
+
+
 static void capacity_increase(QString *qstring, size_t len)
 {
     if (qstring->capacity < (qstring->length + len)) {