4d31d2ee0c9057e9c4e1a1675897708c66157803
[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/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;
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_string_destroy(struct bt_object *object)
91 {
92 g_string_free(BT_OBJECT_TO_STRING(object)->gstr, TRUE);
93 }
94
95 static
96 void bt_object_array_destroy(struct bt_object *object)
97 {
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);
103 }
104
105 static
106 void bt_object_map_destroy(struct bt_object *object)
107 {
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 */
113 g_hash_table_destroy(BT_OBJECT_TO_MAP(object)->ght);
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 {
163 int i;
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
175 for (i = 0; i < typed_array_obj->garray->len; ++i) {
176 struct bt_object *element_obj_copy;
177 struct bt_object *element_obj =
178 bt_object_array_get(array_obj, i);
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 {
307 int i;
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
317 for (i = 0; i < array_obj_a->garray->len; ++i) {
318 struct bt_object *element_obj_a;
319 struct bt_object *element_obj_b;
320
321 element_obj_a = bt_object_array_get(object_a, i);
322 element_obj_b = bt_object_array_get(object_b, i);
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
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 {
397 int i;
398 struct bt_object_array *typed_array_obj =
399 BT_OBJECT_TO_ARRAY(object);
400
401 for (i = 0; i < typed_array_obj->garray->len; ++i) {
402 struct bt_object *element_obj =
403 g_ptr_array_index(typed_array_obj->garray, i);
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
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
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
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;
515 base.is_frozen = false;
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);
630 array_obj->garray = g_ptr_array_new_full(0,
631 (GDestroyNotify) bt_object_put);
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
667 enum bt_object_status bt_object_bool_get(const struct bt_object *bool_obj,
668 bool *val)
669 {
670 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
671 struct bt_object_bool *typed_bool_obj = BT_OBJECT_TO_BOOL(bool_obj);
672
673 if (!bool_obj || !bt_object_is_bool(bool_obj) || !val) {
674 ret = BT_OBJECT_STATUS_INVAL;
675 goto end;
676 }
677
678 *val = typed_bool_obj->value;
679
680 end:
681 return ret;
682 }
683
684 enum bt_object_status bt_object_bool_set(struct bt_object *bool_obj, bool val)
685 {
686 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
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)) {
690 ret = BT_OBJECT_STATUS_INVAL;
691 goto end;
692 }
693
694 if (bool_obj->is_frozen) {
695 ret = BT_OBJECT_STATUS_FROZEN;
696 goto end;
697 }
698
699 typed_bool_obj->value = val;
700
701 end:
702 return ret;
703 }
704
705 enum bt_object_status bt_object_integer_get(const struct bt_object *integer_obj,
706 int64_t *val)
707 {
708 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
709 struct bt_object_integer *typed_integer_obj =
710 BT_OBJECT_TO_INTEGER(integer_obj);
711
712 if (!integer_obj || !bt_object_is_integer(integer_obj) || !val) {
713 ret = BT_OBJECT_STATUS_INVAL;
714 goto end;
715 }
716
717 *val = typed_integer_obj->value;
718
719 end:
720 return ret;
721 }
722
723 enum bt_object_status bt_object_integer_set(struct bt_object *integer_obj,
724 int64_t val)
725 {
726 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
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)) {
731 ret = BT_OBJECT_STATUS_INVAL;
732 goto end;
733 }
734
735 if (integer_obj->is_frozen) {
736 ret = BT_OBJECT_STATUS_FROZEN;
737 goto end;
738 }
739
740 typed_integer_obj->value = val;
741
742 end:
743 return ret;
744 }
745
746 enum bt_object_status bt_object_float_get(const struct bt_object *float_obj,
747 double *val)
748 {
749 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
750 struct bt_object_float *typed_float_obj =
751 BT_OBJECT_TO_FLOAT(float_obj);
752
753 if (!float_obj || !bt_object_is_float(float_obj) || !val) {
754 ret = BT_OBJECT_STATUS_INVAL;
755 goto end;
756 }
757
758 *val = typed_float_obj->value;
759
760 end:
761 return ret;
762 }
763
764 enum bt_object_status bt_object_float_set(struct bt_object *float_obj,
765 double val)
766 {
767 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
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)) {
772 ret = BT_OBJECT_STATUS_INVAL;
773 goto end;
774 }
775
776 if (float_obj->is_frozen) {
777 ret = BT_OBJECT_STATUS_FROZEN;
778 goto end;
779 }
780
781 typed_float_obj->value = val;
782
783 end:
784 return ret;
785 }
786
787 enum bt_object_status bt_object_string_get(const struct bt_object *string_obj,
788 const char **val)
789 {
790 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
791 struct bt_object_string *typed_string_obj =
792 BT_OBJECT_TO_STRING(string_obj);
793
794 if (!string_obj || !bt_object_is_string(string_obj) || !val) {
795 ret = BT_OBJECT_STATUS_INVAL;
796 goto end;
797 }
798
799 *val = typed_string_obj->gstr->str;
800
801 end:
802 return ret;
803 }
804
805 enum bt_object_status bt_object_string_set(struct bt_object *string_obj,
806 const char *val)
807 {
808 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
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) {
813 ret = BT_OBJECT_STATUS_INVAL;
814 goto end;
815 }
816
817 if (string_obj->is_frozen) {
818 ret = BT_OBJECT_STATUS_FROZEN;
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 {
830 int ret;
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)) {
835 ret = BT_OBJECT_STATUS_INVAL;
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
863 ret = g_ptr_array_index(typed_array_obj->garray, index);
864 bt_object_get(ret);
865
866 end:
867 return ret;
868 }
869
870 enum bt_object_status bt_object_array_append(struct bt_object *array_obj,
871 struct bt_object *element_obj)
872 {
873 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
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) {
878 ret = BT_OBJECT_STATUS_INVAL;
879 goto end;
880 }
881
882 if (array_obj->is_frozen) {
883 ret = BT_OBJECT_STATUS_FROZEN;
884 goto end;
885 }
886
887 g_ptr_array_add(typed_array_obj->garray, element_obj);
888 bt_object_get(element_obj);
889
890 end:
891 return ret;
892 }
893
894 enum bt_object_status bt_object_array_append_bool(struct bt_object *array_obj,
895 bool val)
896 {
897 enum bt_object_status ret;
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
907 enum bt_object_status bt_object_array_append_integer(
908 struct bt_object *array_obj, int64_t val)
909 {
910 enum bt_object_status ret;
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
920 enum bt_object_status bt_object_array_append_float(struct bt_object *array_obj,
921 double val)
922 {
923 enum bt_object_status ret;
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
933 enum bt_object_status bt_object_array_append_string(struct bt_object *array_obj,
934 const char *val)
935 {
936 enum bt_object_status ret;
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
946 enum bt_object_status bt_object_array_append_array(struct bt_object *array_obj)
947 {
948 enum bt_object_status ret;
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
958 enum bt_object_status bt_object_array_append_map(struct bt_object *array_obj)
959 {
960 enum bt_object_status ret;
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
970 enum bt_object_status bt_object_array_set(struct bt_object *array_obj,
971 size_t index, struct bt_object *element_obj)
972 {
973 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
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) {
979 ret = BT_OBJECT_STATUS_INVAL;
980 goto end;
981 }
982
983 if (array_obj->is_frozen) {
984 ret = BT_OBJECT_STATUS_FROZEN;
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
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)) {
1002 ret = BT_OBJECT_STATUS_INVAL;
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
1059 enum bt_object_status bt_object_map_insert(struct bt_object *map_obj,
1060 const char *key, struct bt_object *element_obj)
1061 {
1062 GQuark quark;
1063 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
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) {
1067 ret = BT_OBJECT_STATUS_INVAL;
1068 goto end;
1069 }
1070
1071 if (map_obj->is_frozen) {
1072 ret = BT_OBJECT_STATUS_FROZEN;
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
1085 enum bt_object_status bt_object_map_insert_bool(struct bt_object *map_obj,
1086 const char *key, bool val)
1087 {
1088 enum bt_object_status ret;
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
1098 enum bt_object_status bt_object_map_insert_integer(struct bt_object *map_obj,
1099 const char *key, int64_t val)
1100 {
1101 enum bt_object_status ret;
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
1111 enum bt_object_status bt_object_map_insert_float(struct bt_object *map_obj,
1112 const char *key, double val)
1113 {
1114 enum bt_object_status ret;
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
1124 enum bt_object_status bt_object_map_insert_string(struct bt_object *map_obj,
1125 const char *key, const char *val)
1126 {
1127 enum bt_object_status ret;
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
1137 enum bt_object_status bt_object_map_insert_array(struct bt_object *map_obj,
1138 const char *key)
1139 {
1140 enum bt_object_status ret;
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
1150 enum bt_object_status bt_object_map_insert_map(struct bt_object *map_obj,
1151 const char *key)
1152 {
1153 enum bt_object_status ret;
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
1163 enum bt_object_status bt_object_map_foreach(const struct bt_object *map_obj,
1164 bt_object_map_foreach_cb cb, void *data)
1165 {
1166 enum bt_object_status ret = BT_OBJECT_STATUS_OK;
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) {
1172 ret = BT_OBJECT_STATUS_INVAL;
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)) {
1182 ret = BT_OBJECT_STATUS_CANCELLED;
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 }
This page took 0.050574 seconds and 3 git commands to generate.