From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Mz8wM-0002rx-Nw for qemu-devel@nongnu.org; Sat, 17 Oct 2009 09:03:22 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Mz8wI-0002qi-2u for qemu-devel@nongnu.org; Sat, 17 Oct 2009 09:03:21 -0400 Received: from [199.232.76.173] (port=37939 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Mz8wF-0002qA-2x for qemu-devel@nongnu.org; Sat, 17 Oct 2009 09:03:16 -0400 Received: from mail-qy0-f194.google.com ([209.85.221.194]:62482) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1Mz8wE-0003f0-GS for qemu-devel@nongnu.org; Sat, 17 Oct 2009 09:03:14 -0400 Received: by qyk32 with SMTP id 32so1982469qyk.4 for ; Sat, 17 Oct 2009 06:03:14 -0700 (PDT) Message-ID: <4AD9C08F.20108@codemonkey.ws> Date: Sat, 17 Oct 2009 08:03:11 -0500 From: Anthony Liguori MIME-Version: 1.0 Subject: Re: [Qemu-devel] [PATCH 4/7] add mutable qstring functions References: <1255766136-3028-1-git-send-email-pbonzini@redhat.com> <1255766136-3028-5-git-send-email-pbonzini@redhat.com> In-Reply-To: <1255766136-3028-5-git-send-email-pbonzini@redhat.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Paolo Bonzini Cc: qemu-devel@nongnu.org, Luiz Capitulino Paolo Bonzini wrote: > qemu does not have a string buffer object, so I added this capability > to QString. > > Cc: Luiz Capitulino > Signed-off-by: Paolo Bonzini > --- > 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