1
2
3
4
5
6
7
8
9
10
11
12
13#include "qemu/osdep.h"
14#include "qapi/qmp/qnum.h"
15#include "qapi/qmp/qdict.h"
16#include "qapi/qmp/qbool.h"
17#include "qapi/qmp/qnull.h"
18#include "qapi/qmp/qstring.h"
19#include "qobject-internal.h"
20
21
22
23
24
25
26QDict *qdict_new(void)
27{
28 QDict *qdict;
29
30 qdict = g_malloc0(sizeof(*qdict));
31 qobject_init(QOBJECT(qdict), QTYPE_QDICT);
32
33 return qdict;
34}
35
36
37
38
39
40static unsigned int tdb_hash(const char *name)
41{
42 unsigned value;
43 unsigned i;
44
45
46 for (value = 0x238F13AF * strlen(name), i = 0; name[i]; i++) {
47 value = (value + (((const unsigned char *)name)[i] << (i * 5 % 24)));
48 }
49
50 return (1103515243 * value + 12345);
51}
52
53
54
55
56static QDictEntry *alloc_entry(const char *key, QObject *value)
57{
58 QDictEntry *entry;
59
60 entry = g_malloc0(sizeof(*entry));
61 entry->key = g_strdup(key);
62 entry->value = value;
63
64 return entry;
65}
66
67
68
69
70
71
72QObject *qdict_entry_value(const QDictEntry *entry)
73{
74 return entry->value;
75}
76
77
78
79
80
81
82
83const char *qdict_entry_key(const QDictEntry *entry)
84{
85 return entry->key;
86}
87
88
89
90
91static QDictEntry *qdict_find(const QDict *qdict,
92 const char *key, unsigned int bucket)
93{
94 QDictEntry *entry;
95
96 QLIST_FOREACH(entry, &qdict->table[bucket], next)
97 if (!strcmp(entry->key, key)) {
98 return entry;
99 }
100
101 return NULL;
102}
103
104
105
106
107
108
109
110
111
112
113
114
115void qdict_put_obj(QDict *qdict, const char *key, QObject *value)
116{
117 unsigned int bucket;
118 QDictEntry *entry;
119
120 bucket = tdb_hash(key) % QDICT_BUCKET_MAX;
121 entry = qdict_find(qdict, key, bucket);
122 if (entry) {
123
124 qobject_unref(entry->value);
125 entry->value = value;
126 } else {
127
128 entry = alloc_entry(key, value);
129 QLIST_INSERT_HEAD(&qdict->table[bucket], entry, next);
130 qdict->size++;
131 }
132}
133
134void qdict_put_int(QDict *qdict, const char *key, int64_t value)
135{
136 qdict_put(qdict, key, qnum_from_int(value));
137}
138
139void qdict_put_bool(QDict *qdict, const char *key, bool value)
140{
141 qdict_put(qdict, key, qbool_from_bool(value));
142}
143
144void qdict_put_str(QDict *qdict, const char *key, const char *value)
145{
146 qdict_put(qdict, key, qstring_from_str(value));
147}
148
149void qdict_put_null(QDict *qdict, const char *key)
150{
151 qdict_put(qdict, key, qnull());
152}
153
154
155
156
157
158
159
160QObject *qdict_get(const QDict *qdict, const char *key)
161{
162 QDictEntry *entry;
163
164 entry = qdict_find(qdict, key, tdb_hash(key) % QDICT_BUCKET_MAX);
165 return (entry == NULL ? NULL : entry->value);
166}
167
168
169
170
171
172
173int qdict_haskey(const QDict *qdict, const char *key)
174{
175 unsigned int bucket = tdb_hash(key) % QDICT_BUCKET_MAX;
176 return (qdict_find(qdict, key, bucket) == NULL ? 0 : 1);
177}
178
179
180
181
182size_t qdict_size(const QDict *qdict)
183{
184 return qdict->size;
185}
186
187
188
189
190
191
192
193
194double qdict_get_double(const QDict *qdict, const char *key)
195{
196 return qnum_get_double(qobject_to(QNum, qdict_get(qdict, key)));
197}
198
199
200
201
202
203
204
205
206
207int64_t qdict_get_int(const QDict *qdict, const char *key)
208{
209 return qnum_get_int(qobject_to(QNum, qdict_get(qdict, key)));
210}
211
212
213
214
215
216
217
218
219
220bool qdict_get_bool(const QDict *qdict, const char *key)
221{
222 return qbool_get_bool(qobject_to(QBool, qdict_get(qdict, key)));
223}
224
225
226
227
228QList *qdict_get_qlist(const QDict *qdict, const char *key)
229{
230 return qobject_to(QList, qdict_get(qdict, key));
231}
232
233
234
235
236QDict *qdict_get_qdict(const QDict *qdict, const char *key)
237{
238 return qobject_to(QDict, qdict_get(qdict, key));
239}
240
241
242
243
244
245
246
247
248
249
250const char *qdict_get_str(const QDict *qdict, const char *key)
251{
252 return qstring_get_str(qobject_to(QString, qdict_get(qdict, key)));
253}
254
255
256
257
258
259
260
261
262int64_t qdict_get_try_int(const QDict *qdict, const char *key,
263 int64_t def_value)
264{
265 QNum *qnum = qobject_to(QNum, qdict_get(qdict, key));
266 int64_t val;
267
268 if (!qnum || !qnum_get_try_int(qnum, &val)) {
269 return def_value;
270 }
271
272 return val;
273}
274
275
276
277
278
279
280
281
282bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_value)
283{
284 QBool *qbool = qobject_to(QBool, qdict_get(qdict, key));
285
286 return qbool ? qbool_get_bool(qbool) : def_value;
287}
288
289
290
291
292
293
294
295
296
297const char *qdict_get_try_str(const QDict *qdict, const char *key)
298{
299 QString *qstr = qobject_to(QString, qdict_get(qdict, key));
300
301 return qstr ? qstring_get_str(qstr) : NULL;
302}
303
304static QDictEntry *qdict_next_entry(const QDict *qdict, int first_bucket)
305{
306 int i;
307
308 for (i = first_bucket; i < QDICT_BUCKET_MAX; i++) {
309 if (!QLIST_EMPTY(&qdict->table[i])) {
310 return QLIST_FIRST(&qdict->table[i]);
311 }
312 }
313
314 return NULL;
315}
316
317
318
319
320const QDictEntry *qdict_first(const QDict *qdict)
321{
322 return qdict_next_entry(qdict, 0);
323}
324
325
326
327
328const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry)
329{
330 QDictEntry *ret;
331
332 ret = QLIST_NEXT(entry, next);
333 if (!ret) {
334 unsigned int bucket = tdb_hash(entry->key) % QDICT_BUCKET_MAX;
335 ret = qdict_next_entry(qdict, bucket + 1);
336 }
337
338 return ret;
339}
340
341
342
343
344
345QDict *qdict_clone_shallow(const QDict *src)
346{
347 QDict *dest;
348 QDictEntry *entry;
349 int i;
350
351 dest = qdict_new();
352
353 for (i = 0; i < QDICT_BUCKET_MAX; i++) {
354 QLIST_FOREACH(entry, &src->table[i], next) {
355 qdict_put_obj(dest, entry->key, qobject_ref(entry->value));
356 }
357 }
358
359 return dest;
360}
361
362
363
364
365static void qentry_destroy(QDictEntry *e)
366{
367 assert(e != NULL);
368 assert(e->key != NULL);
369 assert(e->value != NULL);
370
371 qobject_unref(e->value);
372 g_free(e->key);
373 g_free(e);
374}
375
376
377
378
379
380
381void qdict_del(QDict *qdict, const char *key)
382{
383 QDictEntry *entry;
384
385 entry = qdict_find(qdict, key, tdb_hash(key) % QDICT_BUCKET_MAX);
386 if (entry) {
387 QLIST_REMOVE(entry, next);
388 qentry_destroy(entry);
389 qdict->size--;
390 }
391}
392
393
394
395
396
397
398
399
400bool qdict_is_equal(const QObject *x, const QObject *y)
401{
402 const QDict *dict_x = qobject_to(QDict, x);
403 const QDict *dict_y = qobject_to(QDict, y);
404 const QDictEntry *e;
405
406 if (qdict_size(dict_x) != qdict_size(dict_y)) {
407 return false;
408 }
409
410 for (e = qdict_first(dict_x); e; e = qdict_next(dict_x, e)) {
411 const QObject *obj_x = qdict_entry_value(e);
412 const QObject *obj_y = qdict_get(dict_y, qdict_entry_key(e));
413
414 if (!qobject_is_equal(obj_x, obj_y)) {
415 return false;
416 }
417 }
418
419 return true;
420}
421
422
423
424
425void qdict_destroy_obj(QObject *obj)
426{
427 int i;
428 QDict *qdict;
429
430 assert(obj != NULL);
431 qdict = qobject_to(QDict, obj);
432
433 for (i = 0; i < QDICT_BUCKET_MAX; i++) {
434 QDictEntry *entry = QLIST_FIRST(&qdict->table[i]);
435 while (entry) {
436 QDictEntry *tmp = QLIST_NEXT(entry, next);
437 QLIST_REMOVE(entry, next);
438 qentry_destroy(entry);
439 entry = tmp;
440 }
441 }
442
443 g_free(qdict);
444}
445