xref: /qemu/qobject/qlist.c (revision b38dd678a21582e03ecd2dec76ccf8290455628a)
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"
147b1b5d19SPaolo Bonzini #include "qapi/qmp/qlist.h"
157b1b5d19SPaolo Bonzini #include "qapi/qmp/qobject.h"
161de7afc9SPaolo Bonzini #include "qemu/queue.h"
17a6fd08ebSLuiz Capitulino #include "qemu-common.h"
18a6fd08ebSLuiz Capitulino 
19a6fd08ebSLuiz Capitulino /**
20a6fd08ebSLuiz Capitulino  * qlist_new(): Create a new QList
21a6fd08ebSLuiz Capitulino  *
22a6fd08ebSLuiz Capitulino  * Return strong reference.
23a6fd08ebSLuiz Capitulino  */
24a6fd08ebSLuiz Capitulino QList *qlist_new(void)
25a6fd08ebSLuiz Capitulino {
26a6fd08ebSLuiz Capitulino     QList *qlist;
27a6fd08ebSLuiz Capitulino 
287267c094SAnthony Liguori     qlist = g_malloc(sizeof(*qlist));
2955e1819cSEric Blake     qobject_init(QOBJECT(qlist), QTYPE_QLIST);
30a6fd08ebSLuiz Capitulino     QTAILQ_INIT(&qlist->head);
31a6fd08ebSLuiz Capitulino 
32a6fd08ebSLuiz Capitulino     return qlist;
33a6fd08ebSLuiz Capitulino }
34a6fd08ebSLuiz Capitulino 
35033815feSAnthony Liguori static void qlist_copy_elem(QObject *obj, void *opaque)
36033815feSAnthony Liguori {
37033815feSAnthony Liguori     QList *dst = opaque;
38033815feSAnthony Liguori 
39033815feSAnthony Liguori     qobject_incref(obj);
40033815feSAnthony Liguori     qlist_append_obj(dst, obj);
41033815feSAnthony Liguori }
42033815feSAnthony Liguori 
43033815feSAnthony Liguori QList *qlist_copy(QList *src)
44033815feSAnthony Liguori {
45033815feSAnthony Liguori     QList *dst = qlist_new();
46033815feSAnthony Liguori 
47033815feSAnthony Liguori     qlist_iter(src, qlist_copy_elem, dst);
48033815feSAnthony Liguori 
49033815feSAnthony Liguori     return dst;
50033815feSAnthony Liguori }
51033815feSAnthony Liguori 
52a6fd08ebSLuiz Capitulino /**
53a6fd08ebSLuiz Capitulino  * qlist_append_obj(): Append an QObject into QList
54a6fd08ebSLuiz Capitulino  *
55a6fd08ebSLuiz Capitulino  * NOTE: ownership of 'value' is transferred to the QList
56a6fd08ebSLuiz Capitulino  */
57a6fd08ebSLuiz Capitulino void qlist_append_obj(QList *qlist, QObject *value)
58a6fd08ebSLuiz Capitulino {
59a6fd08ebSLuiz Capitulino     QListEntry *entry;
60a6fd08ebSLuiz Capitulino 
617267c094SAnthony Liguori     entry = g_malloc(sizeof(*entry));
62a6fd08ebSLuiz Capitulino     entry->value = value;
63a6fd08ebSLuiz Capitulino 
64a6fd08ebSLuiz Capitulino     QTAILQ_INSERT_TAIL(&qlist->head, entry, next);
65a6fd08ebSLuiz Capitulino }
66a6fd08ebSLuiz Capitulino 
67a6fd08ebSLuiz Capitulino /**
68a6fd08ebSLuiz Capitulino  * qlist_iter(): Iterate over all the list's stored values.
69a6fd08ebSLuiz Capitulino  *
70a6fd08ebSLuiz Capitulino  * This function allows the user to provide an iterator, which will be
71a6fd08ebSLuiz Capitulino  * called for each stored value in the list.
72a6fd08ebSLuiz Capitulino  */
73a6fd08ebSLuiz Capitulino void qlist_iter(const QList *qlist,
74a6fd08ebSLuiz Capitulino                 void (*iter)(QObject *obj, void *opaque), void *opaque)
75a6fd08ebSLuiz Capitulino {
76a6fd08ebSLuiz Capitulino     QListEntry *entry;
77a6fd08ebSLuiz Capitulino 
78a6fd08ebSLuiz Capitulino     QTAILQ_FOREACH(entry, &qlist->head, next)
79a6fd08ebSLuiz Capitulino         iter(entry->value, opaque);
80a6fd08ebSLuiz Capitulino }
81a6fd08ebSLuiz Capitulino 
82033815feSAnthony Liguori QObject *qlist_pop(QList *qlist)
83033815feSAnthony Liguori {
84033815feSAnthony Liguori     QListEntry *entry;
85033815feSAnthony Liguori     QObject *ret;
86033815feSAnthony Liguori 
87033815feSAnthony Liguori     if (qlist == NULL || QTAILQ_EMPTY(&qlist->head)) {
88033815feSAnthony Liguori         return NULL;
89033815feSAnthony Liguori     }
90033815feSAnthony Liguori 
91033815feSAnthony Liguori     entry = QTAILQ_FIRST(&qlist->head);
92033815feSAnthony Liguori     QTAILQ_REMOVE(&qlist->head, entry, next);
93033815feSAnthony Liguori 
94033815feSAnthony Liguori     ret = entry->value;
957267c094SAnthony Liguori     g_free(entry);
96033815feSAnthony Liguori 
97033815feSAnthony Liguori     return ret;
98033815feSAnthony Liguori }
99033815feSAnthony Liguori 
100033815feSAnthony Liguori QObject *qlist_peek(QList *qlist)
101033815feSAnthony Liguori {
102033815feSAnthony Liguori     QListEntry *entry;
103033815feSAnthony Liguori 
104033815feSAnthony Liguori     if (qlist == NULL || QTAILQ_EMPTY(&qlist->head)) {
105033815feSAnthony Liguori         return NULL;
106033815feSAnthony Liguori     }
107033815feSAnthony Liguori 
108033815feSAnthony Liguori     entry = QTAILQ_FIRST(&qlist->head);
109033815feSAnthony Liguori 
1109be38598SEduardo Habkost     return entry->value;
111033815feSAnthony Liguori }
112033815feSAnthony Liguori 
113033815feSAnthony Liguori int qlist_empty(const QList *qlist)
114033815feSAnthony Liguori {
115033815feSAnthony Liguori     return QTAILQ_EMPTY(&qlist->head);
116033815feSAnthony Liguori }
117033815feSAnthony Liguori 
118a86a4c2fSMichael Roth static void qlist_size_iter(QObject *obj, void *opaque)
119a86a4c2fSMichael Roth {
120a86a4c2fSMichael Roth     size_t *count = opaque;
121a86a4c2fSMichael Roth     (*count)++;
122a86a4c2fSMichael Roth }
123a86a4c2fSMichael Roth 
124a86a4c2fSMichael Roth size_t qlist_size(const QList *qlist)
125a86a4c2fSMichael Roth {
126a86a4c2fSMichael Roth     size_t count = 0;
127a86a4c2fSMichael Roth     qlist_iter(qlist, qlist_size_iter, &count);
128a86a4c2fSMichael Roth     return count;
129a86a4c2fSMichael Roth }
130a86a4c2fSMichael Roth 
131a6fd08ebSLuiz Capitulino /**
132a6fd08ebSLuiz Capitulino  * qobject_to_qlist(): Convert a QObject into a QList
133a6fd08ebSLuiz Capitulino  */
134a6fd08ebSLuiz Capitulino QList *qobject_to_qlist(const QObject *obj)
135a6fd08ebSLuiz Capitulino {
1362d6421a9SMarkus Armbruster     if (!obj || qobject_type(obj) != QTYPE_QLIST) {
137a6fd08ebSLuiz Capitulino         return NULL;
138a6fd08ebSLuiz Capitulino     }
139a6fd08ebSLuiz Capitulino     return container_of(obj, QList, base);
140a6fd08ebSLuiz Capitulino }
141a6fd08ebSLuiz Capitulino 
142a6fd08ebSLuiz Capitulino /**
143*b38dd678SMax Reitz  * qlist_is_equal(): Test whether the two QLists are equal
144*b38dd678SMax Reitz  *
145*b38dd678SMax Reitz  * In order to be considered equal, the respective two objects at each
146*b38dd678SMax Reitz  * index of the two lists have to compare equal (regarding
147*b38dd678SMax Reitz  * qobject_is_equal()), and both lists have to have the same number of
148*b38dd678SMax Reitz  * elements.
149*b38dd678SMax Reitz  * That means both lists have to contain equal objects in equal order.
150*b38dd678SMax Reitz  */
151*b38dd678SMax Reitz bool qlist_is_equal(const QObject *x, const QObject *y)
152*b38dd678SMax Reitz {
153*b38dd678SMax Reitz     const QList *list_x = qobject_to_qlist(x);
154*b38dd678SMax Reitz     const QList *list_y = qobject_to_qlist(y);
155*b38dd678SMax Reitz     const QListEntry *entry_x, *entry_y;
156*b38dd678SMax Reitz 
157*b38dd678SMax Reitz     entry_x = qlist_first(list_x);
158*b38dd678SMax Reitz     entry_y = qlist_first(list_y);
159*b38dd678SMax Reitz 
160*b38dd678SMax Reitz     while (entry_x && entry_y) {
161*b38dd678SMax Reitz         if (!qobject_is_equal(qlist_entry_obj(entry_x),
162*b38dd678SMax Reitz                               qlist_entry_obj(entry_y)))
163*b38dd678SMax Reitz         {
164*b38dd678SMax Reitz             return false;
165*b38dd678SMax Reitz         }
166*b38dd678SMax Reitz 
167*b38dd678SMax Reitz         entry_x = qlist_next(entry_x);
168*b38dd678SMax Reitz         entry_y = qlist_next(entry_y);
169*b38dd678SMax Reitz     }
170*b38dd678SMax Reitz 
171*b38dd678SMax Reitz     return !entry_x && !entry_y;
172*b38dd678SMax Reitz }
173*b38dd678SMax Reitz 
174*b38dd678SMax Reitz /**
175a6fd08ebSLuiz Capitulino  * qlist_destroy_obj(): Free all the memory allocated by a QList
176a6fd08ebSLuiz Capitulino  */
17755e1819cSEric Blake void qlist_destroy_obj(QObject *obj)
178a6fd08ebSLuiz Capitulino {
179a6fd08ebSLuiz Capitulino     QList *qlist;
180a6fd08ebSLuiz Capitulino     QListEntry *entry, *next_entry;
181a6fd08ebSLuiz Capitulino 
182a6fd08ebSLuiz Capitulino     assert(obj != NULL);
183a6fd08ebSLuiz Capitulino     qlist = qobject_to_qlist(obj);
184a6fd08ebSLuiz Capitulino 
185a6fd08ebSLuiz Capitulino     QTAILQ_FOREACH_SAFE(entry, &qlist->head, next, next_entry) {
186a6fd08ebSLuiz Capitulino         QTAILQ_REMOVE(&qlist->head, entry, next);
187a6fd08ebSLuiz Capitulino         qobject_decref(entry->value);
1887267c094SAnthony Liguori         g_free(entry);
189a6fd08ebSLuiz Capitulino     }
190a6fd08ebSLuiz Capitulino 
1917267c094SAnthony Liguori     g_free(qlist);
192a6fd08ebSLuiz Capitulino }
193