qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH v3.2 27/31] qapi: make string input visitor pars


From: Michael S. Tsirkin
Subject: Re: [Qemu-devel] [PATCH v3.2 27/31] qapi: make string input visitor parse int list
Date: Sun, 8 Jun 2014 13:11:03 +0300

On Wed, May 14, 2014 at 05:43:31PM +0800, Hu Tao wrote:
> Signed-off-by: Hu Tao <address@hidden>


Conflicts with
commit e2cd0f4fb42b1fae65ad22e8efde9804446e6254
    qapi: Replace start_optional()/end_optional() by optional()

needs a rebase.

> ---
>  qapi/string-input-visitor.c       | 181 
> ++++++++++++++++++++++++++++++++++++--
>  tests/test-string-input-visitor.c |  39 ++++++++
>  2 files changed, 212 insertions(+), 8 deletions(-)
> 
> diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
> index 793548a..0f6add7 100644
> --- a/qapi/string-input-visitor.c
> +++ b/qapi/string-input-visitor.c
> @@ -15,31 +15,182 @@
>  #include "qapi/visitor-impl.h"
>  #include "qapi/qmp/qerror.h"
>  #include "qemu/option.h"
> +#include "qemu/queue.h"
> +#include "qemu/range.h"
> +
>  
>  struct StringInputVisitor
>  {
>      Visitor visitor;
> +
> +    bool head;
> +
> +    SignedRangeList *ranges;
> +    SignedRange *cur_range;
> +    int64_t cur;
> +
>      const char *string;
>  };
>  
> +static void parse_str(StringInputVisitor *siv, Error **errp)
> +{
> +    char *str = (char *) siv->string;
> +    long long start, end;
> +    SignedRange *r, *next;
> +    char *endptr;
> +
> +    if (siv->ranges) {
> +        return;
> +    }
> +
> +    siv->ranges = g_malloc0(sizeof(*siv->ranges));
> +    QTAILQ_INIT(siv->ranges);
> +    errno = 0;
> +    do {
> +        start = strtoll(str, &endptr, 0);
> +        if (errno == 0 && endptr > str && INT64_MIN <= start &&
> +            start <= INT64_MAX) {
> +            if (*endptr == '\0') {
> +                if (!range_list_add(siv->ranges, start, 1)) {
> +                    goto error;
> +                }
> +                str = NULL;
> +            } else if (*endptr == '-') {
> +                str = endptr + 1;
> +                end = strtoll(str, &endptr, 0);
> +                if (errno == 0 && endptr > str &&
> +                    INT64_MIN <= end && end <= INT64_MAX && start <= end &&
> +                    (start > INT64_MAX - 65536 ||
> +                     end < start + 65536)) {
> +                    if (*endptr == '\0') {
> +                        if (!range_list_add(siv->ranges, start,
> +                                            end - start + 1)) {
> +                            goto error;
> +                        }
> +                        str = NULL;
> +                    } else if (*endptr == ',') {
> +                        str = endptr + 1;
> +                        if (!range_list_add(siv->ranges, start,
> +                                            end - start + 1)) {
> +                            goto error;
> +                        }
> +                    } else {
> +                        goto error;
> +                    }
> +                } else {
> +                    goto error;
> +                }
> +            } else if (*endptr == ',') {
> +                str = endptr + 1;
> +                if (!range_list_add(siv->ranges, start, 1)) {
> +                    goto error;
> +                }
> +            } else {
> +                goto error;
> +            }
> +        } else {
> +            goto error;
> +        }
> +    } while (str);
> +
> +    return;
> +error:
> +    if (siv->ranges) {
> +        QTAILQ_FOREACH_SAFE(r, siv->ranges, entry, next) {
> +            QTAILQ_REMOVE(siv->ranges, r, entry);
> +            g_free(r);
> +        }
> +        g_free(siv->ranges);
> +        siv->ranges = NULL;
> +    }
> +}
> +
> +static void
> +start_list(Visitor *v, const char *name, Error **errp)
> +{
> +    StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
> +
> +    parse_str(siv, errp);
> +
> +    if (siv->ranges) {
> +        siv->cur_range = QTAILQ_FIRST(siv->ranges);
> +        if (siv->cur_range) {
> +            siv->cur = siv->cur_range->start;
> +        }
> +    }
> +}
> +
> +static GenericList *
> +next_list(Visitor *v, GenericList **list, Error **errp)
> +{
> +    StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
> +    GenericList **link;
> +
> +    if (!siv->ranges || !siv->cur_range) {
> +        return NULL;
> +    }
> +
> +    if (siv->cur < siv->cur_range->start ||
> +        siv->cur >= (siv->cur_range->start + siv->cur_range->length)) {
> +        siv->cur_range = QTAILQ_NEXT(siv->cur_range, entry);
> +        if (siv->cur_range) {
> +            siv->cur = siv->cur_range->start;
> +        } else {
> +            return NULL;
> +        }
> +    }
> +
> +    if (siv->head) {
> +        link = list;
> +        siv->head = false;
> +    } else {
> +        link = &(*list)->next;
> +    }
> +
> +    *link = g_malloc0(sizeof **link);
> +    return *link;
> +}
> +
> +static void
> +end_list(Visitor *v, Error **errp)
> +{
> +    StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
> +    siv->head = true;
> +}
> +
>  static void parse_type_int(Visitor *v, int64_t *obj, const char *name,
>                             Error **errp)
>  {
>      StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
> -    char *endp = (char *) siv->string;
> -    long long val;
>  
> -    errno = 0;
> -    if (siv->string) {
> -        val = strtoll(siv->string, &endp, 0);
> -    }
> -    if (!siv->string || errno || endp == siv->string || *endp) {
> +    if (!siv->string) {
>          error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
>                    "integer");
>          return;
>      }
>  
> -    *obj = val;
> +    parse_str(siv, errp);
> +
> +    if (!siv->ranges) {
> +        goto error;
> +    }
> +
> +    if (!siv->cur_range) {
> +        siv->cur_range = QTAILQ_FIRST(siv->ranges);
> +        if (siv->cur_range) {
> +            siv->cur = siv->cur_range->start;
> +        } else {
> +            goto error;
> +        }
> +    }
> +
> +    *obj = siv->cur;
> +    siv->cur++;
> +    return;
> +
> +error:
> +    error_set(errp, QERR_INVALID_PARAMETER_VALUE, name,
> +              "an int64 value or range");
>  }
>  
>  static void parse_type_size(Visitor *v, uint64_t *obj, const char *name,
> @@ -140,6 +291,16 @@ Visitor *string_input_get_visitor(StringInputVisitor *v)
>  
>  void string_input_visitor_cleanup(StringInputVisitor *v)
>  {
> +    SignedRange *r, *next;
> +
> +    if (v->ranges) {
> +        QTAILQ_FOREACH_SAFE(r, v->ranges, entry, next) {
> +            QTAILQ_REMOVE(v->ranges, r, entry);
> +            g_free(r);
> +        }
> +        g_free(v->ranges);
> +    }
> +
>      g_free(v);
>  }
>  
> @@ -155,8 +316,12 @@ StringInputVisitor *string_input_visitor_new(const char 
> *str)
>      v->visitor.type_bool = parse_type_bool;
>      v->visitor.type_str = parse_type_str;
>      v->visitor.type_number = parse_type_number;
> +    v->visitor.start_list = start_list;
> +    v->visitor.next_list = next_list;
> +    v->visitor.end_list = end_list;
>      v->visitor.start_optional = parse_start_optional;
>  
>      v->string = str;
> +    v->head = true;
>      return v;
>  }
> diff --git a/tests/test-string-input-visitor.c 
> b/tests/test-string-input-visitor.c
> index 877e737..05b3dab 100644
> --- a/tests/test-string-input-visitor.c
> +++ b/tests/test-string-input-visitor.c
> @@ -64,6 +64,35 @@ static void test_visitor_in_int(TestInputVisitorData *data,
>      g_assert_cmpint(res, ==, value);
>  }
>  
> +static void test_visitor_in_intList(TestInputVisitorData *data,
> +                                    const void *unused)
> +{
> +    int64_t value[] = {-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20};
> +    int16List *res = NULL, *tmp;
> +    Error *errp = NULL;
> +    Visitor *v;
> +    int i = 0;
> +
> +    v = visitor_input_test_init(data, "1,2,-2-1,2-4,20,5-9,1-8");
> +
> +    visit_type_int16List(v, &res, NULL, &errp);
> +    g_assert(!error_is_set(&errp));
> +    tmp = res;
> +    while (i < sizeof(value) / sizeof(value[0])) {
> +        g_assert(tmp);
> +        g_assert_cmpint(tmp->value, ==, value[i++]);
> +        tmp = tmp->next;
> +    }
> +    g_assert(!tmp);
> +
> +    tmp = res;
> +    while (tmp) {
> +        res = res->next;
> +        g_free(tmp);
> +        tmp = res;
> +    }
> +}
> +
>  static void test_visitor_in_bool(TestInputVisitorData *data,
>                                   const void *unused)
>  {
> @@ -170,6 +199,7 @@ static void test_visitor_in_fuzz(TestInputVisitorData 
> *data,
>                                   const void *unused)
>  {
>      int64_t ires;
> +    intList *ilres;
>      bool bres;
>      double nres;
>      char *sres;
> @@ -193,6 +223,11 @@ static void test_visitor_in_fuzz(TestInputVisitorData 
> *data,
>  
>          v = visitor_input_test_init(data, buf);
>          visit_type_int(v, &ires, NULL, NULL);
> +        visitor_input_teardown(data, NULL);
> +
> +        v = visitor_input_test_init(data, buf);
> +        visit_type_intList(v, &ilres, NULL, NULL);
> +        visitor_input_teardown(data, NULL);
>  
>          v = visitor_input_test_init(data, buf);
>          visit_type_bool(v, &bres, NULL, NULL);
> @@ -200,11 +235,13 @@ static void test_visitor_in_fuzz(TestInputVisitorData 
> *data,
>  
>          v = visitor_input_test_init(data, buf);
>          visit_type_number(v, &nres, NULL, NULL);
> +        visitor_input_teardown(data, NULL);
>  
>          v = visitor_input_test_init(data, buf);
>          sres = NULL;
>          visit_type_str(v, &sres, NULL, NULL);
>          g_free(sres);
> +        visitor_input_teardown(data, NULL);
>  
>          v = visitor_input_test_init(data, buf);
>          visit_type_EnumOne(v, &eres, NULL, NULL);
> @@ -228,6 +265,8 @@ int main(int argc, char **argv)
>  
>      input_visitor_test_add("/string-visitor/input/int",
>                             &in_visitor_data, test_visitor_in_int);
> +    input_visitor_test_add("/string-visitor/input/intList",
> +                           &in_visitor_data, test_visitor_in_intList);
>      input_visitor_test_add("/string-visitor/input/bool",
>                             &in_visitor_data, test_visitor_in_bool);
>      input_visitor_test_add("/string-visitor/input/number",
> -- 
> 1.8.5.2.229.g4448466
> 



reply via email to

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