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