lib/values.c: logging: log array size when out of bound
[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 #define BT_LOG_TAG "VALUES"
29 #include <babeltrace/lib-logging-internal.h>
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <assert.h>
34 #include <string.h>
35 #include <inttypes.h>
36 #include <babeltrace/compiler-internal.h>
37 #include <babeltrace/ref.h>
38 #include <babeltrace/values.h>
39 #include <babeltrace/compat/glib-internal.h>
40 #include <babeltrace/types.h>
41 #include <babeltrace/object-internal.h>
42 #include <babeltrace/values-internal.h>
43
44 #define BT_VALUE_FROM_CONCRETE(_concrete) ((struct bt_value *) (_concrete))
45 #define BT_VALUE_TO_BOOL(_base) ((struct bt_value_bool *) (_base))
46 #define BT_VALUE_TO_INTEGER(_base) ((struct bt_value_integer *) (_base))
47 #define BT_VALUE_TO_FLOAT(_base) ((struct bt_value_float *) (_base))
48 #define BT_VALUE_TO_STRING(_base) ((struct bt_value_string *) (_base))
49 #define BT_VALUE_TO_ARRAY(_base) ((struct bt_value_array *) (_base))
50 #define BT_VALUE_TO_MAP(_base) ((struct bt_value_map *) (_base))
51
52 struct bt_value {
53 struct bt_object base;
54 enum bt_value_type type;
55 bt_bool is_frozen;
56 };
57
58 static
59 struct bt_value bt_value_null_instance = {
60 .base = {
61 .ref_count = {
62 .count = 1,
63 .release = NULL,
64 },
65 .release = NULL,
66 .parent = NULL,
67 },
68 .type = BT_VALUE_TYPE_NULL,
69 .is_frozen = BT_TRUE,
70 };
71
72 struct bt_value *bt_value_null = &bt_value_null_instance;
73
74 struct bt_value_bool {
75 struct bt_value base;
76 bt_bool value;
77 };
78
79 struct bt_value_integer {
80 struct bt_value base;
81 int64_t value;
82 };
83
84 struct bt_value_float {
85 struct bt_value base;
86 double value;
87 };
88
89 struct bt_value_string {
90 struct bt_value base;
91 GString *gstr;
92 };
93
94 struct bt_value_array {
95 struct bt_value base;
96 GPtrArray *garray;
97 };
98
99 struct bt_value_map {
100 struct bt_value base;
101 GHashTable *ght;
102 };
103
104 static
105 void bt_value_destroy(struct bt_object *obj);
106
107 static
108 void bt_value_string_destroy(struct bt_value *object)
109 {
110 g_string_free(BT_VALUE_TO_STRING(object)->gstr, TRUE);
111 }
112
113 static
114 void bt_value_array_destroy(struct bt_value *object)
115 {
116 /*
117 * Pointer array's registered value destructor will take care
118 * of putting each contained object.
119 */
120 g_ptr_array_free(BT_VALUE_TO_ARRAY(object)->garray, TRUE);
121 }
122
123 static
124 void bt_value_map_destroy(struct bt_value *object)
125 {
126 /*
127 * Hash table's registered value destructor will take care of
128 * putting each contained object. Keys are GQuarks and cannot
129 * be destroyed anyway.
130 */
131 g_hash_table_destroy(BT_VALUE_TO_MAP(object)->ght);
132 }
133
134 static
135 void (* const destroy_funcs[])(struct bt_value *) = {
136 [BT_VALUE_TYPE_NULL] = NULL,
137 [BT_VALUE_TYPE_BOOL] = NULL,
138 [BT_VALUE_TYPE_INTEGER] = NULL,
139 [BT_VALUE_TYPE_FLOAT] = NULL,
140 [BT_VALUE_TYPE_STRING] = bt_value_string_destroy,
141 [BT_VALUE_TYPE_ARRAY] = bt_value_array_destroy,
142 [BT_VALUE_TYPE_MAP] = bt_value_map_destroy,
143 };
144
145 static
146 struct bt_value *bt_value_null_copy(const struct bt_value *null_obj)
147 {
148 return bt_value_null;
149 }
150
151 static
152 struct bt_value *bt_value_bool_copy(const struct bt_value *bool_obj)
153 {
154 return bt_value_bool_create_init(BT_VALUE_TO_BOOL(bool_obj)->value);
155 }
156
157 static
158 struct bt_value *bt_value_integer_copy(const struct bt_value *integer_obj)
159 {
160 return bt_value_integer_create_init(
161 BT_VALUE_TO_INTEGER(integer_obj)->value);
162 }
163
164 static
165 struct bt_value *bt_value_float_copy(const struct bt_value *float_obj)
166 {
167 return bt_value_float_create_init(
168 BT_VALUE_TO_FLOAT(float_obj)->value);
169 }
170
171 static
172 struct bt_value *bt_value_string_copy(const struct bt_value *string_obj)
173 {
174 return bt_value_string_create_init(
175 BT_VALUE_TO_STRING(string_obj)->gstr->str);
176 }
177
178 static
179 struct bt_value *bt_value_array_copy(const struct bt_value *array_obj)
180 {
181 int i;
182 int ret;
183 struct bt_value *copy_obj;
184 struct bt_value_array *typed_array_obj;
185
186 BT_LOGD("Copying array value: addr=%p", array_obj);
187 typed_array_obj = BT_VALUE_TO_ARRAY(array_obj);
188 copy_obj = bt_value_array_create();
189
190 if (!copy_obj) {
191 BT_LOGE_STR("Cannot create empty array value.");
192 goto end;
193 }
194
195 for (i = 0; i < typed_array_obj->garray->len; ++i) {
196 struct bt_value *element_obj_copy;
197 struct bt_value *element_obj = bt_value_array_get(array_obj, i);
198
199 if (!element_obj) {
200 BT_LOGE("Cannot get array value's element: "
201 "addr=%p, index=%d",
202 array_obj, i);
203 BT_PUT(copy_obj);
204 goto end;
205 }
206
207 element_obj_copy = bt_value_copy(element_obj);
208 BT_PUT(element_obj);
209
210 if (!element_obj_copy) {
211 BT_LOGE("Cannot copy array value's element: "
212 "array-addr=%p, index=%d",
213 array_obj, i);
214 BT_PUT(copy_obj);
215 goto end;
216 }
217
218 ret = bt_value_array_append(copy_obj, element_obj_copy);
219 BT_PUT(element_obj_copy);
220
221 if (ret) {
222 BT_LOGE("Cannot append to array value: addr=%p",
223 array_obj);
224 BT_PUT(copy_obj);
225 goto end;
226 }
227 }
228
229 BT_LOGD("Copied array value: addr=%p", array_obj);
230
231 end:
232 return copy_obj;
233 }
234
235 static
236 struct bt_value *bt_value_map_copy(const struct bt_value *map_obj)
237 {
238 int ret;
239 GHashTableIter iter;
240 gpointer key, element_obj;
241 struct bt_value *copy_obj;
242 struct bt_value *element_obj_copy;
243 struct bt_value_map *typed_map_obj;
244
245 BT_LOGD("Copying map value: addr=%p", map_obj);
246 typed_map_obj = BT_VALUE_TO_MAP(map_obj);
247 copy_obj = bt_value_map_create();
248
249 if (!copy_obj) {
250 goto end;
251 }
252
253 g_hash_table_iter_init(&iter, typed_map_obj->ght);
254
255 while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
256 const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
257
258 element_obj_copy = bt_value_copy(element_obj);
259
260 if (!element_obj_copy) {
261 BT_LOGE("Cannot copy map value's element: "
262 "map-addr=%p, key=\"%s\"",
263 map_obj, key_str);
264 BT_PUT(copy_obj);
265 goto end;
266 }
267
268 ret = bt_value_map_insert(copy_obj, key_str, element_obj_copy);
269 BT_PUT(element_obj_copy);
270
271 if (ret) {
272 BT_LOGE("Cannot insert into map value: addr=%p, key=\"%s\"",
273 map_obj, key_str);
274 BT_PUT(copy_obj);
275 goto end;
276 }
277 }
278
279 BT_LOGD("Copied map value: addr=%p", map_obj);
280
281 end:
282 return copy_obj;
283 }
284
285 static
286 struct bt_value *(* const copy_funcs[])(const struct bt_value *) = {
287 [BT_VALUE_TYPE_NULL] = bt_value_null_copy,
288 [BT_VALUE_TYPE_BOOL] = bt_value_bool_copy,
289 [BT_VALUE_TYPE_INTEGER] = bt_value_integer_copy,
290 [BT_VALUE_TYPE_FLOAT] = bt_value_float_copy,
291 [BT_VALUE_TYPE_STRING] = bt_value_string_copy,
292 [BT_VALUE_TYPE_ARRAY] = bt_value_array_copy,
293 [BT_VALUE_TYPE_MAP] = bt_value_map_copy,
294 };
295
296 static
297 bt_bool bt_value_null_compare(const struct bt_value *object_a,
298 const struct bt_value *object_b)
299 {
300 /*
301 * Always BT_TRUE since bt_value_compare() already checks if both
302 * object_a and object_b have the same type, and in the case of
303 * null value objects, they're always the same if it is so.
304 */
305 return BT_TRUE;
306 }
307
308 static
309 bt_bool bt_value_bool_compare(const struct bt_value *object_a,
310 const struct bt_value *object_b)
311 {
312 return BT_VALUE_TO_BOOL(object_a)->value ==
313 BT_VALUE_TO_BOOL(object_b)->value;
314 }
315
316 static
317 bt_bool bt_value_integer_compare(const struct bt_value *object_a,
318 const struct bt_value *object_b)
319 {
320 return BT_VALUE_TO_INTEGER(object_a)->value ==
321 BT_VALUE_TO_INTEGER(object_b)->value;
322 }
323
324 static
325 bt_bool bt_value_float_compare(const struct bt_value *object_a,
326 const struct bt_value *object_b)
327 {
328 return BT_VALUE_TO_FLOAT(object_a)->value ==
329 BT_VALUE_TO_FLOAT(object_b)->value;
330 }
331
332 static
333 bt_bool bt_value_string_compare(const struct bt_value *object_a,
334 const struct bt_value *object_b)
335 {
336 return !strcmp(BT_VALUE_TO_STRING(object_a)->gstr->str,
337 BT_VALUE_TO_STRING(object_b)->gstr->str);
338 }
339
340 static
341 bt_bool bt_value_array_compare(const struct bt_value *object_a,
342 const struct bt_value *object_b)
343 {
344 int i;
345 bt_bool ret = BT_TRUE;
346 const struct bt_value_array *array_obj_a =
347 BT_VALUE_TO_ARRAY(object_a);
348
349 if (bt_value_array_size(object_a) != bt_value_array_size(object_b)) {
350 BT_LOGV("Array values are different: size mismatch "
351 "value-a-addr=%p, value-b-addr=%p, "
352 "value-a-size=%" PRId64 ", value-b-size=%" PRId64,
353 object_a, object_b,
354 bt_value_array_size(object_a),
355 bt_value_array_size(object_b));
356 ret = BT_FALSE;
357 goto end;
358 }
359
360 for (i = 0; i < array_obj_a->garray->len; ++i) {
361 struct bt_value *element_obj_a;
362 struct bt_value *element_obj_b;
363
364 element_obj_a = bt_value_array_get(object_a, i);
365 element_obj_b = bt_value_array_get(object_b, i);
366
367 if (!bt_value_compare(element_obj_a, element_obj_b)) {
368 BT_LOGV("Array values's elements are different: "
369 "value-a-addr=%p, value-b-addr=%p, index=%d",
370 element_obj_a, element_obj_b, index);
371 BT_PUT(element_obj_a);
372 BT_PUT(element_obj_b);
373 ret = BT_FALSE;
374 goto end;
375 }
376
377 BT_PUT(element_obj_a);
378 BT_PUT(element_obj_b);
379 }
380
381 end:
382 return ret;
383 }
384
385 static
386 bt_bool bt_value_map_compare(const struct bt_value *object_a,
387 const struct bt_value *object_b)
388 {
389 bt_bool ret = BT_TRUE;
390 GHashTableIter iter;
391 gpointer key, element_obj_a;
392 const struct bt_value_map *map_obj_a = BT_VALUE_TO_MAP(object_a);
393
394 if (bt_value_map_size(object_a) != bt_value_map_size(object_b)) {
395 BT_LOGV("Map values are different: size mismatch "
396 "value-a-addr=%p, value-b-addr=%p, "
397 "value-a-size=%" PRId64 ", value-b-size=%" PRId64,
398 object_a, object_b,
399 bt_value_map_size(object_a),
400 bt_value_map_size(object_b));
401 ret = BT_FALSE;
402 goto end;
403 }
404
405 g_hash_table_iter_init(&iter, map_obj_a->ght);
406
407 while (g_hash_table_iter_next(&iter, &key, &element_obj_a)) {
408 struct bt_value *element_obj_b;
409 const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
410
411 element_obj_b = bt_value_map_get(object_b, key_str);
412
413 if (!bt_value_compare(element_obj_a, element_obj_b)) {
414 BT_LOGV("Map values's elements are different: "
415 "value-a-addr=%p, value-b-addr=%p, key=\"%s\"",
416 element_obj_a, element_obj_b, key_str);
417 BT_PUT(element_obj_b);
418 ret = BT_FALSE;
419 goto end;
420 }
421
422 BT_PUT(element_obj_b);
423 }
424
425 end:
426 return ret;
427 }
428
429 static
430 bt_bool (* const compare_funcs[])(const struct bt_value *,
431 const struct bt_value *) = {
432 [BT_VALUE_TYPE_NULL] = bt_value_null_compare,
433 [BT_VALUE_TYPE_BOOL] = bt_value_bool_compare,
434 [BT_VALUE_TYPE_INTEGER] = bt_value_integer_compare,
435 [BT_VALUE_TYPE_FLOAT] = bt_value_float_compare,
436 [BT_VALUE_TYPE_STRING] = bt_value_string_compare,
437 [BT_VALUE_TYPE_ARRAY] = bt_value_array_compare,
438 [BT_VALUE_TYPE_MAP] = bt_value_map_compare,
439 };
440
441 void bt_value_null_freeze(struct bt_value *object)
442 {
443 }
444
445 void bt_value_generic_freeze(struct bt_value *object)
446 {
447 object->is_frozen = BT_TRUE;
448 }
449
450 void bt_value_array_freeze(struct bt_value *object)
451 {
452 int i;
453 struct bt_value_array *typed_array_obj =
454 BT_VALUE_TO_ARRAY(object);
455
456 for (i = 0; i < typed_array_obj->garray->len; ++i) {
457 struct bt_value *element_obj =
458 g_ptr_array_index(typed_array_obj->garray, i);
459
460 bt_value_freeze(element_obj);
461 }
462
463 bt_value_generic_freeze(object);
464 }
465
466 void bt_value_map_freeze(struct bt_value *object)
467 {
468 GHashTableIter iter;
469 gpointer key, element_obj;
470 const struct bt_value_map *map_obj = BT_VALUE_TO_MAP(object);
471
472 g_hash_table_iter_init(&iter, map_obj->ght);
473
474 while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
475 bt_value_freeze(element_obj);
476 }
477
478 bt_value_generic_freeze(object);
479 }
480
481 static
482 void (* const freeze_funcs[])(struct bt_value *) = {
483 [BT_VALUE_TYPE_NULL] = bt_value_null_freeze,
484 [BT_VALUE_TYPE_BOOL] = bt_value_generic_freeze,
485 [BT_VALUE_TYPE_INTEGER] = bt_value_generic_freeze,
486 [BT_VALUE_TYPE_FLOAT] = bt_value_generic_freeze,
487 [BT_VALUE_TYPE_STRING] = bt_value_generic_freeze,
488 [BT_VALUE_TYPE_ARRAY] = bt_value_array_freeze,
489 [BT_VALUE_TYPE_MAP] = bt_value_map_freeze,
490 };
491
492 static
493 void bt_value_destroy(struct bt_object *obj)
494 {
495 struct bt_value *value;
496
497 value = container_of(obj, struct bt_value, base);
498 assert(value->type != BT_VALUE_TYPE_UNKNOWN);
499 BT_LOGD("Destroying value: addr=%p", value);
500
501 if (bt_value_is_null(value)) {
502 BT_LOGD_STR("Not destroying the null value singleton.");
503 return;
504 }
505
506 if (destroy_funcs[value->type]) {
507 destroy_funcs[value->type](value);
508 }
509
510 g_free(value);
511 }
512
513 enum bt_value_status bt_value_freeze(struct bt_value *object)
514 {
515 enum bt_value_status ret = BT_VALUE_STATUS_OK;
516
517 if (!object) {
518 BT_LOGW_STR("Invalid parameter: value object is NULL.");
519 ret = BT_VALUE_STATUS_INVAL;
520 goto end;
521 }
522
523 if (object->is_frozen) {
524 goto end;
525 }
526
527 BT_LOGD("Freezing value: addr=%p", object);
528 freeze_funcs[object->type](object);
529
530 end:
531 return ret;
532 }
533
534 bt_bool bt_value_is_frozen(const struct bt_value *object)
535 {
536 return object && object->is_frozen;
537 }
538
539 enum bt_value_type bt_value_get_type(const struct bt_value *object)
540 {
541 if (!object) {
542 BT_LOGW_STR("Invalid parameter: value object is NULL.");
543 return BT_VALUE_TYPE_UNKNOWN;
544 }
545
546 return object->type;
547 }
548
549 static
550 struct bt_value bt_value_create_base(enum bt_value_type type)
551 {
552 struct bt_value base;
553
554 base.type = type;
555 base.is_frozen = BT_FALSE;
556 bt_object_init(&base, bt_value_destroy);
557 return base;
558 }
559
560 struct bt_value *bt_value_bool_create_init(bt_bool val)
561 {
562 struct bt_value_bool *bool_obj;
563
564 BT_LOGD("Creating boolean value object: val=%d", val);
565 bool_obj = g_new0(struct bt_value_bool, 1);
566
567 if (!bool_obj) {
568 BT_LOGE_STR("Failed to allocate one boolean value object.");
569 goto end;
570 }
571
572 bool_obj->base = bt_value_create_base(BT_VALUE_TYPE_BOOL);
573 bool_obj->value = val;
574 BT_LOGD("Created boolean value object: addr=%p", bool_obj);
575
576 end:
577 return BT_VALUE_FROM_CONCRETE(bool_obj);
578 }
579
580 struct bt_value *bt_value_bool_create(void)
581 {
582 return bt_value_bool_create_init(BT_FALSE);
583 }
584
585 struct bt_value *bt_value_integer_create_init(int64_t val)
586 {
587 struct bt_value_integer *integer_obj;
588
589 BT_LOGD("Creating integer value object: val=%" PRId64, val);
590 integer_obj = g_new0(struct bt_value_integer, 1);
591
592 if (!integer_obj) {
593 BT_LOGE_STR("Failed to allocate one integer value object.");
594 goto end;
595 }
596
597 integer_obj->base = bt_value_create_base(BT_VALUE_TYPE_INTEGER);
598 integer_obj->value = val;
599 BT_LOGD("Created integer value object: addr=%p",
600 integer_obj);
601
602 end:
603 return BT_VALUE_FROM_CONCRETE(integer_obj);
604 }
605
606 struct bt_value *bt_value_integer_create(void)
607 {
608 return bt_value_integer_create_init(0);
609 }
610
611 struct bt_value *bt_value_float_create_init(double val)
612 {
613 struct bt_value_float *float_obj;
614
615 BT_LOGD("Creating floating point number value object: val=%f", val);
616 float_obj = g_new0(struct bt_value_float, 1);
617
618 if (!float_obj) {
619 BT_LOGE_STR("Failed to allocate one floating point number value object.");
620 goto end;
621 }
622
623 float_obj->base = bt_value_create_base(BT_VALUE_TYPE_FLOAT);
624 float_obj->value = val;
625 BT_LOGD("Created floating point number value object: addr=%p",
626 float_obj);
627
628 end:
629 return BT_VALUE_FROM_CONCRETE(float_obj);
630 }
631
632 struct bt_value *bt_value_float_create(void)
633 {
634 return bt_value_float_create_init(0.);
635 }
636
637 struct bt_value *bt_value_string_create_init(const char *val)
638 {
639 struct bt_value_string *string_obj = NULL;
640
641 if (!val) {
642 BT_LOGW_STR("Invalid parameter: value is NULL.");
643 goto end;
644 }
645
646 BT_LOGD("Creating string value object: val-len=%u", strlen(val));
647 string_obj = g_new0(struct bt_value_string, 1);
648
649 if (!string_obj) {
650 BT_LOGE_STR("Failed to allocate one string object.");
651 goto end;
652 }
653
654 string_obj->base = bt_value_create_base(BT_VALUE_TYPE_STRING);
655 string_obj->gstr = g_string_new(val);
656
657 if (!string_obj->gstr) {
658 BT_LOGE_STR("Failed to allocate a GString.");
659 g_free(string_obj);
660 string_obj = NULL;
661 goto end;
662 }
663
664 BT_LOGD("Created string value object: addr=%p",
665 string_obj);
666
667 end:
668 return BT_VALUE_FROM_CONCRETE(string_obj);
669 }
670
671 struct bt_value *bt_value_string_create(void)
672 {
673 return bt_value_string_create_init("");
674 }
675
676 struct bt_value *bt_value_array_create(void)
677 {
678 struct bt_value_array *array_obj;
679
680 BT_LOGD_STR("Creating empty array value object.");
681 array_obj = g_new0(struct bt_value_array, 1);
682
683 if (!array_obj) {
684 BT_LOGE_STR("Failed to allocate one array object.");
685 goto end;
686 }
687
688 array_obj->base = bt_value_create_base(BT_VALUE_TYPE_ARRAY);
689 array_obj->garray = bt_g_ptr_array_new_full(0,
690 (GDestroyNotify) bt_put);
691
692 if (!array_obj->garray) {
693 BT_LOGE_STR("Failed to allocate a GPtrArray.");
694 g_free(array_obj);
695 array_obj = NULL;
696 goto end;
697 }
698
699 BT_LOGD("Created array value object: addr=%p",
700 array_obj);
701
702 end:
703 return BT_VALUE_FROM_CONCRETE(array_obj);
704 }
705
706 struct bt_value *bt_value_map_create(void)
707 {
708 struct bt_value_map *map_obj;
709
710 BT_LOGD_STR("Creating empty map value object.");
711 map_obj = g_new0(struct bt_value_map, 1);
712
713 if (!map_obj) {
714 BT_LOGE_STR("Failed to allocate one map object.");
715 goto end;
716 }
717
718 map_obj->base = bt_value_create_base(BT_VALUE_TYPE_MAP);
719 map_obj->ght = g_hash_table_new_full(g_direct_hash, g_direct_equal,
720 NULL, (GDestroyNotify) bt_put);
721
722 if (!map_obj->ght) {
723 BT_LOGE_STR("Failed to allocate a GHashTable.");
724 g_free(map_obj);
725 map_obj = NULL;
726 goto end;
727 }
728
729 BT_LOGD("Created map value object: addr=%p",
730 map_obj);
731
732 end:
733 return BT_VALUE_FROM_CONCRETE(map_obj);
734 }
735
736 enum bt_value_status bt_value_bool_get(const struct bt_value *bool_obj,
737 bt_bool *val)
738 {
739 enum bt_value_status ret = BT_VALUE_STATUS_OK;
740 struct bt_value_bool *typed_bool_obj = BT_VALUE_TO_BOOL(bool_obj);
741
742 if (!bool_obj || !val) {
743 BT_LOGW("Invalid parameter: value object or value is NULL: "
744 "value-addr=%p, raw-value-addr=%p",
745 bool_obj, val);
746 ret = BT_VALUE_STATUS_INVAL;
747 goto end;
748 }
749
750 if (!bt_value_is_bool(bool_obj)) {
751 BT_LOGW("Invalid parameter: value is not a boolean value: addr=%p, "
752 "type=%s", bool_obj, bool_obj->type,
753 bt_value_type_string(bool_obj->type));
754 ret = BT_VALUE_STATUS_INVAL;
755 goto end;
756 }
757
758 *val = typed_bool_obj->value;
759
760 end:
761 return ret;
762 }
763
764 enum bt_value_status bt_value_bool_set(struct bt_value *bool_obj, bt_bool val)
765 {
766 enum bt_value_status ret = BT_VALUE_STATUS_OK;
767 struct bt_value_bool *typed_bool_obj = BT_VALUE_TO_BOOL(bool_obj);
768
769 if (!bool_obj) {
770 BT_LOGW_STR("Invalid parameter: value object is NULL.");
771 ret = BT_VALUE_STATUS_INVAL;
772 goto end;
773 }
774
775 if (!bt_value_is_bool(bool_obj)) {
776 BT_LOGW("Invalid parameter: value is not a boolean value: addr=%p, "
777 "type=%s", bool_obj,
778 bt_value_type_string(bool_obj->type));
779 ret = BT_VALUE_STATUS_INVAL;
780 goto end;
781 }
782
783 if (bool_obj->is_frozen) {
784 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
785 bool_obj);
786 ret = BT_VALUE_STATUS_FROZEN;
787 goto end;
788 }
789
790 typed_bool_obj->value = val;
791 BT_LOGV("Set boolean value's raw value: value-addr=%p, value=%d",
792 bool_obj, val);
793
794 end:
795 return ret;
796 }
797
798 enum bt_value_status bt_value_integer_get(const struct bt_value *integer_obj,
799 int64_t *val)
800 {
801 enum bt_value_status ret = BT_VALUE_STATUS_OK;
802 struct bt_value_integer *typed_integer_obj =
803 BT_VALUE_TO_INTEGER(integer_obj);
804
805 if (!integer_obj || !val) {
806 BT_LOGW("Invalid parameter: value object or value is NULL: "
807 "value-addr=%p, raw-value-addr=%p",
808 integer_obj, val);
809 ret = BT_VALUE_STATUS_INVAL;
810 goto end;
811 }
812
813 if (!bt_value_is_integer(integer_obj)) {
814 BT_LOGW("Invalid parameter: value is not an integer value: addr=%p, "
815 "type=%s", integer_obj,
816 bt_value_type_string(integer_obj->type));
817 ret = BT_VALUE_STATUS_INVAL;
818 goto end;
819 }
820
821 *val = typed_integer_obj->value;
822
823 end:
824 return ret;
825 }
826
827 enum bt_value_status bt_value_integer_set(struct bt_value *integer_obj,
828 int64_t val)
829 {
830 enum bt_value_status ret = BT_VALUE_STATUS_OK;
831 struct bt_value_integer *typed_integer_obj =
832 BT_VALUE_TO_INTEGER(integer_obj);
833
834 if (!integer_obj) {
835 BT_LOGW_STR("Invalid parameter: value object is NULL.");
836 ret = BT_VALUE_STATUS_INVAL;
837 goto end;
838 }
839
840 if (!bt_value_is_integer(integer_obj)) {
841 BT_LOGW("Invalid parameter: value is not an integer value: addr=%p, "
842 "type=%s", integer_obj,
843 bt_value_type_string(integer_obj->type));
844 ret = BT_VALUE_STATUS_INVAL;
845 goto end;
846 }
847
848 if (integer_obj->is_frozen) {
849 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
850 integer_obj);
851 ret = BT_VALUE_STATUS_FROZEN;
852 goto end;
853 }
854
855 typed_integer_obj->value = val;
856 BT_LOGV("Set integer value's raw value: value-addr=%p, value=%" PRId64,
857 integer_obj, val);
858
859 end:
860 return ret;
861 }
862
863 enum bt_value_status bt_value_float_get(const struct bt_value *float_obj,
864 double *val)
865 {
866 enum bt_value_status ret = BT_VALUE_STATUS_OK;
867 struct bt_value_float *typed_float_obj =
868 BT_VALUE_TO_FLOAT(float_obj);
869
870 if (!float_obj || !val) {
871 BT_LOGW("Invalid parameter: value object or value is NULL: "
872 "value-addr=%p, raw-value-addr=%p",
873 float_obj, val);
874 ret = BT_VALUE_STATUS_INVAL;
875 goto end;
876 }
877
878 if (!bt_value_is_float(float_obj)) {
879 BT_LOGW("Invalid parameter: value is not a floating point number value: addr=%p, "
880 "type=%s", float_obj,
881 bt_value_type_string(float_obj->type));
882 ret = BT_VALUE_STATUS_INVAL;
883 goto end;
884 }
885
886 *val = typed_float_obj->value;
887
888 end:
889 return ret;
890 }
891
892 enum bt_value_status bt_value_float_set(struct bt_value *float_obj,
893 double val)
894 {
895 enum bt_value_status ret = BT_VALUE_STATUS_OK;
896 struct bt_value_float *typed_float_obj =
897 BT_VALUE_TO_FLOAT(float_obj);
898
899 if (!float_obj) {
900 BT_LOGW_STR("Invalid parameter: value object is NULL.");
901 ret = BT_VALUE_STATUS_INVAL;
902 goto end;
903 }
904
905 if (!bt_value_is_float(float_obj)) {
906 BT_LOGW("Invalid parameter: value is not a floating point number value: addr=%p, "
907 "type=%s", float_obj,
908 bt_value_type_string(float_obj->type));
909 ret = BT_VALUE_STATUS_INVAL;
910 goto end;
911 }
912
913 if (float_obj->is_frozen) {
914 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
915 float_obj);
916 ret = BT_VALUE_STATUS_FROZEN;
917 goto end;
918 }
919
920 typed_float_obj->value = val;
921 BT_LOGV("Set floating point number value's raw value: value-addr=%p, value=%f",
922 float_obj, val);
923
924 end:
925 return ret;
926 }
927
928 enum bt_value_status bt_value_string_get(const struct bt_value *string_obj,
929 const char **val)
930 {
931 enum bt_value_status ret = BT_VALUE_STATUS_OK;
932 struct bt_value_string *typed_string_obj =
933 BT_VALUE_TO_STRING(string_obj);
934
935 if (!string_obj || !val) {
936 BT_LOGW("Invalid parameter: value object or value is NULL: "
937 "value-addr=%p, raw-value-addr=%p",
938 string_obj, val);
939 ret = BT_VALUE_STATUS_INVAL;
940 goto end;
941 }
942
943 if (!bt_value_is_string(string_obj)) {
944 BT_LOGW("Invalid parameter: value is not a string value: addr=%p, "
945 "type=%s", string_obj,
946 bt_value_type_string(string_obj->type));
947 ret = BT_VALUE_STATUS_INVAL;
948 goto end;
949 }
950
951 *val = typed_string_obj->gstr->str;
952
953 end:
954 return ret;
955 }
956
957 enum bt_value_status bt_value_string_set(struct bt_value *string_obj,
958 const char *val)
959 {
960 enum bt_value_status ret = BT_VALUE_STATUS_OK;
961 struct bt_value_string *typed_string_obj =
962 BT_VALUE_TO_STRING(string_obj);
963
964 if (!string_obj || !val) {
965 BT_LOGW("Invalid parameter: value object or value is NULL: "
966 "value-addr=%p, raw-value-addr=%p",
967 string_obj, val);
968 ret = BT_VALUE_STATUS_INVAL;
969 goto end;
970 }
971
972 if (!bt_value_is_string(string_obj)) {
973 BT_LOGW("Invalid parameter: value is not a string value: addr=%p, "
974 "type=%s", string_obj,
975 bt_value_type_string(string_obj->type));
976 ret = BT_VALUE_STATUS_INVAL;
977 goto end;
978 }
979
980 if (string_obj->is_frozen) {
981 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
982 string_obj);
983 ret = BT_VALUE_STATUS_FROZEN;
984 goto end;
985 }
986
987 g_string_assign(typed_string_obj->gstr, val);
988 BT_LOGV("Set string value's raw value: value-addr=%p, raw-value-addr=%p",
989 string_obj, val);
990
991 end:
992 return ret;
993 }
994
995 int64_t bt_value_array_size(const struct bt_value *array_obj)
996 {
997 int64_t ret;
998 struct bt_value_array *typed_array_obj =
999 BT_VALUE_TO_ARRAY(array_obj);
1000
1001 if (!array_obj) {
1002 BT_LOGW_STR("Invalid parameter: value object is NULL.");
1003 ret = (int64_t) BT_VALUE_STATUS_INVAL;
1004 goto end;
1005 }
1006
1007 if (!bt_value_is_array(array_obj)) {
1008 BT_LOGW("Invalid parameter: value is not an array value: addr=%p, "
1009 "type=%s", array_obj,
1010 bt_value_type_string(array_obj->type));
1011 ret = BT_VALUE_STATUS_INVAL;
1012 goto end;
1013 }
1014
1015 ret = (int64_t) typed_array_obj->garray->len;
1016
1017 end:
1018 return ret;
1019 }
1020
1021 bt_bool bt_value_array_is_empty(const struct bt_value *array_obj)
1022 {
1023 return bt_value_array_size(array_obj) == 0;
1024 }
1025
1026 struct bt_value *bt_value_array_get(const struct bt_value *array_obj,
1027 uint64_t index)
1028 {
1029 struct bt_value *ret;
1030 struct bt_value_array *typed_array_obj =
1031 BT_VALUE_TO_ARRAY(array_obj);
1032
1033 if (!array_obj) {
1034 BT_LOGW("Invalid parameter: value object is NULL: index=%" PRIu64,
1035 index);
1036 ret = NULL;
1037 goto end;
1038 }
1039
1040 if (!bt_value_is_array(array_obj)) {
1041 BT_LOGW("Invalid parameter: value is not an array value: addr=%p, "
1042 "type=%s", array_obj,
1043 bt_value_type_string(array_obj->type));
1044 ret = NULL;
1045 goto end;
1046 }
1047
1048 if (index >= typed_array_obj->garray->len) {
1049 BT_LOGW("Invalid parameter: index is out of bounds: "
1050 "addr=%p, index=%" PRIu64 ", size=%u",
1051 array_obj, index, typed_array_obj->garray->len);
1052 ret = NULL;
1053 goto end;
1054 }
1055
1056 ret = g_ptr_array_index(typed_array_obj->garray, index);
1057 bt_get(ret);
1058
1059 end:
1060 return ret;
1061 }
1062
1063 enum bt_value_status bt_value_array_append(struct bt_value *array_obj,
1064 struct bt_value *element_obj)
1065 {
1066 enum bt_value_status ret = BT_VALUE_STATUS_OK;
1067 struct bt_value_array *typed_array_obj =
1068 BT_VALUE_TO_ARRAY(array_obj);
1069
1070 if (!array_obj || !element_obj) {
1071 BT_LOGW("Invalid parameter: array value or element value is NULL: "
1072 "array-value-addr=%p, element-value-addr=%p",
1073 array_obj, element_obj);
1074 ret = BT_VALUE_STATUS_INVAL;
1075 goto end;
1076 }
1077
1078 if (!bt_value_is_array(array_obj)) {
1079 BT_LOGW("Invalid parameter: value is not an array value: addr=%p, "
1080 "type=%s", array_obj,
1081 bt_value_type_string(array_obj->type));
1082 ret = BT_VALUE_STATUS_INVAL;
1083 goto end;
1084 }
1085
1086 if (array_obj->is_frozen) {
1087 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1088 array_obj);
1089 ret = BT_VALUE_STATUS_FROZEN;
1090 goto end;
1091 }
1092
1093 g_ptr_array_add(typed_array_obj->garray, element_obj);
1094 bt_get(element_obj);
1095 BT_LOGV("Appended element to array value: array-value-addr=%p, "
1096 "element-value-addr=%p, new-size=%u",
1097 array_obj, element_obj, typed_array_obj->garray->len);
1098
1099 end:
1100 return ret;
1101 }
1102
1103 enum bt_value_status bt_value_array_append_bool(struct bt_value *array_obj,
1104 bt_bool val)
1105 {
1106 enum bt_value_status ret;
1107 struct bt_value *bool_obj = NULL;
1108
1109 bool_obj = bt_value_bool_create_init(val);
1110 ret = bt_value_array_append(array_obj, bool_obj);
1111 bt_put(bool_obj);
1112 return ret;
1113 }
1114
1115 enum bt_value_status bt_value_array_append_integer(
1116 struct bt_value *array_obj, int64_t val)
1117 {
1118 enum bt_value_status ret;
1119 struct bt_value *integer_obj = NULL;
1120
1121 integer_obj = bt_value_integer_create_init(val);
1122 ret = bt_value_array_append(array_obj, integer_obj);
1123 bt_put(integer_obj);
1124 return ret;
1125 }
1126
1127 enum bt_value_status bt_value_array_append_float(struct bt_value *array_obj,
1128 double val)
1129 {
1130 enum bt_value_status ret;
1131 struct bt_value *float_obj = NULL;
1132
1133 float_obj = bt_value_float_create_init(val);
1134 ret = bt_value_array_append(array_obj, float_obj);
1135 bt_put(float_obj);
1136 return ret;
1137 }
1138
1139 enum bt_value_status bt_value_array_append_string(struct bt_value *array_obj,
1140 const char *val)
1141 {
1142 enum bt_value_status ret;
1143 struct bt_value *string_obj = NULL;
1144
1145 string_obj = bt_value_string_create_init(val);
1146 ret = bt_value_array_append(array_obj, string_obj);
1147 bt_put(string_obj);
1148 return ret;
1149 }
1150
1151 enum bt_value_status bt_value_array_append_empty_array(
1152 struct bt_value *array_obj)
1153 {
1154 enum bt_value_status ret;
1155 struct bt_value *empty_array_obj = NULL;
1156
1157 empty_array_obj = bt_value_array_create();
1158 ret = bt_value_array_append(array_obj, empty_array_obj);
1159 bt_put(empty_array_obj);
1160 return ret;
1161 }
1162
1163 enum bt_value_status bt_value_array_append_empty_map(struct bt_value *array_obj)
1164 {
1165 enum bt_value_status ret;
1166 struct bt_value *map_obj = NULL;
1167
1168 map_obj = bt_value_map_create();
1169 ret = bt_value_array_append(array_obj, map_obj);
1170 bt_put(map_obj);
1171 return ret;
1172 }
1173
1174 enum bt_value_status bt_value_array_set(struct bt_value *array_obj,
1175 uint64_t index, struct bt_value *element_obj)
1176 {
1177 enum bt_value_status ret = BT_VALUE_STATUS_OK;
1178 struct bt_value_array *typed_array_obj =
1179 BT_VALUE_TO_ARRAY(array_obj);
1180
1181 if (!array_obj || !element_obj) {
1182 BT_LOGW("Invalid parameter: array value or element value is NULL: "
1183 "index=%" PRIu64 ", array-value-addr=%p, element-value-addr=%p",
1184 index, array_obj, element_obj);
1185 ret = BT_VALUE_STATUS_INVAL;
1186 goto end;
1187 }
1188
1189 if (!bt_value_is_array(array_obj)) {
1190 BT_LOGW("Invalid parameter: value is not an array value: addr=%p, "
1191 "type=%s", array_obj,
1192 bt_value_type_string(array_obj->type));
1193 ret = BT_VALUE_STATUS_INVAL;
1194 goto end;
1195 }
1196
1197 if (index >= typed_array_obj->garray->len) {
1198 BT_LOGW("Invalid parameter: index is out of bounds: "
1199 "addr=%p, index=%" PRIu64 ", size=%u",
1200 array_obj, index, typed_array_obj->garray->len);
1201 ret = BT_VALUE_STATUS_INVAL;
1202 goto end;
1203 }
1204
1205 if (array_obj->is_frozen) {
1206 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1207 array_obj);
1208 ret = BT_VALUE_STATUS_FROZEN;
1209 goto end;
1210 }
1211
1212 bt_put(g_ptr_array_index(typed_array_obj->garray, index));
1213 g_ptr_array_index(typed_array_obj->garray, index) = element_obj;
1214 bt_get(element_obj);
1215 BT_LOGV("Set array value's element: array-value-addr=%p, "
1216 "index=%" PRIu64 ", element-value-addr=%p",
1217 array_obj, index, element_obj);
1218
1219 end:
1220 return ret;
1221 }
1222
1223 int64_t bt_value_map_size(const struct bt_value *map_obj)
1224 {
1225 int64_t ret;
1226 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1227
1228 if (!map_obj) {
1229 BT_LOGW_STR("Invalid parameter: value object is NULL.");
1230 ret = (int64_t) BT_VALUE_STATUS_INVAL;
1231 goto end;
1232 }
1233
1234 if (!bt_value_is_map(map_obj)) {
1235 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
1236 "type=%s", map_obj,
1237 bt_value_type_string(map_obj->type));
1238 ret = (int64_t) BT_VALUE_STATUS_INVAL;
1239 goto end;
1240 }
1241
1242 ret = (int64_t) g_hash_table_size(typed_map_obj->ght);
1243
1244 end:
1245 return ret;
1246 }
1247
1248 bt_bool bt_value_map_is_empty(const struct bt_value *map_obj)
1249 {
1250 return bt_value_map_size(map_obj) == 0;
1251 }
1252
1253 struct bt_value *bt_value_map_get(const struct bt_value *map_obj,
1254 const char *key)
1255 {
1256 GQuark quark;
1257 struct bt_value *ret;
1258 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1259
1260 if (!map_obj || !key) {
1261 BT_LOGW("Invalid parameter: value object or key is NULL: "
1262 "value-addr=%p, key-addr=%p", map_obj, key);
1263 ret = NULL;
1264 goto end;
1265 }
1266
1267 if (!bt_value_is_map(map_obj)) {
1268 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
1269 "type=%s", map_obj,
1270 bt_value_type_string(map_obj->type));
1271 ret = NULL;
1272 goto end;
1273 }
1274
1275 quark = g_quark_from_string(key);
1276 ret = g_hash_table_lookup(typed_map_obj->ght, GUINT_TO_POINTER(quark));
1277 if (ret) {
1278 bt_get(ret);
1279 }
1280
1281 end:
1282 return ret;
1283 }
1284
1285 bt_bool bt_value_map_has_key(const struct bt_value *map_obj, const char *key)
1286 {
1287 bt_bool ret;
1288 GQuark quark;
1289 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1290
1291 if (!map_obj || !key) {
1292 BT_LOGW("Invalid parameter: value object or key is NULL: "
1293 "value-addr=%p, key-addr=%p", map_obj, key);
1294 ret = BT_FALSE;
1295 goto end;
1296 }
1297
1298 if (!bt_value_is_map(map_obj)) {
1299 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
1300 "type=%s", map_obj,
1301 bt_value_type_string(map_obj->type));
1302 ret = BT_FALSE;
1303 goto end;
1304 }
1305
1306 quark = g_quark_from_string(key);
1307 ret = bt_g_hash_table_contains(typed_map_obj->ght,
1308 GUINT_TO_POINTER(quark));
1309
1310 end:
1311 return ret;
1312 }
1313
1314 enum bt_value_status bt_value_map_insert(struct bt_value *map_obj,
1315 const char *key, struct bt_value *element_obj)
1316 {
1317 GQuark quark;
1318 enum bt_value_status ret = BT_VALUE_STATUS_OK;
1319 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1320
1321 if (!map_obj || !key || !element_obj) {
1322 BT_LOGW("Invalid parameter: map value, key, or element value is NULL: "
1323 "map-value-addr=%p, key-addr=%p, element-value-addr=%p",
1324 map_obj, key, element_obj);
1325 ret = BT_VALUE_STATUS_INVAL;
1326 goto end;
1327 }
1328
1329 if (!bt_value_is_map(map_obj)) {
1330 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
1331 "type=%s", map_obj,
1332 bt_value_type_string(map_obj->type));
1333 ret = BT_VALUE_STATUS_INVAL;
1334 goto end;
1335 }
1336
1337 if (map_obj->is_frozen) {
1338 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1339 map_obj);
1340 ret = BT_VALUE_STATUS_FROZEN;
1341 goto end;
1342 }
1343
1344 quark = g_quark_from_string(key);
1345 g_hash_table_insert(typed_map_obj->ght,
1346 GUINT_TO_POINTER(quark), element_obj);
1347 bt_get(element_obj);
1348 BT_LOGV("Inserted value into map value: map-value-addr=%p, "
1349 "key=\"%s\", element-value-addr=%p",
1350 map_obj, key, element_obj);
1351
1352 end:
1353 return ret;
1354 }
1355
1356 enum bt_value_status bt_value_map_insert_bool(struct bt_value *map_obj,
1357 const char *key, bt_bool val)
1358 {
1359 enum bt_value_status ret;
1360 struct bt_value *bool_obj = NULL;
1361
1362 bool_obj = bt_value_bool_create_init(val);
1363 ret = bt_value_map_insert(map_obj, key, bool_obj);
1364 bt_put(bool_obj);
1365 return ret;
1366 }
1367
1368 enum bt_value_status bt_value_map_insert_integer(struct bt_value *map_obj,
1369 const char *key, int64_t val)
1370 {
1371 enum bt_value_status ret;
1372 struct bt_value *integer_obj = NULL;
1373
1374 integer_obj = bt_value_integer_create_init(val);
1375 ret = bt_value_map_insert(map_obj, key, integer_obj);
1376 bt_put(integer_obj);
1377 return ret;
1378 }
1379
1380 enum bt_value_status bt_value_map_insert_float(struct bt_value *map_obj,
1381 const char *key, double val)
1382 {
1383 enum bt_value_status ret;
1384 struct bt_value *float_obj = NULL;
1385
1386 float_obj = bt_value_float_create_init(val);
1387 ret = bt_value_map_insert(map_obj, key, float_obj);
1388 bt_put(float_obj);
1389 return ret;
1390 }
1391
1392 enum bt_value_status bt_value_map_insert_string(struct bt_value *map_obj,
1393 const char *key, const char *val)
1394 {
1395 enum bt_value_status ret;
1396 struct bt_value *string_obj = NULL;
1397
1398 string_obj = bt_value_string_create_init(val);
1399 ret = bt_value_map_insert(map_obj, key, string_obj);
1400 bt_put(string_obj);
1401 return ret;
1402 }
1403
1404 enum bt_value_status bt_value_map_insert_empty_array(struct bt_value *map_obj,
1405 const char *key)
1406 {
1407 enum bt_value_status ret;
1408 struct bt_value *array_obj = NULL;
1409
1410 array_obj = bt_value_array_create();
1411 ret = bt_value_map_insert(map_obj, key, array_obj);
1412 bt_put(array_obj);
1413 return ret;
1414 }
1415
1416 enum bt_value_status bt_value_map_insert_empty_map(struct bt_value *map_obj,
1417 const char *key)
1418 {
1419 enum bt_value_status ret;
1420 struct bt_value *empty_map_obj = NULL;
1421
1422 empty_map_obj = bt_value_map_create();
1423 ret = bt_value_map_insert(map_obj, key, empty_map_obj);
1424 bt_put(empty_map_obj);
1425 return ret;
1426 }
1427
1428 enum bt_value_status bt_value_map_foreach(const struct bt_value *map_obj,
1429 bt_value_map_foreach_cb cb, void *data)
1430 {
1431 enum bt_value_status ret = BT_VALUE_STATUS_OK;
1432 gpointer key, element_obj;
1433 GHashTableIter iter;
1434 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1435
1436 if (!map_obj || !cb) {
1437 BT_LOGW("Invalid parameter: map value or callback is NULL: "
1438 "value-addr=%p, cb-addr=%p", map_obj, cb);
1439 ret = BT_VALUE_STATUS_INVAL;
1440 goto end;
1441 }
1442
1443 if (!bt_value_is_map(map_obj)) {
1444 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
1445 "type=%s", map_obj,
1446 bt_value_type_string(map_obj->type));
1447 ret = BT_VALUE_STATUS_INVAL;
1448 goto end;
1449 }
1450
1451 g_hash_table_iter_init(&iter, typed_map_obj->ght);
1452
1453 while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
1454 const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
1455
1456 if (!cb(key_str, element_obj, data)) {
1457 BT_LOGV("User cancelled the loop: key=\"%s\", "
1458 "value-addr=%p, data=%p",
1459 key_str, element_obj, data);
1460 ret = BT_VALUE_STATUS_CANCELLED;
1461 break;
1462 }
1463 }
1464
1465 end:
1466 return ret;
1467 }
1468
1469 struct extend_map_element_data {
1470 struct bt_value *extended_obj;
1471 bt_bool got_error;
1472 };
1473
1474 static
1475 bt_bool extend_map_element(const char *key,
1476 struct bt_value *extension_obj_elem, void *data)
1477 {
1478 bt_bool ret = BT_TRUE;
1479
1480 struct extend_map_element_data *extend_data = data;
1481
1482 /* Copy object which is to replace the current one */
1483 struct bt_value *extension_obj_elem_copy =
1484 bt_value_copy(extension_obj_elem);
1485
1486 /* Replace in extended object */
1487 if (bt_value_map_insert(extend_data->extended_obj, key,
1488 extension_obj_elem_copy)) {
1489 BT_LOGE("Cannot replace value in extended value: key=\"%s\", "
1490 "extended-value-addr=%p, element-value-addr=%p",
1491 key, extend_data->extended_obj,
1492 extension_obj_elem_copy);
1493 goto error;
1494 }
1495
1496 goto end;
1497
1498 error:
1499 ret = BT_FALSE;
1500 extend_data->got_error = BT_TRUE;
1501
1502 end:
1503 BT_PUT(extension_obj_elem_copy);
1504 return ret;
1505 }
1506
1507 struct bt_value *bt_value_map_extend(struct bt_value *base_map_obj,
1508 struct bt_value *extension_obj)
1509 {
1510 struct bt_value *extended_obj = NULL;
1511 struct extend_map_element_data extend_data = { 0 };
1512
1513 if (!base_map_obj || !extension_obj) {
1514 BT_LOGW("Invalid parameter: base value or extension value is NULL: "
1515 "base-value-addr=%p, extension-value-addr=%p",
1516 base_map_obj, extension_obj);
1517 goto error;
1518 }
1519
1520 if (!bt_value_is_map(base_map_obj)) {
1521 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
1522 "type=%s", base_map_obj,
1523 bt_value_type_string(base_map_obj->type));
1524 goto error;
1525 }
1526
1527 if (!bt_value_is_map(extension_obj)) {
1528 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
1529 "type=%s", extension_obj,
1530 bt_value_type_string(extension_obj->type));
1531 goto error;
1532 }
1533
1534 BT_LOGD("Extending map value: base-value-addr=%p, extension-value-addr=%p",
1535 base_map_obj, extension_obj);
1536
1537 /* Create copy of base map object to start with */
1538 extended_obj = bt_value_copy(base_map_obj);
1539 if (!extended_obj) {
1540 BT_LOGE("Cannot copy base value: base-value-addr=%p",
1541 base_map_obj);
1542 goto error;
1543 }
1544
1545 /*
1546 * For each key in the extension map object, replace this key
1547 * in the copied map object.
1548 */
1549 extend_data.extended_obj = extended_obj;
1550
1551 if (bt_value_map_foreach(extension_obj, extend_map_element,
1552 &extend_data)) {
1553 BT_LOGE("Cannot iterate on the extension object's elements: ",
1554 "extension-value-addr=%p", extension_obj);
1555 goto error;
1556 }
1557
1558 if (extend_data.got_error) {
1559 BT_LOGE("Failed to successfully iterate on the extension object's elements: ",
1560 "extension-value-addr=%p", extension_obj);
1561 goto error;
1562 }
1563
1564 BT_LOGD("Extended map value: extended-value-addr=%p",
1565 extended_obj);
1566 goto end;
1567
1568 error:
1569 BT_PUT(extended_obj);
1570
1571 end:
1572 return extended_obj;
1573 }
1574
1575 struct bt_value *bt_value_copy(const struct bt_value *object)
1576 {
1577 struct bt_value *copy_obj = NULL;
1578
1579 if (!object) {
1580 BT_LOGW_STR("Invalid parameter: value object is NULL.");
1581 goto end;
1582 }
1583
1584 BT_LOGD("Copying value object: addr=%p", object);
1585 copy_obj = copy_funcs[object->type](object);
1586 if (copy_obj) {
1587 BT_LOGD("Copied value object: copy-value-addr=%p",
1588 copy_obj);
1589 } else {
1590 BT_LOGE_STR("Failed to copy value object.");
1591 }
1592
1593 end:
1594 return copy_obj;
1595 }
1596
1597 bt_bool bt_value_compare(const struct bt_value *object_a,
1598 const struct bt_value *object_b)
1599 {
1600 bt_bool ret = BT_FALSE;
1601
1602 if (!object_a || !object_b) {
1603 BT_LOGW("Invalid parameter: value A or value B is NULL: "
1604 "value-a-addr=%p, value-b-addr=%p",
1605 object_a, object_b);
1606 goto end;
1607 }
1608
1609 if (object_a->type != object_b->type) {
1610 BT_LOGV("Values are different: type mismatch: "
1611 "value-a-addr=%p, value-b-addr=%p, "
1612 "value-a-type=%s, value-b-type=%s",
1613 object_a, object_b,
1614 bt_value_type_string(object_a->type),
1615 bt_value_type_string(object_b->type));
1616 goto end;
1617 }
1618
1619 ret = compare_funcs[object_a->type](object_a, object_b);
1620
1621 end:
1622 return ret;
1623 }
This page took 0.063385 seconds and 5 git commands to generate.