aboutsummaryrefslogtreecommitdiff
path: root/qobject
diff options
context:
space:
mode:
Diffstat (limited to 'qobject')
-rw-r--r--qobject/json-parser.c30
-rw-r--r--qobject/json-writer.c247
-rw-r--r--qobject/meson.build5
-rw-r--r--qobject/qbool.c1
-rw-r--r--qobject/qdict.c1
-rw-r--r--qobject/qjson.c146
-rw-r--r--qobject/qlist.c1
-rw-r--r--qobject/qnull.c1
-rw-r--r--qobject/qnum.c28
-rw-r--r--qobject/qobject-internal.h39
-rw-r--r--qobject/qobject.c1
-rw-r--r--qobject/qstring.c113
12 files changed, 362 insertions, 251 deletions
diff --git a/qobject/json-parser.c b/qobject/json-parser.c
index c0f521b56b..d351039b10 100644
--- a/qobject/json-parser.c
+++ b/qobject/json-parser.c
@@ -130,7 +130,7 @@ static int cvt4hex(const char *s)
static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
{
const char *ptr = token->str;
- QString *str;
+ GString *str;
char quote;
const char *beg;
int cp, trailing;
@@ -140,7 +140,7 @@ static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
assert(*ptr == '"' || *ptr == '\'');
quote = *ptr++;
- str = qstring_new();
+ str = g_string_new(NULL);
while (*ptr != quote) {
assert(*ptr);
@@ -149,31 +149,31 @@ static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
beg = ptr++;
switch (*ptr++) {
case '"':
- qstring_append_chr(str, '"');
+ g_string_append_c(str, '"');
break;
case '\'':
- qstring_append_chr(str, '\'');
+ g_string_append_c(str, '\'');
break;
case '\\':
- qstring_append_chr(str, '\\');
+ g_string_append_c(str, '\\');
break;
case '/':
- qstring_append_chr(str, '/');
+ g_string_append_c(str, '/');
break;
case 'b':
- qstring_append_chr(str, '\b');
+ g_string_append_c(str, '\b');
break;
case 'f':
- qstring_append_chr(str, '\f');
+ g_string_append_c(str, '\f');
break;
case 'n':
- qstring_append_chr(str, '\n');
+ g_string_append_c(str, '\n');
break;
case 'r':
- qstring_append_chr(str, '\r');
+ g_string_append_c(str, '\r');
break;
case 't':
- qstring_append_chr(str, '\t');
+ g_string_append_c(str, '\t');
break;
case 'u':
cp = cvt4hex(ptr);
@@ -200,7 +200,7 @@ static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
(int)(ptr - beg), beg);
goto out;
}
- qstring_append(str, utf8_buf);
+ g_string_append(str, utf8_buf);
break;
default:
parse_error(ctxt, token, "invalid escape sequence in string");
@@ -225,14 +225,14 @@ static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
ptr = end;
len = mod_utf8_encode(utf8_buf, sizeof(utf8_buf), cp);
assert(len >= 0);
- qstring_append(str, utf8_buf);
+ g_string_append(str, utf8_buf);
}
}
- return str;
+ return qstring_from_gstring(str);
out:
- qobject_unref(str);
+ g_string_free(str, true);
return NULL;
}
diff --git a/qobject/json-writer.c b/qobject/json-writer.c
new file mode 100644
index 0000000000..309a31d57a
--- /dev/null
+++ b/qobject/json-writer.c
@@ -0,0 +1,247 @@
+/*
+ * JSON Writer
+ *
+ * Copyright IBM, Corp. 2009
+ * Copyright (c) 2010-2020 Red Hat Inc.
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ * Markus Armbruster <armbru@redhat.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/qmp/json-writer.h"
+#include "qemu/unicode.h"
+
+struct JSONWriter {
+ bool pretty;
+ bool need_comma;
+ GString *contents;
+ GByteArray *container_is_array;
+};
+
+JSONWriter *json_writer_new(bool pretty)
+{
+ JSONWriter *writer = g_new(JSONWriter, 1);
+
+ writer->pretty = pretty;
+ writer->need_comma = false;
+ writer->contents = g_string_new(NULL);
+ writer->container_is_array = g_byte_array_new();
+ return writer;
+}
+
+const char *json_writer_get(JSONWriter *writer)
+{
+ g_assert(!writer->container_is_array->len);
+ return writer->contents->str;
+}
+
+GString *json_writer_get_and_free(JSONWriter *writer)
+{
+ GString *contents = writer->contents;
+
+ writer->contents = NULL;
+ g_byte_array_free(writer->container_is_array, true);
+ g_free(writer);
+ return contents;
+}
+
+void json_writer_free(JSONWriter *writer)
+{
+ if (writer) {
+ g_string_free(json_writer_get_and_free(writer), true);
+ }
+}
+
+static void enter_container(JSONWriter *writer, bool is_array)
+{
+ unsigned depth = writer->container_is_array->len;
+
+ g_byte_array_set_size(writer->container_is_array, depth + 1);
+ writer->container_is_array->data[depth] = is_array;
+ writer->need_comma = false;
+}
+
+static void leave_container(JSONWriter *writer, bool is_array)
+{
+ unsigned depth = writer->container_is_array->len;
+
+ assert(depth);
+ assert(writer->container_is_array->data[depth - 1] == is_array);
+ g_byte_array_set_size(writer->container_is_array, depth - 1);
+ writer->need_comma = true;
+}
+
+static bool in_object(JSONWriter *writer)
+{
+ unsigned depth = writer->container_is_array->len;
+
+ return depth && !writer->container_is_array->data[depth - 1];
+}
+
+static void pretty_newline(JSONWriter *writer)
+{
+ if (writer->pretty) {
+ g_string_append_printf(writer->contents, "\n%*s",
+ writer->container_is_array->len * 4, "");
+ }
+}
+
+static void pretty_newline_or_space(JSONWriter *writer)
+{
+ if (writer->pretty) {
+ g_string_append_printf(writer->contents, "\n%*s",
+ writer->container_is_array->len * 4, "");
+ } else {
+ g_string_append_c(writer->contents, ' ');
+ }
+}
+
+static void quoted_str(JSONWriter *writer, const char *str)
+{
+ const char *ptr;
+ char *end;
+ int cp;
+
+ g_string_append_c(writer->contents, '"');
+
+ for (ptr = str; *ptr; ptr = end) {
+ cp = mod_utf8_codepoint(ptr, 6, &end);
+ switch (cp) {
+ case '\"':
+ g_string_append(writer->contents, "\\\"");
+ break;
+ case '\\':
+ g_string_append(writer->contents, "\\\\");
+ break;
+ case '\b':
+ g_string_append(writer->contents, "\\b");
+ break;
+ case '\f':
+ g_string_append(writer->contents, "\\f");
+ break;
+ case '\n':
+ g_string_append(writer->contents, "\\n");
+ break;
+ case '\r':
+ g_string_append(writer->contents, "\\r");
+ break;
+ case '\t':
+ g_string_append(writer->contents, "\\t");
+ break;
+ default:
+ if (cp < 0) {
+ cp = 0xFFFD; /* replacement character */
+ }
+ if (cp > 0xFFFF) {
+ /* beyond BMP; need a surrogate pair */
+ g_string_append_printf(writer->contents, "\\u%04X\\u%04X",
+ 0xD800 + ((cp - 0x10000) >> 10),
+ 0xDC00 + ((cp - 0x10000) & 0x3FF));
+ } else if (cp < 0x20 || cp >= 0x7F) {
+ g_string_append_printf(writer->contents, "\\u%04X", cp);
+ } else {
+ g_string_append_c(writer->contents, cp);
+ }
+ }
+ };
+
+ g_string_append_c(writer->contents, '"');
+}
+
+static void maybe_comma_name(JSONWriter *writer, const char *name)
+{
+ if (writer->need_comma) {
+ g_string_append_c(writer->contents, ',');
+ pretty_newline_or_space(writer);
+ } else {
+ if (writer->contents->len) {
+ pretty_newline(writer);
+ }
+ writer->need_comma = true;
+ }
+
+ if (in_object(writer)) {
+ quoted_str(writer, name);
+ g_string_append(writer->contents, ": ");
+ }
+}
+
+void json_writer_start_object(JSONWriter *writer, const char *name)
+{
+ maybe_comma_name(writer, name);
+ g_string_append_c(writer->contents, '{');
+ enter_container(writer, false);
+}
+
+void json_writer_end_object(JSONWriter *writer)
+{
+ leave_container(writer, false);
+ pretty_newline(writer);
+ g_string_append_c(writer->contents, '}');
+}
+
+void json_writer_start_array(JSONWriter *writer, const char *name)
+{
+ maybe_comma_name(writer, name);
+ g_string_append_c(writer->contents, '[');
+ enter_container(writer, true);
+}
+
+void json_writer_end_array(JSONWriter *writer)
+{
+ leave_container(writer, true);
+ pretty_newline(writer);
+ g_string_append_c(writer->contents, ']');
+}
+
+void json_writer_bool(JSONWriter *writer, const char *name, bool val)
+{
+ maybe_comma_name(writer, name);
+ g_string_append(writer->contents, val ? "true" : "false");
+}
+
+void json_writer_null(JSONWriter *writer, const char *name)
+{
+ maybe_comma_name(writer, name);
+ g_string_append(writer->contents, "null");
+}
+
+void json_writer_int64(JSONWriter *writer, const char *name, int64_t val)
+{
+ maybe_comma_name(writer, name);
+ g_string_append_printf(writer->contents, "%" PRId64, val);
+}
+
+void json_writer_uint64(JSONWriter *writer, const char *name, uint64_t val)
+{
+ maybe_comma_name(writer, name);
+ g_string_append_printf(writer->contents, "%" PRIu64, val);
+}
+
+void json_writer_double(JSONWriter *writer, const char *name, double val)
+{
+ maybe_comma_name(writer, name);
+
+ /*
+ * FIXME: g_string_append_printf() is locale dependent; but JSON
+ * requires numbers to be formatted as if in the C locale.
+ * Dependence on C locale is a pervasive issue in QEMU.
+ */
+ /*
+ * FIXME: This risks printing Inf or NaN, which are not valid
+ * JSON values.
+ */
+ g_string_append_printf(writer->contents, "%.17g", val);
+}
+
+void json_writer_str(JSONWriter *writer, const char *name, const char *str)
+{
+ maybe_comma_name(writer, name);
+ quoted_str(writer, str);
+}
diff --git a/qobject/meson.build b/qobject/meson.build
index bb63c06b63..4683a852a2 100644
--- a/qobject/meson.build
+++ b/qobject/meson.build
@@ -1,3 +1,4 @@
-util_ss.add(files('qnull.c', 'qnum.c', 'qstring.c', 'qdict.c', 'qlist.c', 'qbool.c',
- 'qlit.c', 'qjson.c', 'qobject.c', 'json-lexer.c', 'json-streamer.c', 'json-parser.c',
+util_ss.add(files('qnull.c', 'qnum.c', 'qstring.c', 'qdict.c',
+ 'qlist.c', 'qbool.c', 'qlit.c', 'qjson.c', 'qobject.c',
+ 'json-writer.c', 'json-lexer.c', 'json-streamer.c', 'json-parser.c',
'block-qdict.c'))
diff --git a/qobject/qbool.c b/qobject/qbool.c
index 06dfc43498..16a600abb9 100644
--- a/qobject/qbool.c
+++ b/qobject/qbool.c
@@ -13,6 +13,7 @@
#include "qemu/osdep.h"
#include "qapi/qmp/qbool.h"
+#include "qobject-internal.h"
/**
* qbool_from_bool(): Create a new QBool from a bool
diff --git a/qobject/qdict.c b/qobject/qdict.c
index 1079bd3f6f..d84443391e 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -16,6 +16,7 @@
#include "qapi/qmp/qbool.h"
#include "qapi/qmp/qnull.h"
#include "qapi/qmp/qstring.h"
+#include "qobject-internal.h"
/**
* qdict_new(): Create a new QDict
diff --git a/qobject/qjson.c b/qobject/qjson.c
index f1f2c69704..bcc376e626 100644
--- a/qobject/qjson.c
+++ b/qobject/qjson.c
@@ -14,13 +14,13 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qapi/qmp/json-parser.h"
+#include "qapi/qmp/json-writer.h"
#include "qapi/qmp/qjson.h"
#include "qapi/qmp/qbool.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qlist.h"
#include "qapi/qmp/qnum.h"
#include "qapi/qmp/qstring.h"
-#include "qemu/unicode.h"
typedef struct JSONParsingState
{
@@ -149,144 +149,69 @@ QDict *qdict_from_jsonf_nofail(const char *string, ...)
return qdict;
}
-static void to_json(const QObject *obj, QString *str, int pretty, int indent);
-
-static void json_pretty_newline(QString *str, bool pretty, int indent)
-{
- int i;
-
- if (pretty) {
- qstring_append(str, "\n");
- for (i = 0; i < indent; i++) {
- qstring_append(str, " ");
- }
- }
-}
-
-static void to_json(const QObject *obj, QString *str, int pretty, int indent)
+static void to_json(JSONWriter *writer, const char *name,
+ const QObject *obj)
{
switch (qobject_type(obj)) {
case QTYPE_QNULL:
- qstring_append(str, "null");
+ json_writer_null(writer, name);
break;
case QTYPE_QNUM: {
QNum *val = qobject_to(QNum, obj);
- char *buffer = qnum_to_string(val);
- qstring_append(str, buffer);
- g_free(buffer);
+
+ switch (val->kind) {
+ case QNUM_I64:
+ json_writer_int64(writer, name, val->u.i64);
+ break;
+ case QNUM_U64:
+ json_writer_uint64(writer, name, val->u.u64);
+ break;
+ case QNUM_DOUBLE:
+ json_writer_double(writer, name, val->u.dbl);
+ break;
+ default:
+ abort();
+ }
break;
}
case QTYPE_QSTRING: {
QString *val = qobject_to(QString, obj);
- const char *ptr;
- int cp;
- char buf[16];
- char *end;
-
- ptr = qstring_get_str(val);
- qstring_append(str, "\"");
-
- for (; *ptr; ptr = end) {
- cp = mod_utf8_codepoint(ptr, 6, &end);
- switch (cp) {
- 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 (cp < 0) {
- cp = 0xFFFD; /* replacement character */
- }
- 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));
- } else if (cp < 0x20 || cp >= 0x7F) {
- snprintf(buf, sizeof(buf), "\\u%04X", cp);
- } else {
- buf[0] = cp;
- buf[1] = 0;
- }
- qstring_append(str, buf);
- }
- };
-
- qstring_append(str, "\"");
+
+ json_writer_str(writer, name, qstring_get_str(val));
break;
}
case QTYPE_QDICT: {
QDict *val = qobject_to(QDict, obj);
- const char *comma = pretty ? "," : ", ";
- const char *sep = "";
const QDictEntry *entry;
- QString *qkey;
- qstring_append(str, "{");
+ json_writer_start_object(writer, name);
for (entry = qdict_first(val);
entry;
entry = qdict_next(val, entry)) {
- qstring_append(str, sep);
- json_pretty_newline(str, pretty, indent + 1);
-
- qkey = qstring_from_str(qdict_entry_key(entry));
- to_json(QOBJECT(qkey), str, pretty, indent + 1);
- qobject_unref(qkey);
-
- qstring_append(str, ": ");
- to_json(qdict_entry_value(entry), str, pretty, indent + 1);
- sep = comma;
+ to_json(writer, qdict_entry_key(entry), qdict_entry_value(entry));
}
- json_pretty_newline(str, pretty, indent);
- qstring_append(str, "}");
+ json_writer_end_object(writer);
break;
}
case QTYPE_QLIST: {
QList *val = qobject_to(QList, obj);
- const char *comma = pretty ? "," : ", ";
- const char *sep = "";
QListEntry *entry;
- qstring_append(str, "[");
+ json_writer_start_array(writer, name);
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);
- sep = comma;
+ to_json(writer, NULL, qlist_entry_obj(entry));
}
- json_pretty_newline(str, pretty, indent);
- qstring_append(str, "]");
+ json_writer_end_array(writer);
break;
}
case QTYPE_QBOOL: {
QBool *val = qobject_to(QBool, obj);
- if (qbool_get_bool(val)) {
- qstring_append(str, "true");
- } else {
- qstring_append(str, "false");
- }
+ json_writer_bool(writer, name, qbool_get_bool(val));
break;
}
default:
@@ -294,20 +219,15 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent)
}
}
-QString *qobject_to_json(const QObject *obj)
+GString *qobject_to_json_pretty(const QObject *obj, bool pretty)
{
- QString *str = qstring_new();
-
- to_json(obj, str, 0, 0);
+ JSONWriter *writer = json_writer_new(pretty);
- return str;
+ to_json(writer, NULL, obj);
+ return json_writer_get_and_free(writer);
}
-QString *qobject_to_json_pretty(const QObject *obj)
+GString *qobject_to_json(const QObject *obj)
{
- QString *str = qstring_new();
-
- to_json(obj, str, 1, 0);
-
- return str;
+ return qobject_to_json_pretty(obj, false);
}
diff --git a/qobject/qlist.c b/qobject/qlist.c
index 1be95367d1..60562a1f52 100644
--- a/qobject/qlist.c
+++ b/qobject/qlist.c
@@ -17,6 +17,7 @@
#include "qapi/qmp/qnum.h"
#include "qapi/qmp/qstring.h"
#include "qemu/queue.h"
+#include "qobject-internal.h"
/**
* qlist_new(): Create a new QList
diff --git a/qobject/qnull.c b/qobject/qnull.c
index 00870a1824..b26b368219 100644
--- a/qobject/qnull.c
+++ b/qobject/qnull.c
@@ -12,6 +12,7 @@
#include "qemu/osdep.h"
#include "qapi/qmp/qnull.h"
+#include "qobject-internal.h"
QNull qnull_ = {
.base = {
diff --git a/qobject/qnum.c b/qobject/qnum.c
index 7012fc57f2..5dd66938dd 100644
--- a/qobject/qnum.c
+++ b/qobject/qnum.c
@@ -14,6 +14,7 @@
#include "qemu/osdep.h"
#include "qapi/qmp/qnum.h"
+#include "qobject-internal.h"
/**
* qnum_from_int(): Create a new QNum from an int64_t
@@ -161,37 +162,14 @@ double qnum_get_double(QNum *qn)
char *qnum_to_string(QNum *qn)
{
- char *buffer;
- int len;
-
switch (qn->kind) {
case QNUM_I64:
return g_strdup_printf("%" PRId64, qn->u.i64);
case QNUM_U64:
return g_strdup_printf("%" PRIu64, qn->u.u64);
case QNUM_DOUBLE:
- /* FIXME: snprintf() is locale dependent; but JSON requires
- * numbers to be formatted as if in the C locale. Dependence
- * on C locale is a pervasive issue in QEMU. */
- /* FIXME: This risks printing Inf or NaN, which are not valid
- * JSON values. */
- /* FIXME: the default precision of 6 for %f often causes
- * rounding errors; we should be using DBL_DECIMAL_DIG (17),
- * and only rounding to a shorter number if the result would
- * still produce the same floating point value. */
- buffer = g_strdup_printf("%f" , qn->u.dbl);
- len = strlen(buffer);
- while (len > 0 && buffer[len - 1] == '0') {
- len--;
- }
-
- if (len && buffer[len - 1] == '.') {
- buffer[len - 1] = 0;
- } else {
- buffer[len] = 0;
- }
-
- return buffer;
+ /* 17 digits suffice for IEEE double */
+ return g_strdup_printf("%.17g", qn->u.dbl);
}
assert(0);
diff --git a/qobject/qobject-internal.h b/qobject/qobject-internal.h
new file mode 100644
index 0000000000..b310c8e1b5
--- /dev/null
+++ b/qobject/qobject-internal.h
@@ -0,0 +1,39 @@
+/*
+ * QObject internals
+ *
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * 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.
+ */
+
+#ifndef QOBJECT_INTERNAL_H
+#define QOBJECT_INTERNAL_H
+
+#include "qapi/qmp/qobject.h"
+
+static inline void qobject_init(QObject *obj, QType type)
+{
+ assert(QTYPE_NONE < type && type < QTYPE__MAX);
+ obj->base.refcnt = 1;
+ obj->base.type = type;
+}
+
+void qbool_destroy_obj(QObject *obj);
+bool qbool_is_equal(const QObject *x, const QObject *y);
+
+void qdict_destroy_obj(QObject *obj);
+bool qdict_is_equal(const QObject *x, const QObject *y);
+
+void qlist_destroy_obj(QObject *obj);
+bool qlist_is_equal(const QObject *x, const QObject *y);
+
+bool qnull_is_equal(const QObject *x, const QObject *y);
+
+void qnum_destroy_obj(QObject *obj);
+bool qnum_is_equal(const QObject *x, const QObject *y);
+
+void qstring_destroy_obj(QObject *obj);
+bool qstring_is_equal(const QObject *x, const QObject *y);
+
+#endif
diff --git a/qobject/qobject.c b/qobject/qobject.c
index 878dd76e79..d7077b8f2a 100644
--- a/qobject/qobject.c
+++ b/qobject/qobject.c
@@ -14,6 +14,7 @@
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qlist.h"
#include "qapi/qmp/qstring.h"
+#include "qobject-internal.h"
QEMU_BUILD_BUG_MSG(
offsetof(QNull, base) != 0 ||
diff --git a/qobject/qstring.c b/qobject/qstring.c
index b66a2c35f2..b4613899b9 100644
--- a/qobject/qstring.c
+++ b/qobject/qstring.c
@@ -12,6 +12,7 @@
#include "qemu/osdep.h"
#include "qapi/qmp/qstring.h"
+#include "qobject-internal.h"
/**
* qstring_new(): Create a new empty QString
@@ -24,14 +25,6 @@ QString *qstring_new(void)
}
/**
- * qstring_get_length(): Get the length of a QString
- */
-size_t qstring_get_length(const QString *qstring)
-{
- return qstring->length;
-}
-
-/**
* qstring_from_substr(): Create a new QString from a C string substring
*
* Return string reference
@@ -41,18 +34,9 @@ QString *qstring_from_substr(const char *str, size_t start, size_t end)
QString *qstring;
assert(start <= end);
-
qstring = g_malloc(sizeof(*qstring));
qobject_init(QOBJECT(qstring), QTYPE_QSTRING);
-
- qstring->length = end - start;
- qstring->capacity = qstring->length;
-
- assert(qstring->capacity < SIZE_MAX);
- qstring->string = g_malloc(qstring->capacity + 1);
- memcpy(qstring->string, str + start, qstring->length);
- qstring->string[qstring->length] = 0;
-
+ qstring->string = g_strndup(str + start, end - start);
return qstring;
}
@@ -66,47 +50,22 @@ QString *qstring_from_str(const char *str)
return qstring_from_substr(str, 0, strlen(str));
}
-static void capacity_increase(QString *qstring, size_t len)
-{
- if (qstring->capacity < (qstring->length + len)) {
- assert(len <= SIZE_MAX - qstring->capacity);
- qstring->capacity += len;
- assert(qstring->capacity <= SIZE_MAX / 2);
- qstring->capacity *= 2; /* use exponential growth */
-
- qstring->string = g_realloc(qstring->string, qstring->capacity + 1);
- }
-}
-
-/* qstring_append(): Append a C string to a QString
+/**
+ * qstring_from_gstring(): Convert a GString to a QString
+ *
+ * Return strong reference.
*/
-void qstring_append(QString *qstring, const char *str)
-{
- size_t len = strlen(str);
-
- capacity_increase(qstring, len);
- memcpy(qstring->string + qstring->length, str, len);
- qstring->length += len;
- qstring->string[qstring->length] = 0;
-}
-void qstring_append_int(QString *qstring, int64_t value)
+QString *qstring_from_gstring(GString *gstr)
{
- char num[32];
+ QString *qstring;
- snprintf(num, sizeof(num), "%" PRId64, value);
- qstring_append(qstring, num);
+ qstring = g_malloc(sizeof(*qstring));
+ qobject_init(QOBJECT(qstring), QTYPE_QSTRING);
+ qstring->string = g_string_free(gstr, false);
+ return qstring;
}
-/**
- * qstring_append_chr(): Append a C char to a QString
- */
-void qstring_append_chr(QString *qstring, int c)
-{
- capacity_increase(qstring, 1);
- qstring->string[qstring->length++] = c;
- qstring->string[qstring->length] = 0;
-}
/**
* qstring_get_str(): Return a pointer to the stored string
@@ -120,27 +79,6 @@ const char *qstring_get_str(const QString *qstring)
}
/**
- * qstring_get_try_str(): Return a pointer to the stored string
- *
- * NOTE: will return NULL if qstring is not provided.
- */
-const char *qstring_get_try_str(const QString *qstring)
-{
- return qstring ? qstring_get_str(qstring) : NULL;
-}
-
-/**
- * qobject_get_try_str(): Return a pointer to the corresponding string
- *
- * NOTE: the string will only be returned if the object is valid, and
- * its type is QString, otherwise NULL is returned.
- */
-const char *qobject_get_try_str(const QObject *qstring)
-{
- return qstring_get_try_str(qobject_to(QString, qstring));
-}
-
-/**
* qstring_is_equal(): Test whether the two QStrings are equal
*/
bool qstring_is_equal(const QObject *x, const QObject *y)
@@ -150,32 +88,15 @@ bool qstring_is_equal(const QObject *x, const QObject *y)
}
/**
- * qstring_free(): Free the memory allocated by a QString object
- *
- * Return: if @return_str, return the underlying string, to be
- * g_free(), otherwise NULL is returned.
- */
-char *qstring_free(QString *qstring, bool return_str)
-{
- char *rv = NULL;
-
- if (return_str) {
- rv = qstring->string;
- } else {
- g_free(qstring->string);
- }
-
- g_free(qstring);
-
- return rv;
-}
-
-/**
* qstring_destroy_obj(): Free all memory allocated by a QString
* object
*/
void qstring_destroy_obj(QObject *obj)
{
+ QString *qs;
+
assert(obj != NULL);
- qstring_free(qobject_to(QString, obj), FALSE);
+ qs = qobject_to(QString, obj);
+ g_free((char *)qs->string);
+ g_free(qs);
}