ir: consolidate reference counting functions
[babeltrace.git] / lib / objects.c
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/ref-internal.h>
33 #include <babeltrace/compiler.h>
34 #include <babeltrace/objects.h>
35 #include <glib.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_ref ref_count;
48 bool is_frozen;
49 };
50
51 static
52 struct bt_object bt_object_null_instance = {
53 .type = BT_OBJECT_TYPE_NULL,
54 .is_frozen = true,
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;
81 GPtrArray *garray;
82 };
83
84 struct bt_object_map {
85 struct bt_object base;
86 GHashTable *ght;
87 };
88
89 static
90 void bt_object_destroy(struct bt_ref *ref_count);
91
92 static
93 void bt_object_string_destroy(struct bt_object *object)
94 {
95 g_string_free(BT_OBJECT_TO_STRING(object)->gstr, TRUE);
96 }
97
98 static
99 void bt_object_array_destroy(struct bt_object *object)
100 {
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);
106 }
107
108 static
109 void bt_object_map_destroy(struct bt_object *object)
110 {
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 */
116 g_hash_table_destroy(BT_OBJECT_TO_MAP(object)->ght);
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 {
166 int i;
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
178 for (i = 0; i < typed_array_obj->garray->len; ++i) {
179 struct bt_object *element_obj_copy;
180 struct bt_object *element_obj =
181 bt_object_array_get(array_obj, i);
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 {
310 int i;
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
320 for (i = 0; i < array_obj_a->garray->len; ++i) {
321 struct bt_object *element_obj_a;
322 struct bt_object *element_obj_b;
323
324 element_obj_a = bt_object_array_get(object_a, i);
325 element_obj_b = bt_object_array_get(object_b, i);
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
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 {
400 int i;
401 struct bt_object_array *typed_array_obj =
402 BT_OBJECT_TO_ARRAY(object);
403
404 for (i = 0; i < typed_array_obj->garray->len; ++i) {
405 struct bt_object *element_obj =
406 g_ptr_array_index(typed_array_obj->garray, i);
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
440 static
441 void bt_object_destroy(struct bt_ref *ref_count)
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 {
461 if (object && !bt_object_is_null(object)) {
462 bt_ref_get(&object->ref_count);
463 }
464
465 return;
466 }
467
468 void bt_object_put(struct bt_object *object)
469 {
470 if (object && !bt_object_is_null(object)) {
471 bt_ref_put(&object->ref_count);
472 }
473 }
474
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
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;
510 base.is_frozen = false;
511 bt_ref_init(&base.ref_count, bt_object_destroy);
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);
625 array_obj->garray = g_ptr_array_new_full(0,
626 (GDestroyNotify) bt_object_put);
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
662 enum bt_object_status bt_object_bool_get(const struct bt_object *bool_obj,
663 bool *val)
664 {
665 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
666 struct bt_object_bool *typed_bool_obj = BT_OBJECT_TO_BOOL(bool_obj);
667
668 if (!bool_obj || !bt_object_is_bool(bool_obj) || !val) {
669 ret = BT_OBJECT_STATUS_INVAL;
670 goto end;
671 }
672
673 *val = typed_bool_obj->value;
674
675 end:
676 return ret;
677 }
678
679 enum bt_object_status bt_object_bool_set(struct bt_object *bool_obj, bool val)
680 {
681 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
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)) {
685 ret = BT_OBJECT_STATUS_INVAL;
686 goto end;
687 }
688
689 if (bool_obj->is_frozen) {
690 ret = BT_OBJECT_STATUS_FROZEN;
691 goto end;
692 }
693
694 typed_bool_obj->value = val;
695
696 end:
697 return ret;
698 }
699
700 enum bt_object_status bt_object_integer_get(const struct bt_object *integer_obj,
701 int64_t *val)
702 {
703 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
704 struct bt_object_integer *typed_integer_obj =
705 BT_OBJECT_TO_INTEGER(integer_obj);
706
707 if (!integer_obj || !bt_object_is_integer(integer_obj) || !val) {
708 ret = BT_OBJECT_STATUS_INVAL;
709 goto end;
710 }
711
712 *val = typed_integer_obj->value;
713
714 end:
715 return ret;
716 }
717
718 enum bt_object_status bt_object_integer_set(struct bt_object *integer_obj,
719 int64_t val)
720 {
721 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
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)) {
726 ret = BT_OBJECT_STATUS_INVAL;
727 goto end;
728 }
729
730 if (integer_obj->is_frozen) {
731 ret = BT_OBJECT_STATUS_FROZEN;
732 goto end;
733 }
734
735 typed_integer_obj->value = val;
736
737 end:
738 return ret;
739 }
740
741 enum bt_object_status bt_object_float_get(const struct bt_object *float_obj,
742 double *val)
743 {
744 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
745 struct bt_object_float *typed_float_obj =
746 BT_OBJECT_TO_FLOAT(float_obj);
747
748 if (!float_obj || !bt_object_is_float(float_obj) || !val) {
749 ret = BT_OBJECT_STATUS_INVAL;
750 goto end;
751 }
752
753 *val = typed_float_obj->value;
754
755 end:
756 return ret;
757 }
758
759 enum bt_object_status bt_object_float_set(struct bt_object *float_obj,
760 double val)
761 {
762 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
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)) {
767 ret = BT_OBJECT_STATUS_INVAL;
768 goto end;
769 }
770
771 if (float_obj->is_frozen) {
772 ret = BT_OBJECT_STATUS_FROZEN;
773 goto end;
774 }
775
776 typed_float_obj->value = val;
777
778 end:
779 return ret;
780 }
781
782 enum bt_object_status bt_object_string_get(const struct bt_object *string_obj,
783 const char **val)
784 {
785 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
786 struct bt_object_string *typed_string_obj =
787 BT_OBJECT_TO_STRING(string_obj);
788
789 if (!string_obj || !bt_object_is_string(string_obj) || !val) {
790 ret = BT_OBJECT_STATUS_INVAL;
791 goto end;
792 }
793
794 *val = typed_string_obj->gstr->str;
795
796 end:
797 return ret;
798 }
799
800 enum bt_object_status bt_object_string_set(struct bt_object *string_obj,
801 const char *val)
802 {
803 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
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) {
808 ret = BT_OBJECT_STATUS_INVAL;
809 goto end;
810 }
811
812 if (string_obj->is_frozen) {
813 ret = BT_OBJECT_STATUS_FROZEN;
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 {
825 int ret;
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)) {
830 ret = BT_OBJECT_STATUS_INVAL;
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
858 ret = g_ptr_array_index(typed_array_obj->garray, index);
859 bt_object_get(ret);
860
861 end:
862 return ret;
863 }
864
865 enum bt_object_status bt_object_array_append(struct bt_object *array_obj,
866 struct bt_object *element_obj)
867 {
868 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
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) {
873 ret = BT_OBJECT_STATUS_INVAL;
874 goto end;
875 }
876
877 if (array_obj->is_frozen) {
878 ret = BT_OBJECT_STATUS_FROZEN;
879 goto end;
880 }
881
882 g_ptr_array_add(typed_array_obj->garray, element_obj);
883 bt_object_get(element_obj);
884
885 end:
886 return ret;
887 }
888
889 enum bt_object_status bt_object_array_append_bool(struct bt_object *array_obj,
890 bool val)
891 {
892 enum bt_object_status ret;
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
902 enum bt_object_status bt_object_array_append_integer(
903 struct bt_object *array_obj, int64_t val)
904 {
905 enum bt_object_status ret;
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
915 enum bt_object_status bt_object_array_append_float(struct bt_object *array_obj,
916 double val)
917 {
918 enum bt_object_status ret;
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
928 enum bt_object_status bt_object_array_append_string(struct bt_object *array_obj,
929 const char *val)
930 {
931 enum bt_object_status ret;
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
941 enum bt_object_status bt_object_array_append_array(struct bt_object *array_obj)
942 {
943 enum bt_object_status ret;
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
953 enum bt_object_status bt_object_array_append_map(struct bt_object *array_obj)
954 {
955 enum bt_object_status ret;
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
965 enum bt_object_status bt_object_array_set(struct bt_object *array_obj,
966 size_t index, struct bt_object *element_obj)
967 {
968 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
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) {
974 ret = BT_OBJECT_STATUS_INVAL;
975 goto end;
976 }
977
978 if (array_obj->is_frozen) {
979 ret = BT_OBJECT_STATUS_FROZEN;
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
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)) {
997 ret = BT_OBJECT_STATUS_INVAL;
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
1054 enum bt_object_status bt_object_map_insert(struct bt_object *map_obj,
1055 const char *key, struct bt_object *element_obj)
1056 {
1057 GQuark quark;
1058 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
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) {
1062 ret = BT_OBJECT_STATUS_INVAL;
1063 goto end;
1064 }
1065
1066 if (map_obj->is_frozen) {
1067 ret = BT_OBJECT_STATUS_FROZEN;
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
1080 enum bt_object_status bt_object_map_insert_bool(struct bt_object *map_obj,
1081 const char *key, bool val)
1082 {
1083 enum bt_object_status ret;
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
1093 enum bt_object_status bt_object_map_insert_integer(struct bt_object *map_obj,
1094 const char *key, int64_t val)
1095 {
1096 enum bt_object_status ret;
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
1106 enum bt_object_status bt_object_map_insert_float(struct bt_object *map_obj,
1107 const char *key, double val)
1108 {
1109 enum bt_object_status ret;
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
1119 enum bt_object_status bt_object_map_insert_string(struct bt_object *map_obj,
1120 const char *key, const char *val)
1121 {
1122 enum bt_object_status ret;
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
1132 enum bt_object_status bt_object_map_insert_array(struct bt_object *map_obj,
1133 const char *key)
1134 {
1135 enum bt_object_status ret;
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
1145 enum bt_object_status bt_object_map_insert_map(struct bt_object *map_obj,
1146 const char *key)
1147 {
1148 enum bt_object_status ret;
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
1158 enum bt_object_status bt_object_map_foreach(const struct bt_object *map_obj,
1159 bt_object_map_foreach_cb cb, void *data)
1160 {
1161 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
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) {
1167 ret = BT_OBJECT_STATUS_INVAL;
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)) {
1177 ret = BT_OBJECT_STATUS_CANCELLED;
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 }
This page took 0.058605 seconds and 4 git commands to generate.