qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 4/7] add mutable qstring functions


From: Anthony Liguori
Subject: Re: [Qemu-devel] [PATCH 4/7] add mutable qstring functions
Date: Sat, 17 Oct 2009 08:03:11 -0500
User-agent: Thunderbird 2.0.0.23 (X11/20090825)

Paolo Bonzini wrote:
qemu does not have a string buffer object, so I added this capability
to QString.

Cc: Luiz Capitulino <address@hidden>
Signed-off-by: Paolo Bonzini <address@hidden>
---
 check-qstring.c |   79 ++++++++++++++++++++++++++++++++++++++++-
 qstring.c       |  105 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 qstring.h       |    5 +++
 3 files changed, 186 insertions(+), 3 deletions(-)

diff --git a/check-qstring.c b/check-qstring.c
index ea4dfd0..842cd7f 100644
--- a/check-qstring.c
+++ b/check-qstring.c
@@ -17,6 +17,23 @@
  * (with some violations to access 'private' data)
  */
+START_TEST(qstring_new_test)
+{
+    QString *qstring;
+
+    qstring = qstring_new();
+    fail_unless(qstring != NULL);
+    fail_unless(qstring->base.refcnt == 1);
+    fail_unless(qstring->n == 0);
+    fail_unless(qstring->alloc < 1000);
+    fail_unless(qobject_type(QOBJECT(qstring)) == QTYPE_QSTRING);
+
+    // destroy doesn't exit yet
+    qemu_free(qstring->string);
+    qemu_free(qstring);
+}
+END_TEST
+
 START_TEST(qstring_from_str_test)
 {
     QString *qstring;
@@ -25,7 +42,9 @@ START_TEST(qstring_from_str_test)
     qstring = qstring_from_str(str);
     fail_unless(qstring != NULL);
     fail_unless(qstring->base.refcnt == 1);
-    fail_unless(strcmp(str, qstring->string) == 0);
+    fail_unless(qstring->n == 4);
+    fail_unless(qstring->alloc >= 4);
+    fail_unless(memcmp(str, qstring->string, 4) == 0);
     fail_unless(qobject_type(QOBJECT(qstring)) == QTYPE_QSTRING);
// destroy doesn't exit yet
@@ -55,6 +74,60 @@ START_TEST(qstring_get_str_test)
 }
 END_TEST
