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