configure: re-enable '-Wunused-parameter'
[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 enum bt_value_type expected_type __attribute__((unused)),
833 uint64_t uval,
834 const char *api_func)
835 {
836 BT_ASSERT_PRE_DEV_VALUE_HOT_FROM_FUNC(api_func, integer_obj);
837 BT_VALUE_TO_INTEGER(integer_obj)->value.u = uval;
838 }
839
840 BT_EXPORT
841 void bt_value_integer_unsigned_set(struct bt_value *integer_obj,
842 uint64_t val)
843 {
844 BT_ASSERT_PRE_VALUE_NON_NULL(integer_obj);
845 BT_ASSERT_PRE_VALUE_IS_UNSIGNED_INT(integer_obj);
846 set_integer_value(integer_obj, BT_VALUE_TYPE_UNSIGNED_INTEGER, val,
847 __func__);
848 BT_LOGT("Set unsigned integer value's raw value: "
849 "value-addr=%p, value=%" PRIu64, integer_obj, val);
850 }
851
852 BT_EXPORT
853 void bt_value_integer_signed_set(struct bt_value *integer_obj,
854 int64_t val)
855 {
856 BT_ASSERT_PRE_VALUE_NON_NULL(integer_obj);
857 BT_ASSERT_PRE_VALUE_IS_SIGNED_INT(integer_obj);
858 set_integer_value(integer_obj, BT_VALUE_TYPE_SIGNED_INTEGER,
859 (uint64_t) val, __func__);
860 BT_LOGT("Set signed integer value's raw value: "
861 "value-addr=%p, value=%" PRId64, integer_obj, val);
862 }
863
864 BT_EXPORT
865 double bt_value_real_get(const struct bt_value *real_obj)
866 {
867 BT_ASSERT_PRE_DEV_VALUE_NON_NULL(real_obj);
868 BT_ASSERT_PRE_DEV_VALUE_IS_REAL(real_obj);
869 return BT_VALUE_TO_REAL(real_obj)->value;
870 }
871
872 BT_EXPORT
873 void bt_value_real_set(struct bt_value *real_obj, double val)
874 {
875 BT_ASSERT_PRE_VALUE_NON_NULL(real_obj);
876 BT_ASSERT_PRE_VALUE_IS_REAL(real_obj);
877 BT_ASSERT_PRE_DEV_VALUE_HOT(real_obj);
878 BT_VALUE_TO_REAL(real_obj)->value = val;
879 BT_LOGT("Set real number value's raw value: value-addr=%p, value=%f",
880 real_obj, val);
881 }
882
883 BT_EXPORT
884 const char *bt_value_string_get(const struct bt_value *string_obj)
885 {
886 BT_ASSERT_PRE_DEV_VALUE_NON_NULL(string_obj);
887 BT_ASSERT_PRE_DEV_VALUE_IS_STRING(string_obj);
888 return BT_VALUE_TO_STRING(string_obj)->gstr->str;
889 }
890
891 BT_EXPORT
892 enum bt_value_string_set_status bt_value_string_set(
893 struct bt_value *string_obj, const char *val)
894 {
895 BT_ASSERT_PRE_NO_ERROR();
896 BT_ASSERT_PRE_VALUE_NON_NULL(string_obj);
897 BT_ASSERT_PRE_VALUE_IS_STRING(string_obj);
898 BT_ASSERT_PRE_DEV_VALUE_HOT(string_obj);
899 g_string_assign(BT_VALUE_TO_STRING(string_obj)->gstr, val);
900 BT_LOGT("Set string value's raw value: value-addr=%p, raw-value-addr=%p",
901 string_obj, val);
902 return BT_FUNC_STATUS_OK;
903 }
904
905 BT_EXPORT
906 uint64_t bt_value_array_get_length(const struct bt_value *array_obj)
907 {
908 BT_ASSERT_PRE_DEV_VALUE_NON_NULL(array_obj);
909 BT_ASSERT_PRE_DEV_VALUE_IS_ARRAY(array_obj);
910 return (uint64_t) BT_VALUE_TO_ARRAY(array_obj)->garray->len;
911 }
912
913 BT_EXPORT
914 struct bt_value *bt_value_array_borrow_element_by_index(
915 struct bt_value *array_obj, uint64_t index)
916 {
917 struct bt_value_array *typed_array_obj =
918 BT_VALUE_TO_ARRAY(array_obj);
919
920 BT_ASSERT_PRE_DEV_VALUE_NON_NULL(array_obj);
921 BT_ASSERT_PRE_DEV_VALUE_IS_ARRAY(array_obj);
922 BT_ASSERT_PRE_DEV_VALID_INDEX(index, typed_array_obj->garray->len);
923 return g_ptr_array_index(typed_array_obj->garray, index);
924 }
925
926 BT_EXPORT
927 const struct bt_value *bt_value_array_borrow_element_by_index_const(
928 const struct bt_value *array_obj,
929 uint64_t index)
930 {
931 return bt_value_array_borrow_element_by_index(
932 (void *) array_obj, index);
933 }
934
935 static
936 enum bt_value_array_append_element_status append_array_element(
937 struct bt_value *array_obj,
938 struct bt_value *element_obj, const char *api_func)
939 {
940 struct bt_value_array *typed_array_obj =
941 BT_VALUE_TO_ARRAY(array_obj);
942
943 BT_ASSERT_PRE_NO_ERROR_FROM_FUNC(api_func);
944 BT_ASSERT_PRE_NON_NULL_FROM_FUNC(api_func, "array-value-object",
945 array_obj, "Array value object");
946 BT_ASSERT_PRE_NON_NULL_FROM_FUNC(api_func, "element-value-object",
947 element_obj, "Element value object");
948 BT_ASSERT_PRE_VALUE_HAS_TYPE_FROM_FUNC(api_func, "value-object",
949 array_obj, "array", BT_VALUE_TYPE_ARRAY);
950 BT_ASSERT_PRE_DEV_VALUE_HOT_FROM_FUNC(api_func, array_obj);
951 g_ptr_array_add(typed_array_obj->garray, element_obj);
952 bt_object_get_ref(element_obj);
953 BT_LOGT("Appended element to array value: array-value-addr=%p, "
954 "element-value-addr=%p, new-size=%u",
955 array_obj, element_obj, typed_array_obj->garray->len);
956 return BT_FUNC_STATUS_OK;
957 }
958
959 BT_EXPORT
960 enum bt_value_array_append_element_status bt_value_array_append_element(
961 struct bt_value *array_obj,
962 struct bt_value *element_obj)
963 {
964 return append_array_element(array_obj, element_obj, __func__);
965 }
966
967 BT_EXPORT
968 enum bt_value_array_append_element_status
969 bt_value_array_append_bool_element(struct bt_value *array_obj, bt_bool val)
970 {
971 enum bt_value_array_append_element_status ret;
972 struct bt_value *bool_obj = NULL;
973
974 BT_ASSERT_PRE_NO_ERROR();
975
976 bool_obj = bt_value_bool_create_init(val);
977 ret = append_array_element(array_obj,
978 (void *) bool_obj, __func__);
979 bt_object_put_ref(bool_obj);
980 return ret;
981 }
982
983 BT_EXPORT
984 enum bt_value_array_append_element_status
985 bt_value_array_append_unsigned_integer_element(struct bt_value *array_obj,
986 uint64_t val)
987 {
988 enum bt_value_array_append_element_status ret;
989 struct bt_value *integer_obj = NULL;
990
991 BT_ASSERT_PRE_NO_ERROR();
992
993 integer_obj = bt_value_integer_unsigned_create_init(val);
994 ret = append_array_element(array_obj,
995 (void *) integer_obj, __func__);
996 bt_object_put_ref(integer_obj);
997 return ret;
998 }
999
1000 BT_EXPORT
1001 enum bt_value_array_append_element_status
1002 bt_value_array_append_signed_integer_element(struct bt_value *array_obj,
1003 int64_t val)
1004 {
1005 enum bt_value_array_append_element_status ret;
1006 struct bt_value *integer_obj = NULL;
1007
1008 BT_ASSERT_PRE_NO_ERROR();
1009
1010 integer_obj = bt_value_integer_signed_create_init(val);
1011 ret = append_array_element(array_obj,
1012 (void *) integer_obj, __func__);
1013 bt_object_put_ref(integer_obj);
1014 return ret;
1015 }
1016
1017 BT_EXPORT
1018 enum bt_value_array_append_element_status
1019 bt_value_array_append_real_element(struct bt_value *array_obj, double val)
1020 {
1021 enum bt_value_array_append_element_status ret;
1022 struct bt_value *real_obj = NULL;
1023
1024 BT_ASSERT_PRE_NO_ERROR();
1025
1026 real_obj = bt_value_real_create_init(val);
1027 ret = append_array_element(array_obj,
1028 (void *) real_obj, __func__);
1029 bt_object_put_ref(real_obj);
1030 return ret;
1031 }
1032
1033 BT_EXPORT
1034 enum bt_value_array_append_element_status
1035 bt_value_array_append_string_element(struct bt_value *array_obj,
1036 const char *val)
1037 {
1038 enum bt_value_array_append_element_status ret;
1039 struct bt_value *string_obj = NULL;
1040
1041 BT_ASSERT_PRE_NO_ERROR();
1042
1043 string_obj = bt_value_string_create_init(val);
1044 ret = append_array_element(array_obj,
1045 (void *) string_obj, __func__);
1046 bt_object_put_ref(string_obj);
1047 return ret;
1048 }
1049
1050 BT_EXPORT
1051 enum bt_value_array_append_element_status
1052 bt_value_array_append_empty_array_element(struct bt_value *array_obj,
1053 struct bt_value **element_obj)
1054 {
1055 enum bt_value_array_append_element_status ret;
1056 struct bt_value *empty_array_obj = NULL;
1057
1058 BT_ASSERT_PRE_NO_ERROR();
1059
1060 empty_array_obj = bt_value_array_create();
1061 ret = append_array_element(array_obj,
1062 (void *) empty_array_obj, __func__);
1063
1064 if (element_obj) {
1065 *element_obj = empty_array_obj;
1066 }
1067
1068 bt_object_put_ref(empty_array_obj);
1069 return ret;
1070 }
1071
1072 BT_EXPORT
1073 enum bt_value_array_append_element_status
1074 bt_value_array_append_empty_map_element(struct bt_value *array_obj,
1075 struct bt_value **element_obj)
1076 {
1077 enum bt_value_array_append_element_status ret;
1078 struct bt_value *map_obj = NULL;
1079
1080 BT_ASSERT_PRE_NO_ERROR();
1081
1082 map_obj = bt_value_map_create();
1083 ret = append_array_element(array_obj,
1084 (void *) map_obj, __func__);
1085
1086 if (element_obj) {
1087 *element_obj = map_obj;
1088 }
1089
1090 bt_object_put_ref(map_obj);
1091 return ret;
1092 }
1093
1094 BT_EXPORT
1095 enum bt_value_array_set_element_by_index_status
1096 bt_value_array_set_element_by_index(struct bt_value *array_obj, uint64_t index,
1097 struct bt_value *element_obj)
1098 {
1099 struct bt_value_array *typed_array_obj =
1100 BT_VALUE_TO_ARRAY(array_obj);
1101
1102 BT_ASSERT_PRE_NO_ERROR();
1103 BT_ASSERT_PRE_NON_NULL("array-value-object", array_obj,
1104 "Array value object");
1105 BT_ASSERT_PRE_NON_NULL("element-value-object", element_obj,
1106 "Element value object");
1107 BT_ASSERT_PRE_VALUE_IS_ARRAY(array_obj);
1108 BT_ASSERT_PRE_DEV_VALUE_HOT(array_obj);
1109 BT_ASSERT_PRE_VALID_INDEX(index, typed_array_obj->garray->len);
1110 bt_object_put_ref(g_ptr_array_index(typed_array_obj->garray, index));
1111 g_ptr_array_index(typed_array_obj->garray, index) = element_obj;
1112 bt_object_get_ref(element_obj);
1113 BT_LOGT("Set array value's element: array-value-addr=%p, "
1114 "index=%" PRIu64 ", element-value-addr=%p",
1115 array_obj, index, element_obj);
1116 return BT_FUNC_STATUS_OK;
1117 }
1118
1119 BT_EXPORT
1120 uint64_t bt_value_map_get_size(const struct bt_value *map_obj)
1121 {
1122 BT_ASSERT_PRE_DEV_VALUE_NON_NULL(map_obj);
1123 BT_ASSERT_PRE_DEV_VALUE_IS_MAP(map_obj);
1124 return (uint64_t) g_hash_table_size(BT_VALUE_TO_MAP(map_obj)->ght);
1125 }
1126
1127 BT_EXPORT
1128 struct bt_value *bt_value_map_borrow_entry_value(struct bt_value *map_obj,
1129 const char *key)
1130 {
1131 BT_ASSERT_PRE_DEV_VALUE_NON_NULL(map_obj);
1132 BT_ASSERT_PRE_DEV_KEY_NON_NULL(key);
1133 BT_ASSERT_PRE_DEV_VALUE_IS_MAP(map_obj);
1134 return g_hash_table_lookup(BT_VALUE_TO_MAP(map_obj)->ght,
1135 GUINT_TO_POINTER(g_quark_from_string(key)));
1136 }
1137
1138 BT_EXPORT
1139 const struct bt_value *bt_value_map_borrow_entry_value_const(
1140 const struct bt_value *map_obj, const char *key)
1141 {
1142 return bt_value_map_borrow_entry_value((void *) map_obj, key);
1143 }
1144
1145 BT_EXPORT
1146 bt_bool bt_value_map_has_entry(const struct bt_value *map_obj, const char *key)
1147 {
1148 BT_ASSERT_PRE_DEV_VALUE_NON_NULL(map_obj);
1149 BT_ASSERT_PRE_DEV_KEY_NON_NULL(key);
1150 BT_ASSERT_PRE_DEV_VALUE_IS_MAP(map_obj);
1151 return bt_g_hash_table_contains(BT_VALUE_TO_MAP(map_obj)->ght,
1152 GUINT_TO_POINTER(g_quark_from_string(key)));
1153 }
1154
1155 static
1156 enum bt_value_map_insert_entry_status insert_map_value_entry(
1157 struct bt_value *map_obj, const char *key,
1158 struct bt_value *element_obj, const char *api_func)
1159 {
1160 BT_ASSERT_PRE_NO_ERROR_FROM_FUNC(api_func);
1161 BT_ASSERT_PRE_NON_NULL_FROM_FUNC(api_func, "map-value-object",
1162 map_obj, "Map value object");
1163 BT_ASSERT_PRE_KEY_NON_NULL_FROM_FUNC(api_func, key);
1164 BT_ASSERT_PRE_NON_NULL_FROM_FUNC(api_func,
1165 "element-value-object", element_obj, "Element value object");
1166 BT_ASSERT_PRE_VALUE_HAS_TYPE_FROM_FUNC(api_func, "value-object",
1167 map_obj, "map", BT_VALUE_TYPE_MAP);
1168 BT_ASSERT_PRE_DEV_VALUE_HOT_FROM_FUNC(api_func, map_obj);
1169 g_hash_table_insert(BT_VALUE_TO_MAP(map_obj)->ght,
1170 GUINT_TO_POINTER(g_quark_from_string(key)), element_obj);
1171 bt_object_get_ref(element_obj);
1172 BT_LOGT("Inserted value into map value: map-value-addr=%p, "
1173 "key=\"%s\", element-value-addr=%p",
1174 map_obj, key, element_obj);
1175 return BT_FUNC_STATUS_OK;
1176 }
1177
1178 BT_EXPORT
1179 enum bt_value_map_insert_entry_status bt_value_map_insert_entry(
1180 struct bt_value *map_obj, const char *key,
1181 struct bt_value *element_obj)
1182 {
1183 return insert_map_value_entry(map_obj, key, element_obj, __func__);
1184 }
1185
1186 BT_EXPORT
1187 enum bt_value_map_insert_entry_status bt_value_map_insert_bool_entry(
1188 struct bt_value *map_obj, const char *key, bt_bool val)
1189 {
1190 enum bt_value_map_insert_entry_status ret;
1191 struct bt_value *bool_obj = NULL;
1192
1193 BT_ASSERT_PRE_NO_ERROR();
1194
1195 bool_obj = bt_value_bool_create_init(val);
1196 ret = insert_map_value_entry(map_obj, key,
1197 (void *) bool_obj, __func__);
1198 bt_object_put_ref(bool_obj);
1199 return ret;
1200 }
1201
1202 BT_EXPORT
1203 enum bt_value_map_insert_entry_status
1204 bt_value_map_insert_unsigned_integer_entry(struct bt_value *map_obj,
1205 const char *key, uint64_t val)
1206 {
1207 enum bt_value_map_insert_entry_status ret;
1208 struct bt_value *integer_obj = NULL;
1209
1210 BT_ASSERT_PRE_NO_ERROR();
1211
1212 integer_obj = bt_value_integer_unsigned_create_init(val);
1213 ret = insert_map_value_entry(map_obj, key,
1214 (void *) integer_obj, __func__);
1215 bt_object_put_ref(integer_obj);
1216 return ret;
1217 }
1218
1219 BT_EXPORT
1220 enum bt_value_map_insert_entry_status
1221 bt_value_map_insert_signed_integer_entry(struct bt_value *map_obj,
1222 const char *key, int64_t val)
1223 {
1224 enum bt_value_map_insert_entry_status ret;
1225 struct bt_value *integer_obj = NULL;
1226
1227 BT_ASSERT_PRE_NO_ERROR();
1228
1229 integer_obj = bt_value_integer_signed_create_init(val);
1230 ret = insert_map_value_entry(map_obj, key,
1231 (void *) integer_obj, __func__);
1232 bt_object_put_ref(integer_obj);
1233 return ret;
1234 }
1235
1236 BT_EXPORT
1237 enum bt_value_map_insert_entry_status bt_value_map_insert_real_entry(
1238 struct bt_value *map_obj, const char *key, double val)
1239 {
1240 enum bt_value_map_insert_entry_status ret;
1241 struct bt_value *real_obj = NULL;
1242
1243 BT_ASSERT_PRE_NO_ERROR();
1244
1245 real_obj = bt_value_real_create_init(val);
1246 ret = insert_map_value_entry(map_obj, key,
1247 (void *) real_obj, __func__);
1248 bt_object_put_ref(real_obj);
1249 return ret;
1250 }
1251
1252 BT_EXPORT
1253 enum bt_value_map_insert_entry_status bt_value_map_insert_string_entry(
1254 struct bt_value *map_obj, const char *key,
1255 const char *val)
1256 {
1257 enum bt_value_map_insert_entry_status ret;
1258 struct bt_value *string_obj = NULL;
1259
1260 BT_ASSERT_PRE_NO_ERROR();
1261
1262 string_obj = bt_value_string_create_init(val);
1263 ret = insert_map_value_entry(map_obj, key,
1264 (void *) string_obj, __func__);
1265 bt_object_put_ref(string_obj);
1266 return ret;
1267 }
1268
1269 BT_EXPORT
1270 enum bt_value_map_insert_entry_status
1271 bt_value_map_insert_empty_array_entry(
1272 struct bt_value *map_obj, const char *key,
1273 bt_value **entry_obj)
1274 {
1275 enum bt_value_map_insert_entry_status ret;
1276 struct bt_value *array_obj = NULL;
1277
1278 BT_ASSERT_PRE_NO_ERROR();
1279
1280 array_obj = bt_value_array_create();
1281 ret = insert_map_value_entry(map_obj, key,
1282 (void *) array_obj, __func__);
1283
1284 if (entry_obj) {
1285 *entry_obj = array_obj;
1286 }
1287
1288 bt_object_put_ref(array_obj);
1289 return ret;
1290 }
1291
1292 BT_EXPORT
1293 enum bt_value_map_insert_entry_status
1294 bt_value_map_insert_empty_map_entry(struct bt_value *map_obj, const char *key,
1295 bt_value **entry_obj)
1296 {
1297 enum bt_value_map_insert_entry_status ret;
1298 struct bt_value *empty_map_obj = NULL;
1299
1300 BT_ASSERT_PRE_NO_ERROR();
1301
1302 empty_map_obj = bt_value_map_create();
1303 ret = insert_map_value_entry(map_obj, key,
1304 (void *) empty_map_obj, __func__);
1305
1306 if (entry_obj) {
1307 *entry_obj = empty_map_obj;
1308 }
1309
1310 bt_object_put_ref(empty_map_obj);
1311 return ret;
1312 }
1313
1314 static
1315 enum bt_value_map_foreach_entry_status foreach_map_entry(
1316 struct bt_value *map_obj, bt_value_map_foreach_entry_func func,
1317 void *data, const char *api_func,
1318 const char *user_func_name)
1319 {
1320 int status = BT_FUNC_STATUS_OK;
1321 gpointer key, element_obj;
1322 GHashTableIter iter;
1323 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1324
1325 BT_ASSERT_PRE_NO_ERROR_FROM_FUNC(api_func);
1326 BT_ASSERT_PRE_DEV_VALUE_NON_NULL_FROM_FUNC(api_func, map_obj);
1327 BT_ASSERT_PRE_DEV_NON_NULL_FROM_FUNC(api_func, "user-function",
1328 func, "User function");
1329 BT_ASSERT_PRE_VALUE_HAS_TYPE_FROM_FUNC(api_func, "value-object",
1330 map_obj, "map", BT_VALUE_TYPE_MAP);
1331 g_hash_table_iter_init(&iter, typed_map_obj->ght);
1332
1333 while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
1334 const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
1335
1336 status = func(key_str, element_obj, data);
1337 BT_ASSERT_POST_NO_ERROR_IF_NO_ERROR_STATUS(user_func_name,
1338 status);
1339 if (status != BT_FUNC_STATUS_OK) {
1340 if (status < 0) {
1341 BT_LIB_LOGE_APPEND_CAUSE(
1342 "User function failed while iterating "
1343 "map value entries: "
1344 "status=%s, key=\"%s\", "
1345 "value-addr=%p, data=%p",
1346 bt_common_func_status_string(status),
1347 key_str, element_obj, data);
1348
1349 if (status == BT_FUNC_STATUS_ERROR) {
1350 /*
1351 * User function error becomes a
1352 * user error from this
1353 * function's caller's
1354 * perspective.
1355 */
1356 status = BT_FUNC_STATUS_USER_ERROR;
1357 }
1358 } else {
1359 BT_ASSERT(status == BT_FUNC_STATUS_INTERRUPTED);
1360 BT_LOGT("User interrupted the loop: status=%s, "
1361 "key=\"%s\", value-addr=%p, data=%p",
1362 bt_common_func_status_string(status),
1363 key_str, element_obj, data);
1364 }
1365
1366 break;
1367 }
1368 }
1369
1370 return status;
1371 }
1372
1373 BT_EXPORT
1374 enum bt_value_map_foreach_entry_status bt_value_map_foreach_entry(
1375 struct bt_value *map_obj, bt_value_map_foreach_entry_func func,
1376 void *data)
1377 {
1378 return foreach_map_entry(map_obj, func, data, __func__,
1379 "bt_value_map_foreach_entry_func");
1380 }
1381
1382 BT_EXPORT
1383 enum bt_value_map_foreach_entry_const_status bt_value_map_foreach_entry_const(
1384 const struct bt_value *map_obj,
1385 bt_value_map_foreach_entry_const_func func, void *data)
1386 {
1387 return (int) foreach_map_entry((void *) map_obj,
1388 (bt_value_map_foreach_entry_func) func, data, __func__,
1389 "bt_value_map_foreach_entry_const_func");
1390 }
1391
1392 struct extend_map_element_data {
1393 struct bt_value *base_obj;
1394 };
1395
1396 static
1397 bt_value_map_foreach_entry_const_func_status extend_map_element(
1398 const char *key, const struct bt_value *extension_obj_elem,
1399 void *data)
1400 {
1401 int status;
1402 struct extend_map_element_data *extend_data = data;
1403 struct bt_value *extension_obj_elem_copy = NULL;
1404
1405 /* Copy object which is to replace the current one */
1406 status = bt_value_copy(extension_obj_elem, &extension_obj_elem_copy);
1407 if (status) {
1408 BT_LIB_LOGE_APPEND_CAUSE("Cannot copy map element: %!+v",
1409 extension_obj_elem);
1410 goto error;
1411 }
1412
1413 BT_ASSERT(extension_obj_elem_copy);
1414
1415 /* Replace in base map value. */
1416 status = bt_value_map_insert_entry(extend_data->base_obj, key,
1417 extension_obj_elem_copy);
1418 if (status) {
1419 BT_LIB_LOGE_APPEND_CAUSE(
1420 "Cannot replace value in base map value: key=\"%s\", "
1421 "%![base-map-value-]+v, %![element-value-]+v",
1422 key, extend_data->base_obj, extension_obj_elem_copy);
1423 goto error;
1424 }
1425
1426 goto end;
1427
1428 error:
1429 BT_ASSERT(status < 0);
1430
1431 end:
1432 BT_OBJECT_PUT_REF_AND_RESET(extension_obj_elem_copy);
1433 BT_ASSERT(status == BT_FUNC_STATUS_OK ||
1434 status == BT_FUNC_STATUS_MEMORY_ERROR);
1435 return status;
1436 }
1437
1438 BT_EXPORT
1439 enum bt_value_map_extend_status bt_value_map_extend(
1440 struct bt_value *base_map_obj,
1441 const struct bt_value *extension_obj)
1442 {
1443 int status = BT_FUNC_STATUS_OK;
1444 struct extend_map_element_data extend_data = {
1445 .base_obj = NULL,
1446 };
1447
1448 BT_ASSERT_PRE_NO_ERROR();
1449 BT_ASSERT_PRE_NON_NULL("base-value-object", base_map_obj,
1450 "Base value object");
1451 BT_ASSERT_PRE_DEV_VALUE_HOT(base_map_obj);
1452 BT_ASSERT_PRE_NON_NULL("extension-value-object", extension_obj,
1453 "Extension value object");
1454 BT_ASSERT_PRE_VALUE_HAS_TYPE("base-value-object", base_map_obj,
1455 "map", BT_VALUE_TYPE_MAP);
1456 BT_ASSERT_PRE_VALUE_HAS_TYPE("extension-value-object", extension_obj,
1457 "map", BT_VALUE_TYPE_MAP);
1458 BT_LOGD("Extending map value: base-value-addr=%p, extension-value-addr=%p",
1459 base_map_obj, extension_obj);
1460
1461 /*
1462 * For each key in the extension map object, replace this key
1463 * in the base map object.
1464 */
1465 extend_data.base_obj = base_map_obj;
1466 status = bt_value_map_foreach_entry_const(extension_obj,
1467 extend_map_element, &extend_data);
1468 if (status != BT_FUNC_STATUS_OK) {
1469 BT_ASSERT(status == BT_FUNC_STATUS_MEMORY_ERROR);
1470 BT_LIB_LOGE_APPEND_CAUSE(
1471 "Cannot iterate on the extension object's elements: "
1472 "%![extension-value-]+v", extension_obj);
1473 }
1474
1475 return status;
1476 }
1477
1478 BT_EXPORT
1479 enum bt_value_copy_status bt_value_copy(const struct bt_value *object,
1480 struct bt_value **copy_obj)
1481 {
1482 enum bt_value_copy_status status = BT_FUNC_STATUS_OK;
1483
1484 BT_ASSERT_PRE_NO_ERROR();
1485 BT_ASSERT_PRE_VALUE_NON_NULL(object);
1486 BT_ASSERT_PRE_NON_NULL("value-object-copy-output", copy_obj,
1487 "Value object copy (output)");
1488 BT_LOGD("Copying value object: addr=%p", object);
1489 *copy_obj = copy_funcs[object->type](object);
1490 if (*copy_obj) {
1491 BT_LOGD("Copied value object: copy-value-addr=%p",
1492 copy_obj);
1493 } else {
1494 status = BT_FUNC_STATUS_MEMORY_ERROR;
1495 *copy_obj = NULL;
1496 BT_LIB_LOGE_APPEND_CAUSE("Failed to copy value object.");
1497 }
1498
1499 return status;
1500 }
1501
1502 BT_EXPORT
1503 bt_bool bt_value_is_equal(const struct bt_value *object_a,
1504 const struct bt_value *object_b)
1505 {
1506 bt_bool ret = BT_FALSE;
1507
1508 BT_ASSERT_PRE_DEV_NON_NULL("value-object-a", object_a,
1509 "Value object A");
1510 BT_ASSERT_PRE_DEV_NON_NULL("value-object-b", object_b,
1511 "Value object B");
1512
1513 if (object_a->type != object_b->type) {
1514 BT_LOGT("Values are different: type mismatch: "
1515 "value-a-addr=%p, value-b-addr=%p, "
1516 "value-a-type=%s, value-b-type=%s",
1517 object_a, object_b,
1518 bt_common_value_type_string(object_a->type),
1519 bt_common_value_type_string(object_b->type));
1520 goto end;
1521 }
1522
1523 ret = is_equal_funcs[object_a->type](object_a, object_b);
1524
1525 end:
1526 return ret;
1527 }
1528
1529 BT_EXPORT
1530 void bt_value_get_ref(const struct bt_value *value)
1531 {
1532 bt_object_get_ref(value);
1533 }
1534
1535 BT_EXPORT
1536 void bt_value_put_ref(const struct bt_value *value)
1537 {
1538 bt_object_put_ref(value);
1539 }
This page took 0.118763 seconds and 4 git commands to generate.