From: Markus Armbruster <armbru@redhat.com>
To: qemu-devel@nongnu.org
Cc: peter.maydell@linaro.org
Subject: [PULL 17/33] qobject: Use GString instead of QString to accumulate JSON
Date: Sat, 19 Dec 2020 11:55:16 +0100 [thread overview]
Message-ID: <20201219105532.1734134-18-armbru@redhat.com> (raw)
In-Reply-To: <20201219105532.1734134-1-armbru@redhat.com>
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 | 1 +
qobject/qjson.c | 85 +++++++++++++++++---------------------
qobject/qstring.c | 19 +++++++++
3 files changed, 58 insertions(+), 47 deletions(-)
diff --git a/include/qapi/qmp/qstring.h b/include/qapi/qmp/qstring.h
index e2e356e5e7..ae7698d6c7 100644
--- a/include/qapi/qmp/qstring.h
+++ b/include/qapi/qmp/qstring.h
@@ -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);
diff --git a/qobject/qjson.c b/qobject/qjson.c
index 523a4ab8de..e7100a539c 100644
--- a/qobject/qjson.c
+++ b/qobject/qjson.c
@@ -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();
+ GString *accu = g_string_new(NULL);
- to_json(obj, str, pretty, 0);
-
- return str;
+ to_json(obj, accu, pretty, 0);
+ return qstring_from_gstring(accu);
}
QString *qobject_to_json(const QObject *obj)
diff --git a/qobject/qstring.c b/qobject/qstring.c
index b66a2c35f2..af7c18ca73 100644
--- a/qobject/qstring.c
+++ b/qobject/qstring.c
@@ -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)) {
--
2.26.2
next prev parent reply other threads:[~2020-12-19 11:17 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-19 10:54 [PULL 00/33] QAPI patches patches for 2020-12-19 Markus Armbruster
2020-12-19 10:55 ` [PULL 01/33] rocker: Revamp fp_port_get_info Markus Armbruster
2020-12-19 10:55 ` [PULL 02/33] migration: Refactor migrate_cap_add Markus Armbruster
2020-12-19 10:55 ` [PULL 03/33] qapi: Use QAPI_LIST_PREPEND() where possible Markus Armbruster
2020-12-19 10:55 ` [PULL 04/33] tests/check-qjson: Don't skip funny QNumber to JSON conversions Markus Armbruster
2020-12-19 10:55 ` [PULL 05/33] tests/check-qjson: Examine QNum more thoroughly Markus Armbruster
2020-12-19 10:55 ` [PULL 06/33] tests/check-qjson: Cover number 2^63 Markus Armbruster
2020-12-19 10:55 ` [PULL 07/33] tests/check-qjson: Replace redundant large_number() Markus Armbruster
2020-12-19 10:55 ` [PULL 08/33] tests/check-qnum: Cover qnum_to_string() for "unround" argument Markus Armbruster
2020-12-19 10:55 ` [PULL 09/33] qobject: Fix qnum_to_string() to use sufficient precision Markus Armbruster
2020-12-19 10:55 ` [PULL 10/33] test-string-output-visitor: Cover "unround" number Markus Armbruster
2020-12-19 10:55 ` [PULL 11/33] string-output-visitor: Fix to use sufficient precision Markus Armbruster
2020-12-19 10:55 ` [PULL 12/33] test-visitor-serialization: Drop insufficient precision workaround Markus Armbruster
2020-12-19 10:55 ` [PULL 13/33] test-visitor-serialization: Clean up test_primitives() Markus Armbruster
2020-12-19 10:55 ` [PULL 14/33] hmp: Simplify how qmp_human_monitor_command() gets output Markus Armbruster
2020-12-19 10:55 ` [PULL 15/33] monitor: Use GString instead of QString for output buffer Markus Armbruster
2020-12-19 10:55 ` [PULL 16/33] qobject: Make qobject_to_json_pretty() take a pretty argument Markus Armbruster
2020-12-19 10:55 ` Markus Armbruster [this message]
2020-12-19 10:55 ` [PULL 18/33] qobject: Change qobject_to_json()'s value to GString Markus Armbruster
2020-12-19 10:55 ` [PULL 19/33] Revert "qstring: add qstring_free()" Markus Armbruster
2020-12-19 10:55 ` [PULL 20/33] hw/rdma: Replace QList by GQueue Markus Armbruster
2020-12-19 10:55 ` [PULL 21/33] qobject: Move internals to qobject-internal.h Markus Armbruster
2020-12-19 10:55 ` [PULL 22/33] qmp: Fix tracing of non-string command IDs Markus Armbruster
2020-12-19 10:55 ` [PULL 23/33] block: Avoid qobject_get_try_str() Markus Armbruster
2020-12-19 10:55 ` [PULL 24/33] Revert "qobject: let object_property_get_str() use new API" Markus Armbruster
2020-12-19 10:55 ` [PULL 25/33] qobject: Drop qobject_get_try_str() Markus Armbruster
2020-12-19 10:55 ` [PULL 26/33] qobject: Drop qstring_get_try_str() Markus Armbruster
2020-12-19 10:55 ` [PULL 27/33] qobject: Factor quoted_str() out of to_json() Markus Armbruster
2020-12-19 10:55 ` [PULL 28/33] qobject: Factor JSON writer out of qobject_to_json() Markus Armbruster
2020-12-19 10:55 ` [PULL 29/33] migration: Replace migration's JSON writer by the general one Markus Armbruster
2020-12-19 10:55 ` [PULL 30/33] json: Use GString instead of QString to accumulate strings Markus Armbruster
2020-12-19 10:55 ` [PULL 31/33] keyval: Use GString to accumulate value strings Markus Armbruster
2020-12-19 10:55 ` [PULL 32/33] block: Use GString instead of QString to build filenames Markus Armbruster
2020-12-19 10:55 ` [PULL 33/33] qobject: Make QString immutable Markus Armbruster
2020-12-19 11:24 ` [PULL 00/33] QAPI patches patches for 2020-12-19 no-reply
2021-01-01 16:56 ` Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201219105532.1734134-18-armbru@redhat.com \
--to=armbru@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).