Unify reference counting using a common bt_object base
[babeltrace.git] / lib / values.c
1 /*
2 * Values.c: value objects
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/compiler.h>
33 #include <babeltrace/object-internal.h>
34 #include <babeltrace/ref.h>
35 #include <babeltrace/values.h>
36 #include <glib.h>
37
38 #define BT_VALUE_FROM_CONCRETE(_concrete) ((struct bt_value *) (_concrete))
39 #define BT_VALUE_TO_BOOL(_base) ((struct bt_value_bool *) (_base))
40 #define BT_VALUE_TO_INTEGER(_base) ((struct bt_value_integer *) (_base))
41 #define BT_VALUE_TO_FLOAT(_base) ((struct bt_value_float *) (_base))
42 #define BT_VALUE_TO_STRING(_base) ((struct bt_value_string *) (_base))
43 #define BT_VALUE_TO_ARRAY(_base) ((struct bt_value_array *) (_base))
44 #define BT_VALUE_TO_MAP(_base) ((struct bt_value_map *) (_base))
45
46 struct bt_value {
47 struct bt_object base;
48 enum bt_value_type type;
49 bool is_frozen;
50 };
51
52 static
53 struct bt_value bt_value_null_instance = {
54 .type = BT_VALUE_TYPE_NULL,
55 .is_frozen = true,
56 };
57
58 struct bt_value *bt_value_null = &bt_value_null_instance;
59
60 struct bt_value_bool {
61 struct bt_value base;
62 bool value;
63 };
64
65 struct bt_value_integer {
66 struct bt_value base;
67 int64_t value;
68 };
69
70 struct bt_value_float {
71 struct bt_value base;
72 double value;
73 };
74
75 struct bt_value_string {
76 struct bt_value base;
77 GString *gstr;
78 };
79
80 struct bt_value_array {
81 struct bt_value base;
82 GPtrArray *garray;
83 };
84
85 struct bt_value_map {
86 struct bt_value base;
87 GHashTable *ght;
88 };
89
90 static
91 void bt_value_destroy(struct bt_object *obj);
92
93 static
94 void bt_value_string_destroy(struct bt_value *object)
95 {
96 g_string_free(BT_VALUE_TO_STRING(object)->gstr, TRUE);
97 }
98
99 static
100 void bt_value_array_destroy(struct bt_value *object)
101 {
102 /*
103 * Pointer array's registered value destructor will take care
104 * of putting each contained object.
105 */
106 g_ptr_array_free(BT_VALUE_TO_ARRAY(object)->garray, TRUE);
107 }
108
109 static
110 void bt_value_map_destroy(struct bt_value *object)
111 {
112 /*
113 * Hash table's registered value destructor will take care of
114 * putting each contained object. Keys are GQuarks and cannot
115 * be destroyed anyway.
116 */
117 g_hash_table_destroy(BT_VALUE_TO_MAP(object)->ght);
118 }
119
120 static
121 void (* const destroy_funcs[])(struct bt_value *) = {
122 [BT_VALUE_TYPE_NULL] = NULL,
123 [BT_VALUE_TYPE_BOOL] = NULL,
124 [BT_VALUE_TYPE_INTEGER] = NULL,
125 [BT_VALUE_TYPE_FLOAT] = NULL,
126 [BT_VALUE_TYPE_STRING] = bt_value_string_destroy,
127 [BT_VALUE_TYPE_ARRAY] = bt_value_array_destroy,
128 [BT_VALUE_TYPE_MAP] = bt_value_map_destroy,
129 };
130
131 static
132 struct bt_value *bt_value_null_copy(const struct bt_value *null_obj)
133 {
134 return bt_value_null;
135 }
136
137 static
138 struct bt_value *bt_value_bool_copy(const struct bt_value *bool_obj)
139 {
140 return bt_value_bool_create_init(BT_VALUE_TO_BOOL(bool_obj)->value);
141 }
142
143 static
144 struct bt_value *bt_value_integer_copy(const struct bt_value *integer_obj)
145 {
146 return bt_value_integer_create_init(
147 BT_VALUE_TO_INTEGER(integer_obj)->value);
148 }
149
150 static
151 struct bt_value *bt_value_float_copy(const struct bt_value *float_obj)
152 {
153 return bt_value_float_create_init(
154 BT_VALUE_TO_FLOAT(float_obj)->value);
155 }
156
157 static
158 struct bt_value *bt_value_string_copy(const struct bt_value *string_obj)
159 {
160 return bt_value_string_create_init(
161 BT_VALUE_TO_STRING(string_obj)->gstr->str);
162 }
163
164 static
165 struct bt_value *bt_value_array_copy(const struct bt_value *array_obj)
166 {
167 int i;
168 int ret;
169 struct bt_value *copy_obj;
170 struct bt_value_array *typed_array_obj;
171
172 typed_array_obj = BT_VALUE_TO_ARRAY(array_obj);
173 copy_obj = bt_value_array_create();
174
175 if (!copy_obj) {
176 goto end;
177 }
178
179 for (i = 0; i < typed_array_obj->garray->len; ++i) {
180 struct bt_value *element_obj_copy;
181 struct bt_value *element_obj = bt_value_array_get(array_obj, i);
182
183 if (!element_obj) {
184 BT_PUT(copy_obj);
185 goto end;
186 }
187
188 element_obj_copy = bt_value_copy(element_obj);
189 BT_PUT(element_obj);
190
191 if (!element_obj_copy) {
192 BT_PUT(copy_obj);
193 goto end;
194 }
195
196 ret = bt_value_array_append(copy_obj, element_obj_copy);
197 BT_PUT(element_obj_copy);
198
199 if (ret) {
200 BT_PUT(copy_obj);
201 goto end;
202 }
203 }
204
205 end:
206 return copy_obj;
207 }
208
209 static
210 struct bt_value *bt_value_map_copy(const struct bt_value *map_obj)
211 {
212 int ret;
213 GHashTableIter iter;
214 gpointer key, element_obj;
215 struct bt_value *copy_obj;
216 struct bt_value *element_obj_copy;
217 struct bt_value_map *typed_map_obj;
218
219 typed_map_obj = BT_VALUE_TO_MAP(map_obj);
220 copy_obj = bt_value_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_value_copy(element_obj);
232
233 if (!element_obj_copy) {
234 BT_PUT(copy_obj);
235 goto end;
236 }
237
238 ret = bt_value_map_insert(copy_obj, key_str, element_obj_copy);
239 BT_PUT(element_obj_copy);
240
241 if (ret) {
242 BT_PUT(copy_obj);
243 goto end;
244 }
245 }
246
247 end:
248 return copy_obj;
249 }
250
251 static
252 struct bt_value *(* const copy_funcs[])(const struct bt_value *) = {
253 [BT_VALUE_TYPE_NULL] = bt_value_null_copy,
254 [BT_VALUE_TYPE_BOOL] = bt_value_bool_copy,
255 [BT_VALUE_TYPE_INTEGER] = bt_value_integer_copy,
256 [BT_VALUE_TYPE_FLOAT] = bt_value_float_copy,
257 [BT_VALUE_TYPE_STRING] = bt_value_string_copy,
258 [BT_VALUE_TYPE_ARRAY] = bt_value_array_copy,
259 [BT_VALUE_TYPE_MAP] = bt_value_map_copy,
260 };
261
262 static
263 bool bt_value_null_compare(const struct bt_value *object_a,
264 const struct bt_value *object_b)
265 {
266 /*
267 * Always true since bt_value_compare() already checks if both
268 * object_a and object_b have the same type, and in the case of
269 * null value objects, they're always the same if it is so.
270 */
271 return true;
272 }
273
274 static
275 bool bt_value_bool_compare(const struct bt_value *object_a,
276 const struct bt_value *object_b)
277 {
278 return BT_VALUE_TO_BOOL(object_a)->value ==
279 BT_VALUE_TO_BOOL(object_b)->value;
280 }
281
282 static
283 bool bt_value_integer_compare(const struct bt_value *object_a,
284 const struct bt_value *object_b)
285 {
286 return BT_VALUE_TO_INTEGER(object_a)->value ==
287 BT_VALUE_TO_INTEGER(object_b)->value;
288 }
289
290 static
291 bool bt_value_float_compare(const struct bt_value *object_a,
292 const struct bt_value *object_b)
293 {
294 return BT_VALUE_TO_FLOAT(object_a)->value ==
295 BT_VALUE_TO_FLOAT(object_b)->value;
296 }
297
298 static
299 bool bt_value_string_compare(const struct bt_value *object_a,
300 const struct bt_value *object_b)
301 {
302 return !strcmp(BT_VALUE_TO_STRING(object_a)->gstr->str,
303 BT_VALUE_TO_STRING(object_b)->gstr->str);
304 }
305
306 static
307 bool bt_value_array_compare(const struct bt_value *object_a,
308 const struct bt_value *object_b)
309 {
310 int i;
311 bool ret = true;
312 const struct bt_value_array *array_obj_a =
313 BT_VALUE_TO_ARRAY(object_a);
314
315 if (bt_value_array_size(object_a) != bt_value_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_value *element_obj_a;
322 struct bt_value *element_obj_b;
323
324 element_obj_a = bt_value_array_get(object_a, i);
325 element_obj_b = bt_value_array_get(object_b, i);
326
327 if (!bt_value_compare(element_obj_a, element_obj_b)) {
328 BT_PUT(element_obj_a);
329 BT_PUT(element_obj_b);
330 ret = false;
331 goto end;
332 }
333
334 BT_PUT(element_obj_a);
335 BT_PUT(element_obj_b);
336 }
337
338 end:
339 return ret;
340 }
341
342 static
343 bool bt_value_map_compare(const struct bt_value *object_a,
344 const struct bt_value *object_b)
345 {
346 bool ret = true;
347 GHashTableIter iter;
348 gpointer key, element_obj_a;
349 const struct bt_value_map *map_obj_a = BT_VALUE_TO_MAP(object_a);
350
351 if (bt_value_map_size(object_a) != bt_value_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_value *element_obj_b;
360 const char *key_str = g_quark_to_string((unsigned long) key);
361
362 element_obj_b = bt_value_map_get(object_b, key_str);
363
364 if (!bt_value_compare(element_obj_a, element_obj_b)) {
365 BT_PUT(element_obj_b);
366 ret = false;
367 goto end;
368 }
369
370 BT_PUT(element_obj_b);
371 }
372
373 end:
374 return ret;
375 }
376
377 static
378 bool (* const compare_funcs[])(const struct bt_value *,
379 const struct bt_value *) = {
380 [BT_VALUE_TYPE_NULL] = bt_value_null_compare,
381 [BT_VALUE_TYPE_BOOL] = bt_value_bool_compare,
382 [BT_VALUE_TYPE_INTEGER] = bt_value_integer_compare,
383 [BT_VALUE_TYPE_FLOAT] = bt_value_float_compare,
384 [BT_VALUE_TYPE_STRING] = bt_value_string_compare,
385 [BT_VALUE_TYPE_ARRAY] = bt_value_array_compare,
386 [BT_VALUE_TYPE_MAP] = bt_value_map_compare,
387 };
388
389 void bt_value_null_freeze(struct bt_value *object)
390 {
391 }
392
393 void bt_value_generic_freeze(struct bt_value *object)
394 {
395 object->is_frozen = true;
396 }
397
398 void bt_value_array_freeze(struct bt_value *object)
399 {
400 int i;
401 struct bt_value_array *typed_array_obj =
402 BT_VALUE_TO_ARRAY(object);
403
404 for (i = 0; i < typed_array_obj->garray->len; ++i) {
405 struct bt_value *element_obj =
406 g_ptr_array_index(typed_array_obj->garray, i);
407
408 bt_value_freeze(element_obj);
409 }
410
411 bt_value_generic_freeze(object);
412 }
413
414 void bt_value_map_freeze(struct bt_value *object)
415 {
416 GHashTableIter iter;
417 gpointer key, element_obj;
418 const struct bt_value_map *map_obj = BT_VALUE_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_value_freeze(element_obj);
424 }
425
426 bt_value_generic_freeze(object);
427 }
428
429 static
430 void (* const freeze_funcs[])(struct bt_value *) = {
431 [BT_VALUE_TYPE_NULL] = bt_value_null_freeze,
432 [BT_VALUE_TYPE_BOOL] = bt_value_generic_freeze,
433 [BT_VALUE_TYPE_INTEGER] = bt_value_generic_freeze,
434 [BT_VALUE_TYPE_FLOAT] = bt_value_generic_freeze,
435 [BT_VALUE_TYPE_STRING] = bt_value_generic_freeze,
436 [BT_VALUE_TYPE_ARRAY] = bt_value_array_freeze,
437 [BT_VALUE_TYPE_MAP] = bt_value_map_freeze,
438 };
439
440 static
441 void bt_value_destroy(struct bt_object *obj)
442 {
443 struct bt_value *value;
444
445 value = container_of(obj, struct bt_value, base);
446 assert(value->type != BT_VALUE_TYPE_UNKNOWN);
447
448 if (bt_value_is_null(value)) {
449 return;
450 }
451
452 if (destroy_funcs[value->type]) {
453 destroy_funcs[value->type](value);
454 }
455
456 g_free(value);
457 }
458
459 enum bt_value_status bt_value_freeze(struct bt_value *object)
460 {
461 enum bt_value_status ret = BT_VALUE_STATUS_OK;
462
463 if (!object) {
464 ret = BT_VALUE_STATUS_INVAL;
465 goto end;
466 }
467
468 freeze_funcs[object->type](object);
469
470 end:
471 return ret;
472 }
473
474 bool bt_value_is_frozen(const struct bt_value *object)
475 {
476 return object && object->is_frozen;
477 }
478
479 enum bt_value_type bt_value_get_type(const struct bt_value *object)
480 {
481 if (!object) {
482 return BT_VALUE_TYPE_UNKNOWN;
483 }
484
485 return object->type;
486 }
487
488 static
489 struct bt_value bt_value_create_base(enum bt_value_type type)
490 {
491 struct bt_value base;
492
493 base.type = type;
494 base.is_frozen = false;
495 bt_object_init(&base, bt_value_destroy);
496
497 return base;
498 }
499
500 struct bt_value *bt_value_bool_create_init(bool val)
501 {
502 struct bt_value_bool *bool_obj;
503
504 bool_obj = g_new0(struct bt_value_bool, 1);
505
506 if (!bool_obj) {
507 goto end;
508 }
509
510 bool_obj->base = bt_value_create_base(BT_VALUE_TYPE_BOOL);
511 bool_obj->value = val;
512
513 end:
514 return BT_VALUE_FROM_CONCRETE(bool_obj);
515 }
516
517 struct bt_value *bt_value_bool_create(void)
518 {
519 return bt_value_bool_create_init(false);
520 }
521
522 struct bt_value *bt_value_integer_create_init(int64_t val)
523 {
524 struct bt_value_integer *integer_obj;
525
526 integer_obj = g_new0(struct bt_value_integer, 1);
527
528 if (!integer_obj) {
529 goto end;
530 }
531
532 integer_obj->base = bt_value_create_base(BT_VALUE_TYPE_INTEGER);
533 integer_obj->value = val;
534
535 end:
536 return BT_VALUE_FROM_CONCRETE(integer_obj);
537 }
538
539 struct bt_value *bt_value_integer_create(void)
540 {
541 return bt_value_integer_create_init(0);
542 }
543
544 struct bt_value *bt_value_float_create_init(double val)
545 {
546 struct bt_value_float *float_obj;
547
548 float_obj = g_new0(struct bt_value_float, 1);
549
550 if (!float_obj) {
551 goto end;
552 }
553
554 float_obj->base = bt_value_create_base(BT_VALUE_TYPE_FLOAT);
555 float_obj->value = val;
556
557 end:
558 return BT_VALUE_FROM_CONCRETE(float_obj);
559 }
560
561 struct bt_value *bt_value_float_create(void)
562 {
563 return bt_value_float_create_init(0.);
564 }
565
566 struct bt_value *bt_value_string_create_init(const char *val)
567 {
568 struct bt_value_string *string_obj = NULL;
569
570 if (!val) {
571 goto end;
572 }
573
574 string_obj = g_new0(struct bt_value_string, 1);
575
576 if (!string_obj) {
577 goto end;
578 }
579
580 string_obj->base = bt_value_create_base(BT_VALUE_TYPE_STRING);
581 string_obj->gstr = g_string_new(val);
582
583 if (!string_obj->gstr) {
584 g_free(string_obj);
585 string_obj = NULL;
586 goto end;
587 }
588
589 end:
590 return BT_VALUE_FROM_CONCRETE(string_obj);
591 }
592
593 struct bt_value *bt_value_string_create(void)
594 {
595 return bt_value_string_create_init("");
596 }
597
598 struct bt_value *bt_value_array_create(void)
599 {
600 struct bt_value_array *array_obj;
601
602 array_obj = g_new0(struct bt_value_array, 1);
603
604 if (!array_obj) {
605 goto end;
606 }
607
608 array_obj->base = bt_value_create_base(BT_VALUE_TYPE_ARRAY);
609 array_obj->garray = g_ptr_array_new_full(0,
610 (GDestroyNotify) bt_put);
611
612 if (!array_obj->garray) {
613 g_free(array_obj);
614 array_obj = NULL;
615 goto end;
616 }
617
618 end:
619 return BT_VALUE_FROM_CONCRETE(array_obj);
620 }
621
622 struct bt_value *bt_value_map_create(void)
623 {
624 struct bt_value_map *map_obj;
625
626 map_obj = g_new0(struct bt_value_map, 1);
627
628 if (!map_obj) {
629 goto end;
630 }
631
632 map_obj->base = bt_value_create_base(BT_VALUE_TYPE_MAP);
633 map_obj->ght = g_hash_table_new_full(g_direct_hash, g_direct_equal,
634 NULL, (GDestroyNotify) bt_put);
635
636 if (!map_obj->ght) {
637 g_free(map_obj);
638 map_obj = NULL;
639 goto end;
640 }
641
642 end:
643 return BT_VALUE_FROM_CONCRETE(map_obj);
644 }
645
646 enum bt_value_status bt_value_bool_get(const struct bt_value *bool_obj,
647 bool *val)
648 {
649 enum bt_value_status ret = BT_VALUE_STATUS_OK;
650 struct bt_value_bool *typed_bool_obj = BT_VALUE_TO_BOOL(bool_obj);
651
652 if (!bool_obj || !bt_value_is_bool(bool_obj) || !val) {
653 ret = BT_VALUE_STATUS_INVAL;
654 goto end;
655 }
656
657 *val = typed_bool_obj->value;
658
659 end:
660 return ret;
661 }
662
663 enum bt_value_status bt_value_bool_set(struct bt_value *bool_obj, bool val)
664 {
665 enum bt_value_status ret = BT_VALUE_STATUS_OK;
666 struct bt_value_bool *typed_bool_obj = BT_VALUE_TO_BOOL(bool_obj);
667
668 if (!bool_obj || !bt_value_is_bool(bool_obj)) {
669 ret = BT_VALUE_STATUS_INVAL;
670 goto end;
671 }
672
673 if (bool_obj->is_frozen) {
674 ret = BT_VALUE_STATUS_FROZEN;
675 goto end;
676 }
677
678 typed_bool_obj->value = val;
679
680 end:
681 return ret;
682 }
683
684 enum bt_value_status bt_value_integer_get(const struct bt_value *integer_obj,
685 int64_t *val)
686 {
687 enum bt_value_status ret = BT_VALUE_STATUS_OK;
688 struct bt_value_integer *typed_integer_obj =
689 BT_VALUE_TO_INTEGER(integer_obj);
690
691 if (!integer_obj || !bt_value_is_integer(integer_obj) || !val) {
692 ret = BT_VALUE_STATUS_INVAL;
693 goto end;
694 }
695
696 *val = typed_integer_obj->value;
697
698 end:
699 return ret;
700 }
701
702 enum bt_value_status bt_value_integer_set(struct bt_value *integer_obj,
703 int64_t val)
704 {
705 enum bt_value_status ret = BT_VALUE_STATUS_OK;
706 struct bt_value_integer *typed_integer_obj =
707 BT_VALUE_TO_INTEGER(integer_obj);
708
709 if (!integer_obj || !bt_value_is_integer(integer_obj)) {
710 ret = BT_VALUE_STATUS_INVAL;
711 goto end;
712 }
713
714 if (integer_obj->is_frozen) {
715 ret = BT_VALUE_STATUS_FROZEN;
716 goto end;
717 }
718
719 typed_integer_obj->value = val;
720
721 end:
722 return ret;
723 }
724
725 enum bt_value_status bt_value_float_get(const struct bt_value *float_obj,
726 double *val)
727 {
728 enum bt_value_status ret = BT_VALUE_STATUS_OK;
729 struct bt_value_float *typed_float_obj =
730 BT_VALUE_TO_FLOAT(float_obj);
731
732 if (!float_obj || !bt_value_is_float(float_obj) || !val) {
733 ret = BT_VALUE_STATUS_INVAL;
734 goto end;
735 }
736
737 *val = typed_float_obj->value;
738
739 end:
740 return ret;
741 }
742
743 enum bt_value_status bt_value_float_set(struct bt_value *float_obj,
744 double val)
745 {
746 enum bt_value_status ret = BT_VALUE_STATUS_OK;
747 struct bt_value_float *typed_float_obj =
748 BT_VALUE_TO_FLOAT(float_obj);
749
750 if (!float_obj || !bt_value_is_float(float_obj)) {
751 ret = BT_VALUE_STATUS_INVAL;
752 goto end;
753 }
754
755 if (float_obj->is_frozen) {
756 ret = BT_VALUE_STATUS_FROZEN;
757 goto end;
758 }
759
760 typed_float_obj->value = val;
761
762 end:
763 return ret;
764 }
765
766 enum bt_value_status bt_value_string_get(const struct bt_value *string_obj,
767 const char **val)
768 {
769 enum bt_value_status ret = BT_VALUE_STATUS_OK;
770 struct bt_value_string *typed_string_obj =
771 BT_VALUE_TO_STRING(string_obj);
772
773 if (!string_obj || !bt_value_is_string(string_obj) || !val) {
774 ret = BT_VALUE_STATUS_INVAL;
775 goto end;
776 }
777
778 *val = typed_string_obj->gstr->str;
779
780 end:
781 return ret;
782 }
783
784 enum bt_value_status bt_value_string_set(struct bt_value *string_obj,
785 const char *val)
786 {
787 enum bt_value_status ret = BT_VALUE_STATUS_OK;
788 struct bt_value_string *typed_string_obj =
789 BT_VALUE_TO_STRING(string_obj);
790
791 if (!string_obj || !bt_value_is_string(string_obj) || !val) {
792 ret = BT_VALUE_STATUS_INVAL;
793 goto end;
794 }
795
796 if (string_obj->is_frozen) {
797 ret = BT_VALUE_STATUS_FROZEN;
798 goto end;
799 }
800
801 g_string_assign(typed_string_obj->gstr, val);
802
803 end:
804 return ret;
805 }
806
807 int bt_value_array_size(const struct bt_value *array_obj)
808 {
809 int ret;
810 struct bt_value_array *typed_array_obj =
811 BT_VALUE_TO_ARRAY(array_obj);
812
813 if (!array_obj || !bt_value_is_array(array_obj)) {
814 ret = BT_VALUE_STATUS_INVAL;
815 goto end;
816 }
817
818 ret = (int) typed_array_obj->garray->len;
819
820 end:
821 return ret;
822 }
823
824 bool bt_value_array_is_empty(const struct bt_value *array_obj)
825 {
826 return bt_value_array_size(array_obj) == 0;
827 }
828
829 struct bt_value *bt_value_array_get(const struct bt_value *array_obj,
830 size_t index)
831 {
832 struct bt_value *ret;
833 struct bt_value_array *typed_array_obj =
834 BT_VALUE_TO_ARRAY(array_obj);
835
836 if (!array_obj || !bt_value_is_array(array_obj) ||
837 index >= typed_array_obj->garray->len) {
838 ret = NULL;
839 goto end;
840 }
841
842 ret = g_ptr_array_index(typed_array_obj->garray, index);
843 bt_get(ret);
844
845 end:
846 return ret;
847 }
848
849 enum bt_value_status bt_value_array_append(struct bt_value *array_obj,
850 struct bt_value *element_obj)
851 {
852 enum bt_value_status ret = BT_VALUE_STATUS_OK;
853 struct bt_value_array *typed_array_obj =
854 BT_VALUE_TO_ARRAY(array_obj);
855
856 if (!array_obj || !bt_value_is_array(array_obj) || !element_obj) {
857 ret = BT_VALUE_STATUS_INVAL;
858 goto end;
859 }
860
861 if (array_obj->is_frozen) {
862 ret = BT_VALUE_STATUS_FROZEN;
863 goto end;
864 }
865
866 g_ptr_array_add(typed_array_obj->garray, element_obj);
867 bt_get(element_obj);
868
869 end:
870 return ret;
871 }
872
873 enum bt_value_status bt_value_array_append_bool(struct bt_value *array_obj,
874 bool val)
875 {
876 enum bt_value_status ret;
877 struct bt_value *bool_obj = NULL;
878
879 bool_obj = bt_value_bool_create_init(val);
880 ret = bt_value_array_append(array_obj, bool_obj);
881 bt_put(bool_obj);
882
883 return ret;
884 }
885
886 enum bt_value_status bt_value_array_append_integer(
887 struct bt_value *array_obj, int64_t val)
888 {
889 enum bt_value_status ret;
890 struct bt_value *integer_obj = NULL;
891
892 integer_obj = bt_value_integer_create_init(val);
893 ret = bt_value_array_append(array_obj, integer_obj);
894 bt_put(integer_obj);
895
896 return ret;
897 }
898
899 enum bt_value_status bt_value_array_append_float(struct bt_value *array_obj,
900 double val)
901 {
902 enum bt_value_status ret;
903 struct bt_value *float_obj = NULL;
904
905 float_obj = bt_value_float_create_init(val);
906 ret = bt_value_array_append(array_obj, float_obj);
907 bt_put(float_obj);
908
909 return ret;
910 }
911
912 enum bt_value_status bt_value_array_append_string(struct bt_value *array_obj,
913 const char *val)
914 {
915 enum bt_value_status ret;
916 struct bt_value *string_obj = NULL;
917
918 string_obj = bt_value_string_create_init(val);
919 ret = bt_value_array_append(array_obj, string_obj);
920 bt_put(string_obj);
921
922 return ret;
923 }
924
925 enum bt_value_status bt_value_array_append_array(struct bt_value *array_obj)
926 {
927 enum bt_value_status ret;
928 struct bt_value *empty_array_obj = NULL;
929
930 empty_array_obj = bt_value_array_create();
931 ret = bt_value_array_append(array_obj, empty_array_obj);
932 bt_put(empty_array_obj);
933
934 return ret;
935 }
936
937 enum bt_value_status bt_value_array_append_map(struct bt_value *array_obj)
938 {
939 enum bt_value_status ret;
940 struct bt_value *map_obj = NULL;
941
942 map_obj = bt_value_map_create();
943 ret = bt_value_array_append(array_obj, map_obj);
944 bt_put(map_obj);
945
946 return ret;
947 }
948
949 enum bt_value_status bt_value_array_set(struct bt_value *array_obj,
950 size_t index, struct bt_value *element_obj)
951 {
952 enum bt_value_status ret = BT_VALUE_STATUS_OK;
953 struct bt_value_array *typed_array_obj =
954 BT_VALUE_TO_ARRAY(array_obj);
955
956 if (!array_obj || !bt_value_is_array(array_obj) || !element_obj ||
957 index >= typed_array_obj->garray->len) {
958 ret = BT_VALUE_STATUS_INVAL;
959 goto end;
960 }
961
962 if (array_obj->is_frozen) {
963 ret = BT_VALUE_STATUS_FROZEN;
964 goto end;
965 }
966
967 bt_put(g_ptr_array_index(typed_array_obj->garray, index));
968 g_ptr_array_index(typed_array_obj->garray, index) = element_obj;
969 bt_get(element_obj);
970
971 end:
972 return ret;
973 }
974
975 int bt_value_map_size(const struct bt_value *map_obj)
976 {
977 int ret;
978 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
979
980 if (!map_obj || !bt_value_is_map(map_obj)) {
981 ret = BT_VALUE_STATUS_INVAL;
982 goto end;
983 }
984
985 ret = (int) g_hash_table_size(typed_map_obj->ght);
986
987 end:
988 return ret;
989 }
990
991 bool bt_value_map_is_empty(const struct bt_value *map_obj)
992 {
993 return bt_value_map_size(map_obj) == 0;
994 }
995
996 struct bt_value *bt_value_map_get(const struct bt_value *map_obj,
997 const char *key)
998 {
999 GQuark quark;
1000 struct bt_value *ret;
1001 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1002
1003 if (!map_obj || !bt_value_is_map(map_obj) || !key) {
1004 ret = NULL;
1005 goto end;
1006 }
1007
1008 quark = g_quark_from_string(key);
1009 ret = g_hash_table_lookup(typed_map_obj->ght, GUINT_TO_POINTER(quark));
1010
1011 if (ret) {
1012 bt_get(ret);
1013 }
1014
1015 end:
1016 return ret;
1017 }
1018
1019 bool bt_value_map_has_key(const struct bt_value *map_obj, const char *key)
1020 {
1021 bool ret;
1022 GQuark quark;
1023 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1024
1025 if (!map_obj || !bt_value_is_map(map_obj) || !key) {
1026 ret = false;
1027 goto end;
1028 }
1029
1030 quark = g_quark_from_string(key);
1031 ret = g_hash_table_contains(typed_map_obj->ght,
1032 GUINT_TO_POINTER(quark));
1033
1034 end:
1035 return ret;
1036 }
1037
1038 enum bt_value_status bt_value_map_insert(struct bt_value *map_obj,
1039 const char *key, struct bt_value *element_obj)
1040 {
1041 GQuark quark;
1042 enum bt_value_status ret = BT_VALUE_STATUS_OK;
1043 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1044
1045 if (!map_obj || !bt_value_is_map(map_obj) || !key || !element_obj) {
1046 ret = BT_VALUE_STATUS_INVAL;
1047 goto end;
1048 }
1049
1050 if (map_obj->is_frozen) {
1051 ret = BT_VALUE_STATUS_FROZEN;
1052 goto end;
1053 }
1054
1055 quark = g_quark_from_string(key);
1056 g_hash_table_insert(typed_map_obj->ght,
1057 GUINT_TO_POINTER(quark), element_obj);
1058 bt_get(element_obj);
1059
1060 end:
1061 return ret;
1062 }
1063
1064 enum bt_value_status bt_value_map_insert_bool(struct bt_value *map_obj,
1065 const char *key, bool val)
1066 {
1067 enum bt_value_status ret;
1068 struct bt_value *bool_obj = NULL;
1069
1070 bool_obj = bt_value_bool_create_init(val);
1071 ret = bt_value_map_insert(map_obj, key, bool_obj);
1072 bt_put(bool_obj);
1073
1074 return ret;
1075 }
1076
1077 enum bt_value_status bt_value_map_insert_integer(struct bt_value *map_obj,
1078 const char *key, int64_t val)
1079 {
1080 enum bt_value_status ret;
1081 struct bt_value *integer_obj = NULL;
1082
1083 integer_obj = bt_value_integer_create_init(val);
1084 ret = bt_value_map_insert(map_obj, key, integer_obj);
1085 bt_put(integer_obj);
1086
1087 return ret;
1088 }
1089
1090 enum bt_value_status bt_value_map_insert_float(struct bt_value *map_obj,
1091 const char *key, double val)
1092 {
1093 enum bt_value_status ret;
1094 struct bt_value *float_obj = NULL;
1095
1096 float_obj = bt_value_float_create_init(val);
1097 ret = bt_value_map_insert(map_obj, key, float_obj);
1098 bt_put(float_obj);
1099
1100 return ret;
1101 }
1102
1103 enum bt_value_status bt_value_map_insert_string(struct bt_value *map_obj,
1104 const char *key, const char *val)
1105 {
1106 enum bt_value_status ret;
1107 struct bt_value *string_obj = NULL;
1108
1109 string_obj = bt_value_string_create_init(val);
1110 ret = bt_value_map_insert(map_obj, key, string_obj);
1111 bt_put(string_obj);
1112
1113 return ret;
1114 }
1115
1116 enum bt_value_status bt_value_map_insert_array(struct bt_value *map_obj,
1117 const char *key)
1118 {
1119 enum bt_value_status ret;
1120 struct bt_value *array_obj = NULL;
1121
1122 array_obj = bt_value_array_create();
1123 ret = bt_value_map_insert(map_obj, key, array_obj);
1124 bt_put(array_obj);
1125
1126 return ret;
1127 }
1128
1129 enum bt_value_status bt_value_map_insert_map(struct bt_value *map_obj,
1130 const char *key)
1131 {
1132 enum bt_value_status ret;
1133 struct bt_value *empty_map_obj = NULL;
1134
1135 empty_map_obj = bt_value_map_create();
1136 ret = bt_value_map_insert(map_obj, key, empty_map_obj);
1137 bt_put(empty_map_obj);
1138
1139 return ret;
1140 }
1141
1142 enum bt_value_status bt_value_map_foreach(const struct bt_value *map_obj,
1143 bt_value_map_foreach_cb cb, void *data)
1144 {
1145 enum bt_value_status ret = BT_VALUE_STATUS_OK;
1146 gpointer key, element_obj;
1147 GHashTableIter iter;
1148 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1149
1150 if (!map_obj || !bt_value_is_map(map_obj) || !cb) {
1151 ret = BT_VALUE_STATUS_INVAL;
1152 goto end;
1153 }
1154
1155 g_hash_table_iter_init(&iter, typed_map_obj->ght);
1156
1157 while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
1158 const char *key_str = g_quark_to_string((unsigned long) key);
1159
1160 if (!cb(key_str, element_obj, data)) {
1161 ret = BT_VALUE_STATUS_CANCELLED;
1162 break;
1163 }
1164 }
1165
1166 end:
1167 return ret;
1168 }
1169
1170 struct bt_value *bt_value_copy(const struct bt_value *object)
1171 {
1172 struct bt_value *copy_obj = NULL;
1173
1174 if (!object) {
1175 goto end;
1176 }
1177
1178 copy_obj = copy_funcs[object->type](object);
1179
1180 end:
1181 return copy_obj;
1182 }
1183
1184 bool bt_value_compare(const struct bt_value *object_a,
1185 const struct bt_value *object_b)
1186 {
1187 bool ret = false;
1188
1189 if (!object_a || !object_b) {
1190 goto end;
1191 }
1192
1193 if (object_a->type != object_b->type) {
1194 goto end;
1195 }
1196
1197 ret = compare_funcs[object_a->type](object_a, object_b);
1198
1199 end:
1200 return ret;
1201 }
This page took 0.054324 seconds and 4 git commands to generate.