[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v5 14/16] qapi: make string input visitor parse int
From: |
Hu Tao |
Subject: |
[Qemu-devel] [PATCH v5 14/16] qapi: make string input visitor parse int list |
Date: |
Tue, 10 Jun 2014 19:15:27 +0800 |
Signed-off-by: Hu Tao <address@hidden>
---
qapi/string-input-visitor.c | 181 ++++++++++++++++++++++++++++++++++++--
tests/test-string-input-visitor.c | 36 ++++++++
2 files changed, 209 insertions(+), 8 deletions(-)
diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
index 5780944..85ac6a1 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.optional = parse_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 01a78f0..b08a7db 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(errp == NULL);
+ 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;
@@ -196,6 +226,10 @@ static void test_visitor_in_fuzz(TestInputVisitorData
*data,
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);
visitor_input_teardown(data, NULL);
@@ -231,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.9.3
- [Qemu-devel] [PATCH v5 07/16] fixup! numa: add -numa node, memdev= option, (continued)
- [Qemu-devel] [PATCH v5 07/16] fixup! numa: add -numa node, memdev= option, Hu Tao, 2014/06/10
- [Qemu-devel] [PATCH v5 08/16] hostmem: add file-based HostMemoryBackend, Hu Tao, 2014/06/10
- [Qemu-devel] [PATCH v5 09/16] hostmem: add merge and dump properties, Hu Tao, 2014/06/10
- [Qemu-devel] [PATCH v5 10/16] hostmem: allow preallocation of any memory region, Hu Tao, 2014/06/10
- [Qemu-devel] [PATCH v5 11/16] hostmem: add property to map memory with MAP_SHARED, Hu Tao, 2014/06/10
- [Qemu-devel] [PATCH v5 12/16] hostmem: add properties for NUMA memory policy, Hu Tao, 2014/06/10
- [Qemu-devel] [PATCH v5 13/16] tests: fix memory leak in test of string input visitor, Hu Tao, 2014/06/10
- [Qemu-devel] [PATCH v5 14/16] qapi: make string input visitor parse int list,
Hu Tao <=
- [Qemu-devel] [PATCH v5 15/16] qapi: make string output visitor parse int list, Hu Tao, 2014/06/10
- [Qemu-devel] [PATCH v5 16/16] qmp: add query-memdev, Hu Tao, 2014/06/10
- Re: [Qemu-devel] [PATCH v5 00/16] NUMA series v5, Michael S. Tsirkin, 2014/06/12
- Re: [Qemu-devel] [PATCH v5 00/16] NUMA series v5, Hu Tao, 2014/06/12
- Re: [Qemu-devel] [PATCH v5 00/16] NUMA series v5, Michael S. Tsirkin, 2014/06/13
- Re: [Qemu-devel] [PATCH v5 00/16] NUMA series v5, Paolo Bonzini, 2014/06/13
- Re: [Qemu-devel] [PATCH v5 00/16] NUMA series v5, Michael S. Tsirkin, 2014/06/13
- Re: [Qemu-devel] [PATCH v5 00/16] NUMA series v5, Hu Tao, 2014/06/13
- Re: [Qemu-devel] [PATCH v5 00/16] NUMA series v5, Michael S. Tsirkin, 2014/06/13
- [Qemu-devel] [PATCH RFC 0/4] fixes for pci tree, Hu Tao, 2014/06/14