From: Chunyan Liu <cy...@suse.com>

The qemu_opts_append() function is intended to merge to different
QemuOptsList's. The resulting list must be freed by its user.

Signed-off-by: Chunyan Liu <cy...@suse.com>
Signed-off-by: Leandro Dorileo <l...@dorileo.org>
---
 include/qemu/option.h |  1 +
 util/qemu-option.c    | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/include/qemu/option.h b/include/qemu/option.h
index f0d4798..3f4976d 100644
--- a/include/qemu/option.h
+++ b/include/qemu/option.h
@@ -157,6 +157,7 @@ int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc 
func, void *opaque,
 QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id);
 QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
                            int fail_if_exists, Error **errp);
+QemuOptsList *qemu_opts_append(QemuOptsList *head, QemuOptsList *tail);
 void qemu_opts_reset(QemuOptsList *list);
 void qemu_opts_loc_restore(QemuOpts *opts);
 int qemu_opts_set(QemuOptsList *list, const char *id,
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 612a966..026d2ff 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -863,6 +863,75 @@ QemuOpts *qemu_opts_create(QemuOptsList *list, const char 
*id,
     return opts;
 }
 
+static size_t count_opts_list(QemuOptsList *list)
+{
+    QemuOptDesc *desc = NULL;
+    size_t num_opts = 0;
+
+    if (!list) {
+        return 0;
+    }
+
+    desc = list->desc;
+    while (desc && desc->name) {
+        num_opts++;
+        desc++;
+    }
+
+    return num_opts;
+}
+
+/**
+ * Merge two QEMUOptsList. First argument's QemuOptDesc members take precedence
+ * over second's.
+ *
+ * @note The result's name and implied_opt_name are not copied from them.
+ * Both merge_lists should not be set. Both lists can be NULL.
+ *
+ * The resulting QemuOptsList should be freed by this functions caller.
+ */
+QemuOptsList *qemu_opts_append(QemuOptsList *dst, QemuOptsList *list)
+{
+    size_t num_opts, num_dst_opts;
+    QemuOptsList *tmp;
+    QemuOptDesc *desc;
+
+    if (!dst && !list) {
+        return NULL;
+    }
+
+    num_opts = count_opts_list(dst);
+    num_opts += count_opts_list(list);
+    tmp = g_malloc0(sizeof(QemuOptsList) +
+                    (num_opts + 1) * sizeof(QemuOptDesc));
+    QTAILQ_INIT(&tmp->head);
+    num_dst_opts = 0;
+
+    /* copy dst->desc to new list */
+    if (dst) {
+        desc = dst->desc;
+        while (desc && desc->name) {
+            tmp->desc[num_dst_opts++] = *desc;
+            tmp->desc[num_dst_opts].name = NULL;
+            desc++;
+        }
+    }
+
+    /* add list->desc to new list */
+    if (list) {
+        desc = list->desc;
+        while (desc && desc->name) {
+            if (find_desc_by_name(tmp->desc, desc->name) == NULL) {
+                tmp->desc[num_dst_opts++] = *desc;
+                tmp->desc[num_dst_opts].name = NULL;
+            }
+            desc++;
+        }
+    }
+
+    return tmp;
+}
+
 void qemu_opts_reset(QemuOptsList *list)
 {
     QemuOpts *opts, *next_opts;
-- 
1.9.0


Reply via email to