xref: /qemu/qobject/qlist.c (revision 15280c360e54a65e2c7be1a47bfbe41dce1ef986)
1a6fd08ebSLuiz Capitulino /*
241836a9fSLuiz Capitulino  * QList Module
3a6fd08ebSLuiz Capitulino  *
4a6fd08ebSLuiz Capitulino  * Copyright (C) 2009 Red Hat Inc.
5a6fd08ebSLuiz Capitulino  *
6a6fd08ebSLuiz Capitulino  * Authors:
7a6fd08ebSLuiz Capitulino  *  Luiz Capitulino <lcapitulino@redhat.com>
8a6fd08ebSLuiz Capitulino  *
941836a9fSLuiz Capitulino  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
1041836a9fSLuiz Capitulino  * See the COPYING.LIB file in the top-level directory.
11a6fd08ebSLuiz Capitulino  */
1241836a9fSLuiz Capitulino 
13f2ad72b3SPeter Maydell #include "qemu/osdep.h"
14*15280c36SMarkus Armbruster #include "qapi/qmp/qbool.h"
157b1b5d19SPaolo Bonzini #include "qapi/qmp/qlist.h"
16*15280c36SMarkus Armbruster #include "qapi/qmp/qnull.h"
17*15280c36SMarkus Armbruster #include "qapi/qmp/qnum.h"
187b1b5d19SPaolo Bonzini #include "qapi/qmp/qobject.h"
19*15280c36SMarkus Armbruster #include "qapi/qmp/qstring.h"
201de7afc9SPaolo Bonzini #include "qemu/queue.h"
21a6fd08ebSLuiz Capitulino #include "qemu-common.h"
22a6fd08ebSLuiz Capitulino 
23a6fd08ebSLuiz Capitulino /**
24a6fd08ebSLuiz Capitulino  * qlist_new(): Create a new QList
25a6fd08ebSLuiz Capitulino  *
26a6fd08ebSLuiz Capitulino  * Return strong reference.
27a6fd08ebSLuiz Capitulino  */
28a6fd08ebSLuiz Capitulino QList *qlist_new(void)
29a6fd08ebSLuiz Capitulino {
30a6fd08ebSLuiz Capitulino     QList *qlist;
31a6fd08ebSLuiz Capitulino 
327267c094SAnthony Liguori     qlist = g_malloc(sizeof(*qlist));
3355e1819cSEric Blake     qobject_init(QOBJECT(qlist), QTYPE_QLIST);
34a6fd08ebSLuiz Capitulino     QTAILQ_INIT(&qlist->head);
35a6fd08ebSLuiz Capitulino 
36a6fd08ebSLuiz Capitulino     return qlist;
37a6fd08ebSLuiz Capitulino }
38a6fd08ebSLuiz Capitulino 
39033815feSAnthony Liguori static void qlist_copy_elem(QObject *obj, void *opaque)
40033815feSAnthony Liguori {
41033815feSAnthony Liguori     QList *dst = opaque;
42033815feSAnthony Liguori 
43033815feSAnthony Liguori     qobject_incref(obj);
44033815feSAnthony Liguori     qlist_append_obj(dst, obj);
45033815feSAnthony Liguori }
46033815feSAnthony Liguori 
47033815feSAnthony Liguori QList *qlist_copy(QList *src)
48033815feSAnthony Liguori {
49033815feSAnthony Liguori     QList *dst = qlist_new();
50033815feSAnthony Liguori 
51033815feSAnthony Liguori     qlist_iter(src, qlist_copy_elem, dst);
52033815feSAnthony Liguori 
53033815feSAnthony Liguori     return dst;
54033815feSAnthony Liguori }
55033815feSAnthony Liguori 
56a6fd08ebSLuiz Capitulino /**
57a6fd08ebSLuiz Capitulino  * qlist_append_obj(): Append an QObject into QList
58a6fd08ebSLuiz Capitulino  *
59a6fd08ebSLuiz Capitulino  * NOTE: ownership of 'value' is transferred to the QList
60a6fd08ebSLuiz Capitulino  */
61a6fd08ebSLuiz Capitulino void qlist_append_obj(QList *qlist, QObject *value)
62a6fd08ebSLuiz Capitulino {
63a6fd08ebSLuiz Capitulino     QListEntry *entry;
64a6fd08ebSLuiz Capitulino 
657267c094SAnthony Liguori     entry = g_malloc(sizeof(*entry));
66a6fd08ebSLuiz Capitulino     entry->value = value;
67a6fd08ebSLuiz Capitulino 
68a6fd08ebSLuiz Capitulino     QTAILQ_INSERT_TAIL(&qlist->head, entry, next);
69a6fd08ebSLuiz Capitulino }
70a6fd08ebSLuiz Capitulino 
71*15280c36SMarkus Armbruster void qlist_append_int(QList *qlist, int64_t value)
72*15280c36SMarkus Armbruster {
73*15280c36SMarkus Armbruster     qlist_append(qlist, qnum_from_int(value));
74*15280c36SMarkus Armbruster }
75*15280c36SMarkus Armbruster 
76*15280c36SMarkus Armbruster void qlist_append_bool(QList *qlist, bool value)
77*15280c36SMarkus Armbruster {
78*15280c36SMarkus Armbruster     qlist_append(qlist, qbool_from_bool(value));
79*15280c36SMarkus Armbruster }
80*15280c36SMarkus Armbruster 
81*15280c36SMarkus Armbruster void qlist_append_str(QList *qlist, const char *value)
82*15280c36SMarkus Armbruster {
83*15280c36SMarkus Armbruster     qlist_append(qlist, qstring_from_str(value));
84*15280c36SMarkus Armbruster }
85*15280c36SMarkus Armbruster 
86*15280c36SMarkus Armbruster void qlist_append_null(QList *qlist)
87*15280c36SMarkus Armbruster {
88*15280c36SMarkus Armbruster     qlist_append(qlist, qnull());
89*15280c36SMarkus Armbruster }
90*15280c36SMarkus Armbruster 
91a6fd08ebSLuiz Capitulino /**
92a6fd08ebSLuiz Capitulino  * qlist_iter(): Iterate over all the list's stored values.
93a6fd08ebSLuiz Capitulino  *
94a6fd08ebSLuiz Capitulino  * This function allows the user to provide an iterator, which will be
95a6fd08ebSLuiz Capitulino  * called for each stored value in the list.
96a6fd08ebSLuiz Capitulino  */
97a6fd08ebSLuiz Capitulino void qlist_iter(const QList *qlist,
98a6fd08ebSLuiz Capitulino                 void (*iter)(QObject *obj, void *opaque), void *opaque)
99a6fd08ebSLuiz Capitulino {
100a6fd08ebSLuiz Capitulino     QListEntry *entry;
101a6fd08ebSLuiz Capitulino 
102a6fd08ebSLuiz Capitulino     QTAILQ_FOREACH(entry, &qlist->head, next)
103a6fd08ebSLuiz Capitulino         iter(entry->value, opaque);
104a6fd08ebSLuiz Capitulino }
105a6fd08ebSLuiz Capitulino 
106033815feSAnthony Liguori QObject *qlist_pop(QList *qlist)
107033815feSAnthony Liguori {
108033815feSAnthony Liguori     QListEntry *entry;
109033815feSAnthony Liguori     QObject *ret;
110033815feSAnthony Liguori 
111033815feSAnthony Liguori     if (qlist == NULL || QTAILQ_EMPTY(&qlist->head)) {
112033815feSAnthony Liguori         return NULL;
113033815feSAnthony Liguori     }
114033815feSAnthony Liguori 
115033815feSAnthony Liguori     entry = QTAILQ_FIRST(&qlist->head);
116033815feSAnthony Liguori     QTAILQ_REMOVE(&qlist->head, entry, next);
117033815feSAnthony Liguori 
118033815feSAnthony Liguori     ret = entry->value;
1197267c094SAnthony Liguori     g_free(entry);
120033815feSAnthony Liguori 
121033815feSAnthony Liguori     return ret;
122033815feSAnthony Liguori }
123033815feSAnthony Liguori 
124033815feSAnthony Liguori QObject *qlist_peek(QList *qlist)
125033815feSAnthony Liguori {
126033815feSAnthony Liguori     QListEntry *entry;
127033815feSAnthony Liguori 
128033815feSAnthony Liguori     if (qlist == NULL || QTAILQ_EMPTY(&qlist->head)) {
129033815feSAnthony Liguori         return NULL;
130033815feSAnthony Liguori     }
131033815feSAnthony Liguori 
132033815feSAnthony Liguori     entry = QTAILQ_FIRST(&qlist->head);
133033815feSAnthony Liguori 
1349be38598SEduardo Habkost     return entry->value;
135033815feSAnthony Liguori }
136033815feSAnthony Liguori 
137033815feSAnthony Liguori int qlist_empty(const QList *qlist)
138033815feSAnthony Liguori {
139033815feSAnthony Liguori     return QTAILQ_EMPTY(&qlist->head);
140033815feSAnthony Liguori }
141033815feSAnthony Liguori 
142a86a4c2fSMichael Roth static void qlist_size_iter(QObject *obj, void *opaque)
143a86a4c2fSMichael Roth {
144a86a4c2fSMichael Roth     size_t *count = opaque;
145a86a4c2fSMichael Roth     (*count)++;
146a86a4c2fSMichael Roth }
147a86a4c2fSMichael Roth 
148a86a4c2fSMichael Roth size_t qlist_size(const QList *qlist)
149a86a4c2fSMichael Roth {
150a86a4c2fSMichael Roth     size_t count = 0;
151a86a4c2fSMichael Roth     qlist_iter(qlist, qlist_size_iter, &count);
152a86a4c2fSMichael Roth     return count;
153a86a4c2fSMichael Roth }
154a86a4c2fSMichael Roth 
155a6fd08ebSLuiz Capitulino /**
156a6fd08ebSLuiz Capitulino  * qobject_to_qlist(): Convert a QObject into a QList
157a6fd08ebSLuiz Capitulino  */
158a6fd08ebSLuiz Capitulino QList *qobject_to_qlist(const QObject *obj)
159a6fd08ebSLuiz Capitulino {
1602d6421a9SMarkus Armbruster     if (!obj || qobject_type(obj) != QTYPE_QLIST) {
161a6fd08ebSLuiz Capitulino         return NULL;
162a6fd08ebSLuiz Capitulino     }
163a6fd08ebSLuiz Capitulino     return container_of(obj, QList, base);
164a6fd08ebSLuiz Capitulino }
165a6fd08ebSLuiz Capitulino 
166a6fd08ebSLuiz Capitulino /**
167b38dd678SMax Reitz  * qlist_is_equal(): Test whether the two QLists are equal
168b38dd678SMax Reitz  *
169b38dd678SMax Reitz  * In order to be considered equal, the respective two objects at each
170b38dd678SMax Reitz  * index of the two lists have to compare equal (regarding
171b38dd678SMax Reitz  * qobject_is_equal()), and both lists have to have the same number of
172b38dd678SMax Reitz  * elements.
173b38dd678SMax Reitz  * That means both lists have to contain equal objects in equal order.
174b38dd678SMax Reitz  */
175b38dd678SMax Reitz bool qlist_is_equal(const QObject *x, const QObject *y)
176b38dd678SMax Reitz {
177b38dd678SMax Reitz     const QList *list_x = qobject_to_qlist(x);
178b38dd678SMax Reitz     const QList *list_y = qobject_to_qlist(y);
179b38dd678SMax Reitz     const QListEntry *entry_x, *entry_y;
180b38dd678SMax Reitz 
181b38dd678SMax Reitz     entry_x = qlist_first(list_x);
182b38dd678SMax Reitz     entry_y = qlist_first(list_y);
183b38dd678SMax Reitz 
184b38dd678SMax Reitz     while (entry_x && entry_y) {
185b38dd678SMax Reitz         if (!qobject_is_equal(qlist_entry_obj(entry_x),
186b38dd678SMax Reitz                               qlist_entry_obj(entry_y)))
187b38dd678SMax Reitz         {
188b38dd678SMax Reitz             return false;
189b38dd678SMax Reitz         }
190b38dd678SMax Reitz 
191b38dd678SMax Reitz         entry_x = qlist_next(entry_x);
192b38dd678SMax Reitz         entry_y = qlist_next(entry_y);
193b38dd678SMax Reitz     }
194b38dd678SMax Reitz 
195b38dd678SMax Reitz     return !entry_x && !entry_y;
196b38dd678SMax Reitz }
197b38dd678SMax Reitz 
198b38dd678SMax Reitz /**
199a6fd08ebSLuiz Capitulino  * qlist_destroy_obj(): Free all the memory allocated by a QList
200a6fd08ebSLuiz Capitulino  */
20155e1819cSEric Blake void qlist_destroy_obj(QObject *obj)
202a6fd08ebSLuiz Capitulino {
203a6fd08ebSLuiz Capitulino     QList *qlist;
204a6fd08ebSLuiz Capitulino     QListEntry *entry, *next_entry;
205a6fd08ebSLuiz Capitulino 
206a6fd08ebSLuiz Capitulino     assert(obj != NULL);
207a6fd08ebSLuiz Capitulino     qlist = qobject_to_qlist(obj);
208a6fd08ebSLuiz Capitulino 
209a6fd08ebSLuiz Capitulino     QTAILQ_FOREACH_SAFE(entry, &qlist->head, next, next_entry) {
210a6fd08ebSLuiz Capitulino         QTAILQ_REMOVE(&qlist->head, entry, next);
211a6fd08ebSLuiz Capitulino         qobject_decref(entry->value);
2127267c094SAnthony Liguori         g_free(entry);
213a6fd08ebSLuiz Capitulino     }
214a6fd08ebSLuiz Capitulino 
2157267c094SAnthony Liguori     g_free(qlist);
216a6fd08ebSLuiz Capitulino }
217