Fix: lib: pass down API function name to some helpers
[babeltrace.git] / src / lib / value.c
... / ...
CommitLineData
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
39static
40void bt_value_null_instance_release_func(struct bt_object *obj)
41{
42 BT_LOGW("Releasing the null value singleton: addr=%p", obj);
43}
44
45static
46struct 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
59struct bt_value *const bt_value_null = &bt_value_null_instance;
60
61static
62void bt_value_destroy(struct bt_object *obj);
63
64static
65void 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
71static
72void 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
82static
83void 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
94static
95void (* 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
106static
107struct 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
115static
116struct 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
122static inline
123struct bt_value *bt_value_integer_create_init(enum bt_value_type type,
124 uint64_t uval);
125
126static
127struct 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
134static
135struct 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
141static
142struct 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
148static
149struct 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
198end:
199 return copy_obj;
200}
201
202static
203struct 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
252end:
253 return copy_obj;
254}
255
256static
257struct 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
268static
269bt_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
280static
281bt_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
296static
297bt_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
320static
321bt_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
336static
337bt_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
352static
353bt_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
391end:
392 return ret;
393}
394
395static
396bt_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
434end:
435 return ret;
436}
437
438static
439bt_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
451static
452void bt_value_null_freeze(struct bt_value *object)
453{
454}
455
456static
457void bt_value_generic_freeze(struct bt_value *object)
458{
459 object->frozen = BT_TRUE;
460}
461
462static
463void 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
476static
477void 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
492static
493void (* 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
504static
505void 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
524BT_HIDDEN
525void _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
538end:
539 return;
540}
541
542enum 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
548static
549struct 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
559struct 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
577end:
578 return (void *) bool_obj;
579}
580
581struct 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
588static inline
589struct 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
618end:
619 return (void *) integer_obj;
620}
621
622struct 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
630struct 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
637struct 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
645struct 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
652struct 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
671end:
672 return (void *) real_obj;
673}
674
675struct 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
682struct 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
710end:
711 return (void *) string_obj;
712}
713
714struct bt_value *bt_value_string_create(void)
715{
716 BT_ASSERT_PRE_NO_ERROR();
717
718 return bt_value_string_create_init("");
719}
720
721struct 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
748end:
749 return (void *) array_obj;
750}
751
752struct 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
778end:
779 return (void *) map_obj;
780}
781
782bt_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
789void 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
798uint64_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
805int64_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
812static inline
813void 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
821void 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
832void 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
843double 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
850void 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
860const 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
867enum 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
880uint64_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
887struct 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
899const 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
907static
908enum 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
931enum 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
938enum bt_value_array_append_element_status
939bt_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
953enum bt_value_array_append_element_status
954bt_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
969enum bt_value_array_append_element_status
970bt_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
985enum bt_value_array_append_element_status
986bt_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
1000enum bt_value_array_append_element_status
1001bt_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
1016enum bt_value_array_append_element_status
1017bt_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
1037enum bt_value_array_append_element_status
1038bt_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
1058enum bt_value_array_set_element_by_index_status
1059bt_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
1082uint64_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
1089struct 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
1099const 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
1105bt_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
1114static
1115enum 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
1137enum 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
1144enum 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
1159enum bt_value_map_insert_entry_status
1160bt_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
1175enum bt_value_map_insert_entry_status
1176bt_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
1191enum 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
1206enum 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
1222enum bt_value_map_insert_entry_status
1223bt_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
1244enum bt_value_map_insert_entry_status
1245bt_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
1265static
1266enum 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
1324enum 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
1332enum 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
1341struct extend_map_element_data {
1342 struct bt_value *base_obj;
1343};
1344
1345static
1346bt_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
1377error:
1378 BT_ASSERT(status < 0);
1379
1380end:
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
1387enum 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
1426enum 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
1449bt_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
1471end:
1472 return ret;
1473}
1474
1475void bt_value_get_ref(const struct bt_value *value)
1476{
1477 bt_object_get_ref(value);
1478}
1479
1480void bt_value_put_ref(const struct bt_value *value)
1481{
1482 bt_object_put_ref(value);
1483}
This page took 0.02672 seconds and 4 git commands to generate.