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