xref: /openbmc/qemu/qobject/qlist.c (revision 15280c360e54a65e2c7be1a47bfbe41dce1ef986)
1 /*
2  * QList Module
3  *
4  * Copyright (C) 2009 Red Hat Inc.
5  *
6  * Authors:
7  *  Luiz Capitulino <lcapitulino@redhat.com>
8  *
9  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10  * See the COPYING.LIB file in the top-level directory.
11  */
12 
13 #include "qemu/osdep.h"
14 #include "qapi/qmp/qbool.h"
15 #include "qapi/qmp/qlist.h"
16 #include "qapi/qmp/qnull.h"
17 #include "qapi/qmp/qnum.h"
18 #include "qapi/qmp/qobject.h"
19 #include "qapi/qmp/qstring.h"
20 #include "qemu/queue.h"
21 #include "qemu-common.h"
22 
23 /**
24  * qlist_new(): Create a new QList
25  *
26  * Return strong reference.
27  */
28 QList *qlist_new(void)
29 {
30     QList *qlist;
31 
32     qlist = g_malloc(sizeof(*qlist));
33     qobject_init(QOBJECT(qlist), QTYPE_QLIST);
34     QTAILQ_INIT(&qlist->head);
35 
36     return qlist;
37 }
38 
39 static void qlist_copy_elem(QObject *obj, void *opaque)
40 {
41     QList *dst = opaque;
42 
43     qobject_incref(obj);
44     qlist_append_obj(dst, obj);
45 }
46 
47 QList *qlist_copy(QList *src)
48 {
49     QList *dst = qlist_new();
50 
51     qlist_iter(src, qlist_copy_elem, dst);
52 
53     return dst;
54 }
55 
56 /**
57  * qlist_append_obj(): Append an QObject into QList
58  *
59  * NOTE: ownership of 'value' is transferred to the QList
60  */
61 void qlist_append_obj(QList *qlist, QObject *value)
62 {
63     QListEntry *entry;
64 
65     entry = g_malloc(sizeof(*entry));
66     entry->value = value;
67 
68     QTAILQ_INSERT_TAIL(&qlist->head, entry, next);
69 }
70 
71 void qlist_append_int(QList *qlist, int64_t value)
72 {
73     qlist_append(qlist, qnum_from_int(value));
74 }
75 
76 void qlist_append_bool(QList *qlist, bool value)
77 {
78     qlist_append(qlist, qbool_from_bool(value));
79 }
80 
81 void qlist_append_str(QList *qlist, const char *value)
82 {
83     qlist_append(qlist, qstring_from_str(value));
84 }
85 
86 void qlist_append_null(QList *qlist)
87 {
88     qlist_append(qlist, qnull());
89 }
90 
91 /**
92  * qlist_iter(): Iterate over all the list's stored values.
93  *
94  * This function allows the user to provide an iterator, which will be
95  * called for each stored value in the list.
96  */
97 void qlist_iter(const QList *qlist,
98                 void (*iter)(QObject *obj, void *opaque), void *opaque)
99 {
100     QListEntry *entry;
101 
102     QTAILQ_FOREACH(entry, &qlist->head, next)
103         iter(entry->value, opaque);
104 }
105 
106 QObject *qlist_pop(QList *qlist)
107 {
108     QListEntry *entry;
109     QObject *ret;
110 
111     if (qlist == NULL || QTAILQ_EMPTY(&qlist->head)) {
112         return NULL;
113     }
114 
115     entry = QTAILQ_FIRST(&qlist->head);
116     QTAILQ_REMOVE(&qlist->head, entry, next);
117 
118     ret = entry->value;
119     g_free(entry);
120 
121     return ret;
122 }
123 
124 QObject *qlist_peek(QList *qlist)
125 {
126     QListEntry *entry;
127 
128     if (qlist == NULL || QTAILQ_EMPTY(&qlist->head)) {
129         return NULL;
130     }
131 
132     entry = QTAILQ_FIRST(&qlist->head);
133 
134     return entry->value;
135 }
136 
137 int qlist_empty(const QList *qlist)
138 {
139     return QTAILQ_EMPTY(&qlist->head);
140 }
141 
142 static void qlist_size_iter(QObject *obj, void *opaque)
143 {
144     size_t *count = opaque;
145     (*count)++;
146 }
147 
148 size_t qlist_size(const QList *qlist)
149 {
150     size_t count = 0;
151     qlist_iter(qlist, qlist_size_iter, &count);
152     return count;
153 }
154 
155 /**
156  * qobject_to_qlist(): Convert a QObject into a QList
157  */
158 QList *qobject_to_qlist(const QObject *obj)
159 {
160     if (!obj || qobject_type(obj) != QTYPE_QLIST) {
161         return NULL;
162     }
163     return container_of(obj, QList, base);
164 }
165 
166 /**
167  * qlist_is_equal(): Test whether the two QLists are equal
168  *
169  * In order to be considered equal, the respective two objects at each
170  * index of the two lists have to compare equal (regarding
171  * qobject_is_equal()), and both lists have to have the same number of
172  * elements.
173  * That means both lists have to contain equal objects in equal order.
174  */
175 bool qlist_is_equal(const QObject *x, const QObject *y)
176 {
177     const QList *list_x = qobject_to_qlist(x);
178     const QList *list_y = qobject_to_qlist(y);
179     const QListEntry *entry_x, *entry_y;
180 
181     entry_x = qlist_first(list_x);
182     entry_y = qlist_first(list_y);
183 
184     while (entry_x && entry_y) {
185         if (!qobject_is_equal(qlist_entry_obj(entry_x),
186                               qlist_entry_obj(entry_y)))
187         {
188             return false;
189         }
190 
191         entry_x = qlist_next(entry_x);
192         entry_y = qlist_next(entry_y);
193     }
194 
195     return !entry_x && !entry_y;
196 }
197 
198 /**
199  * qlist_destroy_obj(): Free all the memory allocated by a QList
200  */
201 void qlist_destroy_obj(QObject *obj)
202 {
203     QList *qlist;
204     QListEntry *entry, *next_entry;
205 
206     assert(obj != NULL);
207     qlist = qobject_to_qlist(obj);
208 
209     QTAILQ_FOREACH_SAFE(entry, &qlist->head, next, next_entry) {
210         QTAILQ_REMOVE(&qlist->head, entry, next);
211         qobject_decref(entry->value);
212         g_free(entry);
213     }
214 
215     g_free(qlist);
216 }
217