2 * Copyright (c) 2015-2018 Philippe Proulx <pproulx@efficios.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #define BT_LOG_TAG "VALUES"
24 #include <babeltrace/lib-logging-internal.h>
30 #include <babeltrace/compiler-internal.h>
31 #include <babeltrace/common-internal.h>
32 #include <babeltrace/value-const.h>
33 #include <babeltrace/value.h>
34 #include <babeltrace/compat/glib-internal.h>
35 #include <babeltrace/types.h>
36 #include <babeltrace/assert-pre-internal.h>
37 #include <babeltrace/value-internal.h>
38 #include <babeltrace/assert-internal.h>
40 #define BT_VALUE_TO_BOOL(_base) ((struct bt_value_bool *) (_base))
41 #define BT_VALUE_TO_INTEGER(_base) ((struct bt_value_integer *) (_base))
42 #define BT_VALUE_TO_REAL(_base) ((struct bt_value_real *) (_base))
43 #define BT_VALUE_TO_STRING(_base) ((struct bt_value_string *) (_base))
44 #define BT_VALUE_TO_ARRAY(_base) ((struct bt_value_array *) (_base))
45 #define BT_VALUE_TO_MAP(_base) ((struct bt_value_map *) (_base))
47 #define BT_ASSERT_PRE_VALUE_IS_TYPE(_value, _type) \
48 BT_ASSERT_PRE(((struct bt_value *) (_value))->type == (_type), \
49 "Value has the wrong type ID: expected-type=%s, " \
50 "%![value-]+v", bt_common_value_type_string(_type), \
53 #define BT_ASSERT_PRE_VALUE_HOT(_value, _name) \
54 BT_ASSERT_PRE_HOT(((struct bt_value *) (_value)), (_name), \
57 #define BT_ASSERT_PRE_VALUE_INDEX_IN_BOUNDS(_index, _count) \
58 BT_ASSERT_PRE((_index) < (_count), \
59 "Index is out of bound: " \
60 "index=%" PRIu64 ", count=%u", (_index), (_count));
63 void bt_value_null_instance_release_func(struct bt_object
*obj
)
65 BT_LOGW("Releasing the null value singleton: addr=%p", obj
);
69 struct bt_value bt_value_null_instance
= {
73 .release_func
= bt_value_null_instance_release_func
,
74 .spec_release_func
= NULL
,
75 .parent_is_owner_listener_func
= NULL
,
78 .type
= BT_VALUE_TYPE_NULL
,
82 struct bt_value
*const bt_value_null
= &bt_value_null_instance
;
85 void bt_value_destroy(struct bt_object
*obj
);
88 void bt_value_string_destroy(struct bt_value
*object
)
90 g_string_free(BT_VALUE_TO_STRING(object
)->gstr
, TRUE
);
91 BT_VALUE_TO_STRING(object
)->gstr
= NULL
;
95 void bt_value_array_destroy(struct bt_value
*object
)
98 * Pointer array's registered value destructor will take care
99 * of putting each contained object.
101 g_ptr_array_free(BT_VALUE_TO_ARRAY(object
)->garray
, TRUE
);
102 BT_VALUE_TO_ARRAY(object
)->garray
= NULL
;
106 void bt_value_map_destroy(struct bt_value
*object
)
109 * Hash table's registered value destructor will take care of
110 * putting each contained object. Keys are GQuarks and cannot
111 * be destroyed anyway.
113 g_hash_table_destroy(BT_VALUE_TO_MAP(object
)->ght
);
114 BT_VALUE_TO_MAP(object
)->ght
= NULL
;
118 void (* const destroy_funcs
[])(struct bt_value
*) = {
119 [BT_VALUE_TYPE_NULL
] = NULL
,
120 [BT_VALUE_TYPE_BOOL
] = NULL
,
121 [BT_VALUE_TYPE_INTEGER
] = NULL
,
122 [BT_VALUE_TYPE_REAL
] = NULL
,
123 [BT_VALUE_TYPE_STRING
] = bt_value_string_destroy
,
124 [BT_VALUE_TYPE_ARRAY
] = bt_value_array_destroy
,
125 [BT_VALUE_TYPE_MAP
] = bt_value_map_destroy
,
129 struct bt_value
*bt_value_null_copy(const struct bt_value
*null_obj
)
131 return (void *) bt_value_null
;
135 struct bt_value
*bt_value_bool_copy(const struct bt_value
*bool_obj
)
137 return bt_value_bool_create_init(
138 BT_VALUE_TO_BOOL(bool_obj
)->value
);
142 struct bt_value
*bt_value_integer_copy(
143 const struct bt_value
*integer_obj
)
145 return bt_value_integer_create_init(
146 BT_VALUE_TO_INTEGER(integer_obj
)->value
);
150 struct bt_value
*bt_value_real_copy(const struct bt_value
*real_obj
)
152 return bt_value_real_create_init(
153 BT_VALUE_TO_REAL(real_obj
)->value
);
157 struct bt_value
*bt_value_string_copy(const struct bt_value
*string_obj
)
159 return bt_value_string_create_init(
160 BT_VALUE_TO_STRING(string_obj
)->gstr
->str
);
164 struct bt_value
*bt_value_array_copy(const struct bt_value
*array_obj
)
168 struct bt_value
*copy_obj
;
169 struct bt_value_array
*typed_array_obj
;
171 BT_LOGD("Copying array value: addr=%p", array_obj
);
172 typed_array_obj
= BT_VALUE_TO_ARRAY(array_obj
);
173 copy_obj
= bt_value_array_create();
175 BT_LOGE_STR("Cannot create empty array value.");
179 for (i
= 0; i
< typed_array_obj
->garray
->len
; ++i
) {
180 struct bt_value
*element_obj_copy
= NULL
;
181 const struct bt_value
*element_obj
=
182 bt_value_array_borrow_element_by_index_const(
185 BT_ASSERT(element_obj
);
186 BT_LOGD("Copying array value's element: element-addr=%p, "
187 "index=%d", element_obj
, i
);
188 ret
= bt_value_copy(element_obj
, &element_obj_copy
);
190 BT_LOGE("Cannot copy array value's element: "
191 "array-addr=%p, index=%d",
193 BT_OBJECT_PUT_REF_AND_RESET(copy_obj
);
197 BT_ASSERT(element_obj_copy
);
198 ret
= bt_value_array_append_element(copy_obj
,
199 (void *) element_obj_copy
);
200 BT_OBJECT_PUT_REF_AND_RESET(element_obj_copy
);
202 BT_LOGE("Cannot append to array value: addr=%p",
204 BT_OBJECT_PUT_REF_AND_RESET(copy_obj
);
209 BT_LOGD("Copied array value: original-addr=%p, copy-addr=%p",
210 array_obj
, copy_obj
);
217 struct bt_value
*bt_value_map_copy(const struct bt_value
*map_obj
)
221 gpointer key
, element_obj
;
222 struct bt_value
*copy_obj
;
223 struct bt_value
*element_obj_copy
= NULL
;
224 struct bt_value_map
*typed_map_obj
;
226 BT_LOGD("Copying map value: addr=%p", map_obj
);
227 typed_map_obj
= BT_VALUE_TO_MAP(map_obj
);
228 copy_obj
= bt_value_map_create();
233 g_hash_table_iter_init(&iter
, typed_map_obj
->ght
);
235 while (g_hash_table_iter_next(&iter
, &key
, &element_obj
)) {
236 const char *key_str
= g_quark_to_string(GPOINTER_TO_UINT(key
));
239 BT_LOGD("Copying map value's element: element-addr=%p, "
240 "key=\"%s\"", element_obj
, key_str
);
241 ret
= bt_value_copy(element_obj
, &element_obj_copy
);
243 BT_LOGE("Cannot copy map value's element: "
244 "map-addr=%p, key=\"%s\"",
246 BT_OBJECT_PUT_REF_AND_RESET(copy_obj
);
250 BT_ASSERT(element_obj_copy
);
251 ret
= bt_value_map_insert_entry(copy_obj
, key_str
,
252 (void *) element_obj_copy
);
253 BT_OBJECT_PUT_REF_AND_RESET(element_obj_copy
);
255 BT_LOGE("Cannot insert into map value: addr=%p, key=\"%s\"",
257 BT_OBJECT_PUT_REF_AND_RESET(copy_obj
);
262 BT_LOGD("Copied map value: addr=%p", map_obj
);
269 struct bt_value
*(* const copy_funcs
[])(const struct bt_value
*) = {
270 [BT_VALUE_TYPE_NULL
] = bt_value_null_copy
,
271 [BT_VALUE_TYPE_BOOL
] = bt_value_bool_copy
,
272 [BT_VALUE_TYPE_INTEGER
] = bt_value_integer_copy
,
273 [BT_VALUE_TYPE_REAL
] = bt_value_real_copy
,
274 [BT_VALUE_TYPE_STRING
] = bt_value_string_copy
,
275 [BT_VALUE_TYPE_ARRAY
] = bt_value_array_copy
,
276 [BT_VALUE_TYPE_MAP
] = bt_value_map_copy
,
280 bt_bool
bt_value_null_compare(const struct bt_value
*object_a
,
281 const struct bt_value
*object_b
)
284 * Always BT_TRUE since bt_value_compare() already checks if both
285 * object_a and object_b have the same type, and in the case of
286 * null value objects, they're always the same if it is so.
292 bt_bool
bt_value_bool_compare(const struct bt_value
*object_a
,
293 const struct bt_value
*object_b
)
295 if (BT_VALUE_TO_BOOL(object_a
)->value
!=
296 BT_VALUE_TO_BOOL(object_b
)->value
) {
297 BT_LOGV("Boolean value objects are different: "
298 "bool-a-val=%d, bool-b-val=%d",
299 BT_VALUE_TO_BOOL(object_a
)->value
,
300 BT_VALUE_TO_BOOL(object_b
)->value
);
308 bt_bool
bt_value_integer_compare(const struct bt_value
*object_a
,
309 const struct bt_value
*object_b
)
311 if (BT_VALUE_TO_INTEGER(object_a
)->value
!=
312 BT_VALUE_TO_INTEGER(object_b
)->value
) {
313 BT_LOGV("Integer value objects are different: "
314 "int-a-val=%" PRId64
", int-b-val=%" PRId64
,
315 BT_VALUE_TO_INTEGER(object_a
)->value
,
316 BT_VALUE_TO_INTEGER(object_b
)->value
);
324 bt_bool
bt_value_real_compare(const struct bt_value
*object_a
,
325 const struct bt_value
*object_b
)
327 if (BT_VALUE_TO_REAL(object_a
)->value
!=
328 BT_VALUE_TO_REAL(object_b
)->value
) {
329 BT_LOGV("Real number value objects are different: "
330 "real-a-val=%f, real-b-val=%f",
331 BT_VALUE_TO_REAL(object_a
)->value
,
332 BT_VALUE_TO_REAL(object_b
)->value
);
340 bt_bool
bt_value_string_compare(const struct bt_value
*object_a
,
341 const struct bt_value
*object_b
)
343 if (strcmp(BT_VALUE_TO_STRING(object_a
)->gstr
->str
,
344 BT_VALUE_TO_STRING(object_b
)->gstr
->str
) != 0) {
345 BT_LOGV("String value objects are different: "
346 "string-a-val=\"%s\", string-b-val=\"%s\"",
347 BT_VALUE_TO_STRING(object_a
)->gstr
->str
,
348 BT_VALUE_TO_STRING(object_b
)->gstr
->str
);
356 bt_bool
bt_value_array_compare(const struct bt_value
*object_a
,
357 const struct bt_value
*object_b
)
360 bt_bool ret
= BT_TRUE
;
361 const struct bt_value_array
*array_obj_a
=
362 BT_VALUE_TO_ARRAY(object_a
);
364 if (bt_value_array_get_size(object_a
) !=
365 bt_value_array_get_size(object_b
)) {
366 BT_LOGV("Array values are different: size mismatch "
367 "value-a-addr=%p, value-b-addr=%p, "
368 "value-a-size=%" PRId64
", value-b-size=%" PRId64
,
370 bt_value_array_get_size(object_a
),
371 bt_value_array_get_size(object_b
));
376 for (i
= 0; i
< array_obj_a
->garray
->len
; ++i
) {
377 const struct bt_value
*element_obj_a
;
378 const struct bt_value
*element_obj_b
;
380 element_obj_a
= bt_value_array_borrow_element_by_index_const(
382 element_obj_b
= bt_value_array_borrow_element_by_index_const(
385 if (!bt_value_compare(element_obj_a
, element_obj_b
)) {
386 BT_LOGV("Array values's elements are different: "
387 "value-a-addr=%p, value-b-addr=%p, index=%d",
388 element_obj_a
, element_obj_b
, i
);
399 bt_bool
bt_value_map_compare(const struct bt_value
*object_a
,
400 const struct bt_value
*object_b
)
402 bt_bool ret
= BT_TRUE
;
404 gpointer key
, element_obj_a
;
405 const struct bt_value_map
*map_obj_a
= BT_VALUE_TO_MAP(object_a
);
407 if (bt_value_map_get_size(object_a
) !=
408 bt_value_map_get_size(object_b
)) {
409 BT_LOGV("Map values are different: size mismatch "
410 "value-a-addr=%p, value-b-addr=%p, "
411 "value-a-size=%" PRId64
", value-b-size=%" PRId64
,
413 bt_value_map_get_size(object_a
),
414 bt_value_map_get_size(object_b
));
419 g_hash_table_iter_init(&iter
, map_obj_a
->ght
);
421 while (g_hash_table_iter_next(&iter
, &key
, &element_obj_a
)) {
422 const struct bt_value
*element_obj_b
;
423 const char *key_str
= g_quark_to_string(GPOINTER_TO_UINT(key
));
425 element_obj_b
= bt_value_map_borrow_entry_value_const(object_b
,
428 if (!bt_value_compare(element_obj_a
, element_obj_b
)) {
429 BT_LOGV("Map values's elements are different: "
430 "value-a-addr=%p, value-b-addr=%p, key=\"%s\"",
431 element_obj_a
, element_obj_b
, key_str
);
442 bt_bool (* const compare_funcs
[])(const struct bt_value
*,
443 const struct bt_value
*) = {
444 [BT_VALUE_TYPE_NULL
] = bt_value_null_compare
,
445 [BT_VALUE_TYPE_BOOL
] = bt_value_bool_compare
,
446 [BT_VALUE_TYPE_INTEGER
] = bt_value_integer_compare
,
447 [BT_VALUE_TYPE_REAL
] = bt_value_real_compare
,
448 [BT_VALUE_TYPE_STRING
] = bt_value_string_compare
,
449 [BT_VALUE_TYPE_ARRAY
] = bt_value_array_compare
,
450 [BT_VALUE_TYPE_MAP
] = bt_value_map_compare
,
454 void bt_value_null_freeze(struct bt_value
*object
)
459 void bt_value_generic_freeze(struct bt_value
*object
)
461 object
->frozen
= BT_TRUE
;
465 void bt_value_array_freeze(struct bt_value
*object
)
468 struct bt_value_array
*typed_array_obj
=
469 BT_VALUE_TO_ARRAY(object
);
471 for (i
= 0; i
< typed_array_obj
->garray
->len
; ++i
) {
472 bt_value_freeze(g_ptr_array_index(typed_array_obj
->garray
, i
));
475 bt_value_generic_freeze(object
);
479 void bt_value_map_freeze(struct bt_value
*object
)
482 gpointer key
, element_obj
;
483 const struct bt_value_map
*map_obj
= BT_VALUE_TO_MAP(object
);
485 g_hash_table_iter_init(&iter
, map_obj
->ght
);
487 while (g_hash_table_iter_next(&iter
, &key
, &element_obj
)) {
488 bt_value_freeze(element_obj
);
491 bt_value_generic_freeze(object
);
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_INTEGER
] = bt_value_generic_freeze
,
499 [BT_VALUE_TYPE_REAL
] = bt_value_generic_freeze
,
500 [BT_VALUE_TYPE_STRING
] = bt_value_generic_freeze
,
501 [BT_VALUE_TYPE_ARRAY
] = bt_value_array_freeze
,
502 [BT_VALUE_TYPE_MAP
] = bt_value_map_freeze
,
506 void bt_value_destroy(struct bt_object
*obj
)
508 struct bt_value
*value
;
510 value
= container_of(obj
, struct bt_value
, base
);
511 BT_LOGD("Destroying value: addr=%p", value
);
513 if (bt_value_is_null(value
)) {
514 BT_LOGD_STR("Not destroying the null value singleton.");
518 if (destroy_funcs
[value
->type
]) {
519 destroy_funcs
[value
->type
](value
);
526 enum bt_value_status
_bt_value_freeze(const struct bt_value
*c_object
)
528 const struct bt_value
*object
= (void *) c_object
;
529 enum bt_value_status ret
= BT_VALUE_STATUS_OK
;
533 if (object
->frozen
) {
537 BT_LOGD("Freezing value: addr=%p", object
);
538 freeze_funcs
[object
->type
]((void *) object
);
544 enum bt_value_type
bt_value_get_type(const struct bt_value
*object
)
546 BT_ASSERT_PRE_NON_NULL(object
, "Value object");
551 struct bt_value
bt_value_create_base(enum bt_value_type type
)
553 struct bt_value value
;
556 value
.frozen
= BT_FALSE
;
557 bt_object_init_shared(&value
.base
, bt_value_destroy
);
561 struct bt_value
*bt_value_bool_create_init(bt_bool val
)
563 struct bt_value_bool
*bool_obj
;
565 BT_LOGD("Creating boolean value object: val=%d", val
);
566 bool_obj
= g_new0(struct bt_value_bool
, 1);
568 BT_LOGE_STR("Failed to allocate one boolean value object.");
572 bool_obj
->base
= bt_value_create_base(BT_VALUE_TYPE_BOOL
);
573 bool_obj
->value
= val
;
574 BT_LOGD("Created boolean value object: addr=%p", bool_obj
);
577 return (void *) bool_obj
;
580 struct bt_value
*bt_value_bool_create(void)
582 return bt_value_bool_create_init(BT_FALSE
);
585 struct bt_value
*bt_value_integer_create_init(int64_t val
)
587 struct bt_value_integer
*integer_obj
;
589 BT_LOGD("Creating integer value object: val=%" PRId64
, val
);
590 integer_obj
= g_new0(struct bt_value_integer
, 1);
592 BT_LOGE_STR("Failed to allocate one integer value object.");
596 integer_obj
->base
= bt_value_create_base(BT_VALUE_TYPE_INTEGER
);
597 integer_obj
->value
= val
;
598 BT_LOGD("Created integer value object: addr=%p",
602 return (void *) integer_obj
;
605 struct bt_value
*bt_value_integer_create(void)
607 return bt_value_integer_create_init(0);
610 struct bt_value
*bt_value_real_create_init(double val
)
612 struct bt_value_real
*real_obj
;
614 BT_LOGD("Creating real number value object: val=%f", val
);
615 real_obj
= g_new0(struct bt_value_real
, 1);
617 BT_LOGE_STR("Failed to allocate one real number value object.");
621 real_obj
->base
= bt_value_create_base(BT_VALUE_TYPE_REAL
);
622 real_obj
->value
= val
;
623 BT_LOGD("Created real number value object: addr=%p",
627 return (void *) real_obj
;
630 struct bt_value
*bt_value_real_create(void)
632 return bt_value_real_create_init(0.);
635 struct bt_value
*bt_value_string_create_init(const char *val
)
637 struct bt_value_string
*string_obj
= NULL
;
640 BT_LOGW_STR("Invalid parameter: value is NULL.");
644 BT_LOGD("Creating string value object: val-len=%zu", strlen(val
));
645 string_obj
= g_new0(struct bt_value_string
, 1);
647 BT_LOGE_STR("Failed to allocate one string object.");
651 string_obj
->base
= bt_value_create_base(BT_VALUE_TYPE_STRING
);
652 string_obj
->gstr
= g_string_new(val
);
653 if (!string_obj
->gstr
) {
654 BT_LOGE_STR("Failed to allocate a GString.");
660 BT_LOGD("Created string value object: addr=%p",
664 return (void *) string_obj
;
667 struct bt_value
*bt_value_string_create(void)
669 return bt_value_string_create_init("");
672 struct bt_value
*bt_value_array_create(void)
674 struct bt_value_array
*array_obj
;
676 BT_LOGD_STR("Creating empty array value object.");
677 array_obj
= g_new0(struct bt_value_array
, 1);
679 BT_LOGE_STR("Failed to allocate one array object.");
683 array_obj
->base
= bt_value_create_base(BT_VALUE_TYPE_ARRAY
);
684 array_obj
->garray
= bt_g_ptr_array_new_full(0,
685 (GDestroyNotify
) bt_object_put_ref
);
686 if (!array_obj
->garray
) {
687 BT_LOGE_STR("Failed to allocate a GPtrArray.");
693 BT_LOGD("Created array value object: addr=%p",
697 return (void *) array_obj
;
700 struct bt_value
*bt_value_map_create(void)
702 struct bt_value_map
*map_obj
;
704 BT_LOGD_STR("Creating empty map value object.");
705 map_obj
= g_new0(struct bt_value_map
, 1);
707 BT_LOGE_STR("Failed to allocate one map object.");
711 map_obj
->base
= bt_value_create_base(BT_VALUE_TYPE_MAP
);
712 map_obj
->ght
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
,
713 NULL
, (GDestroyNotify
) bt_object_put_ref
);
715 BT_LOGE_STR("Failed to allocate a GHashTable.");
721 BT_LOGD("Created map value object: addr=%p",
725 return (void *) map_obj
;
728 bt_bool
bt_value_bool_get(const struct bt_value
*bool_obj
)
730 BT_ASSERT_PRE_NON_NULL(bool_obj
, "Value object");
731 BT_ASSERT_PRE_VALUE_IS_TYPE(bool_obj
, BT_VALUE_TYPE_BOOL
);
732 return BT_VALUE_TO_BOOL(bool_obj
)->value
;
735 void bt_value_bool_set(struct bt_value
*bool_obj
, bt_bool val
)
737 BT_ASSERT_PRE_NON_NULL(bool_obj
, "Value object");
738 BT_ASSERT_PRE_VALUE_IS_TYPE(bool_obj
, BT_VALUE_TYPE_BOOL
);
739 BT_ASSERT_PRE_VALUE_HOT(bool_obj
, "Value object");
740 BT_VALUE_TO_BOOL(bool_obj
)->value
= val
;
741 BT_LOGV("Set boolean value's raw value: value-addr=%p, value=%d",
745 int64_t bt_value_integer_get(const struct bt_value
*integer_obj
)
747 BT_ASSERT_PRE_NON_NULL(integer_obj
, "Value object");
748 BT_ASSERT_PRE_VALUE_IS_TYPE(integer_obj
, BT_VALUE_TYPE_INTEGER
);
749 return BT_VALUE_TO_INTEGER(integer_obj
)->value
;
752 void bt_value_integer_set(struct bt_value
*integer_obj
,
755 BT_ASSERT_PRE_NON_NULL(integer_obj
, "Value object");
756 BT_ASSERT_PRE_VALUE_IS_TYPE(integer_obj
, BT_VALUE_TYPE_INTEGER
);
757 BT_ASSERT_PRE_VALUE_HOT(integer_obj
, "Value object");
758 BT_VALUE_TO_INTEGER(integer_obj
)->value
= val
;
759 BT_LOGV("Set integer value's raw value: value-addr=%p, value=%" PRId64
,
763 double bt_value_real_get(const struct bt_value
*real_obj
)
765 BT_ASSERT_PRE_NON_NULL(real_obj
, "Value object");
766 BT_ASSERT_PRE_VALUE_IS_TYPE(real_obj
, BT_VALUE_TYPE_REAL
);
767 return BT_VALUE_TO_REAL(real_obj
)->value
;
770 void bt_value_real_set(struct bt_value
*real_obj
, double val
)
772 BT_ASSERT_PRE_NON_NULL(real_obj
, "Value object");
773 BT_ASSERT_PRE_VALUE_IS_TYPE(real_obj
, BT_VALUE_TYPE_REAL
);
774 BT_ASSERT_PRE_VALUE_HOT(real_obj
, "Value object");
775 BT_VALUE_TO_REAL(real_obj
)->value
= val
;
776 BT_LOGV("Set real number value's raw value: value-addr=%p, value=%f",
780 const char *bt_value_string_get(const struct bt_value
*string_obj
)
782 BT_ASSERT_PRE_NON_NULL(string_obj
, "Value object");
783 BT_ASSERT_PRE_VALUE_IS_TYPE(string_obj
, BT_VALUE_TYPE_STRING
);
784 return BT_VALUE_TO_STRING(string_obj
)->gstr
->str
;
787 enum bt_value_status
bt_value_string_set(
788 struct bt_value
*string_obj
, const char *val
)
790 BT_ASSERT_PRE_NON_NULL(string_obj
, "Value object");
791 BT_ASSERT_PRE_VALUE_IS_TYPE(string_obj
, BT_VALUE_TYPE_STRING
);
792 BT_ASSERT_PRE_VALUE_HOT(string_obj
, "Value object");
793 g_string_assign(BT_VALUE_TO_STRING(string_obj
)->gstr
, val
);
794 BT_LOGV("Set string value's raw value: value-addr=%p, raw-value-addr=%p",
796 return BT_VALUE_STATUS_OK
;
799 uint64_t bt_value_array_get_size(const struct bt_value
*array_obj
)
801 BT_ASSERT_PRE_NON_NULL(array_obj
, "Value object");
802 BT_ASSERT_PRE_VALUE_IS_TYPE(array_obj
, BT_VALUE_TYPE_ARRAY
);
803 return (uint64_t) BT_VALUE_TO_ARRAY(array_obj
)->garray
->len
;
806 struct bt_value
*bt_value_array_borrow_element_by_index(
807 struct bt_value
*array_obj
, uint64_t index
)
809 struct bt_value_array
*typed_array_obj
=
810 BT_VALUE_TO_ARRAY(array_obj
);
812 BT_ASSERT_PRE_NON_NULL(array_obj
, "Value object");
813 BT_ASSERT_PRE_VALUE_IS_TYPE(array_obj
, BT_VALUE_TYPE_ARRAY
);
814 BT_ASSERT_PRE_VALUE_INDEX_IN_BOUNDS(index
,
815 typed_array_obj
->garray
->len
);
816 return g_ptr_array_index(typed_array_obj
->garray
, index
);
819 const struct bt_value
*bt_value_array_borrow_element_by_index_const(
820 const struct bt_value
*array_obj
,
823 return bt_value_array_borrow_element_by_index(
824 (void *) array_obj
, index
);
827 enum bt_value_status
bt_value_array_append_element(
828 struct bt_value
*array_obj
,
829 struct bt_value
*element_obj
)
831 struct bt_value_array
*typed_array_obj
=
832 BT_VALUE_TO_ARRAY(array_obj
);
834 BT_ASSERT_PRE_NON_NULL(array_obj
, "Array value object");
835 BT_ASSERT_PRE_NON_NULL(element_obj
, "Element value object");
836 BT_ASSERT_PRE_VALUE_IS_TYPE(array_obj
, BT_VALUE_TYPE_ARRAY
);
837 BT_ASSERT_PRE_VALUE_HOT(array_obj
, "Array value object");
838 g_ptr_array_add(typed_array_obj
->garray
, element_obj
);
839 bt_object_get_ref(element_obj
);
840 BT_LOGV("Appended element to array value: array-value-addr=%p, "
841 "element-value-addr=%p, new-size=%u",
842 array_obj
, element_obj
, typed_array_obj
->garray
->len
);
843 return BT_VALUE_STATUS_OK
;
846 enum bt_value_status
bt_value_array_append_bool_element(
847 struct bt_value
*array_obj
, bt_bool val
)
849 enum bt_value_status ret
;
850 struct bt_value
*bool_obj
= NULL
;
852 bool_obj
= bt_value_bool_create_init(val
);
853 ret
= bt_value_array_append_element(array_obj
,
855 bt_object_put_ref(bool_obj
);
859 enum bt_value_status
bt_value_array_append_integer_element(
860 struct bt_value
*array_obj
, int64_t val
)
862 enum bt_value_status ret
;
863 struct bt_value
*integer_obj
= NULL
;
865 integer_obj
= bt_value_integer_create_init(val
);
866 ret
= bt_value_array_append_element(array_obj
,
867 (void *) integer_obj
);
868 bt_object_put_ref(integer_obj
);
872 enum bt_value_status
bt_value_array_append_real_element(
873 struct bt_value
*array_obj
, double val
)
875 enum bt_value_status ret
;
876 struct bt_value
*real_obj
= NULL
;
878 real_obj
= bt_value_real_create_init(val
);
879 ret
= bt_value_array_append_element(array_obj
,
881 bt_object_put_ref(real_obj
);
885 enum bt_value_status
bt_value_array_append_string_element(
886 struct bt_value
*array_obj
, const char *val
)
888 enum bt_value_status ret
;
889 struct bt_value
*string_obj
= NULL
;
891 string_obj
= bt_value_string_create_init(val
);
892 ret
= bt_value_array_append_element(array_obj
,
893 (void *) string_obj
);
894 bt_object_put_ref(string_obj
);
898 enum bt_value_status
bt_value_array_append_empty_array_element(
899 struct bt_value
*array_obj
)
901 enum bt_value_status ret
;
902 struct bt_value
*empty_array_obj
= NULL
;
904 empty_array_obj
= bt_value_array_create();
905 ret
= bt_value_array_append_element(array_obj
,
906 (void *) empty_array_obj
);
907 bt_object_put_ref(empty_array_obj
);
911 enum bt_value_status
bt_value_array_append_empty_map_element(
912 struct bt_value
*array_obj
)
914 enum bt_value_status ret
;
915 struct bt_value
*map_obj
= NULL
;
917 map_obj
= bt_value_map_create();
918 ret
= bt_value_array_append_element(array_obj
,
920 bt_object_put_ref(map_obj
);
924 enum bt_value_status
bt_value_array_set_element_by_index(
925 struct bt_value
*array_obj
, uint64_t index
,
926 struct bt_value
*element_obj
)
928 struct bt_value_array
*typed_array_obj
=
929 BT_VALUE_TO_ARRAY(array_obj
);
931 BT_ASSERT_PRE_NON_NULL(array_obj
, "Array value object");
932 BT_ASSERT_PRE_NON_NULL(element_obj
, "Element value object");
933 BT_ASSERT_PRE_VALUE_IS_TYPE(array_obj
, BT_VALUE_TYPE_ARRAY
);
934 BT_ASSERT_PRE_VALUE_HOT(array_obj
, "Array value object");
935 BT_ASSERT_PRE_VALUE_INDEX_IN_BOUNDS(index
,
936 typed_array_obj
->garray
->len
);
937 bt_object_put_ref(g_ptr_array_index(typed_array_obj
->garray
, index
));
938 g_ptr_array_index(typed_array_obj
->garray
, index
) = element_obj
;
939 bt_object_get_ref(element_obj
);
940 BT_LOGV("Set array value's element: array-value-addr=%p, "
941 "index=%" PRIu64
", element-value-addr=%p",
942 array_obj
, index
, element_obj
);
943 return BT_VALUE_STATUS_OK
;
946 uint64_t bt_value_map_get_size(const struct bt_value
*map_obj
)
948 BT_ASSERT_PRE_NON_NULL(map_obj
, "Value object");
949 BT_ASSERT_PRE_VALUE_IS_TYPE(map_obj
, BT_VALUE_TYPE_MAP
);
950 return (uint64_t) g_hash_table_size(BT_VALUE_TO_MAP(map_obj
)->ght
);
953 struct bt_value
*bt_value_map_borrow_entry_value(struct bt_value
*map_obj
,
956 BT_ASSERT_PRE_NON_NULL(map_obj
, "Value object");
957 BT_ASSERT_PRE_NON_NULL(key
, "Key");
958 BT_ASSERT_PRE_VALUE_IS_TYPE(map_obj
, BT_VALUE_TYPE_MAP
);
959 return g_hash_table_lookup(BT_VALUE_TO_MAP(map_obj
)->ght
,
960 GUINT_TO_POINTER(g_quark_from_string(key
)));
963 const struct bt_value
*bt_value_map_borrow_entry_value_const(
964 const struct bt_value
*map_obj
, const char *key
)
966 return bt_value_map_borrow_entry_value((void *) map_obj
, key
);
969 bt_bool
bt_value_map_has_entry(const struct bt_value
*map_obj
, const char *key
)
971 BT_ASSERT_PRE_NON_NULL(map_obj
, "Value object");
972 BT_ASSERT_PRE_NON_NULL(key
, "Key");
973 BT_ASSERT_PRE_VALUE_IS_TYPE(map_obj
, BT_VALUE_TYPE_MAP
);
974 return bt_g_hash_table_contains(BT_VALUE_TO_MAP(map_obj
)->ght
,
975 GUINT_TO_POINTER(g_quark_from_string(key
)));
978 enum bt_value_status
bt_value_map_insert_entry(
979 struct bt_value
*map_obj
,
980 const char *key
, struct bt_value
*element_obj
)
982 BT_ASSERT_PRE_NON_NULL(map_obj
, "Map value object");
983 BT_ASSERT_PRE_NON_NULL(key
, "Key");
984 BT_ASSERT_PRE_NON_NULL(element_obj
, "Element value object");
985 BT_ASSERT_PRE_VALUE_IS_TYPE(map_obj
, BT_VALUE_TYPE_MAP
);
986 BT_ASSERT_PRE_VALUE_HOT(map_obj
, "Map value object");
987 g_hash_table_insert(BT_VALUE_TO_MAP(map_obj
)->ght
,
988 GUINT_TO_POINTER(g_quark_from_string(key
)), element_obj
);
989 bt_object_get_ref(element_obj
);
990 BT_LOGV("Inserted value into map value: map-value-addr=%p, "
991 "key=\"%s\", element-value-addr=%p",
992 map_obj
, key
, element_obj
);
993 return BT_VALUE_STATUS_OK
;
996 enum bt_value_status
bt_value_map_insert_bool_entry(
997 struct bt_value
*map_obj
, const char *key
, bt_bool val
)
999 enum bt_value_status ret
;
1000 struct bt_value
*bool_obj
= NULL
;
1002 bool_obj
= bt_value_bool_create_init(val
);
1003 ret
= bt_value_map_insert_entry(map_obj
, key
,
1005 bt_object_put_ref(bool_obj
);
1009 enum bt_value_status
bt_value_map_insert_integer_entry(
1010 struct bt_value
*map_obj
, const char *key
, int64_t val
)
1012 enum bt_value_status ret
;
1013 struct bt_value
*integer_obj
= NULL
;
1015 integer_obj
= bt_value_integer_create_init(val
);
1016 ret
= bt_value_map_insert_entry(map_obj
, key
,
1017 (void *) integer_obj
);
1018 bt_object_put_ref(integer_obj
);
1022 enum bt_value_status
bt_value_map_insert_real_entry(
1023 struct bt_value
*map_obj
, const char *key
, double val
)
1025 enum bt_value_status ret
;
1026 struct bt_value
*real_obj
= NULL
;
1028 real_obj
= bt_value_real_create_init(val
);
1029 ret
= bt_value_map_insert_entry(map_obj
, key
,
1031 bt_object_put_ref(real_obj
);
1035 enum bt_value_status
bt_value_map_insert_string_entry(
1036 struct bt_value
*map_obj
, const char *key
,
1039 enum bt_value_status ret
;
1040 struct bt_value
*string_obj
= NULL
;
1042 string_obj
= bt_value_string_create_init(val
);
1043 ret
= bt_value_map_insert_entry(map_obj
, key
,
1044 (void *) string_obj
);
1045 bt_object_put_ref(string_obj
);
1049 enum bt_value_status
bt_value_map_insert_empty_array_entry(
1050 struct bt_value
*map_obj
, const char *key
)
1052 enum bt_value_status ret
;
1053 struct bt_value
*array_obj
= NULL
;
1055 array_obj
= bt_value_array_create();
1056 ret
= bt_value_map_insert_entry(map_obj
, key
,
1057 (void *) array_obj
);
1058 bt_object_put_ref(array_obj
);
1062 enum bt_value_status
bt_value_map_insert_empty_map_entry(
1063 struct bt_value
*map_obj
, const char *key
)
1065 enum bt_value_status ret
;
1066 struct bt_value
*empty_map_obj
= NULL
;
1068 empty_map_obj
= bt_value_map_create();
1069 ret
= bt_value_map_insert_entry(map_obj
, key
,
1070 (void *) empty_map_obj
);
1071 bt_object_put_ref(empty_map_obj
);
1075 enum bt_value_status
bt_value_map_foreach_entry(struct bt_value
*map_obj
,
1076 bt_value_map_foreach_entry_func func
, void *data
)
1078 enum bt_value_status ret
= BT_VALUE_STATUS_OK
;
1079 gpointer key
, element_obj
;
1080 GHashTableIter iter
;
1081 struct bt_value_map
*typed_map_obj
= BT_VALUE_TO_MAP(map_obj
);
1083 BT_ASSERT_PRE_NON_NULL(map_obj
, "Value object");
1084 BT_ASSERT_PRE_NON_NULL(func
, "Callback");
1085 BT_ASSERT_PRE_VALUE_IS_TYPE(map_obj
, BT_VALUE_TYPE_MAP
);
1086 g_hash_table_iter_init(&iter
, typed_map_obj
->ght
);
1088 while (g_hash_table_iter_next(&iter
, &key
, &element_obj
)) {
1089 const char *key_str
= g_quark_to_string(GPOINTER_TO_UINT(key
));
1091 if (!func(key_str
, element_obj
, data
)) {
1092 BT_LOGV("User canceled the loop: key=\"%s\", "
1093 "value-addr=%p, data=%p",
1094 key_str
, element_obj
, data
);
1095 ret
= BT_VALUE_STATUS_CANCELED
;
1103 enum bt_value_status
bt_value_map_foreach_entry_const(
1104 const struct bt_value
*map_obj
,
1105 bt_value_map_foreach_entry_const_func func
, void *data
)
1107 return bt_value_map_foreach_entry((void *) map_obj
,
1108 (bt_value_map_foreach_entry_func
) func
, data
);
1111 struct extend_map_element_data
{
1112 struct bt_value
*extended_obj
;
1113 enum bt_value_status status
;
1117 bt_bool
extend_map_element(const char *key
,
1118 const struct bt_value
*extension_obj_elem
, void *data
)
1120 bt_bool ret
= BT_TRUE
;
1121 struct extend_map_element_data
*extend_data
= data
;
1122 struct bt_value
*extension_obj_elem_copy
= NULL
;
1124 /* Copy object which is to replace the current one */
1125 extend_data
->status
= bt_value_copy(extension_obj_elem
,
1126 &extension_obj_elem_copy
);
1127 if (extend_data
->status
) {
1128 BT_LOGE("Cannot copy map element: addr=%p",
1129 extension_obj_elem
);
1133 BT_ASSERT(extension_obj_elem_copy
);
1135 /* Replace in extended object */
1136 extend_data
->status
= bt_value_map_insert_entry(
1137 extend_data
->extended_obj
, key
,
1138 (void *) extension_obj_elem_copy
);
1139 if (extend_data
->status
) {
1140 BT_LOGE("Cannot replace value in extended value: key=\"%s\", "
1141 "extended-value-addr=%p, element-value-addr=%p",
1142 key
, extend_data
->extended_obj
,
1143 extension_obj_elem_copy
);
1150 BT_ASSERT(extend_data
->status
!= BT_VALUE_STATUS_OK
);
1154 BT_OBJECT_PUT_REF_AND_RESET(extension_obj_elem_copy
);
1158 enum bt_value_status
bt_value_map_extend(
1159 const struct bt_value
*base_map_obj
,
1160 const struct bt_value
*extension_obj
,
1161 struct bt_value
**extended_map_obj
)
1163 struct extend_map_element_data extend_data
= {
1164 .extended_obj
= NULL
,
1165 .status
= BT_VALUE_STATUS_OK
,
1168 BT_ASSERT_PRE_NON_NULL(base_map_obj
, "Base value object");
1169 BT_ASSERT_PRE_NON_NULL(extension_obj
, "Extension value object");
1170 BT_ASSERT_PRE_NON_NULL(extended_map_obj
,
1171 "Extended value object (output)");
1172 BT_ASSERT_PRE_VALUE_IS_TYPE(base_map_obj
, BT_VALUE_TYPE_MAP
);
1173 BT_ASSERT_PRE_VALUE_IS_TYPE(extension_obj
, BT_VALUE_TYPE_MAP
);
1174 BT_LOGD("Extending map value: base-value-addr=%p, extension-value-addr=%p",
1175 base_map_obj
, extension_obj
);
1176 *extended_map_obj
= NULL
;
1178 /* Create copy of base map object to start with */
1179 extend_data
.status
= bt_value_copy(base_map_obj
, extended_map_obj
);
1180 if (extend_data
.status
) {
1181 BT_LOGE("Cannot copy base value: base-value-addr=%p",
1186 BT_ASSERT(extended_map_obj
);
1189 * For each key in the extension map object, replace this key
1190 * in the copied map object.
1192 extend_data
.extended_obj
= *extended_map_obj
;
1194 if (bt_value_map_foreach_entry_const(extension_obj
, extend_map_element
,
1196 BT_LOGE("Cannot iterate on the extension object's elements: "
1197 "extension-value-addr=%p", extension_obj
);
1201 if (extend_data
.status
) {
1202 BT_LOGE("Failed to successfully iterate on the extension object's elements: "
1203 "extension-value-addr=%p", extension_obj
);
1207 BT_LOGD("Extended map value: extended-value-addr=%p",
1212 BT_OBJECT_PUT_REF_AND_RESET(*extended_map_obj
);
1213 *extended_map_obj
= NULL
;
1216 return extend_data
.status
;
1219 enum bt_value_status
bt_value_copy(const struct bt_value
*object
,
1220 struct bt_value
**copy_obj
)
1222 enum bt_value_status status
= BT_VALUE_STATUS_OK
;
1224 BT_ASSERT_PRE_NON_NULL(object
, "Value object");
1225 BT_ASSERT_PRE_NON_NULL(copy_obj
, "Value object copy (output)");
1226 BT_LOGD("Copying value object: addr=%p", object
);
1227 *copy_obj
= copy_funcs
[object
->type
](object
);
1229 BT_LOGD("Copied value object: copy-value-addr=%p",
1232 status
= BT_VALUE_STATUS_NOMEM
;
1234 BT_LOGE_STR("Failed to copy value object.");
1240 bt_bool
bt_value_compare(const struct bt_value
*object_a
,
1241 const struct bt_value
*object_b
)
1243 bt_bool ret
= BT_FALSE
;
1245 BT_ASSERT_PRE_NON_NULL(object_a
, "Value object A");
1246 BT_ASSERT_PRE_NON_NULL(object_b
, "Value object B");
1248 if (object_a
->type
!= object_b
->type
) {
1249 BT_LOGV("Values are different: type mismatch: "
1250 "value-a-addr=%p, value-b-addr=%p, "
1251 "value-a-type=%s, value-b-type=%s",
1253 bt_common_value_type_string(object_a
->type
),
1254 bt_common_value_type_string(object_b
->type
));
1258 ret
= compare_funcs
[object_a
->type
](object_a
, object_b
);
1264 void bt_value_get_ref(const struct bt_value
*value
)
1266 bt_object_get_ref(value
);
1269 void bt_value_put_ref(const struct bt_value
*value
)
1271 bt_object_put_ref(value
);