From: Anthony Liguori <anthony@codemonkey.ws>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: qemu-devel@nongnu.org, Luiz Capitulino <lcapitulino@redhat.com>
Subject: Re: [Qemu-devel] [PATCH 4/7] add mutable qstring functions
Date: Sat, 17 Oct 2009 08:03:11 -0500 [thread overview]
Message-ID: <4AD9C08F.20108@codemonkey.ws> (raw)
In-Reply-To: <1255766136-3028-5-git-send-email-pbonzini@redhat.com>
Paolo Bonzini wrote:
> qemu does not have a string buffer object, so I added this capability
> to QString.
>
> Cc: Luiz Capitulino <lcapitulino@redhat.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> 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
next prev parent reply other threads:[~2009-10-17 13:03 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-10-17 7:55 [Qemu-devel] [PATCH 0/7] Add JSON enconding and formatted printing to QObject Paolo Bonzini
2009-10-17 7:55 ` [Qemu-devel] [PATCH 1/7] add qemu_memdup Paolo Bonzini
2009-10-17 7:55 ` [Qemu-devel] [PATCH 2/7] allow passing NULL to qobject_type Paolo Bonzini
2009-10-17 7:55 ` [Qemu-devel] [PATCH 3/7] forward declare all QObject subclasses in qobject.h Paolo Bonzini
2009-10-17 13:02 ` Anthony Liguori
2009-10-17 7:55 ` [Qemu-devel] [PATCH 4/7] add mutable qstring functions Paolo Bonzini
2009-10-17 13:03 ` Anthony Liguori [this message]
2009-10-17 7:55 ` [Qemu-devel] [PATCH 5/7] add json encoder for qobjects Paolo Bonzini
2009-10-17 13:03 ` Anthony Liguori
2009-10-17 13:44 ` Paolo Bonzini
2009-10-17 16:20 ` Anthony Liguori
2009-10-17 7:55 ` [Qemu-devel] [PATCH 6/7] add testsuite for qobject json encoder Paolo Bonzini
2009-10-17 7:55 ` [Qemu-devel] [PATCH 7/7] add formatted printing of QObjects Paolo Bonzini
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=4AD9C08F.20108@codemonkey.ws \
--to=anthony@codemonkey.ws \
--cc=lcapitulino@redhat.com \
--cc=pbonzini@redhat.com \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.