Commit | Line | Data |
---|---|---|
347829f5 PP |
1 | /* |
2 | * objects.c: basic object system | |
3 | * | |
4 | * Babeltrace Library | |
5 | * | |
6 | * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation | |
7 | * Copyright (c) 2015 Philippe Proulx <pproulx@efficios.com> | |
8 | * | |
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
10 | * of this software and associated documentation files (the "Software"), to deal | |
11 | * in the Software without restriction, including without limitation the rights | |
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
13 | * copies of the Software, and to permit persons to whom the Software is | |
14 | * furnished to do so, subject to the following conditions: | |
15 | * | |
16 | * The above copyright notice and this permission notice shall be included in | |
17 | * all copies or substantial portions of the Software. | |
18 | * | |
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
25 | * SOFTWARE. | |
26 | */ | |
27 | ||
28 | #include <stdlib.h> | |
29 | #include <string.h> | |
30 | #include <assert.h> | |
31 | #include <string.h> | |
32 | #include <babeltrace/ctf-writer/ref-internal.h> | |
33 | #include <babeltrace/compiler.h> | |
34 | #include <glib.h> | |
35 | #include <babeltrace/objects.h> | |
36 | ||
37 | #define BT_OBJECT_FROM_CONCRETE(_concrete) ((struct bt_object *) (_concrete)) | |
38 | #define BT_OBJECT_TO_BOOL(_base) ((struct bt_object_bool *) (_base)) | |
39 | #define BT_OBJECT_TO_INTEGER(_base) ((struct bt_object_integer *) (_base)) | |
40 | #define BT_OBJECT_TO_FLOAT(_base) ((struct bt_object_float *) (_base)) | |
41 | #define BT_OBJECT_TO_STRING(_base) ((struct bt_object_string *) (_base)) | |
42 | #define BT_OBJECT_TO_ARRAY(_base) ((struct bt_object_array *) (_base)) | |
43 | #define BT_OBJECT_TO_MAP(_base) ((struct bt_object_map *) (_base)) | |
44 | ||
45 | struct bt_object { | |
46 | enum bt_object_type type; | |
47 | struct bt_ctf_ref ref_count; | |
a40a567e | 48 | bool is_frozen; |
347829f5 PP |
49 | }; |
50 | ||
51 | static | |
52 | struct bt_object bt_object_null_instance = { | |
53 | .type = BT_OBJECT_TYPE_NULL, | |
a40a567e | 54 | .is_frozen = true, |
347829f5 PP |
55 | }; |
56 | ||
57 | struct bt_object *bt_object_null = &bt_object_null_instance; | |
58 | ||
59 | struct bt_object_bool { | |
60 | struct bt_object base; | |
61 | bool value; | |
62 | }; | |
63 | ||
64 | struct bt_object_integer { | |
65 | struct bt_object base; | |
66 | int64_t value; | |
67 | }; | |
68 | ||
69 | struct bt_object_float { | |
70 | struct bt_object base; | |
71 | double value; | |
72 | }; | |
73 | ||
74 | struct bt_object_string { | |
75 | struct bt_object base; | |
76 | GString *gstr; | |
77 | }; | |
78 | ||
79 | struct bt_object_array { | |
80 | struct bt_object base; | |
a22a5f1b | 81 | GPtrArray *garray; |
347829f5 PP |
82 | }; |
83 | ||
84 | struct bt_object_map { | |
85 | struct bt_object base; | |
86 | GHashTable *ght; | |
87 | }; | |
88 | ||
89 | static | |
90 | void bt_object_string_destroy(struct bt_object *object) | |
91 | { | |
e196f486 | 92 | g_string_free(BT_OBJECT_TO_STRING(object)->gstr, TRUE); |
347829f5 PP |
93 | } |
94 | ||
95 | static | |
96 | void bt_object_array_destroy(struct bt_object *object) | |
97 | { | |
a22a5f1b PP |
98 | /* |
99 | * Pointer array's registered value destructor will take care | |
100 | * of putting each contained object. | |
101 | */ | |
102 | g_ptr_array_free(BT_OBJECT_TO_ARRAY(object)->garray, TRUE); | |
347829f5 PP |
103 | } |
104 | ||
105 | static | |
106 | void bt_object_map_destroy(struct bt_object *object) | |
107 | { | |
347829f5 PP |
108 | /* |
109 | * Hash table's registered value destructor will take care of | |
110 | * putting each contained object. Keys are GQuarks and cannot | |
111 | * be destroyed anyway. | |
112 | */ | |
e196f486 | 113 | g_hash_table_destroy(BT_OBJECT_TO_MAP(object)->ght); |
347829f5 PP |
114 | } |
115 | ||
116 | static | |
117 | void (* const destroy_funcs[])(struct bt_object *) = { | |
118 | [BT_OBJECT_TYPE_NULL] = NULL, | |
119 | [BT_OBJECT_TYPE_BOOL] = NULL, | |
120 | [BT_OBJECT_TYPE_INTEGER] = NULL, | |
121 | [BT_OBJECT_TYPE_FLOAT] = NULL, | |
122 | [BT_OBJECT_TYPE_STRING] = bt_object_string_destroy, | |
123 | [BT_OBJECT_TYPE_ARRAY] = bt_object_array_destroy, | |
124 | [BT_OBJECT_TYPE_MAP] = bt_object_map_destroy, | |
125 | }; | |
126 | ||
127 | static | |
128 | struct bt_object *bt_object_null_copy(const struct bt_object *null_obj) | |
129 | { | |
130 | return bt_object_null; | |
131 | } | |
132 | ||
133 | static | |
134 | struct bt_object *bt_object_bool_copy(const struct bt_object *bool_obj) | |
135 | { | |
136 | return bt_object_bool_create_init(BT_OBJECT_TO_BOOL(bool_obj)->value); | |
137 | } | |
138 | ||
139 | static | |
140 | struct bt_object *bt_object_integer_copy(const struct bt_object *integer_obj) | |
141 | { | |
142 | return bt_object_integer_create_init( | |
143 | BT_OBJECT_TO_INTEGER(integer_obj)->value); | |
144 | } | |
145 | ||
146 | static | |
147 | struct bt_object *bt_object_float_copy(const struct bt_object *float_obj) | |
148 | { | |
149 | return bt_object_float_create_init( | |
150 | BT_OBJECT_TO_FLOAT(float_obj)->value); | |
151 | } | |
152 | ||
153 | static | |
154 | struct bt_object *bt_object_string_copy(const struct bt_object *string_obj) | |
155 | { | |
156 | return bt_object_string_create_init( | |
157 | BT_OBJECT_TO_STRING(string_obj)->gstr->str); | |
158 | } | |
159 | ||
160 | static | |
161 | struct bt_object *bt_object_array_copy(const struct bt_object *array_obj) | |
162 | { | |
8da980bd | 163 | int i; |
347829f5 PP |
164 | int ret; |
165 | struct bt_object *copy_obj; | |
166 | struct bt_object_array *typed_array_obj; | |
167 | ||
168 | typed_array_obj = BT_OBJECT_TO_ARRAY(array_obj); | |
169 | copy_obj = bt_object_array_create(); | |
170 | ||
171 | if (!copy_obj) { | |
172 | goto end; | |
173 | } | |
174 | ||
8da980bd | 175 | for (i = 0; i < typed_array_obj->garray->len; ++i) { |
347829f5 PP |
176 | struct bt_object *element_obj_copy; |
177 | struct bt_object *element_obj = | |
8da980bd | 178 | bt_object_array_get(array_obj, i); |
347829f5 PP |
179 | |
180 | if (!element_obj) { | |
181 | BT_OBJECT_PUT(copy_obj); | |
182 | goto end; | |
183 | } | |
184 | ||
185 | element_obj_copy = bt_object_copy(element_obj); | |
186 | BT_OBJECT_PUT(element_obj); | |
187 | ||
188 | if (!element_obj_copy) { | |
189 | BT_OBJECT_PUT(copy_obj); | |
190 | goto end; | |
191 | } | |
192 | ||
193 | ret = bt_object_array_append(copy_obj, element_obj_copy); | |
194 | BT_OBJECT_PUT(element_obj_copy); | |
195 | ||
196 | if (ret) { | |
197 | BT_OBJECT_PUT(copy_obj); | |
198 | goto end; | |
199 | } | |
200 | } | |
201 | ||
202 | end: | |
203 | return copy_obj; | |
204 | } | |
205 | ||
206 | static | |
207 | struct bt_object *bt_object_map_copy(const struct bt_object *map_obj) | |
208 | { | |
209 | int ret; | |
210 | GHashTableIter iter; | |
211 | gpointer key, element_obj; | |
212 | struct bt_object *copy_obj; | |
213 | struct bt_object *element_obj_copy; | |
214 | struct bt_object_map *typed_map_obj; | |
215 | ||
216 | typed_map_obj = BT_OBJECT_TO_MAP(map_obj); | |
217 | copy_obj = bt_object_map_create(); | |
218 | ||
219 | if (!copy_obj) { | |
220 | goto end; | |
221 | } | |
222 | ||
223 | g_hash_table_iter_init(&iter, typed_map_obj->ght); | |
224 | ||
225 | while (g_hash_table_iter_next(&iter, &key, &element_obj)) { | |
226 | const char *key_str = g_quark_to_string((unsigned long) key); | |
227 | ||
228 | element_obj_copy = bt_object_copy(element_obj); | |
229 | ||
230 | if (!element_obj_copy) { | |
231 | BT_OBJECT_PUT(copy_obj); | |
232 | goto end; | |
233 | } | |
234 | ||
235 | ret = bt_object_map_insert(copy_obj, key_str, element_obj_copy); | |
236 | BT_OBJECT_PUT(element_obj_copy); | |
237 | ||
238 | if (ret) { | |
239 | BT_OBJECT_PUT(copy_obj); | |
240 | goto end; | |
241 | } | |
242 | } | |
243 | ||
244 | end: | |
245 | return copy_obj; | |
246 | } | |
247 | ||
248 | static | |
249 | struct bt_object *(* const copy_funcs[])(const struct bt_object *) = { | |
250 | [BT_OBJECT_TYPE_NULL] = bt_object_null_copy, | |
251 | [BT_OBJECT_TYPE_BOOL] = bt_object_bool_copy, | |
252 | [BT_OBJECT_TYPE_INTEGER] = bt_object_integer_copy, | |
253 | [BT_OBJECT_TYPE_FLOAT] = bt_object_float_copy, | |
254 | [BT_OBJECT_TYPE_STRING] = bt_object_string_copy, | |
255 | [BT_OBJECT_TYPE_ARRAY] = bt_object_array_copy, | |
256 | [BT_OBJECT_TYPE_MAP] = bt_object_map_copy, | |
257 | }; | |
258 | ||
259 | static | |
260 | bool bt_object_null_compare(const struct bt_object *object_a, | |
261 | const struct bt_object *object_b) | |
262 | { | |
263 | /* | |
264 | * Always true since bt_object_compare() already checks if both | |
265 | * object_a and object_b have the same type, and in the case of | |
266 | * null objects, they're always the same if it is so. | |
267 | */ | |
268 | return true; | |
269 | } | |
270 | ||
271 | static | |
272 | bool bt_object_bool_compare(const struct bt_object *object_a, | |
273 | const struct bt_object *object_b) | |
274 | { | |
275 | return BT_OBJECT_TO_BOOL(object_a)->value == | |
276 | BT_OBJECT_TO_BOOL(object_b)->value; | |
277 | } | |
278 | ||
279 | static | |
280 | bool bt_object_integer_compare(const struct bt_object *object_a, | |
281 | const struct bt_object *object_b) | |
282 | { | |
283 | return BT_OBJECT_TO_INTEGER(object_a)->value == | |
284 | BT_OBJECT_TO_INTEGER(object_b)->value; | |
285 | } | |
286 | ||
287 | static | |
288 | bool bt_object_float_compare(const struct bt_object *object_a, | |
289 | const struct bt_object *object_b) | |
290 | { | |
291 | return BT_OBJECT_TO_FLOAT(object_a)->value == | |
292 | BT_OBJECT_TO_FLOAT(object_b)->value; | |
293 | } | |
294 | ||
295 | static | |
296 | bool bt_object_string_compare(const struct bt_object *object_a, | |
297 | const struct bt_object *object_b) | |
298 | { | |
299 | return !strcmp(BT_OBJECT_TO_STRING(object_a)->gstr->str, | |
300 | BT_OBJECT_TO_STRING(object_b)->gstr->str); | |
301 | } | |
302 | ||
303 | static | |
304 | bool bt_object_array_compare(const struct bt_object *object_a, | |
305 | const struct bt_object *object_b) | |
306 | { | |
8da980bd | 307 | int i; |
347829f5 PP |
308 | bool ret = true; |
309 | const struct bt_object_array *array_obj_a = | |
310 | BT_OBJECT_TO_ARRAY(object_a); | |
311 | ||
312 | if (bt_object_array_size(object_a) != bt_object_array_size(object_b)) { | |
313 | ret = false; | |
314 | goto end; | |
315 | } | |
316 | ||
8da980bd | 317 | for (i = 0; i < array_obj_a->garray->len; ++i) { |
347829f5 PP |
318 | struct bt_object *element_obj_a; |
319 | struct bt_object *element_obj_b; | |
320 | ||
8da980bd PP |
321 | element_obj_a = bt_object_array_get(object_a, i); |
322 | element_obj_b = bt_object_array_get(object_b, i); | |
347829f5 PP |
323 | |
324 | if (!bt_object_compare(element_obj_a, element_obj_b)) { | |
325 | BT_OBJECT_PUT(element_obj_a); | |
326 | BT_OBJECT_PUT(element_obj_b); | |
327 | ret = false; | |
328 | goto end; | |
329 | } | |
330 | ||
331 | BT_OBJECT_PUT(element_obj_a); | |
332 | BT_OBJECT_PUT(element_obj_b); | |
333 | } | |
334 | ||
335 | end: | |
336 | return ret; | |
337 | } | |
338 | ||
339 | static | |
340 | bool bt_object_map_compare(const struct bt_object *object_a, | |
341 | const struct bt_object *object_b) | |
342 | { | |
343 | bool ret = true; | |
344 | GHashTableIter iter; | |
345 | gpointer key, element_obj_a; | |
346 | const struct bt_object_map *map_obj_a = BT_OBJECT_TO_MAP(object_a); | |
347 | ||
348 | if (bt_object_map_size(object_a) != bt_object_map_size(object_b)) { | |
349 | ret = false; | |
350 | goto end; | |
351 | } | |
352 | ||
353 | g_hash_table_iter_init(&iter, map_obj_a->ght); | |
354 | ||
355 | while (g_hash_table_iter_next(&iter, &key, &element_obj_a)) { | |
356 | struct bt_object *element_obj_b; | |
357 | const char *key_str = g_quark_to_string((unsigned long) key); | |
358 | ||
359 | element_obj_b = bt_object_map_get(object_b, key_str); | |
360 | ||
361 | if (!bt_object_compare(element_obj_a, element_obj_b)) { | |
362 | BT_OBJECT_PUT(element_obj_b); | |
363 | ret = false; | |
364 | goto end; | |
365 | } | |
366 | ||
367 | BT_OBJECT_PUT(element_obj_b); | |
368 | } | |
369 | ||
370 | end: | |
371 | return ret; | |
372 | } | |
373 | ||
374 | static | |
375 | bool (* const compare_funcs[])(const struct bt_object *, | |
376 | const struct bt_object *) = { | |
377 | [BT_OBJECT_TYPE_NULL] = bt_object_null_compare, | |
378 | [BT_OBJECT_TYPE_BOOL] = bt_object_bool_compare, | |
379 | [BT_OBJECT_TYPE_INTEGER] = bt_object_integer_compare, | |
380 | [BT_OBJECT_TYPE_FLOAT] = bt_object_float_compare, | |
381 | [BT_OBJECT_TYPE_STRING] = bt_object_string_compare, | |
382 | [BT_OBJECT_TYPE_ARRAY] = bt_object_array_compare, | |
383 | [BT_OBJECT_TYPE_MAP] = bt_object_map_compare, | |
384 | }; | |
385 | ||
a40a567e PP |
386 | void bt_object_null_freeze(struct bt_object *object) |
387 | { | |
388 | } | |
389 | ||
390 | void bt_object_generic_freeze(struct bt_object *object) | |
391 | { | |
392 | object->is_frozen = true; | |
393 | } | |
394 | ||
395 | void bt_object_array_freeze(struct bt_object *object) | |
396 | { | |
8da980bd | 397 | int i; |
a40a567e PP |
398 | struct bt_object_array *typed_array_obj = |
399 | BT_OBJECT_TO_ARRAY(object); | |
400 | ||
8da980bd | 401 | for (i = 0; i < typed_array_obj->garray->len; ++i) { |
a40a567e | 402 | struct bt_object *element_obj = |
8da980bd | 403 | g_ptr_array_index(typed_array_obj->garray, i); |
a40a567e PP |
404 | |
405 | bt_object_freeze(element_obj); | |
406 | } | |
407 | ||
408 | bt_object_generic_freeze(object); | |
409 | } | |
410 | ||
411 | void bt_object_map_freeze(struct bt_object *object) | |
412 | { | |
413 | GHashTableIter iter; | |
414 | gpointer key, element_obj; | |
415 | const struct bt_object_map *map_obj = BT_OBJECT_TO_MAP(object); | |
416 | ||
417 | g_hash_table_iter_init(&iter, map_obj->ght); | |
418 | ||
419 | while (g_hash_table_iter_next(&iter, &key, &element_obj)) { | |
420 | bt_object_freeze(element_obj); | |
421 | } | |
422 | ||
423 | bt_object_generic_freeze(object); | |
424 | } | |
425 | ||
426 | static | |
427 | void (* const freeze_funcs[])(struct bt_object *) = { | |
428 | [BT_OBJECT_TYPE_NULL] = bt_object_null_freeze, | |
429 | [BT_OBJECT_TYPE_BOOL] = bt_object_generic_freeze, | |
430 | [BT_OBJECT_TYPE_INTEGER] = bt_object_generic_freeze, | |
431 | [BT_OBJECT_TYPE_FLOAT] = bt_object_generic_freeze, | |
432 | [BT_OBJECT_TYPE_STRING] = bt_object_generic_freeze, | |
433 | [BT_OBJECT_TYPE_ARRAY] = bt_object_array_freeze, | |
434 | [BT_OBJECT_TYPE_MAP] = bt_object_map_freeze, | |
435 | }; | |
436 | ||
347829f5 PP |
437 | static |
438 | void bt_object_destroy(struct bt_ctf_ref *ref_count) | |
439 | { | |
440 | struct bt_object *object; | |
441 | ||
442 | object = container_of(ref_count, struct bt_object, ref_count); | |
443 | assert(object->type != BT_OBJECT_TYPE_UNKNOWN); | |
444 | ||
445 | if (bt_object_is_null(object)) { | |
446 | return; | |
447 | } | |
448 | ||
449 | if (destroy_funcs[object->type]) { | |
450 | destroy_funcs[object->type](object); | |
451 | } | |
452 | ||
453 | g_free(object); | |
454 | } | |
455 | ||
456 | void bt_object_get(struct bt_object *object) | |
457 | { | |
458 | if (!object) { | |
459 | goto skip; | |
460 | } | |
461 | ||
462 | bt_ctf_ref_get(&object->ref_count); | |
463 | ||
464 | skip: | |
465 | return; | |
466 | } | |
467 | ||
468 | void bt_object_put(struct bt_object *object) | |
469 | { | |
470 | if (!object) { | |
471 | goto skip; | |
472 | } | |
473 | ||
474 | bt_ctf_ref_put(&object->ref_count, bt_object_destroy); | |
475 | ||
476 | skip: | |
477 | return; | |
478 | } | |
479 | ||
a40a567e PP |
480 | enum bt_object_status bt_object_freeze(struct bt_object *object) |
481 | { | |
482 | enum bt_object_status ret = BT_OBJECT_STATUS_OK; | |
483 | ||
484 | if (!object) { | |
485 | ret = BT_OBJECT_STATUS_INVAL; | |
486 | goto end; | |
487 | } | |
488 | ||
489 | freeze_funcs[object->type](object); | |
490 | ||
491 | end: | |
492 | return ret; | |
493 | } | |
494 | ||
495 | bool bt_object_is_frozen(const struct bt_object *object) | |
496 | { | |
497 | return object && object->is_frozen; | |
498 | } | |
499 | ||
347829f5 PP |
500 | enum bt_object_type bt_object_get_type(const struct bt_object *object) |
501 | { | |
502 | if (!object) { | |
503 | return BT_OBJECT_TYPE_UNKNOWN; | |
504 | } | |
505 | ||
506 | return object->type; | |
507 | } | |
508 | ||
509 | static | |
510 | struct bt_object bt_object_create_base(enum bt_object_type type) | |
511 | { | |
512 | struct bt_object base; | |
513 | ||
514 | base.type = type; | |
a40a567e | 515 | base.is_frozen = false; |
347829f5 PP |
516 | bt_ctf_ref_init(&base.ref_count); |
517 | ||
518 | return base; | |
519 | } | |
520 | ||
521 | struct bt_object *bt_object_bool_create_init(bool val) | |
522 | { | |
523 | struct bt_object_bool *bool_obj; | |
524 | ||
525 | bool_obj = g_new0(struct bt_object_bool, 1); | |
526 | ||
527 | if (!bool_obj) { | |
528 | goto end; | |
529 | } | |
530 | ||
531 | bool_obj->base = bt_object_create_base(BT_OBJECT_TYPE_BOOL); | |
532 | bool_obj->value = val; | |
533 | ||
534 | end: | |
535 | return BT_OBJECT_FROM_CONCRETE(bool_obj); | |
536 | } | |
537 | ||
538 | struct bt_object *bt_object_bool_create(void) | |
539 | { | |
540 | return bt_object_bool_create_init(false); | |
541 | } | |
542 | ||
543 | struct bt_object *bt_object_integer_create_init(int64_t val) | |
544 | { | |
545 | struct bt_object_integer *integer_obj; | |
546 | ||
547 | integer_obj = g_new0(struct bt_object_integer, 1); | |
548 | ||
549 | if (!integer_obj) { | |
550 | goto end; | |
551 | } | |
552 | ||
553 | integer_obj->base = bt_object_create_base(BT_OBJECT_TYPE_INTEGER); | |
554 | integer_obj->value = val; | |
555 | ||
556 | end: | |
557 | return BT_OBJECT_FROM_CONCRETE(integer_obj); | |
558 | } | |
559 | ||
560 | struct bt_object *bt_object_integer_create(void) | |
561 | { | |
562 | return bt_object_integer_create_init(0); | |
563 | } | |
564 | ||
565 | struct bt_object *bt_object_float_create_init(double val) | |
566 | { | |
567 | struct bt_object_float *float_obj; | |
568 | ||
569 | float_obj = g_new0(struct bt_object_float, 1); | |
570 | ||
571 | if (!float_obj) { | |
572 | goto end; | |
573 | } | |
574 | ||
575 | float_obj->base = bt_object_create_base(BT_OBJECT_TYPE_FLOAT); | |
576 | float_obj->value = val; | |
577 | ||
578 | end: | |
579 | return BT_OBJECT_FROM_CONCRETE(float_obj); | |
580 | } | |
581 | ||
582 | struct bt_object *bt_object_float_create(void) | |
583 | { | |
584 | return bt_object_float_create_init(0.); | |
585 | } | |
586 | ||
587 | struct bt_object *bt_object_string_create_init(const char *val) | |
588 | { | |
589 | struct bt_object_string *string_obj = NULL; | |
590 | ||
591 | if (!val) { | |
592 | goto end; | |
593 | } | |
594 | ||
595 | string_obj = g_new0(struct bt_object_string, 1); | |
596 | ||
597 | if (!string_obj) { | |
598 | goto end; | |
599 | } | |
600 | ||
601 | string_obj->base = bt_object_create_base(BT_OBJECT_TYPE_STRING); | |
602 | string_obj->gstr = g_string_new(val); | |
603 | ||
604 | if (!string_obj->gstr) { | |
605 | g_free(string_obj); | |
606 | string_obj = NULL; | |
607 | goto end; | |
608 | } | |
609 | ||
610 | end: | |
611 | return BT_OBJECT_FROM_CONCRETE(string_obj); | |
612 | } | |
613 | ||
614 | struct bt_object *bt_object_string_create(void) | |
615 | { | |
616 | return bt_object_string_create_init(""); | |
617 | } | |
618 | ||
619 | struct bt_object *bt_object_array_create(void) | |
620 | { | |
621 | struct bt_object_array *array_obj; | |
622 | ||
623 | array_obj = g_new0(struct bt_object_array, 1); | |
624 | ||
625 | if (!array_obj) { | |
626 | goto end; | |
627 | } | |
628 | ||
629 | array_obj->base = bt_object_create_base(BT_OBJECT_TYPE_ARRAY); | |
a22a5f1b PP |
630 | array_obj->garray = g_ptr_array_new_full(0, |
631 | (GDestroyNotify) bt_object_put); | |
347829f5 PP |
632 | |
633 | if (!array_obj->garray) { | |
634 | g_free(array_obj); | |
635 | array_obj = NULL; | |
636 | goto end; | |
637 | } | |
638 | ||
639 | end: | |
640 | return BT_OBJECT_FROM_CONCRETE(array_obj); | |
641 | } | |
642 | ||
643 | struct bt_object *bt_object_map_create(void) | |
644 | { | |
645 | struct bt_object_map *map_obj; | |
646 | ||
647 | map_obj = g_new0(struct bt_object_map, 1); | |
648 | ||
649 | if (!map_obj) { | |
650 | goto end; | |
651 | } | |
652 | ||
653 | map_obj->base = bt_object_create_base(BT_OBJECT_TYPE_MAP); | |
654 | map_obj->ght = g_hash_table_new_full(g_direct_hash, g_direct_equal, | |
655 | NULL, (GDestroyNotify) bt_object_put); | |
656 | ||
657 | if (!map_obj->ght) { | |
658 | g_free(map_obj); | |
659 | map_obj = NULL; | |
660 | goto end; | |
661 | } | |
662 | ||
663 | end: | |
664 | return BT_OBJECT_FROM_CONCRETE(map_obj); | |
665 | } | |
666 | ||
a40a567e PP |
667 | enum bt_object_status bt_object_bool_get(const struct bt_object *bool_obj, |
668 | bool *val) | |
347829f5 | 669 | { |
a40a567e | 670 | enum bt_object_status ret = BT_OBJECT_STATUS_OK; |
347829f5 PP |
671 | struct bt_object_bool *typed_bool_obj = BT_OBJECT_TO_BOOL(bool_obj); |
672 | ||
a40a567e PP |
673 | if (!bool_obj || !bt_object_is_bool(bool_obj) || !val) { |
674 | ret = BT_OBJECT_STATUS_INVAL; | |
347829f5 PP |
675 | goto end; |
676 | } | |
677 | ||
678 | *val = typed_bool_obj->value; | |
679 | ||
680 | end: | |
681 | return ret; | |
682 | } | |
683 | ||
a40a567e | 684 | enum bt_object_status bt_object_bool_set(struct bt_object *bool_obj, bool val) |
347829f5 | 685 | { |
a40a567e | 686 | enum bt_object_status ret = BT_OBJECT_STATUS_OK; |
347829f5 PP |
687 | struct bt_object_bool *typed_bool_obj = BT_OBJECT_TO_BOOL(bool_obj); |
688 | ||
689 | if (!bool_obj || !bt_object_is_bool(bool_obj)) { | |
a40a567e PP |
690 | ret = BT_OBJECT_STATUS_INVAL; |
691 | goto end; | |
692 | } | |
693 | ||
694 | if (bool_obj->is_frozen) { | |
695 | ret = BT_OBJECT_STATUS_FROZEN; | |
347829f5 PP |
696 | goto end; |
697 | } | |
698 | ||
699 | typed_bool_obj->value = val; | |
700 | ||
701 | end: | |
702 | return ret; | |
703 | } | |
704 | ||
a40a567e PP |
705 | enum bt_object_status bt_object_integer_get(const struct bt_object *integer_obj, |
706 | int64_t *val) | |
347829f5 | 707 | { |
a40a567e | 708 | enum bt_object_status ret = BT_OBJECT_STATUS_OK; |
347829f5 PP |
709 | struct bt_object_integer *typed_integer_obj = |
710 | BT_OBJECT_TO_INTEGER(integer_obj); | |
711 | ||
a40a567e PP |
712 | if (!integer_obj || !bt_object_is_integer(integer_obj) || !val) { |
713 | ret = BT_OBJECT_STATUS_INVAL; | |
347829f5 PP |
714 | goto end; |
715 | } | |
716 | ||
717 | *val = typed_integer_obj->value; | |
718 | ||
719 | end: | |
720 | return ret; | |
721 | } | |
722 | ||
a40a567e PP |
723 | enum bt_object_status bt_object_integer_set(struct bt_object *integer_obj, |
724 | int64_t val) | |
347829f5 | 725 | { |
a40a567e | 726 | enum bt_object_status ret = BT_OBJECT_STATUS_OK; |
347829f5 PP |
727 | struct bt_object_integer *typed_integer_obj = |
728 | BT_OBJECT_TO_INTEGER(integer_obj); | |
729 | ||
730 | if (!integer_obj || !bt_object_is_integer(integer_obj)) { | |
a40a567e PP |
731 | ret = BT_OBJECT_STATUS_INVAL; |
732 | goto end; | |
733 | } | |
734 | ||
735 | if (integer_obj->is_frozen) { | |
736 | ret = BT_OBJECT_STATUS_FROZEN; | |
347829f5 PP |
737 | goto end; |
738 | } | |
739 | ||
740 | typed_integer_obj->value = val; | |
741 | ||
742 | end: | |
743 | return ret; | |
744 | } | |
745 | ||
a40a567e PP |
746 | enum bt_object_status bt_object_float_get(const struct bt_object *float_obj, |
747 | double *val) | |
347829f5 | 748 | { |
a40a567e | 749 | enum bt_object_status ret = BT_OBJECT_STATUS_OK; |
347829f5 PP |
750 | struct bt_object_float *typed_float_obj = |
751 | BT_OBJECT_TO_FLOAT(float_obj); | |
752 | ||
a40a567e PP |
753 | if (!float_obj || !bt_object_is_float(float_obj) || !val) { |
754 | ret = BT_OBJECT_STATUS_INVAL; | |
347829f5 PP |
755 | goto end; |
756 | } | |
757 | ||
758 | *val = typed_float_obj->value; | |
759 | ||
760 | end: | |
761 | return ret; | |
762 | } | |
763 | ||
a40a567e PP |
764 | enum bt_object_status bt_object_float_set(struct bt_object *float_obj, |
765 | double val) | |
347829f5 | 766 | { |
a40a567e | 767 | enum bt_object_status ret = BT_OBJECT_STATUS_OK; |
347829f5 PP |
768 | struct bt_object_float *typed_float_obj = |
769 | BT_OBJECT_TO_FLOAT(float_obj); | |
770 | ||
771 | if (!float_obj || !bt_object_is_float(float_obj)) { | |
a40a567e PP |
772 | ret = BT_OBJECT_STATUS_INVAL; |
773 | goto end; | |
774 | } | |
775 | ||
776 | if (float_obj->is_frozen) { | |
777 | ret = BT_OBJECT_STATUS_FROZEN; | |
347829f5 PP |
778 | goto end; |
779 | } | |
780 | ||
781 | typed_float_obj->value = val; | |
782 | ||
783 | end: | |
784 | return ret; | |
785 | } | |
786 | ||
a40a567e PP |
787 | enum bt_object_status bt_object_string_get(const struct bt_object *string_obj, |
788 | const char **val) | |
347829f5 | 789 | { |
a40a567e | 790 | enum bt_object_status ret = BT_OBJECT_STATUS_OK; |
347829f5 PP |
791 | struct bt_object_string *typed_string_obj = |
792 | BT_OBJECT_TO_STRING(string_obj); | |
793 | ||
a40a567e PP |
794 | if (!string_obj || !bt_object_is_string(string_obj) || !val) { |
795 | ret = BT_OBJECT_STATUS_INVAL; | |
347829f5 PP |
796 | goto end; |
797 | } | |
798 | ||
a40a567e | 799 | *val = typed_string_obj->gstr->str; |
347829f5 PP |
800 | |
801 | end: | |
802 | return ret; | |
803 | } | |
804 | ||
a40a567e PP |
805 | enum bt_object_status bt_object_string_set(struct bt_object *string_obj, |
806 | const char *val) | |
347829f5 | 807 | { |
a40a567e | 808 | enum bt_object_status ret = BT_OBJECT_STATUS_OK; |
347829f5 PP |
809 | struct bt_object_string *typed_string_obj = |
810 | BT_OBJECT_TO_STRING(string_obj); | |
811 | ||
812 | if (!string_obj || !bt_object_is_string(string_obj) || !val) { | |
a40a567e PP |
813 | ret = BT_OBJECT_STATUS_INVAL; |
814 | goto end; | |
815 | } | |
816 | ||
817 | if (string_obj->is_frozen) { | |
818 | ret = BT_OBJECT_STATUS_FROZEN; | |
347829f5 PP |
819 | goto end; |
820 | } | |
821 | ||
822 | g_string_assign(typed_string_obj->gstr, val); | |
823 | ||
824 | end: | |
825 | return ret; | |
826 | } | |
827 | ||
828 | int bt_object_array_size(const struct bt_object *array_obj) | |
829 | { | |
a40a567e | 830 | int ret; |
347829f5 PP |
831 | struct bt_object_array *typed_array_obj = |
832 | BT_OBJECT_TO_ARRAY(array_obj); | |
833 | ||
834 | if (!array_obj || !bt_object_is_array(array_obj)) { | |
a40a567e | 835 | ret = BT_OBJECT_STATUS_INVAL; |
347829f5 PP |
836 | goto end; |
837 | } | |
838 | ||
839 | ret = (int) typed_array_obj->garray->len; | |
840 | ||
841 | end: | |
842 | return ret; | |
843 | } | |
844 | ||
845 | bool bt_object_array_is_empty(const struct bt_object *array_obj) | |
846 | { | |
847 | return bt_object_array_size(array_obj) == 0; | |
848 | } | |
849 | ||
850 | struct bt_object *bt_object_array_get(const struct bt_object *array_obj, | |
851 | size_t index) | |
852 | { | |
853 | struct bt_object *ret; | |
854 | struct bt_object_array *typed_array_obj = | |
855 | BT_OBJECT_TO_ARRAY(array_obj); | |
856 | ||
857 | if (!array_obj || !bt_object_is_array(array_obj) || | |
858 | index >= typed_array_obj->garray->len) { | |
859 | ret = NULL; | |
860 | goto end; | |
861 | } | |
862 | ||
a22a5f1b | 863 | ret = g_ptr_array_index(typed_array_obj->garray, index); |
347829f5 PP |
864 | bt_object_get(ret); |
865 | ||
866 | end: | |
867 | return ret; | |
868 | } | |
869 | ||
a40a567e | 870 | enum bt_object_status bt_object_array_append(struct bt_object *array_obj, |
347829f5 PP |
871 | struct bt_object *element_obj) |
872 | { | |
a40a567e | 873 | enum bt_object_status ret = BT_OBJECT_STATUS_OK; |
347829f5 PP |
874 | struct bt_object_array *typed_array_obj = |
875 | BT_OBJECT_TO_ARRAY(array_obj); | |
876 | ||
877 | if (!array_obj || !bt_object_is_array(array_obj) || !element_obj) { | |
a40a567e PP |
878 | ret = BT_OBJECT_STATUS_INVAL; |
879 | goto end; | |
880 | } | |
881 | ||
882 | if (array_obj->is_frozen) { | |
883 | ret = BT_OBJECT_STATUS_FROZEN; | |
347829f5 PP |
884 | goto end; |
885 | } | |
886 | ||
a22a5f1b | 887 | g_ptr_array_add(typed_array_obj->garray, element_obj); |
347829f5 PP |
888 | bt_object_get(element_obj); |
889 | ||
890 | end: | |
891 | return ret; | |
892 | } | |
893 | ||
a40a567e PP |
894 | enum bt_object_status bt_object_array_append_bool(struct bt_object *array_obj, |
895 | bool val) | |
347829f5 | 896 | { |
a40a567e | 897 | enum bt_object_status ret; |
347829f5 PP |
898 | struct bt_object *bool_obj = NULL; |
899 | ||
900 | bool_obj = bt_object_bool_create_init(val); | |
901 | ret = bt_object_array_append(array_obj, bool_obj); | |
902 | bt_object_put(bool_obj); | |
903 | ||
904 | return ret; | |
905 | } | |
906 | ||
a40a567e PP |
907 | enum bt_object_status bt_object_array_append_integer( |
908 | struct bt_object *array_obj, int64_t val) | |
347829f5 | 909 | { |
a40a567e | 910 | enum bt_object_status ret; |
347829f5 PP |
911 | struct bt_object *integer_obj = NULL; |
912 | ||
913 | integer_obj = bt_object_integer_create_init(val); | |
914 | ret = bt_object_array_append(array_obj, integer_obj); | |
915 | bt_object_put(integer_obj); | |
916 | ||
917 | return ret; | |
918 | } | |
919 | ||
a40a567e PP |
920 | enum bt_object_status bt_object_array_append_float(struct bt_object *array_obj, |
921 | double val) | |
347829f5 | 922 | { |
a40a567e | 923 | enum bt_object_status ret; |
347829f5 PP |
924 | struct bt_object *float_obj = NULL; |
925 | ||
926 | float_obj = bt_object_float_create_init(val); | |
927 | ret = bt_object_array_append(array_obj, float_obj); | |
928 | bt_object_put(float_obj); | |
929 | ||
930 | return ret; | |
931 | } | |
932 | ||
a40a567e PP |
933 | enum bt_object_status bt_object_array_append_string(struct bt_object *array_obj, |
934 | const char *val) | |
347829f5 | 935 | { |
a40a567e | 936 | enum bt_object_status ret; |
347829f5 PP |
937 | struct bt_object *string_obj = NULL; |
938 | ||
939 | string_obj = bt_object_string_create_init(val); | |
940 | ret = bt_object_array_append(array_obj, string_obj); | |
941 | bt_object_put(string_obj); | |
942 | ||
943 | return ret; | |
944 | } | |
945 | ||
a40a567e | 946 | enum bt_object_status bt_object_array_append_array(struct bt_object *array_obj) |
347829f5 | 947 | { |
a40a567e | 948 | enum bt_object_status ret; |
347829f5 PP |
949 | struct bt_object *empty_array_obj = NULL; |
950 | ||
951 | empty_array_obj = bt_object_array_create(); | |
952 | ret = bt_object_array_append(array_obj, empty_array_obj); | |
953 | bt_object_put(empty_array_obj); | |
954 | ||
955 | return ret; | |
956 | } | |
957 | ||
a40a567e | 958 | enum bt_object_status bt_object_array_append_map(struct bt_object *array_obj) |
347829f5 | 959 | { |
a40a567e | 960 | enum bt_object_status ret; |
347829f5 PP |
961 | struct bt_object *map_obj = NULL; |
962 | ||
963 | map_obj = bt_object_map_create(); | |
964 | ret = bt_object_array_append(array_obj, map_obj); | |
965 | bt_object_put(map_obj); | |
966 | ||
967 | return ret; | |
968 | } | |
969 | ||
a40a567e PP |
970 | enum bt_object_status bt_object_array_set(struct bt_object *array_obj, |
971 | size_t index, struct bt_object *element_obj) | |
3695540c | 972 | { |
a40a567e | 973 | enum bt_object_status ret = BT_OBJECT_STATUS_OK; |
3695540c PP |
974 | struct bt_object_array *typed_array_obj = |
975 | BT_OBJECT_TO_ARRAY(array_obj); | |
976 | ||
977 | if (!array_obj || !bt_object_is_array(array_obj) || !element_obj || | |
978 | index >= typed_array_obj->garray->len) { | |
a40a567e PP |
979 | ret = BT_OBJECT_STATUS_INVAL; |
980 | goto end; | |
981 | } | |
982 | ||
983 | if (array_obj->is_frozen) { | |
984 | ret = BT_OBJECT_STATUS_FROZEN; | |
3695540c PP |
985 | goto end; |
986 | } | |
987 | ||
988 | bt_object_put(g_ptr_array_index(typed_array_obj->garray, index)); | |
989 | g_ptr_array_index(typed_array_obj->garray, index) = element_obj; | |
990 | bt_object_get(element_obj); | |
991 | ||
992 | end: | |
993 | return ret; | |
994 | } | |
995 | ||
347829f5 PP |
996 | int bt_object_map_size(const struct bt_object *map_obj) |
997 | { | |
998 | int ret; | |
999 | struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj); | |
1000 | ||
1001 | if (!map_obj || !bt_object_is_map(map_obj)) { | |
a40a567e | 1002 | ret = BT_OBJECT_STATUS_INVAL; |
347829f5 PP |
1003 | goto end; |
1004 | } | |
1005 | ||
1006 | ret = (int) g_hash_table_size(typed_map_obj->ght); | |
1007 | ||
1008 | end: | |
1009 | return ret; | |
1010 | } | |
1011 | ||
1012 | bool bt_object_map_is_empty(const struct bt_object *map_obj) | |
1013 | { | |
1014 | return bt_object_map_size(map_obj) == 0; | |
1015 | } | |
1016 | ||
1017 | struct bt_object *bt_object_map_get(const struct bt_object *map_obj, | |
1018 | const char *key) | |
1019 | { | |
1020 | GQuark quark; | |
1021 | struct bt_object *ret; | |
1022 | struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj); | |
1023 | ||
1024 | if (!map_obj || !bt_object_is_map(map_obj) || !key) { | |
1025 | ret = NULL; | |
1026 | goto end; | |
1027 | } | |
1028 | ||
1029 | quark = g_quark_from_string(key); | |
1030 | ret = g_hash_table_lookup(typed_map_obj->ght, GUINT_TO_POINTER(quark)); | |
1031 | ||
1032 | if (ret) { | |
1033 | bt_object_get(ret); | |
1034 | } | |
1035 | ||
1036 | end: | |
1037 | return ret; | |
1038 | } | |
1039 | ||
1040 | bool bt_object_map_has_key(const struct bt_object *map_obj, const char *key) | |
1041 | { | |
1042 | bool ret; | |
1043 | GQuark quark; | |
1044 | struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj); | |
1045 | ||
1046 | if (!map_obj || !bt_object_is_map(map_obj) || !key) { | |
1047 | ret = false; | |
1048 | goto end; | |
1049 | } | |
1050 | ||
1051 | quark = g_quark_from_string(key); | |
1052 | ret = g_hash_table_contains(typed_map_obj->ght, | |
1053 | GUINT_TO_POINTER(quark)); | |
1054 | ||
1055 | end: | |
1056 | return ret; | |
1057 | } | |
1058 | ||
a40a567e PP |
1059 | enum bt_object_status bt_object_map_insert(struct bt_object *map_obj, |
1060 | const char *key, struct bt_object *element_obj) | |
347829f5 | 1061 | { |
347829f5 | 1062 | GQuark quark; |
a40a567e | 1063 | enum bt_object_status ret = BT_OBJECT_STATUS_OK; |
347829f5 PP |
1064 | struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj); |
1065 | ||
1066 | if (!map_obj || !bt_object_is_map(map_obj) || !key || !element_obj) { | |
a40a567e PP |
1067 | ret = BT_OBJECT_STATUS_INVAL; |
1068 | goto end; | |
1069 | } | |
1070 | ||
1071 | if (map_obj->is_frozen) { | |
1072 | ret = BT_OBJECT_STATUS_FROZEN; | |
347829f5 PP |
1073 | goto end; |
1074 | } | |
1075 | ||
1076 | quark = g_quark_from_string(key); | |
1077 | g_hash_table_insert(typed_map_obj->ght, | |
1078 | GUINT_TO_POINTER(quark), element_obj); | |
1079 | bt_object_get(element_obj); | |
1080 | ||
1081 | end: | |
1082 | return ret; | |
1083 | } | |
1084 | ||
a40a567e | 1085 | enum bt_object_status bt_object_map_insert_bool(struct bt_object *map_obj, |
347829f5 PP |
1086 | const char *key, bool val) |
1087 | { | |
a40a567e | 1088 | enum bt_object_status ret; |
347829f5 PP |
1089 | struct bt_object *bool_obj = NULL; |
1090 | ||
1091 | bool_obj = bt_object_bool_create_init(val); | |
1092 | ret = bt_object_map_insert(map_obj, key, bool_obj); | |
1093 | bt_object_put(bool_obj); | |
1094 | ||
1095 | return ret; | |
1096 | } | |
1097 | ||
a40a567e | 1098 | enum bt_object_status bt_object_map_insert_integer(struct bt_object *map_obj, |
347829f5 PP |
1099 | const char *key, int64_t val) |
1100 | { | |
a40a567e | 1101 | enum bt_object_status ret; |
347829f5 PP |
1102 | struct bt_object *integer_obj = NULL; |
1103 | ||
1104 | integer_obj = bt_object_integer_create_init(val); | |
1105 | ret = bt_object_map_insert(map_obj, key, integer_obj); | |
1106 | bt_object_put(integer_obj); | |
1107 | ||
1108 | return ret; | |
1109 | } | |
1110 | ||
a40a567e | 1111 | enum bt_object_status bt_object_map_insert_float(struct bt_object *map_obj, |
347829f5 PP |
1112 | const char *key, double val) |
1113 | { | |
a40a567e | 1114 | enum bt_object_status ret; |
347829f5 PP |
1115 | struct bt_object *float_obj = NULL; |
1116 | ||
1117 | float_obj = bt_object_float_create_init(val); | |
1118 | ret = bt_object_map_insert(map_obj, key, float_obj); | |
1119 | bt_object_put(float_obj); | |
1120 | ||
1121 | return ret; | |
1122 | } | |
1123 | ||
a40a567e | 1124 | enum bt_object_status bt_object_map_insert_string(struct bt_object *map_obj, |
347829f5 PP |
1125 | const char *key, const char *val) |
1126 | { | |
a40a567e | 1127 | enum bt_object_status ret; |
347829f5 PP |
1128 | struct bt_object *string_obj = NULL; |
1129 | ||
1130 | string_obj = bt_object_string_create_init(val); | |
1131 | ret = bt_object_map_insert(map_obj, key, string_obj); | |
1132 | bt_object_put(string_obj); | |
1133 | ||
1134 | return ret; | |
1135 | } | |
1136 | ||
a40a567e | 1137 | enum bt_object_status bt_object_map_insert_array(struct bt_object *map_obj, |
347829f5 PP |
1138 | const char *key) |
1139 | { | |
a40a567e | 1140 | enum bt_object_status ret; |
347829f5 PP |
1141 | struct bt_object *array_obj = NULL; |
1142 | ||
1143 | array_obj = bt_object_array_create(); | |
1144 | ret = bt_object_map_insert(map_obj, key, array_obj); | |
1145 | bt_object_put(array_obj); | |
1146 | ||
1147 | return ret; | |
1148 | } | |
1149 | ||
a40a567e | 1150 | enum bt_object_status bt_object_map_insert_map(struct bt_object *map_obj, |
347829f5 PP |
1151 | const char *key) |
1152 | { | |
a40a567e | 1153 | enum bt_object_status ret; |
347829f5 PP |
1154 | struct bt_object *empty_map_obj = NULL; |
1155 | ||
1156 | empty_map_obj = bt_object_map_create(); | |
1157 | ret = bt_object_map_insert(map_obj, key, empty_map_obj); | |
1158 | bt_object_put(empty_map_obj); | |
1159 | ||
1160 | return ret; | |
1161 | } | |
1162 | ||
a40a567e | 1163 | enum bt_object_status bt_object_map_foreach(const struct bt_object *map_obj, |
347829f5 PP |
1164 | bt_object_map_foreach_cb cb, void *data) |
1165 | { | |
4a512e75 | 1166 | enum bt_object_status ret = BT_OBJECT_STATUS_OK; |
347829f5 PP |
1167 | gpointer key, element_obj; |
1168 | GHashTableIter iter; | |
1169 | struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj); | |
1170 | ||
1171 | if (!map_obj || !bt_object_is_map(map_obj) || !cb) { | |
a40a567e | 1172 | ret = BT_OBJECT_STATUS_INVAL; |
347829f5 PP |
1173 | goto end; |
1174 | } | |
1175 | ||
1176 | g_hash_table_iter_init(&iter, typed_map_obj->ght); | |
1177 | ||
1178 | while (g_hash_table_iter_next(&iter, &key, &element_obj)) { | |
1179 | const char *key_str = g_quark_to_string((unsigned long) key); | |
1180 | ||
1181 | if (!cb(key_str, element_obj, data)) { | |
4a512e75 | 1182 | ret = BT_OBJECT_STATUS_CANCELLED; |
347829f5 PP |
1183 | break; |
1184 | } | |
1185 | } | |
1186 | ||
1187 | end: | |
1188 | return ret; | |
1189 | } | |
1190 | ||
1191 | struct bt_object *bt_object_copy(const struct bt_object *object) | |
1192 | { | |
1193 | struct bt_object *copy_obj = NULL; | |
1194 | ||
1195 | if (!object) { | |
1196 | goto end; | |
1197 | } | |
1198 | ||
1199 | copy_obj = copy_funcs[object->type](object); | |
1200 | ||
1201 | end: | |
1202 | return copy_obj; | |
1203 | } | |
1204 | ||
1205 | bool bt_object_compare(const struct bt_object *object_a, | |
1206 | const struct bt_object *object_b) | |
1207 | { | |
1208 | bool ret = false; | |
1209 | ||
1210 | if (!object_a || !object_b) { | |
1211 | goto end; | |
1212 | } | |
1213 | ||
1214 | if (object_a->type != object_b->type) { | |
1215 | goto end; | |
1216 | } | |
1217 | ||
1218 | ret = compare_funcs[object_a->type](object_a, object_b); | |
1219 | ||
1220 | end: | |
1221 | return ret; | |
1222 | } |