2 * Values.c: value objects
6 * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation
7 * Copyright (c) 2015 Philippe Proulx <pproulx@efficios.com>
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 #include <babeltrace/compiler-internal.h>
34 #include <babeltrace/object-internal.h>
35 #include <babeltrace/ref.h>
36 #include <babeltrace/values.h>
37 #include <babeltrace/compat/glib-internal.h>
39 #define BT_LOG_TAG "VALUES"
40 #include <babeltrace/lib-logging-internal.h>
42 #define BT_VALUE_FROM_CONCRETE(_concrete) ((struct bt_value *) (_concrete))
43 #define BT_VALUE_TO_BOOL(_base) ((struct bt_value_bool *) (_base))
44 #define BT_VALUE_TO_INTEGER(_base) ((struct bt_value_integer *) (_base))
45 #define BT_VALUE_TO_FLOAT(_base) ((struct bt_value_float *) (_base))
46 #define BT_VALUE_TO_STRING(_base) ((struct bt_value_string *) (_base))
47 #define BT_VALUE_TO_ARRAY(_base) ((struct bt_value_array *) (_base))
48 #define BT_VALUE_TO_MAP(_base) ((struct bt_value_map *) (_base))
51 struct bt_object base
;
52 enum bt_value_type type
;
57 struct bt_value bt_value_null_instance
= {
66 .type
= BT_VALUE_TYPE_NULL
,
70 struct bt_value
*bt_value_null
= &bt_value_null_instance
;
72 struct bt_value_bool
{
77 struct bt_value_integer
{
82 struct bt_value_float
{
87 struct bt_value_string
{
92 struct bt_value_array
{
103 void bt_value_destroy(struct bt_object
*obj
);
106 void bt_value_string_destroy(struct bt_value
*object
)
108 g_string_free(BT_VALUE_TO_STRING(object
)->gstr
, TRUE
);
112 void bt_value_array_destroy(struct bt_value
*object
)
115 * Pointer array's registered value destructor will take care
116 * of putting each contained object.
118 g_ptr_array_free(BT_VALUE_TO_ARRAY(object
)->garray
, TRUE
);
122 void bt_value_map_destroy(struct bt_value
*object
)
125 * Hash table's registered value destructor will take care of
126 * putting each contained object. Keys are GQuarks and cannot
127 * be destroyed anyway.
129 g_hash_table_destroy(BT_VALUE_TO_MAP(object
)->ght
);
133 void (* const destroy_funcs
[])(struct bt_value
*) = {
134 [BT_VALUE_TYPE_NULL
] = NULL
,
135 [BT_VALUE_TYPE_BOOL
] = NULL
,
136 [BT_VALUE_TYPE_INTEGER
] = NULL
,
137 [BT_VALUE_TYPE_FLOAT
] = NULL
,
138 [BT_VALUE_TYPE_STRING
] = bt_value_string_destroy
,
139 [BT_VALUE_TYPE_ARRAY
] = bt_value_array_destroy
,
140 [BT_VALUE_TYPE_MAP
] = bt_value_map_destroy
,
144 struct bt_value
*bt_value_null_copy(const struct bt_value
*null_obj
)
146 return bt_value_null
;
150 struct bt_value
*bt_value_bool_copy(const struct bt_value
*bool_obj
)
152 return bt_value_bool_create_init(BT_VALUE_TO_BOOL(bool_obj
)->value
);
156 struct bt_value
*bt_value_integer_copy(const struct bt_value
*integer_obj
)
158 return bt_value_integer_create_init(
159 BT_VALUE_TO_INTEGER(integer_obj
)->value
);
163 struct bt_value
*bt_value_float_copy(const struct bt_value
*float_obj
)
165 return bt_value_float_create_init(
166 BT_VALUE_TO_FLOAT(float_obj
)->value
);
170 struct bt_value
*bt_value_string_copy(const struct bt_value
*string_obj
)
172 return bt_value_string_create_init(
173 BT_VALUE_TO_STRING(string_obj
)->gstr
->str
);
177 struct bt_value
*bt_value_array_copy(const struct bt_value
*array_obj
)
181 struct bt_value
*copy_obj
;
182 struct bt_value_array
*typed_array_obj
;
184 BT_LOGD("Copying array value: addr=%p", array_obj
);
185 typed_array_obj
= BT_VALUE_TO_ARRAY(array_obj
);
186 copy_obj
= bt_value_array_create();
189 BT_LOGE_STR("Cannot create empty array value.");
193 for (i
= 0; i
< typed_array_obj
->garray
->len
; ++i
) {
194 struct bt_value
*element_obj_copy
;
195 struct bt_value
*element_obj
= bt_value_array_get(array_obj
, i
);
198 BT_LOGE("Cannot get array value's element: "
205 element_obj_copy
= bt_value_copy(element_obj
);
208 if (!element_obj_copy
) {
209 BT_LOGE("Cannot copy array value's element: "
210 "array-addr=%p, index=%d",
216 ret
= bt_value_array_append(copy_obj
, element_obj_copy
);
217 BT_PUT(element_obj_copy
);
220 BT_LOGE("Cannot append to array value: addr=%p",
227 BT_LOGD("Copied array value: addr=%p", array_obj
);
234 struct bt_value
*bt_value_map_copy(const struct bt_value
*map_obj
)
238 gpointer key
, element_obj
;
239 struct bt_value
*copy_obj
;
240 struct bt_value
*element_obj_copy
;
241 struct bt_value_map
*typed_map_obj
;
243 BT_LOGD("Copying map value: addr=%p", map_obj
);
244 typed_map_obj
= BT_VALUE_TO_MAP(map_obj
);
245 copy_obj
= bt_value_map_create();
251 g_hash_table_iter_init(&iter
, typed_map_obj
->ght
);
253 while (g_hash_table_iter_next(&iter
, &key
, &element_obj
)) {
254 const char *key_str
= g_quark_to_string(GPOINTER_TO_UINT(key
));
256 element_obj_copy
= bt_value_copy(element_obj
);
258 if (!element_obj_copy
) {
259 BT_LOGE("Cannot copy map value's element: "
260 "map-addr=%p, key=\"%s\"",
266 ret
= bt_value_map_insert(copy_obj
, key_str
, element_obj_copy
);
267 BT_PUT(element_obj_copy
);
270 BT_LOGE("Cannot insert into map value: addr=%p, key=\"%s\"",
277 BT_LOGD("Copied map value: addr=%p", map_obj
);
284 struct bt_value
*(* const copy_funcs
[])(const struct bt_value
*) = {
285 [BT_VALUE_TYPE_NULL
] = bt_value_null_copy
,
286 [BT_VALUE_TYPE_BOOL
] = bt_value_bool_copy
,
287 [BT_VALUE_TYPE_INTEGER
] = bt_value_integer_copy
,
288 [BT_VALUE_TYPE_FLOAT
] = bt_value_float_copy
,
289 [BT_VALUE_TYPE_STRING
] = bt_value_string_copy
,
290 [BT_VALUE_TYPE_ARRAY
] = bt_value_array_copy
,
291 [BT_VALUE_TYPE_MAP
] = bt_value_map_copy
,
295 bool bt_value_null_compare(const struct bt_value
*object_a
,
296 const struct bt_value
*object_b
)
299 * Always true since bt_value_compare() already checks if both
300 * object_a and object_b have the same type, and in the case of
301 * null value objects, they're always the same if it is so.
307 bool bt_value_bool_compare(const struct bt_value
*object_a
,
308 const struct bt_value
*object_b
)
310 return BT_VALUE_TO_BOOL(object_a
)->value
==
311 BT_VALUE_TO_BOOL(object_b
)->value
;
315 bool bt_value_integer_compare(const struct bt_value
*object_a
,
316 const struct bt_value
*object_b
)
318 return BT_VALUE_TO_INTEGER(object_a
)->value
==
319 BT_VALUE_TO_INTEGER(object_b
)->value
;
323 bool bt_value_float_compare(const struct bt_value
*object_a
,
324 const struct bt_value
*object_b
)
326 return BT_VALUE_TO_FLOAT(object_a
)->value
==
327 BT_VALUE_TO_FLOAT(object_b
)->value
;
331 bool bt_value_string_compare(const struct bt_value
*object_a
,
332 const struct bt_value
*object_b
)
334 return !strcmp(BT_VALUE_TO_STRING(object_a
)->gstr
->str
,
335 BT_VALUE_TO_STRING(object_b
)->gstr
->str
);
339 bool bt_value_array_compare(const struct bt_value
*object_a
,
340 const struct bt_value
*object_b
)
344 const struct bt_value_array
*array_obj_a
=
345 BT_VALUE_TO_ARRAY(object_a
);
347 if (bt_value_array_size(object_a
) != bt_value_array_size(object_b
)) {
348 BT_LOGV("Array values are different: size mismatch "
349 "value-a-addr=%p, value-b-addr=%p, "
350 "value-a-size=%" PRId64
", value-b-size=%" PRId64
,
352 bt_value_array_size(object_a
),
353 bt_value_array_size(object_b
));
358 for (i
= 0; i
< array_obj_a
->garray
->len
; ++i
) {
359 struct bt_value
*element_obj_a
;
360 struct bt_value
*element_obj_b
;
362 element_obj_a
= bt_value_array_get(object_a
, i
);
363 element_obj_b
= bt_value_array_get(object_b
, i
);
365 if (!bt_value_compare(element_obj_a
, element_obj_b
)) {
366 BT_LOGV("Array values's elements are different: "
367 "value-a-addr=%p, value-b-addr=%p, index=%d",
368 element_obj_a
, element_obj_b
, index
);
369 BT_PUT(element_obj_a
);
370 BT_PUT(element_obj_b
);
375 BT_PUT(element_obj_a
);
376 BT_PUT(element_obj_b
);
384 bool bt_value_map_compare(const struct bt_value
*object_a
,
385 const struct bt_value
*object_b
)
389 gpointer key
, element_obj_a
;
390 const struct bt_value_map
*map_obj_a
= BT_VALUE_TO_MAP(object_a
);
392 if (bt_value_map_size(object_a
) != bt_value_map_size(object_b
)) {
393 BT_LOGV("Map values are different: size mismatch "
394 "value-a-addr=%p, value-b-addr=%p, "
395 "value-a-size=%" PRId64
", value-b-size=%" PRId64
,
397 bt_value_map_size(object_a
),
398 bt_value_map_size(object_b
));
403 g_hash_table_iter_init(&iter
, map_obj_a
->ght
);
405 while (g_hash_table_iter_next(&iter
, &key
, &element_obj_a
)) {
406 struct bt_value
*element_obj_b
;
407 const char *key_str
= g_quark_to_string(GPOINTER_TO_UINT(key
));
409 element_obj_b
= bt_value_map_get(object_b
, key_str
);
411 if (!bt_value_compare(element_obj_a
, element_obj_b
)) {
412 BT_LOGV("Map values's elements are different: "
413 "value-a-addr=%p, value-b-addr=%p, key=\"%s\"",
414 element_obj_a
, element_obj_b
, key_str
);
415 BT_PUT(element_obj_b
);
420 BT_PUT(element_obj_b
);
428 bool (* const compare_funcs
[])(const struct bt_value
*,
429 const struct bt_value
*) = {
430 [BT_VALUE_TYPE_NULL
] = bt_value_null_compare
,
431 [BT_VALUE_TYPE_BOOL
] = bt_value_bool_compare
,
432 [BT_VALUE_TYPE_INTEGER
] = bt_value_integer_compare
,
433 [BT_VALUE_TYPE_FLOAT
] = bt_value_float_compare
,
434 [BT_VALUE_TYPE_STRING
] = bt_value_string_compare
,
435 [BT_VALUE_TYPE_ARRAY
] = bt_value_array_compare
,
436 [BT_VALUE_TYPE_MAP
] = bt_value_map_compare
,
439 void bt_value_null_freeze(struct bt_value
*object
)
443 void bt_value_generic_freeze(struct bt_value
*object
)
445 object
->is_frozen
= true;
448 void bt_value_array_freeze(struct bt_value
*object
)
451 struct bt_value_array
*typed_array_obj
=
452 BT_VALUE_TO_ARRAY(object
);
454 for (i
= 0; i
< typed_array_obj
->garray
->len
; ++i
) {
455 struct bt_value
*element_obj
=
456 g_ptr_array_index(typed_array_obj
->garray
, i
);
458 bt_value_freeze(element_obj
);
461 bt_value_generic_freeze(object
);
464 void bt_value_map_freeze(struct bt_value
*object
)
467 gpointer key
, element_obj
;
468 const struct bt_value_map
*map_obj
= BT_VALUE_TO_MAP(object
);
470 g_hash_table_iter_init(&iter
, map_obj
->ght
);
472 while (g_hash_table_iter_next(&iter
, &key
, &element_obj
)) {
473 bt_value_freeze(element_obj
);
476 bt_value_generic_freeze(object
);
480 void (* const freeze_funcs
[])(struct bt_value
*) = {
481 [BT_VALUE_TYPE_NULL
] = bt_value_null_freeze
,
482 [BT_VALUE_TYPE_BOOL
] = bt_value_generic_freeze
,
483 [BT_VALUE_TYPE_INTEGER
] = bt_value_generic_freeze
,
484 [BT_VALUE_TYPE_FLOAT
] = bt_value_generic_freeze
,
485 [BT_VALUE_TYPE_STRING
] = bt_value_generic_freeze
,
486 [BT_VALUE_TYPE_ARRAY
] = bt_value_array_freeze
,
487 [BT_VALUE_TYPE_MAP
] = bt_value_map_freeze
,
491 void bt_value_destroy(struct bt_object
*obj
)
493 struct bt_value
*value
;
495 value
= container_of(obj
, struct bt_value
, base
);
496 assert(value
->type
!= BT_VALUE_TYPE_UNKNOWN
);
498 BT_LOGD("Destroying value: addr=%p", value
);
500 if (bt_value_is_null(value
)) {
501 BT_LOGD_STR("Not destroying the null value singleton.");
505 if (destroy_funcs
[value
->type
]) {
506 destroy_funcs
[value
->type
](value
);
512 enum bt_value_status
bt_value_freeze(struct bt_value
*object
)
514 enum bt_value_status ret
= BT_VALUE_STATUS_OK
;
517 BT_LOGW_STR("Invalid parameter: value object is NULL.");
518 ret
= BT_VALUE_STATUS_INVAL
;
522 if (object
->is_frozen
) {
526 BT_LOGD("Freezing value: addr=%p", object
);
527 freeze_funcs
[object
->type
](object
);
533 bool bt_value_is_frozen(const struct bt_value
*object
)
535 return object
&& object
->is_frozen
;
538 enum bt_value_type
bt_value_get_type(const struct bt_value
*object
)
541 BT_LOGW_STR("Invalid parameter: value object is NULL.");
542 return BT_VALUE_TYPE_UNKNOWN
;
549 struct bt_value
bt_value_create_base(enum bt_value_type type
)
551 struct bt_value base
;
554 base
.is_frozen
= false;
555 bt_object_init(&base
, bt_value_destroy
);
559 struct bt_value
*bt_value_bool_create_init(bool val
)
561 struct bt_value_bool
*bool_obj
;
563 BT_LOGD("Creating boolean value object: val=%d", val
);
564 bool_obj
= g_new0(struct bt_value_bool
, 1);
567 BT_LOGE_STR("Failed to allocate one boolean value object.");
571 bool_obj
->base
= bt_value_create_base(BT_VALUE_TYPE_BOOL
);
572 bool_obj
->value
= val
;
573 BT_LOGD("Created boolean value object: addr=%p", bool_obj
);
576 return BT_VALUE_FROM_CONCRETE(bool_obj
);
579 struct bt_value
*bt_value_bool_create(void)
581 return bt_value_bool_create_init(false);
584 struct bt_value
*bt_value_integer_create_init(int64_t val
)
586 struct bt_value_integer
*integer_obj
;
588 BT_LOGD("Creating integer value object: val=%" PRId64
, val
);
589 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 BT_VALUE_FROM_CONCRETE(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_float_create_init(double val
)
612 struct bt_value_float
*float_obj
;
614 BT_LOGD("Creating floating point number value object: val=%f", val
);
615 float_obj
= g_new0(struct bt_value_float
, 1);
618 BT_LOGE_STR("Failed to allocate one floating point number value object.");
622 float_obj
->base
= bt_value_create_base(BT_VALUE_TYPE_FLOAT
);
623 float_obj
->value
= val
;
624 BT_LOGD("Created floating point number value object: addr=%p",
628 return BT_VALUE_FROM_CONCRETE(float_obj
);
631 struct bt_value
*bt_value_float_create(void)
633 return bt_value_float_create_init(0.);
636 struct bt_value
*bt_value_string_create_init(const char *val
)
638 struct bt_value_string
*string_obj
= NULL
;
641 BT_LOGW_STR("Invalid parameter: value is NULL.");
645 BT_LOGD("Creating string value object: val-len=%u", strlen(val
));
646 string_obj
= g_new0(struct bt_value_string
, 1);
649 BT_LOGE_STR("Failed to allocate one string object.");
653 string_obj
->base
= bt_value_create_base(BT_VALUE_TYPE_STRING
);
654 string_obj
->gstr
= g_string_new(val
);
656 if (!string_obj
->gstr
) {
657 BT_LOGE_STR("Failed to allocate a GString.");
663 BT_LOGD("Created string value object: addr=%p",
667 return BT_VALUE_FROM_CONCRETE(string_obj
);
670 struct bt_value
*bt_value_string_create(void)
672 return bt_value_string_create_init("");
675 struct bt_value
*bt_value_array_create(void)
677 struct bt_value_array
*array_obj
;
679 BT_LOGD_STR("Creating empty array value object.");
680 array_obj
= g_new0(struct bt_value_array
, 1);
683 BT_LOGE_STR("Failed to allocate one array object.");
687 array_obj
->base
= bt_value_create_base(BT_VALUE_TYPE_ARRAY
);
688 array_obj
->garray
= bt_g_ptr_array_new_full(0,
689 (GDestroyNotify
) bt_put
);
691 if (!array_obj
->garray
) {
692 BT_LOGE_STR("Failed to allocate a GPtrArray.");
698 BT_LOGD("Created array value object: addr=%p",
702 return BT_VALUE_FROM_CONCRETE(array_obj
);
705 struct bt_value
*bt_value_map_create(void)
707 struct bt_value_map
*map_obj
;
709 BT_LOGD_STR("Creating empty map value object.");
710 map_obj
= g_new0(struct bt_value_map
, 1);
713 BT_LOGE_STR("Failed to allocate one map object.");
717 map_obj
->base
= bt_value_create_base(BT_VALUE_TYPE_MAP
);
718 map_obj
->ght
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
,
719 NULL
, (GDestroyNotify
) bt_put
);
722 BT_LOGE_STR("Failed to allocate a GHashTable.");
728 BT_LOGD("Created map value object: addr=%p",
732 return BT_VALUE_FROM_CONCRETE(map_obj
);
735 enum bt_value_status
bt_value_bool_get(const struct bt_value
*bool_obj
,
738 enum bt_value_status ret
= BT_VALUE_STATUS_OK
;
739 struct bt_value_bool
*typed_bool_obj
= BT_VALUE_TO_BOOL(bool_obj
);
741 if (!bool_obj
|| !val
) {
742 BT_LOGW("Invalid parameter: value object or value is NULL: "
743 "value-addr=%p, raw-value-addr=%p",
745 ret
= BT_VALUE_STATUS_INVAL
;
749 if (!bt_value_is_bool(bool_obj
)) {
750 BT_LOGW("Invalid parameter: value is not a boolean value: addr=%p, "
751 "type=%d", bool_obj
, bool_obj
->type
);
752 ret
= BT_VALUE_STATUS_INVAL
;
756 *val
= typed_bool_obj
->value
;
762 enum bt_value_status
bt_value_bool_set(struct bt_value
*bool_obj
, bool val
)
764 enum bt_value_status ret
= BT_VALUE_STATUS_OK
;
765 struct bt_value_bool
*typed_bool_obj
= BT_VALUE_TO_BOOL(bool_obj
);
768 BT_LOGW_STR("Invalid parameter: value object is NULL.");
769 ret
= BT_VALUE_STATUS_INVAL
;
773 if (!bt_value_is_bool(bool_obj
)) {
774 BT_LOGW("Invalid parameter: value is not a boolean value: addr=%p, "
775 "type=%d", bool_obj
, bool_obj
->type
);
776 ret
= BT_VALUE_STATUS_INVAL
;
780 if (bool_obj
->is_frozen
) {
781 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
783 ret
= BT_VALUE_STATUS_FROZEN
;
787 typed_bool_obj
->value
= val
;
788 BT_LOGV("Set boolean value's raw value: value-addr=%p, value=%d",
795 enum bt_value_status
bt_value_integer_get(const struct bt_value
*integer_obj
,
798 enum bt_value_status ret
= BT_VALUE_STATUS_OK
;
799 struct bt_value_integer
*typed_integer_obj
=
800 BT_VALUE_TO_INTEGER(integer_obj
);
802 if (!integer_obj
|| !val
) {
803 BT_LOGW("Invalid parameter: value object or value is NULL: "
804 "value-addr=%p, raw-value-addr=%p",
806 ret
= BT_VALUE_STATUS_INVAL
;
810 if (!bt_value_is_integer(integer_obj
)) {
811 BT_LOGW("Invalid parameter: value is not an integer value: addr=%p, "
812 "type=%d", integer_obj
, integer_obj
->type
);
813 ret
= BT_VALUE_STATUS_INVAL
;
817 *val
= typed_integer_obj
->value
;
823 enum bt_value_status
bt_value_integer_set(struct bt_value
*integer_obj
,
826 enum bt_value_status ret
= BT_VALUE_STATUS_OK
;
827 struct bt_value_integer
*typed_integer_obj
=
828 BT_VALUE_TO_INTEGER(integer_obj
);
831 BT_LOGW_STR("Invalid parameter: value object is NULL.");
832 ret
= BT_VALUE_STATUS_INVAL
;
836 if (!bt_value_is_integer(integer_obj
)) {
837 BT_LOGW("Invalid parameter: value is not an integer value: addr=%p, "
838 "type=%d", integer_obj
, integer_obj
->type
);
839 ret
= BT_VALUE_STATUS_INVAL
;
843 if (integer_obj
->is_frozen
) {
844 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
846 ret
= BT_VALUE_STATUS_FROZEN
;
850 typed_integer_obj
->value
= val
;
851 BT_LOGV("Set integer value's raw value: value-addr=%p, value=%" PRId64
,
858 enum bt_value_status
bt_value_float_get(const struct bt_value
*float_obj
,
861 enum bt_value_status ret
= BT_VALUE_STATUS_OK
;
862 struct bt_value_float
*typed_float_obj
=
863 BT_VALUE_TO_FLOAT(float_obj
);
865 if (!float_obj
|| !val
) {
866 BT_LOGW("Invalid parameter: value object or value is NULL: "
867 "value-addr=%p, raw-value-addr=%p",
869 ret
= BT_VALUE_STATUS_INVAL
;
873 if (!bt_value_is_float(float_obj
)) {
874 BT_LOGW("Invalid parameter: value is not a floating point number value: addr=%p, "
875 "type=%d", float_obj
, float_obj
->type
);
876 ret
= BT_VALUE_STATUS_INVAL
;
880 *val
= typed_float_obj
->value
;
886 enum bt_value_status
bt_value_float_set(struct bt_value
*float_obj
,
889 enum bt_value_status ret
= BT_VALUE_STATUS_OK
;
890 struct bt_value_float
*typed_float_obj
=
891 BT_VALUE_TO_FLOAT(float_obj
);
894 BT_LOGW_STR("Invalid parameter: value object is NULL.");
895 ret
= BT_VALUE_STATUS_INVAL
;
899 if (!bt_value_is_float(float_obj
)) {
900 BT_LOGW("Invalid parameter: value is not a floating point number value: addr=%p, "
901 "type=%d", float_obj
, float_obj
->type
);
902 ret
= BT_VALUE_STATUS_INVAL
;
906 if (float_obj
->is_frozen
) {
907 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
909 ret
= BT_VALUE_STATUS_FROZEN
;
913 typed_float_obj
->value
= val
;
914 BT_LOGV("Set floating point number value's raw value: value-addr=%p, value=%f",
921 enum bt_value_status
bt_value_string_get(const struct bt_value
*string_obj
,
924 enum bt_value_status ret
= BT_VALUE_STATUS_OK
;
925 struct bt_value_string
*typed_string_obj
=
926 BT_VALUE_TO_STRING(string_obj
);
928 if (!string_obj
|| !val
) {
929 BT_LOGW("Invalid parameter: value object or value is NULL: "
930 "value-addr=%p, raw-value-addr=%p",
932 ret
= BT_VALUE_STATUS_INVAL
;
936 if (!bt_value_is_string(string_obj
)) {
937 BT_LOGW("Invalid parameter: value is not a string value: addr=%p, "
938 "type=%d", string_obj
, string_obj
->type
);
939 ret
= BT_VALUE_STATUS_INVAL
;
943 *val
= typed_string_obj
->gstr
->str
;
949 enum bt_value_status
bt_value_string_set(struct bt_value
*string_obj
,
952 enum bt_value_status ret
= BT_VALUE_STATUS_OK
;
953 struct bt_value_string
*typed_string_obj
=
954 BT_VALUE_TO_STRING(string_obj
);
956 if (!string_obj
|| !val
) {
957 BT_LOGW("Invalid parameter: value object or value is NULL: "
958 "value-addr=%p, raw-value-addr=%p",
960 ret
= BT_VALUE_STATUS_INVAL
;
964 if (!bt_value_is_string(string_obj
)) {
965 BT_LOGW("Invalid parameter: value is not a string value: addr=%p, "
966 "type=%d", string_obj
, string_obj
->type
);
967 ret
= BT_VALUE_STATUS_INVAL
;
971 if (string_obj
->is_frozen
) {
972 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
974 ret
= BT_VALUE_STATUS_FROZEN
;
978 g_string_assign(typed_string_obj
->gstr
, val
);
979 BT_LOGV("Set string value's raw value: value-addr=%p, raw-value-addr=%p",
986 int64_t bt_value_array_size(const struct bt_value
*array_obj
)
989 struct bt_value_array
*typed_array_obj
=
990 BT_VALUE_TO_ARRAY(array_obj
);
993 BT_LOGW_STR("Invalid parameter: value object is NULL.");
994 ret
= (int64_t) BT_VALUE_STATUS_INVAL
;
998 if (!bt_value_is_array(array_obj
)) {
999 BT_LOGW("Invalid parameter: value is not an array value: addr=%p, "
1000 "type=%d", array_obj
, array_obj
->type
);
1001 ret
= BT_VALUE_STATUS_INVAL
;
1005 ret
= (int64_t) typed_array_obj
->garray
->len
;
1011 bool bt_value_array_is_empty(const struct bt_value
*array_obj
)
1013 return bt_value_array_size(array_obj
) == 0;
1016 struct bt_value
*bt_value_array_get(const struct bt_value
*array_obj
,
1019 struct bt_value
*ret
;
1020 struct bt_value_array
*typed_array_obj
=
1021 BT_VALUE_TO_ARRAY(array_obj
);
1024 BT_LOGW("Invalid parameter: value object is NULL: index=%" PRIu64
,
1030 if (!bt_value_is_array(array_obj
)) {
1031 BT_LOGW("Invalid parameter: value is not an array value: addr=%p, "
1032 "type=%d", array_obj
, array_obj
->type
);
1037 if (index
>= typed_array_obj
->garray
->len
) {
1038 BT_LOGW("Invalid parameter: index is out of bounds: "
1039 "addr=%p, index=%" PRIu64
,
1045 ret
= g_ptr_array_index(typed_array_obj
->garray
, index
);
1052 enum bt_value_status
bt_value_array_append(struct bt_value
*array_obj
,
1053 struct bt_value
*element_obj
)
1055 enum bt_value_status ret
= BT_VALUE_STATUS_OK
;
1056 struct bt_value_array
*typed_array_obj
=
1057 BT_VALUE_TO_ARRAY(array_obj
);
1059 if (!array_obj
|| !element_obj
) {
1060 BT_LOGW("Invalid parameter: array value or element value is NULL: "
1061 "array-value-addr=%p, element-value-addr=%p",
1062 array_obj
, element_obj
);
1063 ret
= BT_VALUE_STATUS_INVAL
;
1067 if (!bt_value_is_array(array_obj
)) {
1068 BT_LOGW("Invalid parameter: value is not an array value: addr=%p, "
1069 "type=%d", array_obj
, array_obj
->type
);
1070 ret
= BT_VALUE_STATUS_INVAL
;
1074 if (array_obj
->is_frozen
) {
1075 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1077 ret
= BT_VALUE_STATUS_FROZEN
;
1081 g_ptr_array_add(typed_array_obj
->garray
, element_obj
);
1082 bt_get(element_obj
);
1083 BT_LOGV("Appended element to array value: array-value-addr=%p, "
1084 "element-value-addr=%p, new-size=%u",
1085 array_obj
, element_obj
, typed_array_obj
->garray
->len
);
1091 enum bt_value_status
bt_value_array_append_bool(struct bt_value
*array_obj
,
1094 enum bt_value_status ret
;
1095 struct bt_value
*bool_obj
= NULL
;
1097 bool_obj
= bt_value_bool_create_init(val
);
1098 ret
= bt_value_array_append(array_obj
, bool_obj
);
1103 enum bt_value_status
bt_value_array_append_integer(
1104 struct bt_value
*array_obj
, int64_t val
)
1106 enum bt_value_status ret
;
1107 struct bt_value
*integer_obj
= NULL
;
1109 integer_obj
= bt_value_integer_create_init(val
);
1110 ret
= bt_value_array_append(array_obj
, integer_obj
);
1111 bt_put(integer_obj
);
1115 enum bt_value_status
bt_value_array_append_float(struct bt_value
*array_obj
,
1118 enum bt_value_status ret
;
1119 struct bt_value
*float_obj
= NULL
;
1121 float_obj
= bt_value_float_create_init(val
);
1122 ret
= bt_value_array_append(array_obj
, float_obj
);
1127 enum bt_value_status
bt_value_array_append_string(struct bt_value
*array_obj
,
1130 enum bt_value_status ret
;
1131 struct bt_value
*string_obj
= NULL
;
1133 string_obj
= bt_value_string_create_init(val
);
1134 ret
= bt_value_array_append(array_obj
, string_obj
);
1139 enum bt_value_status
bt_value_array_append_empty_array(
1140 struct bt_value
*array_obj
)
1142 enum bt_value_status ret
;
1143 struct bt_value
*empty_array_obj
= NULL
;
1145 empty_array_obj
= bt_value_array_create();
1146 ret
= bt_value_array_append(array_obj
, empty_array_obj
);
1147 bt_put(empty_array_obj
);
1151 enum bt_value_status
bt_value_array_append_empty_map(struct bt_value
*array_obj
)
1153 enum bt_value_status ret
;
1154 struct bt_value
*map_obj
= NULL
;
1156 map_obj
= bt_value_map_create();
1157 ret
= bt_value_array_append(array_obj
, map_obj
);
1162 enum bt_value_status
bt_value_array_set(struct bt_value
*array_obj
,
1163 uint64_t index
, struct bt_value
*element_obj
)
1165 enum bt_value_status ret
= BT_VALUE_STATUS_OK
;
1166 struct bt_value_array
*typed_array_obj
=
1167 BT_VALUE_TO_ARRAY(array_obj
);
1169 if (!array_obj
|| !element_obj
) {
1170 BT_LOGW("Invalid parameter: array value or element value is NULL: "
1171 "index=%" PRIu64
", array-value-addr=%p, element-value-addr=%p",
1172 index
, array_obj
, element_obj
);
1173 ret
= BT_VALUE_STATUS_INVAL
;
1177 if (!bt_value_is_array(array_obj
)) {
1178 BT_LOGW("Invalid parameter: value is not an array value: addr=%p, "
1179 "type=%d", array_obj
, array_obj
->type
);
1180 ret
= BT_VALUE_STATUS_INVAL
;
1184 if (index
>= typed_array_obj
->garray
->len
) {
1185 BT_LOGW("Invalid parameter: index is out of bounds: "
1186 "addr=%p, index=%" PRIu64
,
1188 ret
= BT_VALUE_STATUS_INVAL
;
1192 if (array_obj
->is_frozen
) {
1193 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1195 ret
= BT_VALUE_STATUS_FROZEN
;
1199 bt_put(g_ptr_array_index(typed_array_obj
->garray
, index
));
1200 g_ptr_array_index(typed_array_obj
->garray
, index
) = element_obj
;
1201 bt_get(element_obj
);
1202 BT_LOGV("Set array value's element: array-value-addr=%p, "
1203 "index=%" PRIu64
", element-value-addr=%p",
1204 array_obj
, index
, element_obj
);
1210 int64_t bt_value_map_size(const struct bt_value
*map_obj
)
1213 struct bt_value_map
*typed_map_obj
= BT_VALUE_TO_MAP(map_obj
);
1216 BT_LOGW_STR("Invalid parameter: value object is NULL.");
1217 ret
= (int64_t) BT_VALUE_STATUS_INVAL
;
1221 if (!bt_value_is_map(map_obj
)) {
1222 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
1223 "type=%d", map_obj
, map_obj
->type
);
1224 ret
= (int64_t) BT_VALUE_STATUS_INVAL
;
1228 ret
= (int64_t) g_hash_table_size(typed_map_obj
->ght
);
1234 bool bt_value_map_is_empty(const struct bt_value
*map_obj
)
1236 return bt_value_map_size(map_obj
) == 0;
1239 struct bt_value
*bt_value_map_get(const struct bt_value
*map_obj
,
1243 struct bt_value
*ret
;
1244 struct bt_value_map
*typed_map_obj
= BT_VALUE_TO_MAP(map_obj
);
1246 if (!map_obj
|| !key
) {
1247 BT_LOGW("Invalid parameter: value object or key is NULL: "
1248 "value-addr=%p, key-addr=%p", map_obj
, key
);
1253 if (!bt_value_is_map(map_obj
)) {
1254 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
1255 "type=%d", map_obj
, map_obj
->type
);
1260 quark
= g_quark_from_string(key
);
1261 ret
= g_hash_table_lookup(typed_map_obj
->ght
, GUINT_TO_POINTER(quark
));
1271 bool bt_value_map_has_key(const struct bt_value
*map_obj
, const char *key
)
1275 struct bt_value_map
*typed_map_obj
= BT_VALUE_TO_MAP(map_obj
);
1277 if (!map_obj
|| !key
) {
1278 BT_LOGW("Invalid parameter: value object or key is NULL: "
1279 "value-addr=%p, key-addr=%p", map_obj
, key
);
1284 if (!bt_value_is_map(map_obj
)) {
1285 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
1286 "type=%d", map_obj
, map_obj
->type
);
1291 quark
= g_quark_from_string(key
);
1292 ret
= bt_g_hash_table_contains(typed_map_obj
->ght
,
1293 GUINT_TO_POINTER(quark
));
1299 enum bt_value_status
bt_value_map_insert(struct bt_value
*map_obj
,
1300 const char *key
, struct bt_value
*element_obj
)
1303 enum bt_value_status ret
= BT_VALUE_STATUS_OK
;
1304 struct bt_value_map
*typed_map_obj
= BT_VALUE_TO_MAP(map_obj
);
1306 if (!map_obj
|| !key
|| !element_obj
) {
1307 BT_LOGW("Invalid parameter: map value, key, or element value is NULL: "
1308 "map-value-addr=%p, key-addr=%p, element-value-addr=%p",
1309 map_obj
, key
, element_obj
);
1310 ret
= BT_VALUE_STATUS_INVAL
;
1314 if (!bt_value_is_map(map_obj
)) {
1315 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
1316 "type=%d", map_obj
, map_obj
->type
);
1317 ret
= BT_VALUE_STATUS_INVAL
;
1321 if (map_obj
->is_frozen
) {
1322 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1324 ret
= BT_VALUE_STATUS_FROZEN
;
1328 quark
= g_quark_from_string(key
);
1329 g_hash_table_insert(typed_map_obj
->ght
,
1330 GUINT_TO_POINTER(quark
), element_obj
);
1331 bt_get(element_obj
);
1332 BT_LOGV("Inserted value into map value: map-value-addr=%p, "
1333 "key=\"%s\", element-value-addr=%p",
1334 map_obj
, key
, element_obj
);
1340 enum bt_value_status
bt_value_map_insert_bool(struct bt_value
*map_obj
,
1341 const char *key
, bool val
)
1343 enum bt_value_status ret
;
1344 struct bt_value
*bool_obj
= NULL
;
1346 bool_obj
= bt_value_bool_create_init(val
);
1347 ret
= bt_value_map_insert(map_obj
, key
, bool_obj
);
1352 enum bt_value_status
bt_value_map_insert_integer(struct bt_value
*map_obj
,
1353 const char *key
, int64_t val
)
1355 enum bt_value_status ret
;
1356 struct bt_value
*integer_obj
= NULL
;
1358 integer_obj
= bt_value_integer_create_init(val
);
1359 ret
= bt_value_map_insert(map_obj
, key
, integer_obj
);
1360 bt_put(integer_obj
);
1364 enum bt_value_status
bt_value_map_insert_float(struct bt_value
*map_obj
,
1365 const char *key
, double val
)
1367 enum bt_value_status ret
;
1368 struct bt_value
*float_obj
= NULL
;
1370 float_obj
= bt_value_float_create_init(val
);
1371 ret
= bt_value_map_insert(map_obj
, key
, float_obj
);
1376 enum bt_value_status
bt_value_map_insert_string(struct bt_value
*map_obj
,
1377 const char *key
, const char *val
)
1379 enum bt_value_status ret
;
1380 struct bt_value
*string_obj
= NULL
;
1382 string_obj
= bt_value_string_create_init(val
);
1383 ret
= bt_value_map_insert(map_obj
, key
, string_obj
);
1388 enum bt_value_status
bt_value_map_insert_empty_array(struct bt_value
*map_obj
,
1391 enum bt_value_status ret
;
1392 struct bt_value
*array_obj
= NULL
;
1394 array_obj
= bt_value_array_create();
1395 ret
= bt_value_map_insert(map_obj
, key
, array_obj
);
1400 enum bt_value_status
bt_value_map_insert_empty_map(struct bt_value
*map_obj
,
1403 enum bt_value_status ret
;
1404 struct bt_value
*empty_map_obj
= NULL
;
1406 empty_map_obj
= bt_value_map_create();
1407 ret
= bt_value_map_insert(map_obj
, key
, empty_map_obj
);
1408 bt_put(empty_map_obj
);
1412 enum bt_value_status
bt_value_map_foreach(const struct bt_value
*map_obj
,
1413 bt_value_map_foreach_cb cb
, void *data
)
1415 enum bt_value_status ret
= BT_VALUE_STATUS_OK
;
1416 gpointer key
, element_obj
;
1417 GHashTableIter iter
;
1418 struct bt_value_map
*typed_map_obj
= BT_VALUE_TO_MAP(map_obj
);
1420 if (!map_obj
|| !cb
) {
1421 BT_LOGW("Invalid parameter: map value or callback is NULL: "
1422 "value-addr=%p, cb-addr=%p", map_obj
, cb
);
1423 ret
= BT_VALUE_STATUS_INVAL
;
1427 if (!bt_value_is_map(map_obj
)) {
1428 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
1429 "type=%d", map_obj
, map_obj
->type
);
1430 ret
= BT_VALUE_STATUS_INVAL
;
1434 g_hash_table_iter_init(&iter
, typed_map_obj
->ght
);
1436 while (g_hash_table_iter_next(&iter
, &key
, &element_obj
)) {
1437 const char *key_str
= g_quark_to_string(GPOINTER_TO_UINT(key
));
1439 if (!cb(key_str
, element_obj
, data
)) {
1440 BT_LOGD("User cancelled the loop: key=\"%s\", "
1441 "value-addr=%p, data=%p",
1442 key_str
, element_obj
, data
);
1443 ret
= BT_VALUE_STATUS_CANCELLED
;
1452 struct extend_map_element_data
{
1453 struct bt_value
*extended_obj
;
1458 bool extend_map_element(const char *key
,
1459 struct bt_value
*extension_obj_elem
, void *data
)
1463 struct extend_map_element_data
*extend_data
= data
;
1465 /* Copy object which is to replace the current one */
1466 struct bt_value
*extension_obj_elem_copy
=
1467 bt_value_copy(extension_obj_elem
);
1469 /* Replace in extended object */
1470 if (bt_value_map_insert(extend_data
->extended_obj
, key
,
1471 extension_obj_elem_copy
)) {
1472 BT_LOGE("Cannot replace value in extended value: key=\"%s\", "
1473 "extended-value-addr=%p, element-value-addr=%p",
1474 key
, extend_data
->extended_obj
,
1475 extension_obj_elem_copy
);
1483 extend_data
->got_error
= true;
1486 BT_PUT(extension_obj_elem_copy
);
1490 struct bt_value
*bt_value_map_extend(struct bt_value
*base_map_obj
,
1491 struct bt_value
*extension_obj
)
1493 struct bt_value
*extended_obj
= NULL
;
1494 struct extend_map_element_data extend_data
= { 0 };
1496 if (!base_map_obj
|| !extension_obj
) {
1497 BT_LOGW("Invalid parameter: base value or extension value is NULL: "
1498 "base-value-addr=%p, extension-value-addr=%p",
1499 base_map_obj
, extension_obj
);
1503 if (!bt_value_is_map(base_map_obj
)) {
1504 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
1505 "type=%d", base_map_obj
, base_map_obj
->type
);
1509 if (!bt_value_is_map(extension_obj
)) {
1510 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
1511 "type=%d", extension_obj
, extension_obj
->type
);
1515 BT_LOGD("Extending map value: base-value-addr=%p, extension-value-addr=%p",
1516 base_map_obj
, extension_obj
);
1518 /* Create copy of base map object to start with */
1519 extended_obj
= bt_value_copy(base_map_obj
);
1520 if (!extended_obj
) {
1521 BT_LOGE("Cannot copy base value: base-value-addr=%p",
1527 * For each key in the extension map object, replace this key
1528 * in the copied map object.
1530 extend_data
.extended_obj
= extended_obj
;
1532 if (bt_value_map_foreach(extension_obj
, extend_map_element
,
1534 BT_LOGE("Cannot iterate on the extension object's elements: ",
1535 "extension-value-addr=%p", extension_obj
);
1539 if (extend_data
.got_error
) {
1540 BT_LOGE("Failed to successfully iterate on the extension object's elements: ",
1541 "extension-value-addr=%p", extension_obj
);
1545 BT_LOGD("Extended map value: extended-value-addr=%p",
1550 BT_PUT(extended_obj
);
1553 return extended_obj
;
1556 struct bt_value
*bt_value_copy(const struct bt_value
*object
)
1558 struct bt_value
*copy_obj
= NULL
;
1561 BT_LOGW_STR("Invalid parameter: value object is NULL.");
1565 BT_LOGD("Copying value object: addr=%p", object
);
1566 copy_obj
= copy_funcs
[object
->type
](object
);
1568 BT_LOGD("Copied value object: copy-value-addr=%p",
1571 BT_LOGE_STR("Failed to copy value object.");
1578 bool bt_value_compare(const struct bt_value
*object_a
,
1579 const struct bt_value
*object_b
)
1583 if (!object_a
|| !object_b
) {
1584 BT_LOGW("Invalid parameter: value A or value B is NULL: "
1585 "value-a-addr=%p, value-b-addr=%p",
1586 object_a
, object_b
);
1590 if (object_a
->type
!= object_b
->type
) {
1591 BT_LOGV("Values are different: type mismatch: "
1592 "value-a-addr=%p, value-b-addr=%p, "
1593 "value-a-type=%d, value-b-type=%d",
1595 object_a
->type
, object_b
->type
);
1599 ret
= compare_funcs
[object_a
->type
](object_a
, object_b
);