aboutsummaryrefslogtreecommitdiff
path: root/qapi/string-input-visitor.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-06-20 18:01:24 +0100
committerPeter Maydell <peter.maydell@linaro.org>2014-06-20 18:01:24 +0100
commit0a99aae5fab5ed260aab96049c274b0334eb4085 (patch)
tree7db67e570b622a37a2139da871b79b0386942e4b /qapi/string-input-visitor.c
parent53001c148340127c2dca1f90329804cd0ac0e236 (diff)
parent705456c0d7f24fbd76733c891525b8eeea332e8b (diff)
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pc,pci,virtio,hotplug fixes, enhancements numa work by Hu Tao and others memory hotplug by Igor vhost-user by Nikolay, Antonios and others guest virtio announcements by Jason qtest fixes by Sergey qdev hotplug fixes by Paolo misc other fixes mostly by myself Signed-off-by: Michael S. Tsirkin <mst@redhat.com> * remotes/mst/tags/for_upstream: (109 commits) numa: use RAM_ADDR_FMT with ram_addr_t qapi/string-output-visitor: fix bugs tests: simplify code qapi: fix input visitor bugs acpi: rephrase comment qmp: add ACPI_DEVICE_OST event handling qmp: add query-acpi-ospm-status command acpi: implement ospm_status() method for PIIX4/ICH9_LPC devices acpi: introduce TYPE_ACPI_DEVICE_IF interface qmp: add query-memory-devices command numa: handle mmaped memory allocation failure correctly pc: acpi: do not hardcode preprocessor qmp: clean out whitespace qdev: recursively unrealize devices when unrealizing bus qdev: reorganize error reporting in bus_set_realized qapi: fix build on glib < 2.28 qapi: make string output visitor parse int list qapi: make string input visitor parse int list tests: fix memory leak in test of string input visitor hmp: add info memdev ... Conflicts: include/hw/i386/pc.h [PMM: fixed minor conflict in pc.h] Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'qapi/string-input-visitor.c')
-rw-r--r--qapi/string-input-visitor.c201
1 files changed, 193 insertions, 8 deletions
diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
index 5780944792..d8a8db02ed 100644
--- a/qapi/string-input-visitor.c
+++ b/qapi/string-input-visitor.c
@@ -15,31 +15,210 @@
#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;
+
+ GList *ranges;
+ GList *cur_range;
+ int64_t cur;
+
const char *string;
};
+static void free_range(void *range, void *dummy)
+{
+ g_free(range);
+}
+
+static void parse_str(StringInputVisitor *siv, Error **errp)
+{
+ char *str = (char *) siv->string;
+ long long start, end;
+ Range *cur;
+ char *endptr;
+
+ if (siv->ranges) {
+ return;
+ }
+
+ do {
+ errno = 0;
+ start = strtoll(str, &endptr, 0);
+ if (errno == 0 && endptr > str) {
+ if (*endptr == '\0') {
+ cur = g_malloc0(sizeof(*cur));
+ cur->begin = start;
+ cur->end = start + 1;
+ siv->ranges = g_list_insert_sorted_merged(siv->ranges, cur,
+ range_compare);
+ cur = NULL;
+ str = NULL;
+ } else if (*endptr == '-') {
+ str = endptr + 1;
+ errno = 0;
+ end = strtoll(str, &endptr, 0);
+ if (errno == 0 && endptr > str && start <= end &&
+ (start > INT64_MAX - 65536 ||
+ end < start + 65536)) {
+ if (*endptr == '\0') {
+ cur = g_malloc0(sizeof(*cur));
+ cur->begin = start;
+ cur->end = end + 1;
+ siv->ranges =
+ g_list_insert_sorted_merged(siv->ranges,
+ cur,
+ range_compare);
+ cur = NULL;
+ str = NULL;
+ } else if (*endptr == ',') {
+ str = endptr + 1;
+ cur = g_malloc0(sizeof(*cur));
+ cur->begin = start;
+ cur->end = end + 1;
+ siv->ranges =
+ g_list_insert_sorted_merged(siv->ranges,
+ cur,
+ range_compare);
+ cur = NULL;
+ } else {
+ goto error;
+ }
+ } else {
+ goto error;
+ }
+ } else if (*endptr == ',') {
+ str = endptr + 1;
+ cur = g_malloc0(sizeof(*cur));
+ cur->begin = start;
+ cur->end = start + 1;
+ siv->ranges = g_list_insert_sorted_merged(siv->ranges,
+ cur,
+ range_compare);
+ cur = NULL;
+ } else {
+ goto error;
+ }
+ } else {
+ goto error;
+ }
+ } while (str);
+
+ return;
+error:
+ g_list_foreach(siv->ranges, free_range, NULL);
+ g_list_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);
+
+ siv->cur_range = g_list_first(siv->ranges);
+ if (siv->cur_range) {
+ Range *r = siv->cur_range->data;
+ if (r) {
+ siv->cur = r->begin;
+ }
+ }
+}
+
+static GenericList *
+next_list(Visitor *v, GenericList **list, Error **errp)
+{
+ StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+ GenericList **link;
+ Range *r;
+
+ if (!siv->ranges || !siv->cur_range) {
+ return NULL;
+ }
+
+ r = siv->cur_range->data;
+ if (!r) {
+ return NULL;
+ }
+
+ if (siv->cur < r->begin || siv->cur >= r->end) {
+ siv->cur_range = g_list_next(siv->cur_range);
+ if (!siv->cur_range) {
+ return NULL;
+ }
+ r = siv->cur_range->data;
+ if (!r) {
+ return NULL;
+ }
+ siv->cur = r->begin;
+ }
+
+ 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) {
+ Range *r;
+
+ siv->cur_range = g_list_first(siv->ranges);
+ if (!siv->cur_range) {
+ goto error;
+ }
+
+ r = siv->cur_range->data;
+ if (!r) {
+ goto error;
+ }
+
+ siv->cur = r->begin;
+ }
+
+ *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 +319,8 @@ Visitor *string_input_get_visitor(StringInputVisitor *v)
void string_input_visitor_cleanup(StringInputVisitor *v)
{
+ g_list_foreach(v->ranges, free_range, NULL);
+ g_list_free(v->ranges);
g_free(v);
}
@@ -155,8 +336,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;
}