Add internal BT_ASSERT() and BT_ASSERT_PRE() helpers
[babeltrace.git] / lib / values.c
CommitLineData
dac5c838 1/*
83509119 2 * Values.c: value objects
dac5c838
PP
3 *
4 * Babeltrace Library
5 *
6 * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation
7 * Copyright (c) 2015 Philippe Proulx <pproulx@efficios.com>
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
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
25 * SOFTWARE.
26 */
27
0f5e83e5 28#define BT_LOG_TAG "VALUES"
40547d22 29#include <babeltrace/lib-logging-internal.h>
0f5e83e5 30
dac5c838
PP
31#include <stdlib.h>
32#include <string.h>
33#include <assert.h>
34#include <string.h>
2f42aa0a 35#include <inttypes.h>
3d9990ac 36#include <babeltrace/compiler-internal.h>
83509119 37#include <babeltrace/ref.h>
dac5c838 38#include <babeltrace/values.h>
3d9990ac 39#include <babeltrace/compat/glib-internal.h>
c55a9f58 40#include <babeltrace/types.h>
0f5e83e5 41#include <babeltrace/object-internal.h>
c4628760 42#include <babeltrace/values-internal.h>
2f42aa0a 43
dac5c838
PP
44#define BT_VALUE_FROM_CONCRETE(_concrete) ((struct bt_value *) (_concrete))
45#define BT_VALUE_TO_BOOL(_base) ((struct bt_value_bool *) (_base))
46#define BT_VALUE_TO_INTEGER(_base) ((struct bt_value_integer *) (_base))
47#define BT_VALUE_TO_FLOAT(_base) ((struct bt_value_float *) (_base))
48#define BT_VALUE_TO_STRING(_base) ((struct bt_value_string *) (_base))
49#define BT_VALUE_TO_ARRAY(_base) ((struct bt_value_array *) (_base))
50#define BT_VALUE_TO_MAP(_base) ((struct bt_value_map *) (_base))
51
52struct bt_value {
83509119 53 struct bt_object base;
dac5c838 54 enum bt_value_type type;
c55a9f58 55 bt_bool is_frozen;
dac5c838
PP
56};
57
58static
59struct bt_value bt_value_null_instance = {
f685129c
PP
60 .base = {
61 .ref_count = {
62 .count = 1,
63 .release = NULL,
64 },
65 .release = NULL,
66 .parent = NULL,
67 },
dac5c838 68 .type = BT_VALUE_TYPE_NULL,
c55a9f58 69 .is_frozen = BT_TRUE,
dac5c838
PP
70};
71
72struct bt_value *bt_value_null = &bt_value_null_instance;
73
74struct bt_value_bool {
75 struct bt_value base;
c55a9f58 76 bt_bool value;
dac5c838
PP
77};
78
79struct bt_value_integer {
80 struct bt_value base;
81 int64_t value;
82};
83
84struct bt_value_float {
85 struct bt_value base;
86 double value;
87};
88
89struct bt_value_string {
90 struct bt_value base;
91 GString *gstr;
92};
93
94struct bt_value_array {
95 struct bt_value base;
96 GPtrArray *garray;
97};
98
99struct bt_value_map {
100 struct bt_value base;
101 GHashTable *ght;
102};
103
104static
83509119 105void bt_value_destroy(struct bt_object *obj);
dac5c838
PP
106
107static
108void bt_value_string_destroy(struct bt_value *object)
109{
110 g_string_free(BT_VALUE_TO_STRING(object)->gstr, TRUE);
111}
112
113static
114void bt_value_array_destroy(struct bt_value *object)
115{
116 /*
117 * Pointer array's registered value destructor will take care
118 * of putting each contained object.
119 */
120 g_ptr_array_free(BT_VALUE_TO_ARRAY(object)->garray, TRUE);
121}
122
123static
124void bt_value_map_destroy(struct bt_value *object)
125{
126 /*
127 * Hash table's registered value destructor will take care of
128 * putting each contained object. Keys are GQuarks and cannot
129 * be destroyed anyway.
130 */
131 g_hash_table_destroy(BT_VALUE_TO_MAP(object)->ght);
132}
133
134static
135void (* const destroy_funcs[])(struct bt_value *) = {
136 [BT_VALUE_TYPE_NULL] = NULL,
137 [BT_VALUE_TYPE_BOOL] = NULL,
138 [BT_VALUE_TYPE_INTEGER] = NULL,
139 [BT_VALUE_TYPE_FLOAT] = NULL,
140 [BT_VALUE_TYPE_STRING] = bt_value_string_destroy,
141 [BT_VALUE_TYPE_ARRAY] = bt_value_array_destroy,
142 [BT_VALUE_TYPE_MAP] = bt_value_map_destroy,
143};
144
145static
146struct bt_value *bt_value_null_copy(const struct bt_value *null_obj)
147{
148 return bt_value_null;
149}
150
151static
152struct bt_value *bt_value_bool_copy(const struct bt_value *bool_obj)
153{
154 return bt_value_bool_create_init(BT_VALUE_TO_BOOL(bool_obj)->value);
155}
156
157static
158struct bt_value *bt_value_integer_copy(const struct bt_value *integer_obj)
159{
160 return bt_value_integer_create_init(
161 BT_VALUE_TO_INTEGER(integer_obj)->value);
162}
163
164static
165struct bt_value *bt_value_float_copy(const struct bt_value *float_obj)
166{
167 return bt_value_float_create_init(
168 BT_VALUE_TO_FLOAT(float_obj)->value);
169}
170
171static
172struct bt_value *bt_value_string_copy(const struct bt_value *string_obj)
173{
174 return bt_value_string_create_init(
175 BT_VALUE_TO_STRING(string_obj)->gstr->str);
176}
177
178static
179struct bt_value *bt_value_array_copy(const struct bt_value *array_obj)
180{
181 int i;
182 int ret;
183 struct bt_value *copy_obj;
184 struct bt_value_array *typed_array_obj;
185
2f42aa0a 186 BT_LOGD("Copying array value: addr=%p", array_obj);
dac5c838
PP
187 typed_array_obj = BT_VALUE_TO_ARRAY(array_obj);
188 copy_obj = bt_value_array_create();
189
190 if (!copy_obj) {
2f42aa0a 191 BT_LOGE_STR("Cannot create empty array value.");
dac5c838
PP
192 goto end;
193 }
194
195 for (i = 0; i < typed_array_obj->garray->len; ++i) {
196 struct bt_value *element_obj_copy;
197 struct bt_value *element_obj = bt_value_array_get(array_obj, i);
198
8fff8ba9 199 assert(element_obj);
40b59ed9
PP
200 BT_LOGD("Copying array value's element: element-addr=%p, "
201 "index=%d", element_obj, i);
dac5c838 202 element_obj_copy = bt_value_copy(element_obj);
83509119 203 BT_PUT(element_obj);
dac5c838 204 if (!element_obj_copy) {
2f42aa0a
PP
205 BT_LOGE("Cannot copy array value's element: "
206 "array-addr=%p, index=%d",
207 array_obj, i);
83509119 208 BT_PUT(copy_obj);
dac5c838
PP
209 goto end;
210 }
211
212 ret = bt_value_array_append(copy_obj, element_obj_copy);
83509119 213 BT_PUT(element_obj_copy);
dac5c838 214 if (ret) {
2f42aa0a
PP
215 BT_LOGE("Cannot append to array value: addr=%p",
216 array_obj);
83509119 217 BT_PUT(copy_obj);
dac5c838
PP
218 goto end;
219 }
220 }
221
a704fb0b
PP
222 BT_LOGD("Copied array value: original-addr=%p, copy-addr=%p",
223 array_obj, copy_obj);
2f42aa0a 224
dac5c838
PP
225end:
226 return copy_obj;
227}
228
229static
230struct bt_value *bt_value_map_copy(const struct bt_value *map_obj)
231{
232 int ret;
233 GHashTableIter iter;
234 gpointer key, element_obj;
235 struct bt_value *copy_obj;
236 struct bt_value *element_obj_copy;
237 struct bt_value_map *typed_map_obj;
238
2f42aa0a 239 BT_LOGD("Copying map value: addr=%p", map_obj);
dac5c838
PP
240 typed_map_obj = BT_VALUE_TO_MAP(map_obj);
241 copy_obj = bt_value_map_create();
242
243 if (!copy_obj) {
244 goto end;
245 }
246
247 g_hash_table_iter_init(&iter, typed_map_obj->ght);
248
249 while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
5b44aff2 250 const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
dac5c838 251
40b59ed9
PP
252 assert(key_str);
253 BT_LOGD("Copying map value's element: element-addr=%p, "
254 "key=\"%s\"", element_obj, key_str);
dac5c838 255 element_obj_copy = bt_value_copy(element_obj);
dac5c838 256 if (!element_obj_copy) {
2f42aa0a
PP
257 BT_LOGE("Cannot copy map value's element: "
258 "map-addr=%p, key=\"%s\"",
259 map_obj, key_str);
83509119 260 BT_PUT(copy_obj);
dac5c838
PP
261 goto end;
262 }
263
264 ret = bt_value_map_insert(copy_obj, key_str, element_obj_copy);
83509119 265 BT_PUT(element_obj_copy);
dac5c838 266 if (ret) {
2f42aa0a
PP
267 BT_LOGE("Cannot insert into map value: addr=%p, key=\"%s\"",
268 map_obj, key_str);
83509119 269 BT_PUT(copy_obj);
dac5c838
PP
270 goto end;
271 }
272 }
273
2f42aa0a
PP
274 BT_LOGD("Copied map value: addr=%p", map_obj);
275
dac5c838
PP
276end:
277 return copy_obj;
278}
279
280static
281struct bt_value *(* const copy_funcs[])(const struct bt_value *) = {
282 [BT_VALUE_TYPE_NULL] = bt_value_null_copy,
283 [BT_VALUE_TYPE_BOOL] = bt_value_bool_copy,
284 [BT_VALUE_TYPE_INTEGER] = bt_value_integer_copy,
285 [BT_VALUE_TYPE_FLOAT] = bt_value_float_copy,
286 [BT_VALUE_TYPE_STRING] = bt_value_string_copy,
287 [BT_VALUE_TYPE_ARRAY] = bt_value_array_copy,
288 [BT_VALUE_TYPE_MAP] = bt_value_map_copy,
289};
290
291static
c55a9f58 292bt_bool bt_value_null_compare(const struct bt_value *object_a,
dac5c838
PP
293 const struct bt_value *object_b)
294{
295 /*
c55a9f58 296 * Always BT_TRUE since bt_value_compare() already checks if both
dac5c838
PP
297 * object_a and object_b have the same type, and in the case of
298 * null value objects, they're always the same if it is so.
299 */
c55a9f58 300 return BT_TRUE;
dac5c838
PP
301}
302
303static
c55a9f58 304bt_bool bt_value_bool_compare(const struct bt_value *object_a,
dac5c838
PP
305 const struct bt_value *object_b)
306{
40b59ed9
PP
307 if (BT_VALUE_TO_BOOL(object_a)->value !=
308 BT_VALUE_TO_BOOL(object_b)->value) {
309 BT_LOGV("Boolean value objects are different: "
310 "bool-a-val=%d, bool-b-val=%d",
311 BT_VALUE_TO_BOOL(object_a)->value,
312 BT_VALUE_TO_BOOL(object_b)->value);
313 return BT_FALSE;
314 }
315
316 return BT_TRUE;
dac5c838
PP
317}
318
319static
c55a9f58 320bt_bool bt_value_integer_compare(const struct bt_value *object_a,
dac5c838
PP
321 const struct bt_value *object_b)
322{
40b59ed9
PP
323 if (BT_VALUE_TO_INTEGER(object_a)->value !=
324 BT_VALUE_TO_INTEGER(object_b)->value) {
325 BT_LOGV("Integer value objects are different: "
326 "int-a-val=%" PRId64 ", int-b-val=%" PRId64,
327 BT_VALUE_TO_INTEGER(object_a)->value,
328 BT_VALUE_TO_INTEGER(object_b)->value);
329 return BT_FALSE;
330 }
331
332 return BT_TRUE;
dac5c838
PP
333}
334
335static
c55a9f58 336bt_bool bt_value_float_compare(const struct bt_value *object_a,
dac5c838
PP
337 const struct bt_value *object_b)
338{
40b59ed9
PP
339 if (BT_VALUE_TO_FLOAT(object_a)->value !=
340 BT_VALUE_TO_FLOAT(object_b)->value) {
341 BT_LOGV("Floating point number value objects are different: "
342 "float-a-val=%f, float-b-val=%f",
343 BT_VALUE_TO_FLOAT(object_a)->value,
344 BT_VALUE_TO_FLOAT(object_b)->value);
345 return BT_FALSE;
346 }
347
348 return BT_TRUE;
dac5c838
PP
349}
350
351static
c55a9f58 352bt_bool bt_value_string_compare(const struct bt_value *object_a,
dac5c838
PP
353 const struct bt_value *object_b)
354{
40b59ed9
PP
355 if (strcmp(BT_VALUE_TO_STRING(object_a)->gstr->str,
356 BT_VALUE_TO_STRING(object_b)->gstr->str) != 0) {
357 BT_LOGV("String value objects are different: "
358 "string-a-val=\"%s\", string-b-val=\"%s\"",
359 BT_VALUE_TO_STRING(object_a)->gstr->str,
360 BT_VALUE_TO_STRING(object_b)->gstr->str);
361 return BT_FALSE;
362 }
363
364 return BT_TRUE;
dac5c838
PP
365}
366
367static
c55a9f58 368bt_bool bt_value_array_compare(const struct bt_value *object_a,
dac5c838
PP
369 const struct bt_value *object_b)
370{
371 int i;
c55a9f58 372 bt_bool ret = BT_TRUE;
dac5c838
PP
373 const struct bt_value_array *array_obj_a =
374 BT_VALUE_TO_ARRAY(object_a);
375
376 if (bt_value_array_size(object_a) != bt_value_array_size(object_b)) {
2f42aa0a
PP
377 BT_LOGV("Array values are different: size mismatch "
378 "value-a-addr=%p, value-b-addr=%p, "
379 "value-a-size=%" PRId64 ", value-b-size=%" PRId64,
380 object_a, object_b,
381 bt_value_array_size(object_a),
382 bt_value_array_size(object_b));
c55a9f58 383 ret = BT_FALSE;
dac5c838
PP
384 goto end;
385 }
386
387 for (i = 0; i < array_obj_a->garray->len; ++i) {
388 struct bt_value *element_obj_a;
389 struct bt_value *element_obj_b;
390
391 element_obj_a = bt_value_array_get(object_a, i);
392 element_obj_b = bt_value_array_get(object_b, i);
393
394 if (!bt_value_compare(element_obj_a, element_obj_b)) {
2f42aa0a
PP
395 BT_LOGV("Array values's elements are different: "
396 "value-a-addr=%p, value-b-addr=%p, index=%d",
32e87ceb 397 element_obj_a, element_obj_b, i);
83509119
JG
398 BT_PUT(element_obj_a);
399 BT_PUT(element_obj_b);
c55a9f58 400 ret = BT_FALSE;
dac5c838
PP
401 goto end;
402 }
403
83509119
JG
404 BT_PUT(element_obj_a);
405 BT_PUT(element_obj_b);
dac5c838
PP
406 }
407
408end:
409 return ret;
410}
411
412static
c55a9f58 413bt_bool bt_value_map_compare(const struct bt_value *object_a,
dac5c838
PP
414 const struct bt_value *object_b)
415{
c55a9f58 416 bt_bool ret = BT_TRUE;
dac5c838
PP
417 GHashTableIter iter;
418 gpointer key, element_obj_a;
419 const struct bt_value_map *map_obj_a = BT_VALUE_TO_MAP(object_a);
420
421 if (bt_value_map_size(object_a) != bt_value_map_size(object_b)) {
2f42aa0a
PP
422 BT_LOGV("Map values are different: size mismatch "
423 "value-a-addr=%p, value-b-addr=%p, "
424 "value-a-size=%" PRId64 ", value-b-size=%" PRId64,
425 object_a, object_b,
426 bt_value_map_size(object_a),
427 bt_value_map_size(object_b));
c55a9f58 428 ret = BT_FALSE;
dac5c838
PP
429 goto end;
430 }
431
432 g_hash_table_iter_init(&iter, map_obj_a->ght);
433
434 while (g_hash_table_iter_next(&iter, &key, &element_obj_a)) {
435 struct bt_value *element_obj_b;
5b44aff2 436 const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
dac5c838
PP
437
438 element_obj_b = bt_value_map_get(object_b, key_str);
439
440 if (!bt_value_compare(element_obj_a, element_obj_b)) {
2f42aa0a
PP
441 BT_LOGV("Map values's elements are different: "
442 "value-a-addr=%p, value-b-addr=%p, key=\"%s\"",
443 element_obj_a, element_obj_b, key_str);
83509119 444 BT_PUT(element_obj_b);
c55a9f58 445 ret = BT_FALSE;
dac5c838
PP
446 goto end;
447 }
448
83509119 449 BT_PUT(element_obj_b);
dac5c838
PP
450 }
451
452end:
453 return ret;
454}
455
456static
c55a9f58 457bt_bool (* const compare_funcs[])(const struct bt_value *,
dac5c838
PP
458 const struct bt_value *) = {
459 [BT_VALUE_TYPE_NULL] = bt_value_null_compare,
460 [BT_VALUE_TYPE_BOOL] = bt_value_bool_compare,
461 [BT_VALUE_TYPE_INTEGER] = bt_value_integer_compare,
40b59ed9 462 [BT_VALUE_TYPE_FLOAT] = bt_value_float_compare,
dac5c838 463 [BT_VALUE_TYPE_STRING] = bt_value_string_compare,
40b59ed9 464 [BT_VALUE_TYPE_ARRAY] = bt_value_array_compare,
dac5c838
PP
465 [BT_VALUE_TYPE_MAP] = bt_value_map_compare,
466};
467
468void bt_value_null_freeze(struct bt_value *object)
469{
470}
471
472void bt_value_generic_freeze(struct bt_value *object)
473{
c55a9f58 474 object->is_frozen = BT_TRUE;
dac5c838
PP
475}
476
477void bt_value_array_freeze(struct bt_value *object)
478{
479 int i;
480 struct bt_value_array *typed_array_obj =
481 BT_VALUE_TO_ARRAY(object);
482
483 for (i = 0; i < typed_array_obj->garray->len; ++i) {
484 struct bt_value *element_obj =
485 g_ptr_array_index(typed_array_obj->garray, i);
486
487 bt_value_freeze(element_obj);
488 }
489
490 bt_value_generic_freeze(object);
491}
492
493void bt_value_map_freeze(struct bt_value *object)
494{
495 GHashTableIter iter;
496 gpointer key, element_obj;
497 const struct bt_value_map *map_obj = BT_VALUE_TO_MAP(object);
498
499 g_hash_table_iter_init(&iter, map_obj->ght);
500
501 while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
502 bt_value_freeze(element_obj);
503 }
504
505 bt_value_generic_freeze(object);
506}
507
508static
509void (* const freeze_funcs[])(struct bt_value *) = {
510 [BT_VALUE_TYPE_NULL] = bt_value_null_freeze,
511 [BT_VALUE_TYPE_BOOL] = bt_value_generic_freeze,
512 [BT_VALUE_TYPE_INTEGER] = bt_value_generic_freeze,
513 [BT_VALUE_TYPE_FLOAT] = bt_value_generic_freeze,
514 [BT_VALUE_TYPE_STRING] = bt_value_generic_freeze,
515 [BT_VALUE_TYPE_ARRAY] = bt_value_array_freeze,
516 [BT_VALUE_TYPE_MAP] = bt_value_map_freeze,
517};
518
519static
83509119 520void bt_value_destroy(struct bt_object *obj)
dac5c838 521{
83509119 522 struct bt_value *value;
dac5c838 523
83509119
JG
524 value = container_of(obj, struct bt_value, base);
525 assert(value->type != BT_VALUE_TYPE_UNKNOWN);
2f42aa0a
PP
526 BT_LOGD("Destroying value: addr=%p", value);
527
83509119 528 if (bt_value_is_null(value)) {
2f42aa0a 529 BT_LOGD_STR("Not destroying the null value singleton.");
dac5c838
PP
530 return;
531 }
532
83509119
JG
533 if (destroy_funcs[value->type]) {
534 destroy_funcs[value->type](value);
dac5c838
PP
535 }
536
83509119 537 g_free(value);
dac5c838
PP
538}
539
540enum bt_value_status bt_value_freeze(struct bt_value *object)
541{
542 enum bt_value_status ret = BT_VALUE_STATUS_OK;
543
544 if (!object) {
2f42aa0a 545 BT_LOGW_STR("Invalid parameter: value object is NULL.");
dac5c838
PP
546 ret = BT_VALUE_STATUS_INVAL;
547 goto end;
548 }
549
2f42aa0a
PP
550 if (object->is_frozen) {
551 goto end;
552 }
553
554 BT_LOGD("Freezing value: addr=%p", object);
dac5c838
PP
555 freeze_funcs[object->type](object);
556
557end:
558 return ret;
559}
560
c55a9f58 561bt_bool bt_value_is_frozen(const struct bt_value *object)
dac5c838
PP
562{
563 return object && object->is_frozen;
564}
565
566enum bt_value_type bt_value_get_type(const struct bt_value *object)
567{
568 if (!object) {
a0d100f8
PP
569 /*
570 * Not an error: user can test NULL value object with
571 * this function.
572 */
573 BT_LOGV_STR("Value object is NULL.");
dac5c838
PP
574 return BT_VALUE_TYPE_UNKNOWN;
575 }
576
577 return object->type;
578}
579
580static
581struct bt_value bt_value_create_base(enum bt_value_type type)
582{
583 struct bt_value base;
584
585 base.type = type;
c55a9f58 586 base.is_frozen = BT_FALSE;
83509119 587 bt_object_init(&base, bt_value_destroy);
dac5c838
PP
588 return base;
589}
590
c55a9f58 591struct bt_value *bt_value_bool_create_init(bt_bool val)
dac5c838
PP
592{
593 struct bt_value_bool *bool_obj;
594
2f42aa0a 595 BT_LOGD("Creating boolean value object: val=%d", val);
dac5c838
PP
596 bool_obj = g_new0(struct bt_value_bool, 1);
597
598 if (!bool_obj) {
2f42aa0a 599 BT_LOGE_STR("Failed to allocate one boolean value object.");
dac5c838
PP
600 goto end;
601 }
602
603 bool_obj->base = bt_value_create_base(BT_VALUE_TYPE_BOOL);
604 bool_obj->value = val;
2f42aa0a 605 BT_LOGD("Created boolean value object: addr=%p", bool_obj);
dac5c838
PP
606
607end:
608 return BT_VALUE_FROM_CONCRETE(bool_obj);
609}
610
611struct bt_value *bt_value_bool_create(void)
612{
c55a9f58 613 return bt_value_bool_create_init(BT_FALSE);
dac5c838
PP
614}
615
616struct bt_value *bt_value_integer_create_init(int64_t val)
617{
618 struct bt_value_integer *integer_obj;
619
2f42aa0a 620 BT_LOGD("Creating integer value object: val=%" PRId64, val);
dac5c838
PP
621 integer_obj = g_new0(struct bt_value_integer, 1);
622
623 if (!integer_obj) {
2f42aa0a 624 BT_LOGE_STR("Failed to allocate one integer value object.");
dac5c838
PP
625 goto end;
626 }
627
628 integer_obj->base = bt_value_create_base(BT_VALUE_TYPE_INTEGER);
629 integer_obj->value = val;
2f42aa0a
PP
630 BT_LOGD("Created integer value object: addr=%p",
631 integer_obj);
dac5c838
PP
632
633end:
634 return BT_VALUE_FROM_CONCRETE(integer_obj);
635}
636
637struct bt_value *bt_value_integer_create(void)
638{
639 return bt_value_integer_create_init(0);
640}
641
642struct bt_value *bt_value_float_create_init(double val)
643{
644 struct bt_value_float *float_obj;
645
2f42aa0a 646 BT_LOGD("Creating floating point number value object: val=%f", val);
dac5c838
PP
647 float_obj = g_new0(struct bt_value_float, 1);
648
649 if (!float_obj) {
2f42aa0a 650 BT_LOGE_STR("Failed to allocate one floating point number value object.");
dac5c838
PP
651 goto end;
652 }
653
654 float_obj->base = bt_value_create_base(BT_VALUE_TYPE_FLOAT);
655 float_obj->value = val;
2f42aa0a
PP
656 BT_LOGD("Created floating point number value object: addr=%p",
657 float_obj);
dac5c838
PP
658
659end:
660 return BT_VALUE_FROM_CONCRETE(float_obj);
661}
662
663struct bt_value *bt_value_float_create(void)
664{
665 return bt_value_float_create_init(0.);
666}
667
668struct bt_value *bt_value_string_create_init(const char *val)
669{
670 struct bt_value_string *string_obj = NULL;
671
672 if (!val) {
2f42aa0a 673 BT_LOGW_STR("Invalid parameter: value is NULL.");
dac5c838
PP
674 goto end;
675 }
676
003c7749 677 BT_LOGD("Creating string value object: val-len=%zu", strlen(val));
dac5c838
PP
678 string_obj = g_new0(struct bt_value_string, 1);
679
680 if (!string_obj) {
2f42aa0a 681 BT_LOGE_STR("Failed to allocate one string object.");
dac5c838
PP
682 goto end;
683 }
684
685 string_obj->base = bt_value_create_base(BT_VALUE_TYPE_STRING);
686 string_obj->gstr = g_string_new(val);
687
688 if (!string_obj->gstr) {
2f42aa0a 689 BT_LOGE_STR("Failed to allocate a GString.");
dac5c838
PP
690 g_free(string_obj);
691 string_obj = NULL;
692 goto end;
693 }
694
2f42aa0a
PP
695 BT_LOGD("Created string value object: addr=%p",
696 string_obj);
697
dac5c838
PP
698end:
699 return BT_VALUE_FROM_CONCRETE(string_obj);
700}
701
702struct bt_value *bt_value_string_create(void)
703{
704 return bt_value_string_create_init("");
705}
706
707struct bt_value *bt_value_array_create(void)
708{
709 struct bt_value_array *array_obj;
710
2f42aa0a 711 BT_LOGD_STR("Creating empty array value object.");
dac5c838
PP
712 array_obj = g_new0(struct bt_value_array, 1);
713
714 if (!array_obj) {
2f42aa0a 715 BT_LOGE_STR("Failed to allocate one array object.");
dac5c838
PP
716 goto end;
717 }
718
719 array_obj->base = bt_value_create_base(BT_VALUE_TYPE_ARRAY);
5d5982ab 720 array_obj->garray = bt_g_ptr_array_new_full(0,
83509119 721 (GDestroyNotify) bt_put);
dac5c838
PP
722
723 if (!array_obj->garray) {
2f42aa0a 724 BT_LOGE_STR("Failed to allocate a GPtrArray.");
dac5c838
PP
725 g_free(array_obj);
726 array_obj = NULL;
727 goto end;
728 }
729
2f42aa0a
PP
730 BT_LOGD("Created array value object: addr=%p",
731 array_obj);
732
dac5c838
PP
733end:
734 return BT_VALUE_FROM_CONCRETE(array_obj);
735}
736
737struct bt_value *bt_value_map_create(void)
738{
739 struct bt_value_map *map_obj;
740
2f42aa0a 741 BT_LOGD_STR("Creating empty map value object.");
dac5c838
PP
742 map_obj = g_new0(struct bt_value_map, 1);
743
744 if (!map_obj) {
2f42aa0a 745 BT_LOGE_STR("Failed to allocate one map object.");
dac5c838
PP
746 goto end;
747 }
748
749 map_obj->base = bt_value_create_base(BT_VALUE_TYPE_MAP);
750 map_obj->ght = g_hash_table_new_full(g_direct_hash, g_direct_equal,
83509119 751 NULL, (GDestroyNotify) bt_put);
dac5c838
PP
752
753 if (!map_obj->ght) {
2f42aa0a 754 BT_LOGE_STR("Failed to allocate a GHashTable.");
dac5c838
PP
755 g_free(map_obj);
756 map_obj = NULL;
757 goto end;
758 }
759
2f42aa0a
PP
760 BT_LOGD("Created map value object: addr=%p",
761 map_obj);
762
dac5c838
PP
763end:
764 return BT_VALUE_FROM_CONCRETE(map_obj);
765}
766
767enum bt_value_status bt_value_bool_get(const struct bt_value *bool_obj,
c55a9f58 768 bt_bool *val)
dac5c838
PP
769{
770 enum bt_value_status ret = BT_VALUE_STATUS_OK;
771 struct bt_value_bool *typed_bool_obj = BT_VALUE_TO_BOOL(bool_obj);
772
2f42aa0a
PP
773 if (!bool_obj || !val) {
774 BT_LOGW("Invalid parameter: value object or value is NULL: "
775 "value-addr=%p, raw-value-addr=%p",
776 bool_obj, val);
777 ret = BT_VALUE_STATUS_INVAL;
778 goto end;
779 }
780
781 if (!bt_value_is_bool(bool_obj)) {
782 BT_LOGW("Invalid parameter: value is not a boolean value: addr=%p, "
32e87ceb 783 "type=%s", bool_obj,
c4628760 784 bt_value_type_string(bool_obj->type));
dac5c838
PP
785 ret = BT_VALUE_STATUS_INVAL;
786 goto end;
787 }
788
789 *val = typed_bool_obj->value;
790
791end:
792 return ret;
793}
794
c55a9f58 795enum bt_value_status bt_value_bool_set(struct bt_value *bool_obj, bt_bool val)
dac5c838
PP
796{
797 enum bt_value_status ret = BT_VALUE_STATUS_OK;
798 struct bt_value_bool *typed_bool_obj = BT_VALUE_TO_BOOL(bool_obj);
799
2f42aa0a
PP
800 if (!bool_obj) {
801 BT_LOGW_STR("Invalid parameter: value object is NULL.");
802 ret = BT_VALUE_STATUS_INVAL;
803 goto end;
804 }
805
806 if (!bt_value_is_bool(bool_obj)) {
807 BT_LOGW("Invalid parameter: value is not a boolean value: addr=%p, "
c4628760
PP
808 "type=%s", bool_obj,
809 bt_value_type_string(bool_obj->type));
dac5c838
PP
810 ret = BT_VALUE_STATUS_INVAL;
811 goto end;
812 }
813
814 if (bool_obj->is_frozen) {
2f42aa0a
PP
815 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
816 bool_obj);
dac5c838
PP
817 ret = BT_VALUE_STATUS_FROZEN;
818 goto end;
819 }
820
821 typed_bool_obj->value = val;
2f42aa0a
PP
822 BT_LOGV("Set boolean value's raw value: value-addr=%p, value=%d",
823 bool_obj, val);
dac5c838
PP
824
825end:
826 return ret;
827}
828
829enum bt_value_status bt_value_integer_get(const struct bt_value *integer_obj,
364747d6 830 int64_t *val)
dac5c838
PP
831{
832 enum bt_value_status ret = BT_VALUE_STATUS_OK;
833 struct bt_value_integer *typed_integer_obj =
834 BT_VALUE_TO_INTEGER(integer_obj);
835
2f42aa0a
PP
836 if (!integer_obj || !val) {
837 BT_LOGW("Invalid parameter: value object or value is NULL: "
838 "value-addr=%p, raw-value-addr=%p",
839 integer_obj, val);
840 ret = BT_VALUE_STATUS_INVAL;
841 goto end;
842 }
843
844 if (!bt_value_is_integer(integer_obj)) {
845 BT_LOGW("Invalid parameter: value is not an integer value: addr=%p, "
c4628760
PP
846 "type=%s", integer_obj,
847 bt_value_type_string(integer_obj->type));
dac5c838
PP
848 ret = BT_VALUE_STATUS_INVAL;
849 goto end;
850 }
851
852 *val = typed_integer_obj->value;
853
854end:
855 return ret;
856}
857
858enum bt_value_status bt_value_integer_set(struct bt_value *integer_obj,
364747d6 859 int64_t val)
dac5c838
PP
860{
861 enum bt_value_status ret = BT_VALUE_STATUS_OK;
862 struct bt_value_integer *typed_integer_obj =
863 BT_VALUE_TO_INTEGER(integer_obj);
864
2f42aa0a
PP
865 if (!integer_obj) {
866 BT_LOGW_STR("Invalid parameter: value object is NULL.");
867 ret = BT_VALUE_STATUS_INVAL;
868 goto end;
869 }
870
871 if (!bt_value_is_integer(integer_obj)) {
872 BT_LOGW("Invalid parameter: value is not an integer value: addr=%p, "
c4628760
PP
873 "type=%s", integer_obj,
874 bt_value_type_string(integer_obj->type));
dac5c838
PP
875 ret = BT_VALUE_STATUS_INVAL;
876 goto end;
877 }
878
879 if (integer_obj->is_frozen) {
2f42aa0a
PP
880 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
881 integer_obj);
dac5c838
PP
882 ret = BT_VALUE_STATUS_FROZEN;
883 goto end;
884 }
885
886 typed_integer_obj->value = val;
2f42aa0a
PP
887 BT_LOGV("Set integer value's raw value: value-addr=%p, value=%" PRId64,
888 integer_obj, val);
dac5c838
PP
889
890end:
891 return ret;
892}
893
894enum bt_value_status bt_value_float_get(const struct bt_value *float_obj,
364747d6 895 double *val)
dac5c838
PP
896{
897 enum bt_value_status ret = BT_VALUE_STATUS_OK;
898 struct bt_value_float *typed_float_obj =
899 BT_VALUE_TO_FLOAT(float_obj);
900
2f42aa0a
PP
901 if (!float_obj || !val) {
902 BT_LOGW("Invalid parameter: value object or value is NULL: "
903 "value-addr=%p, raw-value-addr=%p",
904 float_obj, val);
905 ret = BT_VALUE_STATUS_INVAL;
906 goto end;
907 }
908
909 if (!bt_value_is_float(float_obj)) {
910 BT_LOGW("Invalid parameter: value is not a floating point number value: addr=%p, "
c4628760
PP
911 "type=%s", float_obj,
912 bt_value_type_string(float_obj->type));
dac5c838
PP
913 ret = BT_VALUE_STATUS_INVAL;
914 goto end;
915 }
916
917 *val = typed_float_obj->value;
918
919end:
920 return ret;
921}
922
923enum bt_value_status bt_value_float_set(struct bt_value *float_obj,
364747d6 924 double val)
dac5c838
PP
925{
926 enum bt_value_status ret = BT_VALUE_STATUS_OK;
927 struct bt_value_float *typed_float_obj =
928 BT_VALUE_TO_FLOAT(float_obj);
929
2f42aa0a
PP
930 if (!float_obj) {
931 BT_LOGW_STR("Invalid parameter: value object is NULL.");
932 ret = BT_VALUE_STATUS_INVAL;
933 goto end;
934 }
935
936 if (!bt_value_is_float(float_obj)) {
937 BT_LOGW("Invalid parameter: value is not a floating point number value: addr=%p, "
c4628760
PP
938 "type=%s", float_obj,
939 bt_value_type_string(float_obj->type));
dac5c838
PP
940 ret = BT_VALUE_STATUS_INVAL;
941 goto end;
942 }
943
944 if (float_obj->is_frozen) {
2f42aa0a
PP
945 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
946 float_obj);
dac5c838
PP
947 ret = BT_VALUE_STATUS_FROZEN;
948 goto end;
949 }
950
951 typed_float_obj->value = val;
2f42aa0a
PP
952 BT_LOGV("Set floating point number value's raw value: value-addr=%p, value=%f",
953 float_obj, val);
dac5c838
PP
954
955end:
956 return ret;
957}
958
959enum bt_value_status bt_value_string_get(const struct bt_value *string_obj,
364747d6 960 const char **val)
dac5c838
PP
961{
962 enum bt_value_status ret = BT_VALUE_STATUS_OK;
963 struct bt_value_string *typed_string_obj =
964 BT_VALUE_TO_STRING(string_obj);
965
2f42aa0a
PP
966 if (!string_obj || !val) {
967 BT_LOGW("Invalid parameter: value object or value is NULL: "
968 "value-addr=%p, raw-value-addr=%p",
969 string_obj, val);
970 ret = BT_VALUE_STATUS_INVAL;
971 goto end;
972 }
973
974 if (!bt_value_is_string(string_obj)) {
975 BT_LOGW("Invalid parameter: value is not a string value: addr=%p, "
c4628760
PP
976 "type=%s", string_obj,
977 bt_value_type_string(string_obj->type));
dac5c838
PP
978 ret = BT_VALUE_STATUS_INVAL;
979 goto end;
980 }
981
982 *val = typed_string_obj->gstr->str;
983
984end:
985 return ret;
986}
987
988enum bt_value_status bt_value_string_set(struct bt_value *string_obj,
364747d6 989 const char *val)
dac5c838
PP
990{
991 enum bt_value_status ret = BT_VALUE_STATUS_OK;
992 struct bt_value_string *typed_string_obj =
993 BT_VALUE_TO_STRING(string_obj);
994
2f42aa0a
PP
995 if (!string_obj || !val) {
996 BT_LOGW("Invalid parameter: value object or value is NULL: "
997 "value-addr=%p, raw-value-addr=%p",
998 string_obj, val);
999 ret = BT_VALUE_STATUS_INVAL;
1000 goto end;
1001 }
1002
1003 if (!bt_value_is_string(string_obj)) {
1004 BT_LOGW("Invalid parameter: value is not a string value: addr=%p, "
c4628760
PP
1005 "type=%s", string_obj,
1006 bt_value_type_string(string_obj->type));
dac5c838
PP
1007 ret = BT_VALUE_STATUS_INVAL;
1008 goto end;
1009 }
1010
1011 if (string_obj->is_frozen) {
2f42aa0a
PP
1012 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1013 string_obj);
dac5c838
PP
1014 ret = BT_VALUE_STATUS_FROZEN;
1015 goto end;
1016 }
1017
1018 g_string_assign(typed_string_obj->gstr, val);
2f42aa0a
PP
1019 BT_LOGV("Set string value's raw value: value-addr=%p, raw-value-addr=%p",
1020 string_obj, val);
dac5c838
PP
1021
1022end:
1023 return ret;
1024}
1025
544d0515 1026int64_t bt_value_array_size(const struct bt_value *array_obj)
dac5c838 1027{
544d0515 1028 int64_t ret;
dac5c838
PP
1029 struct bt_value_array *typed_array_obj =
1030 BT_VALUE_TO_ARRAY(array_obj);
1031
2f42aa0a
PP
1032 if (!array_obj) {
1033 BT_LOGW_STR("Invalid parameter: value object is NULL.");
9ac68eb1 1034 ret = (int64_t) BT_VALUE_STATUS_INVAL;
dac5c838
PP
1035 goto end;
1036 }
1037
2f42aa0a
PP
1038 if (!bt_value_is_array(array_obj)) {
1039 BT_LOGW("Invalid parameter: value is not an array value: addr=%p, "
c4628760
PP
1040 "type=%s", array_obj,
1041 bt_value_type_string(array_obj->type));
2f42aa0a
PP
1042 ret = BT_VALUE_STATUS_INVAL;
1043 goto end;
1044 }
1045
544d0515 1046 ret = (int64_t) typed_array_obj->garray->len;
dac5c838
PP
1047
1048end:
1049 return ret;
1050}
1051
c55a9f58 1052bt_bool bt_value_array_is_empty(const struct bt_value *array_obj)
dac5c838
PP
1053{
1054 return bt_value_array_size(array_obj) == 0;
1055}
1056
1057struct bt_value *bt_value_array_get(const struct bt_value *array_obj,
2f42aa0a 1058 uint64_t index)
dac5c838
PP
1059{
1060 struct bt_value *ret;
1061 struct bt_value_array *typed_array_obj =
1062 BT_VALUE_TO_ARRAY(array_obj);
1063
2f42aa0a
PP
1064 if (!array_obj) {
1065 BT_LOGW("Invalid parameter: value object is NULL: index=%" PRIu64,
1066 index);
1067 ret = NULL;
1068 goto end;
1069 }
1070
1071 if (!bt_value_is_array(array_obj)) {
1072 BT_LOGW("Invalid parameter: value is not an array value: addr=%p, "
c4628760
PP
1073 "type=%s", array_obj,
1074 bt_value_type_string(array_obj->type));
2f42aa0a
PP
1075 ret = NULL;
1076 goto end;
1077 }
1078
1079 if (index >= typed_array_obj->garray->len) {
1080 BT_LOGW("Invalid parameter: index is out of bounds: "
78c6e1b1
PP
1081 "addr=%p, index=%" PRIu64 ", size=%u",
1082 array_obj, index, typed_array_obj->garray->len);
dac5c838
PP
1083 ret = NULL;
1084 goto end;
1085 }
1086
1087 ret = g_ptr_array_index(typed_array_obj->garray, index);
83509119 1088 bt_get(ret);
dac5c838
PP
1089
1090end:
1091 return ret;
1092}
1093
1094enum bt_value_status bt_value_array_append(struct bt_value *array_obj,
364747d6 1095 struct bt_value *element_obj)
dac5c838
PP
1096{
1097 enum bt_value_status ret = BT_VALUE_STATUS_OK;
1098 struct bt_value_array *typed_array_obj =
1099 BT_VALUE_TO_ARRAY(array_obj);
1100
2f42aa0a
PP
1101 if (!array_obj || !element_obj) {
1102 BT_LOGW("Invalid parameter: array value or element value is NULL: "
1103 "array-value-addr=%p, element-value-addr=%p",
1104 array_obj, element_obj);
1105 ret = BT_VALUE_STATUS_INVAL;
1106 goto end;
1107 }
1108
1109 if (!bt_value_is_array(array_obj)) {
1110 BT_LOGW("Invalid parameter: value is not an array value: addr=%p, "
c4628760
PP
1111 "type=%s", array_obj,
1112 bt_value_type_string(array_obj->type));
dac5c838
PP
1113 ret = BT_VALUE_STATUS_INVAL;
1114 goto end;
1115 }
1116
1117 if (array_obj->is_frozen) {
2f42aa0a
PP
1118 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1119 array_obj);
dac5c838
PP
1120 ret = BT_VALUE_STATUS_FROZEN;
1121 goto end;
1122 }
1123
1124 g_ptr_array_add(typed_array_obj->garray, element_obj);
83509119 1125 bt_get(element_obj);
2f42aa0a
PP
1126 BT_LOGV("Appended element to array value: array-value-addr=%p, "
1127 "element-value-addr=%p, new-size=%u",
1128 array_obj, element_obj, typed_array_obj->garray->len);
dac5c838
PP
1129
1130end:
1131 return ret;
1132}
1133
1134enum bt_value_status bt_value_array_append_bool(struct bt_value *array_obj,
c55a9f58 1135 bt_bool val)
dac5c838
PP
1136{
1137 enum bt_value_status ret;
1138 struct bt_value *bool_obj = NULL;
1139
1140 bool_obj = bt_value_bool_create_init(val);
1141 ret = bt_value_array_append(array_obj, bool_obj);
83509119 1142 bt_put(bool_obj);
dac5c838
PP
1143 return ret;
1144}
1145
1146enum bt_value_status bt_value_array_append_integer(
364747d6 1147 struct bt_value *array_obj, int64_t val)
dac5c838
PP
1148{
1149 enum bt_value_status ret;
1150 struct bt_value *integer_obj = NULL;
1151
1152 integer_obj = bt_value_integer_create_init(val);
1153 ret = bt_value_array_append(array_obj, integer_obj);
83509119 1154 bt_put(integer_obj);
dac5c838
PP
1155 return ret;
1156}
1157
1158enum bt_value_status bt_value_array_append_float(struct bt_value *array_obj,
364747d6 1159 double val)
dac5c838
PP
1160{
1161 enum bt_value_status ret;
1162 struct bt_value *float_obj = NULL;
1163
1164 float_obj = bt_value_float_create_init(val);
1165 ret = bt_value_array_append(array_obj, float_obj);
83509119 1166 bt_put(float_obj);
dac5c838
PP
1167 return ret;
1168}
1169
1170enum bt_value_status bt_value_array_append_string(struct bt_value *array_obj,
364747d6 1171 const char *val)
dac5c838
PP
1172{
1173 enum bt_value_status ret;
1174 struct bt_value *string_obj = NULL;
1175
1176 string_obj = bt_value_string_create_init(val);
1177 ret = bt_value_array_append(array_obj, string_obj);
83509119 1178 bt_put(string_obj);
dac5c838
PP
1179 return ret;
1180}
1181
5b79e8bf 1182enum bt_value_status bt_value_array_append_empty_array(
364747d6 1183 struct bt_value *array_obj)
dac5c838
PP
1184{
1185 enum bt_value_status ret;
1186 struct bt_value *empty_array_obj = NULL;
1187
1188 empty_array_obj = bt_value_array_create();
1189 ret = bt_value_array_append(array_obj, empty_array_obj);
83509119 1190 bt_put(empty_array_obj);
dac5c838
PP
1191 return ret;
1192}
1193
5b79e8bf 1194enum bt_value_status bt_value_array_append_empty_map(struct bt_value *array_obj)
dac5c838
PP
1195{
1196 enum bt_value_status ret;
1197 struct bt_value *map_obj = NULL;
1198
1199 map_obj = bt_value_map_create();
1200 ret = bt_value_array_append(array_obj, map_obj);
83509119 1201 bt_put(map_obj);
dac5c838
PP
1202 return ret;
1203}
1204
1205enum bt_value_status bt_value_array_set(struct bt_value *array_obj,
2f42aa0a 1206 uint64_t index, struct bt_value *element_obj)
dac5c838
PP
1207{
1208 enum bt_value_status ret = BT_VALUE_STATUS_OK;
1209 struct bt_value_array *typed_array_obj =
1210 BT_VALUE_TO_ARRAY(array_obj);
1211
2f42aa0a
PP
1212 if (!array_obj || !element_obj) {
1213 BT_LOGW("Invalid parameter: array value or element value is NULL: "
1214 "index=%" PRIu64 ", array-value-addr=%p, element-value-addr=%p",
1215 index, array_obj, element_obj);
1216 ret = BT_VALUE_STATUS_INVAL;
1217 goto end;
1218 }
1219
1220 if (!bt_value_is_array(array_obj)) {
1221 BT_LOGW("Invalid parameter: value is not an array value: addr=%p, "
c4628760
PP
1222 "type=%s", array_obj,
1223 bt_value_type_string(array_obj->type));
2f42aa0a
PP
1224 ret = BT_VALUE_STATUS_INVAL;
1225 goto end;
1226 }
1227
1228 if (index >= typed_array_obj->garray->len) {
1229 BT_LOGW("Invalid parameter: index is out of bounds: "
78c6e1b1
PP
1230 "addr=%p, index=%" PRIu64 ", size=%u",
1231 array_obj, index, typed_array_obj->garray->len);
dac5c838
PP
1232 ret = BT_VALUE_STATUS_INVAL;
1233 goto end;
1234 }
1235
1236 if (array_obj->is_frozen) {
2f42aa0a
PP
1237 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1238 array_obj);
dac5c838
PP
1239 ret = BT_VALUE_STATUS_FROZEN;
1240 goto end;
1241 }
1242
83509119 1243 bt_put(g_ptr_array_index(typed_array_obj->garray, index));
dac5c838 1244 g_ptr_array_index(typed_array_obj->garray, index) = element_obj;
83509119 1245 bt_get(element_obj);
2f42aa0a
PP
1246 BT_LOGV("Set array value's element: array-value-addr=%p, "
1247 "index=%" PRIu64 ", element-value-addr=%p",
1248 array_obj, index, element_obj);
dac5c838
PP
1249
1250end:
1251 return ret;
1252}
1253
544d0515 1254int64_t bt_value_map_size(const struct bt_value *map_obj)
dac5c838 1255{
544d0515 1256 int64_t ret;
dac5c838
PP
1257 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1258
2f42aa0a
PP
1259 if (!map_obj) {
1260 BT_LOGW_STR("Invalid parameter: value object is NULL.");
1261 ret = (int64_t) BT_VALUE_STATUS_INVAL;
1262 goto end;
1263 }
1264
1265 if (!bt_value_is_map(map_obj)) {
1266 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
c4628760
PP
1267 "type=%s", map_obj,
1268 bt_value_type_string(map_obj->type));
9ac68eb1 1269 ret = (int64_t) BT_VALUE_STATUS_INVAL;
dac5c838
PP
1270 goto end;
1271 }
1272
544d0515 1273 ret = (int64_t) g_hash_table_size(typed_map_obj->ght);
dac5c838
PP
1274
1275end:
1276 return ret;
1277}
1278
c55a9f58 1279bt_bool bt_value_map_is_empty(const struct bt_value *map_obj)
dac5c838
PP
1280{
1281 return bt_value_map_size(map_obj) == 0;
1282}
1283
1284struct bt_value *bt_value_map_get(const struct bt_value *map_obj,
364747d6 1285 const char *key)
dac5c838
PP
1286{
1287 GQuark quark;
1288 struct bt_value *ret;
1289 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1290
2f42aa0a
PP
1291 if (!map_obj || !key) {
1292 BT_LOGW("Invalid parameter: value object or key is NULL: "
1293 "value-addr=%p, key-addr=%p", map_obj, key);
1294 ret = NULL;
1295 goto end;
1296 }
1297
1298 if (!bt_value_is_map(map_obj)) {
1299 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
c4628760
PP
1300 "type=%s", map_obj,
1301 bt_value_type_string(map_obj->type));
dac5c838
PP
1302 ret = NULL;
1303 goto end;
1304 }
1305
1306 quark = g_quark_from_string(key);
1307 ret = g_hash_table_lookup(typed_map_obj->ght, GUINT_TO_POINTER(quark));
dac5c838 1308 if (ret) {
83509119 1309 bt_get(ret);
dac5c838
PP
1310 }
1311
1312end:
1313 return ret;
1314}
1315
c55a9f58 1316bt_bool bt_value_map_has_key(const struct bt_value *map_obj, const char *key)
dac5c838 1317{
c55a9f58 1318 bt_bool ret;
dac5c838
PP
1319 GQuark quark;
1320 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1321
2f42aa0a
PP
1322 if (!map_obj || !key) {
1323 BT_LOGW("Invalid parameter: value object or key is NULL: "
1324 "value-addr=%p, key-addr=%p", map_obj, key);
c55a9f58 1325 ret = BT_FALSE;
2f42aa0a
PP
1326 goto end;
1327 }
1328
1329 if (!bt_value_is_map(map_obj)) {
1330 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
c4628760
PP
1331 "type=%s", map_obj,
1332 bt_value_type_string(map_obj->type));
c55a9f58 1333 ret = BT_FALSE;
dac5c838
PP
1334 goto end;
1335 }
1336
1337 quark = g_quark_from_string(key);
5d5982ab 1338 ret = bt_g_hash_table_contains(typed_map_obj->ght,
dac5c838
PP
1339 GUINT_TO_POINTER(quark));
1340
1341end:
1342 return ret;
1343}
1344
1345enum bt_value_status bt_value_map_insert(struct bt_value *map_obj,
364747d6 1346 const char *key, struct bt_value *element_obj)
dac5c838
PP
1347{
1348 GQuark quark;
1349 enum bt_value_status ret = BT_VALUE_STATUS_OK;
1350 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1351
2f42aa0a
PP
1352 if (!map_obj || !key || !element_obj) {
1353 BT_LOGW("Invalid parameter: map value, key, or element value is NULL: "
1354 "map-value-addr=%p, key-addr=%p, element-value-addr=%p",
1355 map_obj, key, element_obj);
1356 ret = BT_VALUE_STATUS_INVAL;
1357 goto end;
1358 }
1359
1360 if (!bt_value_is_map(map_obj)) {
1361 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
c4628760
PP
1362 "type=%s", map_obj,
1363 bt_value_type_string(map_obj->type));
dac5c838
PP
1364 ret = BT_VALUE_STATUS_INVAL;
1365 goto end;
1366 }
1367
1368 if (map_obj->is_frozen) {
2f42aa0a
PP
1369 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1370 map_obj);
dac5c838
PP
1371 ret = BT_VALUE_STATUS_FROZEN;
1372 goto end;
1373 }
1374
1375 quark = g_quark_from_string(key);
1376 g_hash_table_insert(typed_map_obj->ght,
1377 GUINT_TO_POINTER(quark), element_obj);
83509119 1378 bt_get(element_obj);
2f42aa0a
PP
1379 BT_LOGV("Inserted value into map value: map-value-addr=%p, "
1380 "key=\"%s\", element-value-addr=%p",
1381 map_obj, key, element_obj);
dac5c838
PP
1382
1383end:
1384 return ret;
1385}
1386
1387enum bt_value_status bt_value_map_insert_bool(struct bt_value *map_obj,
c55a9f58 1388 const char *key, bt_bool val)
dac5c838
PP
1389{
1390 enum bt_value_status ret;
1391 struct bt_value *bool_obj = NULL;
1392
1393 bool_obj = bt_value_bool_create_init(val);
1394 ret = bt_value_map_insert(map_obj, key, bool_obj);
83509119 1395 bt_put(bool_obj);
dac5c838
PP
1396 return ret;
1397}
1398
1399enum bt_value_status bt_value_map_insert_integer(struct bt_value *map_obj,
364747d6 1400 const char *key, int64_t val)
dac5c838
PP
1401{
1402 enum bt_value_status ret;
1403 struct bt_value *integer_obj = NULL;
1404
1405 integer_obj = bt_value_integer_create_init(val);
1406 ret = bt_value_map_insert(map_obj, key, integer_obj);
83509119 1407 bt_put(integer_obj);
dac5c838
PP
1408 return ret;
1409}
1410
1411enum bt_value_status bt_value_map_insert_float(struct bt_value *map_obj,
364747d6 1412 const char *key, double val)
dac5c838
PP
1413{
1414 enum bt_value_status ret;
1415 struct bt_value *float_obj = NULL;
1416
1417 float_obj = bt_value_float_create_init(val);
1418 ret = bt_value_map_insert(map_obj, key, float_obj);
83509119 1419 bt_put(float_obj);
dac5c838
PP
1420 return ret;
1421}
1422
1423enum bt_value_status bt_value_map_insert_string(struct bt_value *map_obj,
364747d6 1424 const char *key, const char *val)
dac5c838
PP
1425{
1426 enum bt_value_status ret;
1427 struct bt_value *string_obj = NULL;
1428
1429 string_obj = bt_value_string_create_init(val);
1430 ret = bt_value_map_insert(map_obj, key, string_obj);
83509119 1431 bt_put(string_obj);
dac5c838
PP
1432 return ret;
1433}
1434
5b79e8bf 1435enum bt_value_status bt_value_map_insert_empty_array(struct bt_value *map_obj,
364747d6 1436 const char *key)
dac5c838
PP
1437{
1438 enum bt_value_status ret;
1439 struct bt_value *array_obj = NULL;
1440
1441 array_obj = bt_value_array_create();
1442 ret = bt_value_map_insert(map_obj, key, array_obj);
83509119 1443 bt_put(array_obj);
dac5c838
PP
1444 return ret;
1445}
1446
5b79e8bf 1447enum bt_value_status bt_value_map_insert_empty_map(struct bt_value *map_obj,
364747d6 1448 const char *key)
dac5c838
PP
1449{
1450 enum bt_value_status ret;
1451 struct bt_value *empty_map_obj = NULL;
1452
1453 empty_map_obj = bt_value_map_create();
1454 ret = bt_value_map_insert(map_obj, key, empty_map_obj);
83509119 1455 bt_put(empty_map_obj);
dac5c838
PP
1456 return ret;
1457}
1458
1459enum bt_value_status bt_value_map_foreach(const struct bt_value *map_obj,
364747d6 1460 bt_value_map_foreach_cb cb, void *data)
dac5c838
PP
1461{
1462 enum bt_value_status ret = BT_VALUE_STATUS_OK;
1463 gpointer key, element_obj;
1464 GHashTableIter iter;
1465 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1466
2f42aa0a
PP
1467 if (!map_obj || !cb) {
1468 BT_LOGW("Invalid parameter: map value or callback is NULL: "
1469 "value-addr=%p, cb-addr=%p", map_obj, cb);
1470 ret = BT_VALUE_STATUS_INVAL;
1471 goto end;
1472 }
1473
1474 if (!bt_value_is_map(map_obj)) {
1475 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
c4628760
PP
1476 "type=%s", map_obj,
1477 bt_value_type_string(map_obj->type));
dac5c838
PP
1478 ret = BT_VALUE_STATUS_INVAL;
1479 goto end;
1480 }
1481
1482 g_hash_table_iter_init(&iter, typed_map_obj->ght);
1483
1484 while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
5b44aff2 1485 const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
dac5c838
PP
1486
1487 if (!cb(key_str, element_obj, data)) {
c4628760 1488 BT_LOGV("User cancelled the loop: key=\"%s\", "
2f42aa0a
PP
1489 "value-addr=%p, data=%p",
1490 key_str, element_obj, data);
dac5c838
PP
1491 ret = BT_VALUE_STATUS_CANCELLED;
1492 break;
1493 }
1494 }
1495
1496end:
1497 return ret;
1498}
1499
770750d3
PP
1500struct extend_map_element_data {
1501 struct bt_value *extended_obj;
c55a9f58 1502 bt_bool got_error;
770750d3
PP
1503};
1504
1505static
c55a9f58 1506bt_bool extend_map_element(const char *key,
770750d3
PP
1507 struct bt_value *extension_obj_elem, void *data)
1508{
c55a9f58 1509 bt_bool ret = BT_TRUE;
770750d3
PP
1510
1511 struct extend_map_element_data *extend_data = data;
1512
1513 /* Copy object which is to replace the current one */
1514 struct bt_value *extension_obj_elem_copy =
1515 bt_value_copy(extension_obj_elem);
1516
1517 /* Replace in extended object */
1518 if (bt_value_map_insert(extend_data->extended_obj, key,
1519 extension_obj_elem_copy)) {
2f42aa0a
PP
1520 BT_LOGE("Cannot replace value in extended value: key=\"%s\", "
1521 "extended-value-addr=%p, element-value-addr=%p",
1522 key, extend_data->extended_obj,
1523 extension_obj_elem_copy);
770750d3
PP
1524 goto error;
1525 }
1526
1527 goto end;
1528
1529error:
c55a9f58
PP
1530 ret = BT_FALSE;
1531 extend_data->got_error = BT_TRUE;
770750d3
PP
1532
1533end:
1534 BT_PUT(extension_obj_elem_copy);
770750d3
PP
1535 return ret;
1536}
1537
1538struct bt_value *bt_value_map_extend(struct bt_value *base_map_obj,
1539 struct bt_value *extension_obj)
1540{
1541 struct bt_value *extended_obj = NULL;
1542 struct extend_map_element_data extend_data = { 0 };
1543
2f42aa0a
PP
1544 if (!base_map_obj || !extension_obj) {
1545 BT_LOGW("Invalid parameter: base value or extension value is NULL: "
1546 "base-value-addr=%p, extension-value-addr=%p",
1547 base_map_obj, extension_obj);
1548 goto error;
1549 }
1550
1551 if (!bt_value_is_map(base_map_obj)) {
1552 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
c4628760
PP
1553 "type=%s", base_map_obj,
1554 bt_value_type_string(base_map_obj->type));
770750d3
PP
1555 goto error;
1556 }
1557
2f42aa0a
PP
1558 if (!bt_value_is_map(extension_obj)) {
1559 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
c4628760
PP
1560 "type=%s", extension_obj,
1561 bt_value_type_string(extension_obj->type));
2f42aa0a
PP
1562 goto error;
1563 }
1564
1565 BT_LOGD("Extending map value: base-value-addr=%p, extension-value-addr=%p",
1566 base_map_obj, extension_obj);
1567
770750d3
PP
1568 /* Create copy of base map object to start with */
1569 extended_obj = bt_value_copy(base_map_obj);
1570 if (!extended_obj) {
2f42aa0a
PP
1571 BT_LOGE("Cannot copy base value: base-value-addr=%p",
1572 base_map_obj);
770750d3
PP
1573 goto error;
1574 }
1575
1576 /*
1577 * For each key in the extension map object, replace this key
1578 * in the copied map object.
1579 */
1580 extend_data.extended_obj = extended_obj;
1581
1582 if (bt_value_map_foreach(extension_obj, extend_map_element,
1583 &extend_data)) {
32e87ceb 1584 BT_LOGE("Cannot iterate on the extension object's elements: "
2f42aa0a 1585 "extension-value-addr=%p", extension_obj);
770750d3
PP
1586 goto error;
1587 }
1588
1589 if (extend_data.got_error) {
32e87ceb 1590 BT_LOGE("Failed to successfully iterate on the extension object's elements: "
2f42aa0a 1591 "extension-value-addr=%p", extension_obj);
770750d3
PP
1592 goto error;
1593 }
1594
2f42aa0a
PP
1595 BT_LOGD("Extended map value: extended-value-addr=%p",
1596 extended_obj);
770750d3
PP
1597 goto end;
1598
1599error:
1600 BT_PUT(extended_obj);
1601
1602end:
1603 return extended_obj;
1604}
1605
dac5c838
PP
1606struct bt_value *bt_value_copy(const struct bt_value *object)
1607{
1608 struct bt_value *copy_obj = NULL;
1609
1610 if (!object) {
2f42aa0a 1611 BT_LOGW_STR("Invalid parameter: value object is NULL.");
dac5c838
PP
1612 goto end;
1613 }
1614
2f42aa0a 1615 BT_LOGD("Copying value object: addr=%p", object);
dac5c838 1616 copy_obj = copy_funcs[object->type](object);
2f42aa0a
PP
1617 if (copy_obj) {
1618 BT_LOGD("Copied value object: copy-value-addr=%p",
1619 copy_obj);
1620 } else {
1621 BT_LOGE_STR("Failed to copy value object.");
1622 }
dac5c838
PP
1623
1624end:
1625 return copy_obj;
1626}
1627
c55a9f58 1628bt_bool bt_value_compare(const struct bt_value *object_a,
dac5c838
PP
1629 const struct bt_value *object_b)
1630{
c55a9f58 1631 bt_bool ret = BT_FALSE;
dac5c838
PP
1632
1633 if (!object_a || !object_b) {
2f42aa0a
PP
1634 BT_LOGW("Invalid parameter: value A or value B is NULL: "
1635 "value-a-addr=%p, value-b-addr=%p",
1636 object_a, object_b);
dac5c838
PP
1637 goto end;
1638 }
1639
1640 if (object_a->type != object_b->type) {
2f42aa0a
PP
1641 BT_LOGV("Values are different: type mismatch: "
1642 "value-a-addr=%p, value-b-addr=%p, "
c4628760 1643 "value-a-type=%s, value-b-type=%s",
2f42aa0a 1644 object_a, object_b,
c4628760
PP
1645 bt_value_type_string(object_a->type),
1646 bt_value_type_string(object_b->type));
dac5c838
PP
1647 goto end;
1648 }
1649
1650 ret = compare_funcs[object_a->type](object_a, object_b);
1651
1652end:
1653 return ret;
1654}
This page took 0.113326 seconds and 4 git commands to generate.