xref: /openbmc/qemu/qobject/qdict.c (revision 1be5a765c08cee3a9587c8a8d3fc2ea247b13f9c)
1a372823aSPaolo Bonzini /*
2a372823aSPaolo Bonzini  * QDict Module
3a372823aSPaolo Bonzini  *
4a372823aSPaolo Bonzini  * Copyright (C) 2009 Red Hat Inc.
5a372823aSPaolo Bonzini  *
6a372823aSPaolo Bonzini  * Authors:
7a372823aSPaolo Bonzini  *  Luiz Capitulino <lcapitulino@redhat.com>
8a372823aSPaolo Bonzini  *
9a372823aSPaolo Bonzini  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10a372823aSPaolo Bonzini  * See the COPYING.LIB file in the top-level directory.
11a372823aSPaolo Bonzini  */
12a372823aSPaolo Bonzini 
13f2ad72b3SPeter Maydell #include "qemu/osdep.h"
1401b2ffceSMarc-André Lureau #include "qapi/qmp/qnum.h"
15a372823aSPaolo Bonzini #include "qapi/qmp/qdict.h"
16a372823aSPaolo Bonzini #include "qapi/qmp/qbool.h"
1715280c36SMarkus Armbruster #include "qapi/qmp/qnull.h"
18a372823aSPaolo Bonzini #include "qapi/qmp/qstring.h"
1980d71121SMarkus Armbruster #include "qobject-internal.h"
20a372823aSPaolo Bonzini 
21a372823aSPaolo Bonzini /**
22a372823aSPaolo Bonzini  * qdict_new(): Create a new QDict
23a372823aSPaolo Bonzini  *
24a372823aSPaolo Bonzini  * Return strong reference.
25a372823aSPaolo Bonzini  */
qdict_new(void)26a372823aSPaolo Bonzini QDict *qdict_new(void)
27a372823aSPaolo Bonzini {
28a372823aSPaolo Bonzini     QDict *qdict;
29a372823aSPaolo Bonzini 
30a372823aSPaolo Bonzini     qdict = g_malloc0(sizeof(*qdict));
3155e1819cSEric Blake     qobject_init(QOBJECT(qdict), QTYPE_QDICT);
32a372823aSPaolo Bonzini 
33a372823aSPaolo Bonzini     return qdict;
34a372823aSPaolo Bonzini }
35a372823aSPaolo Bonzini 
36a372823aSPaolo Bonzini /**
37e3a6e0daSzhaolichang  * tdb_hash(): based on the hash algorithm from gdbm, via tdb
38a372823aSPaolo Bonzini  * (from module-init-tools)
39a372823aSPaolo Bonzini  */
tdb_hash(const char * name)40a372823aSPaolo Bonzini static unsigned int tdb_hash(const char *name)
41a372823aSPaolo Bonzini {
42a372823aSPaolo Bonzini     unsigned value;    /* Used to compute the hash value.  */
43a372823aSPaolo Bonzini     unsigned   i;      /* Used to cycle through random values. */
44a372823aSPaolo Bonzini 
45a372823aSPaolo Bonzini     /* Set the initial value from the key size. */
461841f011SZhang Han     for (value = 0x238F13AF * strlen(name), i = 0; name[i]; i++) {
47a372823aSPaolo Bonzini         value = (value + (((const unsigned char *)name)[i] << (i * 5 % 24)));
481841f011SZhang Han     }
49a372823aSPaolo Bonzini 
50a372823aSPaolo Bonzini     return (1103515243 * value + 12345);
51a372823aSPaolo Bonzini }
52a372823aSPaolo Bonzini 
53a372823aSPaolo Bonzini /**
54a372823aSPaolo Bonzini  * alloc_entry(): allocate a new QDictEntry
55a372823aSPaolo Bonzini  */
alloc_entry(const char * key,QObject * value)56a372823aSPaolo Bonzini static QDictEntry *alloc_entry(const char *key, QObject *value)
57a372823aSPaolo Bonzini {
58a372823aSPaolo Bonzini     QDictEntry *entry;
59a372823aSPaolo Bonzini 
60a372823aSPaolo Bonzini     entry = g_malloc0(sizeof(*entry));
61a372823aSPaolo Bonzini     entry->key = g_strdup(key);
62a372823aSPaolo Bonzini     entry->value = value;
63a372823aSPaolo Bonzini 
64a372823aSPaolo Bonzini     return entry;
65a372823aSPaolo Bonzini }
66a372823aSPaolo Bonzini 
67a372823aSPaolo Bonzini /**
68a372823aSPaolo Bonzini  * qdict_entry_value(): Return qdict entry value
69a372823aSPaolo Bonzini  *
70a372823aSPaolo Bonzini  * Return weak reference.
71a372823aSPaolo Bonzini  */
qdict_entry_value(const QDictEntry * entry)72a372823aSPaolo Bonzini QObject *qdict_entry_value(const QDictEntry *entry)
73a372823aSPaolo Bonzini {
74a372823aSPaolo Bonzini     return entry->value;
75a372823aSPaolo Bonzini }
76a372823aSPaolo Bonzini 
77a372823aSPaolo Bonzini /**
78a372823aSPaolo Bonzini  * qdict_entry_key(): Return qdict entry key
79a372823aSPaolo Bonzini  *
80a372823aSPaolo Bonzini  * Return a *pointer* to the string, it has to be duplicated before being
81a372823aSPaolo Bonzini  * stored.
82a372823aSPaolo Bonzini  */
qdict_entry_key(const QDictEntry * entry)83a372823aSPaolo Bonzini const char *qdict_entry_key(const QDictEntry *entry)
84a372823aSPaolo Bonzini {
85a372823aSPaolo Bonzini     return entry->key;
86a372823aSPaolo Bonzini }
87a372823aSPaolo Bonzini 
88a372823aSPaolo Bonzini /**
89a372823aSPaolo Bonzini  * qdict_find(): List lookup function
90a372823aSPaolo Bonzini  */
qdict_find(const QDict * qdict,const char * key,unsigned int bucket)91a372823aSPaolo Bonzini static QDictEntry *qdict_find(const QDict *qdict,
92a372823aSPaolo Bonzini                               const char *key, unsigned int bucket)
93a372823aSPaolo Bonzini {
94a372823aSPaolo Bonzini     QDictEntry *entry;
95a372823aSPaolo Bonzini 
96a372823aSPaolo Bonzini     QLIST_FOREACH(entry, &qdict->table[bucket], next)
971841f011SZhang Han         if (!strcmp(entry->key, key)) {
98a372823aSPaolo Bonzini             return entry;
991841f011SZhang Han         }
100a372823aSPaolo Bonzini 
101a372823aSPaolo Bonzini     return NULL;
102a372823aSPaolo Bonzini }
103a372823aSPaolo Bonzini 
104a372823aSPaolo Bonzini /**
105a372823aSPaolo Bonzini  * qdict_put_obj(): Put a new QObject into the dictionary
106a372823aSPaolo Bonzini  *
107a372823aSPaolo Bonzini  * Insert the pair 'key:value' into 'qdict', if 'key' already exists
108a372823aSPaolo Bonzini  * its 'value' will be replaced.
109a372823aSPaolo Bonzini  *
110a372823aSPaolo Bonzini  * This is done by freeing the reference to the stored QObject and
111a372823aSPaolo Bonzini  * storing the new one in the same entry.
112a372823aSPaolo Bonzini  *
113a372823aSPaolo Bonzini  * NOTE: ownership of 'value' is transferred to the QDict
114a372823aSPaolo Bonzini  */
qdict_put_obj(QDict * qdict,const char * key,QObject * value)115a372823aSPaolo Bonzini void qdict_put_obj(QDict *qdict, const char *key, QObject *value)
116a372823aSPaolo Bonzini {
117a372823aSPaolo Bonzini     unsigned int bucket;
118a372823aSPaolo Bonzini     QDictEntry *entry;
119a372823aSPaolo Bonzini 
120a372823aSPaolo Bonzini     bucket = tdb_hash(key) % QDICT_BUCKET_MAX;
121a372823aSPaolo Bonzini     entry = qdict_find(qdict, key, bucket);
122a372823aSPaolo Bonzini     if (entry) {
123a372823aSPaolo Bonzini         /* replace key's value */
124cb3e7f08SMarc-André Lureau         qobject_unref(entry->value);
125a372823aSPaolo Bonzini         entry->value = value;
126a372823aSPaolo Bonzini     } else {
127a372823aSPaolo Bonzini         /* allocate a new entry */
128a372823aSPaolo Bonzini         entry = alloc_entry(key, value);
129a372823aSPaolo Bonzini         QLIST_INSERT_HEAD(&qdict->table[bucket], entry, next);
130a372823aSPaolo Bonzini         qdict->size++;
131a372823aSPaolo Bonzini     }
132a372823aSPaolo Bonzini }
133a372823aSPaolo Bonzini 
qdict_put_int(QDict * qdict,const char * key,int64_t value)13415280c36SMarkus Armbruster void qdict_put_int(QDict *qdict, const char *key, int64_t value)
13515280c36SMarkus Armbruster {
13615280c36SMarkus Armbruster     qdict_put(qdict, key, qnum_from_int(value));
13715280c36SMarkus Armbruster }
13815280c36SMarkus Armbruster 
qdict_put_bool(QDict * qdict,const char * key,bool value)13915280c36SMarkus Armbruster void qdict_put_bool(QDict *qdict, const char *key, bool value)
14015280c36SMarkus Armbruster {
14115280c36SMarkus Armbruster     qdict_put(qdict, key, qbool_from_bool(value));
14215280c36SMarkus Armbruster }
14315280c36SMarkus Armbruster 
qdict_put_str(QDict * qdict,const char * key,const char * value)14415280c36SMarkus Armbruster void qdict_put_str(QDict *qdict, const char *key, const char *value)
14515280c36SMarkus Armbruster {
14615280c36SMarkus Armbruster     qdict_put(qdict, key, qstring_from_str(value));
14715280c36SMarkus Armbruster }
14815280c36SMarkus Armbruster 
qdict_put_null(QDict * qdict,const char * key)14915280c36SMarkus Armbruster void qdict_put_null(QDict *qdict, const char *key)
15015280c36SMarkus Armbruster {
15115280c36SMarkus Armbruster     qdict_put(qdict, key, qnull());
15215280c36SMarkus Armbruster }
15315280c36SMarkus Armbruster 
154a372823aSPaolo Bonzini /**
155a372823aSPaolo Bonzini  * qdict_get(): Lookup for a given 'key'
156a372823aSPaolo Bonzini  *
157a372823aSPaolo Bonzini  * Return a weak reference to the QObject associated with 'key' if
158a372823aSPaolo Bonzini  * 'key' is present in the dictionary, NULL otherwise.
159a372823aSPaolo Bonzini  */
qdict_get(const QDict * qdict,const char * key)160a372823aSPaolo Bonzini QObject *qdict_get(const QDict *qdict, const char *key)
161a372823aSPaolo Bonzini {
162a372823aSPaolo Bonzini     QDictEntry *entry;
163a372823aSPaolo Bonzini 
164a372823aSPaolo Bonzini     entry = qdict_find(qdict, key, tdb_hash(key) % QDICT_BUCKET_MAX);
165a372823aSPaolo Bonzini     return (entry == NULL ? NULL : entry->value);
166a372823aSPaolo Bonzini }
167a372823aSPaolo Bonzini 
168a372823aSPaolo Bonzini /**
169a372823aSPaolo Bonzini  * qdict_haskey(): Check if 'key' exists
170a372823aSPaolo Bonzini  *
171a372823aSPaolo Bonzini  * Return 1 if 'key' exists in the dict, 0 otherwise
172a372823aSPaolo Bonzini  */
qdict_haskey(const QDict * qdict,const char * key)173a372823aSPaolo Bonzini int qdict_haskey(const QDict *qdict, const char *key)
174a372823aSPaolo Bonzini {
175a372823aSPaolo Bonzini     unsigned int bucket = tdb_hash(key) % QDICT_BUCKET_MAX;
176a372823aSPaolo Bonzini     return (qdict_find(qdict, key, bucket) == NULL ? 0 : 1);
177a372823aSPaolo Bonzini }
178a372823aSPaolo Bonzini 
179a372823aSPaolo Bonzini /**
180a372823aSPaolo Bonzini  * qdict_size(): Return the size of the dictionary
181a372823aSPaolo Bonzini  */
qdict_size(const QDict * qdict)182a372823aSPaolo Bonzini size_t qdict_size(const QDict *qdict)
183a372823aSPaolo Bonzini {
184a372823aSPaolo Bonzini     return qdict->size;
185a372823aSPaolo Bonzini }
186a372823aSPaolo Bonzini 
187a372823aSPaolo Bonzini /**
188a372823aSPaolo Bonzini  * qdict_get_double(): Get an number mapped by 'key'
189a372823aSPaolo Bonzini  *
19001b2ffceSMarc-André Lureau  * This function assumes that 'key' exists and it stores a QNum.
191a372823aSPaolo Bonzini  *
192a372823aSPaolo Bonzini  * Return number mapped by 'key'.
193a372823aSPaolo Bonzini  */
qdict_get_double(const QDict * qdict,const char * key)194a372823aSPaolo Bonzini double qdict_get_double(const QDict *qdict, const char *key)
195a372823aSPaolo Bonzini {
1967dc847ebSMax Reitz     return qnum_get_double(qobject_to(QNum, qdict_get(qdict, key)));
197a372823aSPaolo Bonzini }
198a372823aSPaolo Bonzini 
199a372823aSPaolo Bonzini /**
200a372823aSPaolo Bonzini  * qdict_get_int(): Get an integer mapped by 'key'
201a372823aSPaolo Bonzini  *
202a372823aSPaolo Bonzini  * This function assumes that 'key' exists and it stores a
20301b2ffceSMarc-André Lureau  * QNum representable as int.
204a372823aSPaolo Bonzini  *
205a372823aSPaolo Bonzini  * Return integer mapped by 'key'.
206a372823aSPaolo Bonzini  */
qdict_get_int(const QDict * qdict,const char * key)207a372823aSPaolo Bonzini int64_t qdict_get_int(const QDict *qdict, const char *key)
208a372823aSPaolo Bonzini {
2097dc847ebSMax Reitz     return qnum_get_int(qobject_to(QNum, qdict_get(qdict, key)));
210a372823aSPaolo Bonzini }
211a372823aSPaolo Bonzini 
212a372823aSPaolo Bonzini /**
213a372823aSPaolo Bonzini  * qdict_get_bool(): Get a bool mapped by 'key'
214a372823aSPaolo Bonzini  *
215a372823aSPaolo Bonzini  * This function assumes that 'key' exists and it stores a
216a372823aSPaolo Bonzini  * QBool object.
217a372823aSPaolo Bonzini  *
218a372823aSPaolo Bonzini  * Return bool mapped by 'key'.
219a372823aSPaolo Bonzini  */
qdict_get_bool(const QDict * qdict,const char * key)22034acbc95SEric Blake bool qdict_get_bool(const QDict *qdict, const char *key)
221a372823aSPaolo Bonzini {
2227dc847ebSMax Reitz     return qbool_get_bool(qobject_to(QBool, qdict_get(qdict, key)));
223a372823aSPaolo Bonzini }
224a372823aSPaolo Bonzini 
225a372823aSPaolo Bonzini /**
226b25f23e7SMarkus Armbruster  * qdict_get_qlist(): If @qdict maps @key to a QList, return it, else NULL.
227a372823aSPaolo Bonzini  */
qdict_get_qlist(const QDict * qdict,const char * key)228a372823aSPaolo Bonzini QList *qdict_get_qlist(const QDict *qdict, const char *key)
229a372823aSPaolo Bonzini {
2307dc847ebSMax Reitz     return qobject_to(QList, qdict_get(qdict, key));
231a372823aSPaolo Bonzini }
232a372823aSPaolo Bonzini 
233a372823aSPaolo Bonzini /**
234b25f23e7SMarkus Armbruster  * qdict_get_qdict(): If @qdict maps @key to a QDict, return it, else NULL.
235a372823aSPaolo Bonzini  */
qdict_get_qdict(const QDict * qdict,const char * key)236a372823aSPaolo Bonzini QDict *qdict_get_qdict(const QDict *qdict, const char *key)
237a372823aSPaolo Bonzini {
2387dc847ebSMax Reitz     return qobject_to(QDict, qdict_get(qdict, key));
239a372823aSPaolo Bonzini }
240a372823aSPaolo Bonzini 
241a372823aSPaolo Bonzini /**
242a372823aSPaolo Bonzini  * qdict_get_str(): Get a pointer to the stored string mapped
243a372823aSPaolo Bonzini  * by 'key'
244a372823aSPaolo Bonzini  *
245a372823aSPaolo Bonzini  * This function assumes that 'key' exists and it stores a
246a372823aSPaolo Bonzini  * QString object.
247a372823aSPaolo Bonzini  *
248a372823aSPaolo Bonzini  * Return pointer to the string mapped by 'key'.
249a372823aSPaolo Bonzini  */
qdict_get_str(const QDict * qdict,const char * key)250a372823aSPaolo Bonzini const char *qdict_get_str(const QDict *qdict, const char *key)
251a372823aSPaolo Bonzini {
2527dc847ebSMax Reitz     return qstring_get_str(qobject_to(QString, qdict_get(qdict, key)));
253a372823aSPaolo Bonzini }
254a372823aSPaolo Bonzini 
255a372823aSPaolo Bonzini /**
256a372823aSPaolo Bonzini  * qdict_get_try_int(): Try to get integer mapped by 'key'
257a372823aSPaolo Bonzini  *
25801b2ffceSMarc-André Lureau  * Return integer mapped by 'key', if it is not present in the
25901b2ffceSMarc-André Lureau  * dictionary or if the stored object is not a QNum representing an
26001b2ffceSMarc-André Lureau  * integer, 'def_value' will be returned.
261a372823aSPaolo Bonzini  */
qdict_get_try_int(const QDict * qdict,const char * key,int64_t def_value)262a372823aSPaolo Bonzini int64_t qdict_get_try_int(const QDict *qdict, const char *key,
263a372823aSPaolo Bonzini                           int64_t def_value)
264a372823aSPaolo Bonzini {
2657dc847ebSMax Reitz     QNum *qnum = qobject_to(QNum, qdict_get(qdict, key));
26601b2ffceSMarc-André Lureau     int64_t val;
267a372823aSPaolo Bonzini 
26801b2ffceSMarc-André Lureau     if (!qnum || !qnum_get_try_int(qnum, &val)) {
26901b2ffceSMarc-André Lureau         return def_value;
27001b2ffceSMarc-André Lureau     }
27101b2ffceSMarc-André Lureau 
27201b2ffceSMarc-André Lureau     return val;
273a372823aSPaolo Bonzini }
274a372823aSPaolo Bonzini 
275a372823aSPaolo Bonzini /**
276a372823aSPaolo Bonzini  * qdict_get_try_bool(): Try to get a bool mapped by 'key'
277a372823aSPaolo Bonzini  *
278a372823aSPaolo Bonzini  * Return bool mapped by 'key', if it is not present in the
279a372823aSPaolo Bonzini  * dictionary or if the stored object is not of QBool type
280a372823aSPaolo Bonzini  * 'def_value' will be returned.
281a372823aSPaolo Bonzini  */
qdict_get_try_bool(const QDict * qdict,const char * key,bool def_value)28234acbc95SEric Blake bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_value)
283a372823aSPaolo Bonzini {
2847dc847ebSMax Reitz     QBool *qbool = qobject_to(QBool, qdict_get(qdict, key));
285a372823aSPaolo Bonzini 
28614b61600SMarkus Armbruster     return qbool ? qbool_get_bool(qbool) : def_value;
287a372823aSPaolo Bonzini }
288a372823aSPaolo Bonzini 
289a372823aSPaolo Bonzini /**
290a372823aSPaolo Bonzini  * qdict_get_try_str(): Try to get a pointer to the stored string
291a372823aSPaolo Bonzini  * mapped by 'key'
292a372823aSPaolo Bonzini  *
293a372823aSPaolo Bonzini  * Return a pointer to the string mapped by 'key', if it is not present
294a372823aSPaolo Bonzini  * in the dictionary or if the stored object is not of QString type
295a372823aSPaolo Bonzini  * NULL will be returned.
296a372823aSPaolo Bonzini  */
qdict_get_try_str(const QDict * qdict,const char * key)297a372823aSPaolo Bonzini const char *qdict_get_try_str(const QDict *qdict, const char *key)
298a372823aSPaolo Bonzini {
2997dc847ebSMax Reitz     QString *qstr = qobject_to(QString, qdict_get(qdict, key));
300a372823aSPaolo Bonzini 
3017f027843SMarkus Armbruster     return qstr ? qstring_get_str(qstr) : NULL;
302a372823aSPaolo Bonzini }
303a372823aSPaolo Bonzini 
qdict_next_entry(const QDict * qdict,int first_bucket)304a372823aSPaolo Bonzini static QDictEntry *qdict_next_entry(const QDict *qdict, int first_bucket)
305a372823aSPaolo Bonzini {
306a372823aSPaolo Bonzini     int i;
307a372823aSPaolo Bonzini 
308a372823aSPaolo Bonzini     for (i = first_bucket; i < QDICT_BUCKET_MAX; i++) {
309a372823aSPaolo Bonzini         if (!QLIST_EMPTY(&qdict->table[i])) {
310a372823aSPaolo Bonzini             return QLIST_FIRST(&qdict->table[i]);
311a372823aSPaolo Bonzini         }
312a372823aSPaolo Bonzini     }
313a372823aSPaolo Bonzini 
314a372823aSPaolo Bonzini     return NULL;
315a372823aSPaolo Bonzini }
316a372823aSPaolo Bonzini 
317a372823aSPaolo Bonzini /**
318a372823aSPaolo Bonzini  * qdict_first(): Return first qdict entry for iteration.
319a372823aSPaolo Bonzini  */
qdict_first(const QDict * qdict)320a372823aSPaolo Bonzini const QDictEntry *qdict_first(const QDict *qdict)
321a372823aSPaolo Bonzini {
322a372823aSPaolo Bonzini     return qdict_next_entry(qdict, 0);
323a372823aSPaolo Bonzini }
324a372823aSPaolo Bonzini 
325a372823aSPaolo Bonzini /**
326a372823aSPaolo Bonzini  * qdict_next(): Return next qdict entry in an iteration.
327a372823aSPaolo Bonzini  */
qdict_next(const QDict * qdict,const QDictEntry * entry)328a372823aSPaolo Bonzini const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry)
329a372823aSPaolo Bonzini {
330a372823aSPaolo Bonzini     QDictEntry *ret;
331a372823aSPaolo Bonzini 
332a372823aSPaolo Bonzini     ret = QLIST_NEXT(entry, next);
333a372823aSPaolo Bonzini     if (!ret) {
334a372823aSPaolo Bonzini         unsigned int bucket = tdb_hash(entry->key) % QDICT_BUCKET_MAX;
335a372823aSPaolo Bonzini         ret = qdict_next_entry(qdict, bucket + 1);
336a372823aSPaolo Bonzini     }
337a372823aSPaolo Bonzini 
338a372823aSPaolo Bonzini     return ret;
339a372823aSPaolo Bonzini }
340a372823aSPaolo Bonzini 
341a372823aSPaolo Bonzini /**
342b382bc9aSKevin Wolf  * qdict_clone_shallow(): Clones a given QDict. Its entries are not copied, but
343b382bc9aSKevin Wolf  * another reference is added.
344b382bc9aSKevin Wolf  */
qdict_clone_shallow(const QDict * src)345b382bc9aSKevin Wolf QDict *qdict_clone_shallow(const QDict *src)
346b382bc9aSKevin Wolf {
347b382bc9aSKevin Wolf     QDict *dest;
348b382bc9aSKevin Wolf     QDictEntry *entry;
349b382bc9aSKevin Wolf     int i;
350b382bc9aSKevin Wolf 
351b382bc9aSKevin Wolf     dest = qdict_new();
352b382bc9aSKevin Wolf 
353b382bc9aSKevin Wolf     for (i = 0; i < QDICT_BUCKET_MAX; i++) {
354b382bc9aSKevin Wolf         QLIST_FOREACH(entry, &src->table[i], next) {
355f5a74a5aSMarc-André Lureau             qdict_put_obj(dest, entry->key, qobject_ref(entry->value));
356b382bc9aSKevin Wolf         }
357b382bc9aSKevin Wolf     }
358b382bc9aSKevin Wolf 
359b382bc9aSKevin Wolf     return dest;
360b382bc9aSKevin Wolf }
361b382bc9aSKevin Wolf 
362b382bc9aSKevin Wolf /**
363a372823aSPaolo Bonzini  * qentry_destroy(): Free all the memory allocated by a QDictEntry
364a372823aSPaolo Bonzini  */
qentry_destroy(QDictEntry * e)365a372823aSPaolo Bonzini static void qentry_destroy(QDictEntry *e)
366a372823aSPaolo Bonzini {
367a372823aSPaolo Bonzini     assert(e != NULL);
368a372823aSPaolo Bonzini     assert(e->key != NULL);
369a372823aSPaolo Bonzini     assert(e->value != NULL);
370a372823aSPaolo Bonzini 
371cb3e7f08SMarc-André Lureau     qobject_unref(e->value);
372a372823aSPaolo Bonzini     g_free(e->key);
373a372823aSPaolo Bonzini     g_free(e);
374a372823aSPaolo Bonzini }
375a372823aSPaolo Bonzini 
376a372823aSPaolo Bonzini /**
377a372823aSPaolo Bonzini  * qdict_del(): Delete a 'key:value' pair from the dictionary
378a372823aSPaolo Bonzini  *
379a372823aSPaolo Bonzini  * This will destroy all data allocated by this entry.
380a372823aSPaolo Bonzini  */
qdict_del(QDict * qdict,const char * key)381a372823aSPaolo Bonzini void qdict_del(QDict *qdict, const char *key)
382a372823aSPaolo Bonzini {
383a372823aSPaolo Bonzini     QDictEntry *entry;
384a372823aSPaolo Bonzini 
385a372823aSPaolo Bonzini     entry = qdict_find(qdict, key, tdb_hash(key) % QDICT_BUCKET_MAX);
386a372823aSPaolo Bonzini     if (entry) {
387a372823aSPaolo Bonzini         QLIST_REMOVE(entry, next);
388a372823aSPaolo Bonzini         qentry_destroy(entry);
389a372823aSPaolo Bonzini         qdict->size--;
390a372823aSPaolo Bonzini     }
391a372823aSPaolo Bonzini }
392a372823aSPaolo Bonzini 
393a372823aSPaolo Bonzini /**
394b38dd678SMax Reitz  * qdict_is_equal(): Test whether the two QDicts are equal
395b38dd678SMax Reitz  *
396b38dd678SMax Reitz  * Here, equality means whether they contain the same keys and whether
397b38dd678SMax Reitz  * the respective values are in turn equal (i.e. invoking
398b38dd678SMax Reitz  * qobject_is_equal() on them yields true).
399b38dd678SMax Reitz  */
qdict_is_equal(const QObject * x,const QObject * y)400b38dd678SMax Reitz bool qdict_is_equal(const QObject *x, const QObject *y)
401b38dd678SMax Reitz {
4027dc847ebSMax Reitz     const QDict *dict_x = qobject_to(QDict, x);
4037dc847ebSMax Reitz     const QDict *dict_y = qobject_to(QDict, y);
404b38dd678SMax Reitz     const QDictEntry *e;
405b38dd678SMax Reitz 
406b38dd678SMax Reitz     if (qdict_size(dict_x) != qdict_size(dict_y)) {
407b38dd678SMax Reitz         return false;
408b38dd678SMax Reitz     }
409b38dd678SMax Reitz 
410b38dd678SMax Reitz     for (e = qdict_first(dict_x); e; e = qdict_next(dict_x, e)) {
411b38dd678SMax Reitz         const QObject *obj_x = qdict_entry_value(e);
412b38dd678SMax Reitz         const QObject *obj_y = qdict_get(dict_y, qdict_entry_key(e));
413b38dd678SMax Reitz 
414b38dd678SMax Reitz         if (!qobject_is_equal(obj_x, obj_y)) {
415b38dd678SMax Reitz             return false;
416b38dd678SMax Reitz         }
417b38dd678SMax Reitz     }
418b38dd678SMax Reitz 
419b38dd678SMax Reitz     return true;
420b38dd678SMax Reitz }
421b38dd678SMax Reitz 
422b38dd678SMax Reitz /**
423a372823aSPaolo Bonzini  * qdict_destroy_obj(): Free all the memory allocated by a QDict
424a372823aSPaolo Bonzini  */
qdict_destroy_obj(QObject * obj)42555e1819cSEric Blake void qdict_destroy_obj(QObject *obj)
426a372823aSPaolo Bonzini {
427a372823aSPaolo Bonzini     int i;
428a372823aSPaolo Bonzini     QDict *qdict;
429a372823aSPaolo Bonzini 
430a372823aSPaolo Bonzini     assert(obj != NULL);
4317dc847ebSMax Reitz     qdict = qobject_to(QDict, obj);
432a372823aSPaolo Bonzini 
433a372823aSPaolo Bonzini     for (i = 0; i < QDICT_BUCKET_MAX; i++) {
434a372823aSPaolo Bonzini         QDictEntry *entry = QLIST_FIRST(&qdict->table[i]);
435a372823aSPaolo Bonzini         while (entry) {
436a372823aSPaolo Bonzini             QDictEntry *tmp = QLIST_NEXT(entry, next);
437a372823aSPaolo Bonzini             QLIST_REMOVE(entry, next);
438a372823aSPaolo Bonzini             qentry_destroy(entry);
439a372823aSPaolo Bonzini             entry = tmp;
440a372823aSPaolo Bonzini         }
441a372823aSPaolo Bonzini     }
442a372823aSPaolo Bonzini 
443a372823aSPaolo Bonzini     g_free(qdict);
444a372823aSPaolo Bonzini }
445*d709bbf3SMarc-André Lureau 
qdict_unref(QDict * q)446*d709bbf3SMarc-André Lureau void qdict_unref(QDict *q)
447*d709bbf3SMarc-André Lureau {
448*d709bbf3SMarc-André Lureau     qobject_unref(q);
449*d709bbf3SMarc-André Lureau }
450