+START_TEST(qstring_append_test)
+{
+    QString *qstring;
+    const char *str = "QEM";
+    const char *longstr = "QEMUQEMUQEMUQEMUQEMUQEMUQEMUQEMUQEMUQEMU";
+
+    qstring = qstring_from_str(str);
+    qstring_append(qstring, "U");
+    fail_unless(qstring->n == 4);
+    fail_unless(qstring->alloc >= 4);
+    fail_unless(memcmp(longstr, qstring->string, 4) == 0);
+
+    qstring_append(qstring, "Q");
+    fail_unless(qstring->n == 5);
+    fail_unless(qstring->alloc >= 5);
+    fail_unless(memcmp(longstr, qstring->string, 5) == 0);
+
+    qstring_append(qstring, longstr + 5);
+    fail_unless(qstring->n == strlen (longstr));
+    fail_unless(qstring->alloc >= qstring->n);
+    fail_unless(memcmp(longstr, qstring->string, qstring->n) == 0);
+    QDECREF(qstring);
+}
+END_TEST
+
+START_TEST(qstring_append_ch_test)
+{
+    QString *qstring;
+    const char *str = "QEM";
+
+    qstring = qstring_from_str(str);
+    qstring_append_ch(qstring, 'U');
+    fail_unless(qstring->n == 4);
+    fail_unless(qstring->alloc >= 4);
+    fail_unless(memcmp("QEMU", qstring->string, 4) == 0);
+    QDECREF(qstring);
+}
+END_TEST
+
+START_TEST(qstring_append_escaped_test)
+{
+    QString *qstring;
+    const char *str = "\"Q\x0EMU\t";
+    const char *result = "\\\"Q\\u000eMU\\t";
+
+    qstring = qstring_new();
+    qstring_append_escaped(qstring, str);
+    fail_unless(qstring->n == strlen (result));
+    fail_unless(qstring->alloc >= qstring->n);
+    fail_unless(memcmp(result, qstring->string, strlen (result)) == 0);
+    QDECREF(qstring);
+}
+END_TEST
+
 START_TEST(qobject_to_qstring_test)
 {
     QString *qstring;
@@ -75,9 +148,13 @@ static Suite *qstring_suite(void)
qstring_public_tcase = tcase_create("Public Interface");
     suite_add_tcase(s, qstring_public_tcase);
+    tcase_add_test(qstring_public_tcase, qstring_new_test);
     tcase_add_test(qstring_public_tcase, qstring_from_str_test);
     tcase_add_test(qstring_public_tcase, qstring_destroy_test);
     tcase_add_test(qstring_public_tcase, qstring_get_str_test);
+    tcase_add_test(qstring_public_tcase, qstring_append_test);
+    tcase_add_test(qstring_public_tcase, qstring_append_ch_test);
+    tcase_add_test(qstring_public_tcase, qstring_append_escaped_test);
     tcase_add_test(qstring_public_tcase, qobject_to_qstring_test);
return s;
diff --git a/qstring.c b/qstring.c
index 6d411da..ab77fba 100644
--- a/qstring.c
+++ b/qstring.c
@@ -21,6 +21,29 @@ static const QType qstring_type = {
 };
/**
+ * Invariant: all strings have an empty byte at the end so that
+ * it is easy to convert them to C strings.
+ */
+
+
+/**
+ * qstring_new(): Create a new empty QString
+ *
+ * Return strong reference.
+ */
+QString *qstring_new(void)
+{
+    QString *qstring;
+    qstring = qemu_malloc(sizeof(*qstring));
+    qstring->n = 0;
+    qstring->alloc = 16;
+    qstring->string = qemu_malloc(qstring->alloc);
+    QOBJECT_INIT(qstring, &qstring_type);
+
+    return qstring;
+}
+
+/**
  * qstring_from_str(): Create a new QString from a regular C string
  *
  * Return strong reference.
@@ -28,15 +51,91 @@ static const QType qstring_type = {
 QString *qstring_from_str(const char *str)
 {
     QString *qstring;
+    size_t n = strlen(str);
qstring = qemu_malloc(sizeof(*qstring));
-    qstring->string = qemu_strdup(str);
+    qstring->n = n;
+    qstring->alloc = n + 1;
+    qstring->string = qemu_memdup(str, qstring->alloc);
     QOBJECT_INIT(qstring, &qstring_type);
return qstring;
 }
/**
+ * qstring_append(): Append a regular C string to a QString
+ */
+void qstring_append(QString *qstring, const char *str)
+{
+    size_t n = strlen(str);
+    size_t total = qstring->n + n + 1;
+
+    if (total > qstring->alloc) {
+        if (qstring->alloc * 2 < total) {
+            qstring->alloc = total;
+        } else {
+            qstring->alloc *= 2;
+        }
+        qstring->string = qemu_realloc (qstring->string, qstring->alloc);
+    }
+    memcpy (qstring->string + qstring->n, str, n + 1);
+    qstring->n += n;
+}
+
+/**
+ * qstring_append(): Append a regular C string to a QString, escaping it
+ * according to JSON syntax.
+ */
+void qstring_append_escaped(QString *qstring, const char *str)
+{
+    for (; *str; str++) {
+        unsigned char ch = *str;
+        switch (*str) {
+        case '\f': ch = 'f'; goto backslash;
+        case '\n': ch = 'n'; goto backslash;
+        case '\r': ch = 'r'; goto backslash;
+        case '\t': ch = 't'; goto backslash;
+        case '\b': ch = 'b'; goto backslash;
+
+        backslash:
+        case '\\':
+        case '\"':
+            qstring_append_ch (qstring, '\\');
+            break;
+
+        default:
+            if (ch < 0x20) {
+                    qstring_append_ch (qstring, '\\');
+                    qstring_append_ch (qstring, 'u');
+                    qstring_append_ch (qstring, '0');
+                    qstring_append_ch (qstring, '0');
+                    qstring_append_ch (qstring, '0' + (ch >> 4));
+                    ch = (ch & 15) + ((ch & 15) > 9 ? 'a' - 10 : '0');
+            }
+            break;
+        }
+
+        qstring_append_ch (qstring, ch);
+    }
+}


The json parser should do the escaping.

Regards,

Anthony Liguori




reply via email to

[Prev in Thread] Current Thread [Next in Thread]