xref: /qemu/qobject/qlist.c (revision 7b1b5d191385ca52e96caae2a05c64f3a63855d9)
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 
13*7b1b5d19SPaolo Bonzini #include "qapi/qmp/qlist.h"
14*7b1b5d19SPaolo Bonzini #include "qapi/qmp/qobject.h"
15a6fd08ebSLuiz Capitulino #include "qemu-queue.h"
16a6fd08ebSLuiz Capitulino #include "qemu-common.h"
17a6fd08ebSLuiz Capitulino 
18a6fd08ebSLuiz Capitulino static void qlist_destroy_obj(QObject *obj);
19a6fd08ebSLuiz Capitulino 
20a6fd08ebSLuiz Capitulino static const QType qlist_type = {
21a6fd08ebSLuiz Capitulino     .code = QTYPE_QLIST,
22a6fd08ebSLuiz Capitulino     .destroy = qlist_destroy_obj,
23a6fd08ebSLuiz Capitulino };
24a6fd08ebSLuiz Capitulino 
25a6fd08ebSLuiz Capitulino /**
26a6fd08ebSLuiz Capitulino  * qlist_new(): Create a new QList
27a6fd08ebSLuiz Capitulino  *
28a6fd08ebSLuiz Capitulino  * Return strong reference.
29a6fd08ebSLuiz Capitulino  */
30a6fd08ebSLuiz Capitulino QList *qlist_new(void)
31a6fd08ebSLuiz Capitulino {
32a6fd08ebSLuiz Capitulino     QList *qlist;
33a6fd08ebSLuiz Capitulino 
347267c094SAnthony Liguori     qlist = g_malloc(sizeof(*qlist));
35a6fd08ebSLuiz Capitulino     QTAILQ_INIT(&qlist->head);
36a6fd08ebSLuiz Capitulino     QOBJECT_INIT(qlist, &qlist_type);
37a6fd08ebSLuiz Capitulino 
38a6fd08ebSLuiz Capitulino     return qlist;
39a6fd08ebSLuiz Capitulino }
40a6fd08ebSLuiz Capitulino 
41033815feSAnthony Liguori static void qlist_copy_elem(QObject *obj, void *opaque)
42033815feSAnthony Liguori {
43033815feSAnthony Liguori     QList *dst = opaque;
44033815feSAnthony Liguori 
45033815feSAnthony Liguori     qobject_incref(obj);
46033815feSAnthony Liguori     qlist_append_obj(dst, obj);
47033815feSAnthony Liguori }
48033815feSAnthony Liguori 
49033815feSAnthony Liguori QList *qlist_copy(QList *src)
50033815feSAnthony Liguori {
51033815feSAnthony Liguori     QList *dst = qlist_new();
52033815feSAnthony Liguori 
53033815feSAnthony Liguori     qlist_iter(src, qlist_copy_elem, dst);
54033815feSAnthony Liguori 
55033815feSAnthony Liguori     return dst;
56033815feSAnthony Liguori }
57033815feSAnthony Liguori 
58a6fd08ebSLuiz Capitulino /**
59a6fd08ebSLuiz Capitulino  * qlist_append_obj(): Append an QObject into QList
60a6fd08ebSLuiz Capitulino  *
61a6fd08ebSLuiz Capitulino  * NOTE: ownership of 'value' is transferred to the QList
62a6fd08ebSLuiz Capitulino  */
63a6fd08ebSLuiz Capitulino void qlist_append_obj(QList *qlist, QObject *value)
64a6fd08ebSLuiz Capitulino {
65a6fd08ebSLuiz Capitulino     QListEntry *entry;
66a6fd08ebSLuiz Capitulino 
677267c094SAnthony Liguori     entry = g_malloc(sizeof(*entry));
68a6fd08ebSLuiz Capitulino     entry->value = value;
69a6fd08ebSLuiz Capitulino 
70a6fd08ebSLuiz Capitulino     QTAILQ_INSERT_TAIL(&qlist->head, entry, next);
71a6fd08ebSLuiz Capitulino }
72a6fd08ebSLuiz Capitulino 
73a6fd08ebSLuiz Capitulino /**
74a6fd08ebSLuiz Capitulino  * qlist_iter(): Iterate over all the list's stored values.
75a6fd08ebSLuiz Capitulino  *
76a6fd08ebSLuiz Capitulino  * This function allows the user to provide an iterator, which will be
77a6fd08ebSLuiz Capitulino  * called for each stored value in the list.
78a6fd08ebSLuiz Capitulino  */
79a6fd08ebSLuiz Capitulino void qlist_iter(const QList *qlist,
80a6fd08ebSLuiz Capitulino                 void (*iter)(QObject *obj, void *opaque), void *opaque)
81a6fd08ebSLuiz Capitulino {
82a6fd08ebSLuiz Capitulino     QListEntry *entry;
83a6fd08ebSLuiz Capitulino 
84a6fd08ebSLuiz Capitulino     QTAILQ_FOREACH(entry, &qlist->head, next)
85a6fd08ebSLuiz Capitulino         iter(entry->value, opaque);
86a6fd08ebSLuiz Capitulino }
87a6fd08ebSLuiz Capitulino 
88033815feSAnthony Liguori QObject *qlist_pop(QList *qlist)
89033815feSAnthony Liguori {
90033815feSAnthony Liguori     QListEntry *entry;
91033815feSAnthony Liguori     QObject *ret;
92033815feSAnthony Liguori 
93033815feSAnthony Liguori     if (qlist == NULL || QTAILQ_EMPTY(&qlist->head)) {
94033815feSAnthony Liguori         return NULL;
95033815feSAnthony Liguori     }
96033815feSAnthony Liguori 
97033815feSAnthony Liguori     entry = QTAILQ_FIRST(&qlist->head);
98033815feSAnthony Liguori     QTAILQ_REMOVE(&qlist->head, entry, next);
99033815feSAnthony Liguori 
100033815feSAnthony Liguori     ret = entry->value;
1017267c094SAnthony Liguori     g_free(entry);
102033815feSAnthony Liguori 
103033815feSAnthony Liguori     return ret;
104033815feSAnthony Liguori }
105033815feSAnthony Liguori 
106033815feSAnthony Liguori QObject *qlist_peek(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 
117033815feSAnthony Liguori     ret = entry->value;
118033815feSAnthony Liguori 
119033815feSAnthony Liguori     return ret;
120033815feSAnthony Liguori }
121033815feSAnthony Liguori 
122033815feSAnthony Liguori int qlist_empty(const QList *qlist)
123033815feSAnthony Liguori {
124033815feSAnthony Liguori     return QTAILQ_EMPTY(&qlist->head);
125033815feSAnthony Liguori }
126033815feSAnthony Liguori 
127a86a4c2fSMichael Roth static void qlist_size_iter(QObject *obj, void *opaque)
128a86a4c2fSMichael Roth {
129a86a4c2fSMichael Roth     size_t *count = opaque;
130a86a4c2fSMichael Roth     (*count)++;
131a86a4c2fSMichael Roth }
132a86a4c2fSMichael Roth 
133a86a4c2fSMichael Roth size_t qlist_size(const QList *qlist)
134a86a4c2fSMichael Roth {
135a86a4c2fSMichael Roth     size_t count = 0;
136a86a4c2fSMichael Roth     qlist_iter(qlist, qlist_size_iter, &count);
137a86a4c2fSMichael Roth     return count;
138a86a4c2fSMichael Roth }
139a86a4c2fSMichael Roth 
140a6fd08ebSLuiz Capitulino /**
141a6fd08ebSLuiz Capitulino  * qobject_to_qlist(): Convert a QObject into a QList
142a6fd08ebSLuiz Capitulino  */
143a6fd08ebSLuiz Capitulino QList *qobject_to_qlist(const QObject *obj)
144a6fd08ebSLuiz Capitulino {
145a6fd08ebSLuiz Capitulino     if (qobject_type(obj) != QTYPE_QLIST) {
146a6fd08ebSLuiz Capitulino         return NULL;
147a6fd08ebSLuiz Capitulino     }
148a6fd08ebSLuiz Capitulino 
149a6fd08ebSLuiz Capitulino     return container_of(obj, QList, base);
150a6fd08ebSLuiz Capitulino }
151a6fd08ebSLuiz Capitulino 
152a6fd08ebSLuiz Capitulino /**
153a6fd08ebSLuiz Capitulino  * qlist_destroy_obj(): Free all the memory allocated by a QList
154a6fd08ebSLuiz Capitulino  */
155a6fd08ebSLuiz Capitulino static void qlist_destroy_obj(QObject *obj)
156a6fd08ebSLuiz Capitulino {
157a6fd08ebSLuiz Capitulino     QList *qlist;
158a6fd08ebSLuiz Capitulino     QListEntry *entry, *next_entry;
159a6fd08ebSLuiz Capitulino 
160a6fd08ebSLuiz Capitulino     assert(obj != NULL);
161a6fd08ebSLuiz Capitulino     qlist = qobject_to_qlist(obj);
162a6fd08ebSLuiz Capitulino 
163a6fd08ebSLuiz Capitulino     QTAILQ_FOREACH_SAFE(entry, &qlist->head, next, next_entry) {
164a6fd08ebSLuiz Capitulino         QTAILQ_REMOVE(&qlist->head, entry, next);
165a6fd08ebSLuiz Capitulino         qobject_decref(entry->value);
1667267c094SAnthony Liguori         g_free(entry);
167a6fd08ebSLuiz Capitulino     }
168a6fd08ebSLuiz Capitulino 
1697267c094SAnthony Liguori     g_free(qlist);
170a6fd08ebSLuiz Capitulino }
171