lib/ctf-ir/event.c: replace some BT_LOGE() with BT_LOGW()
[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",
397 element_obj_a, element_obj_b, index);
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) {
2f42aa0a 569 BT_LOGW_STR("Invalid parameter: value object is NULL.");
dac5c838
PP
570 return BT_VALUE_TYPE_UNKNOWN;
571 }
572
573 return object->type;
574}
575
576static
577struct bt_value bt_value_create_base(enum bt_value_type type)
578{
579 struct bt_value base;
580
581 base.type = type;
c55a9f58 582 base.is_frozen = BT_FALSE;
83509119 583 bt_object_init(&base, bt_value_destroy);
dac5c838
PP
584 return base;
585}
586
c55a9f58 587struct bt_value *bt_value_bool_create_init(bt_bool val)
dac5c838
PP
588{
589 struct bt_value_bool *bool_obj;
590
2f42aa0a 591 BT_LOGD("Creating boolean value object: val=%d", val);
dac5c838
PP
592 bool_obj = g_new0(struct bt_value_bool, 1);
593
594 if (!bool_obj) {
2f42aa0a 595 BT_LOGE_STR("Failed to allocate one boolean value object.");
dac5c838
PP
596 goto end;
597 }
598
599 bool_obj->base = bt_value_create_base(BT_VALUE_TYPE_BOOL);
600 bool_obj->value = val;
2f42aa0a 601 BT_LOGD("Created boolean value object: addr=%p", bool_obj);
dac5c838
PP
602
603end:
604 return BT_VALUE_FROM_CONCRETE(bool_obj);
605}
606
607struct bt_value *bt_value_bool_create(void)
608{
c55a9f58 609 return bt_value_bool_create_init(BT_FALSE);
dac5c838
PP
610}
611
612struct bt_value *bt_value_integer_create_init(int64_t val)
613{
614 struct bt_value_integer *integer_obj;
615
2f42aa0a 616 BT_LOGD("Creating integer value object: val=%" PRId64, val);
dac5c838
PP
617 integer_obj = g_new0(struct bt_value_integer, 1);
618
619 if (!integer_obj) {
2f42aa0a 620 BT_LOGE_STR("Failed to allocate one integer value object.");
dac5c838
PP
621 goto end;
622 }
623
624 integer_obj->base = bt_value_create_base(BT_VALUE_TYPE_INTEGER);
625 integer_obj->value = val;
2f42aa0a
PP
626 BT_LOGD("Created integer value object: addr=%p",
627 integer_obj);
dac5c838
PP
628
629end:
630 return BT_VALUE_FROM_CONCRETE(integer_obj);
631}
632
633struct bt_value *bt_value_integer_create(void)
634{
635 return bt_value_integer_create_init(0);
636}
637
638struct bt_value *bt_value_float_create_init(double val)
639{
640 struct bt_value_float *float_obj;
641
2f42aa0a 642 BT_LOGD("Creating floating point number value object: val=%f", val);
dac5c838
PP
643 float_obj = g_new0(struct bt_value_float, 1);
644
645 if (!float_obj) {
2f42aa0a 646 BT_LOGE_STR("Failed to allocate one floating point number value object.");
dac5c838
PP
647 goto end;
648 }
649
650 float_obj->base = bt_value_create_base(BT_VALUE_TYPE_FLOAT);
651 float_obj->value = val;
2f42aa0a
PP
652 BT_LOGD("Created floating point number value object: addr=%p",
653 float_obj);
dac5c838
PP
654
655end:
656 return BT_VALUE_FROM_CONCRETE(float_obj);
657}
658
659struct bt_value *bt_value_float_create(void)
660{
661 return bt_value_float_create_init(0.);
662}
663
664struct bt_value *bt_value_string_create_init(const char *val)
665{
666 struct bt_value_string *string_obj = NULL;
667
668 if (!val) {
2f42aa0a 669 BT_LOGW_STR("Invalid parameter: value is NULL.");
dac5c838
PP
670 goto end;
671 }
672
2f42aa0a 673 BT_LOGD("Creating string value object: val-len=%u", strlen(val));
dac5c838
PP
674 string_obj = g_new0(struct bt_value_string, 1);
675
676 if (!string_obj) {
2f42aa0a 677 BT_LOGE_STR("Failed to allocate one string object.");
dac5c838
PP
678 goto end;
679 }
680
681 string_obj->base = bt_value_create_base(BT_VALUE_TYPE_STRING);
682 string_obj->gstr = g_string_new(val);
683
684 if (!string_obj->gstr) {
2f42aa0a 685 BT_LOGE_STR("Failed to allocate a GString.");
dac5c838
PP
686 g_free(string_obj);
687 string_obj = NULL;
688 goto end;
689 }
690
2f42aa0a
PP
691 BT_LOGD("Created string value object: addr=%p",
692 string_obj);
693
dac5c838
PP
694end:
695 return BT_VALUE_FROM_CONCRETE(string_obj);
696}
697
698struct bt_value *bt_value_string_create(void)
699{
700 return bt_value_string_create_init("");
701}
702
703struct bt_value *bt_value_array_create(void)
704{
705 struct bt_value_array *array_obj;
706
2f42aa0a 707 BT_LOGD_STR("Creating empty array value object.");
dac5c838
PP
708 array_obj = g_new0(struct bt_value_array, 1);
709
710 if (!array_obj) {
2f42aa0a 711 BT_LOGE_STR("Failed to allocate one array object.");
dac5c838
PP
712 goto end;
713 }
714
715 array_obj->base = bt_value_create_base(BT_VALUE_TYPE_ARRAY);
5d5982ab 716 array_obj->garray = bt_g_ptr_array_new_full(0,
83509119 717 (GDestroyNotify) bt_put);
dac5c838
PP
718
719 if (!array_obj->garray) {
2f42aa0a 720 BT_LOGE_STR("Failed to allocate a GPtrArray.");
dac5c838
PP
721 g_free(array_obj);
722 array_obj = NULL;
723 goto end;
724 }
725
2f42aa0a
PP
726 BT_LOGD("Created array value object: addr=%p",
727 array_obj);
728
dac5c838
PP
729end:
730 return BT_VALUE_FROM_CONCRETE(array_obj);
731}
732
733struct bt_value *bt_value_map_create(void)
734{
735 struct bt_value_map *map_obj;
736
2f42aa0a 737 BT_LOGD_STR("Creating empty map value object.");
dac5c838
PP
738 map_obj = g_new0(struct bt_value_map, 1);
739
740 if (!map_obj) {
2f42aa0a 741 BT_LOGE_STR("Failed to allocate one map object.");
dac5c838
PP
742 goto end;
743 }
744
745 map_obj->base = bt_value_create_base(BT_VALUE_TYPE_MAP);
746 map_obj->ght = g_hash_table_new_full(g_direct_hash, g_direct_equal,
83509119 747 NULL, (GDestroyNotify) bt_put);
dac5c838
PP
748
749 if (!map_obj->ght) {
2f42aa0a 750 BT_LOGE_STR("Failed to allocate a GHashTable.");
dac5c838
PP
751 g_free(map_obj);
752 map_obj = NULL;
753 goto end;
754 }
755
2f42aa0a
PP
756 BT_LOGD("Created map value object: addr=%p",
757 map_obj);
758
dac5c838
PP
759end:
760 return BT_VALUE_FROM_CONCRETE(map_obj);
761}
762
763enum bt_value_status bt_value_bool_get(const struct bt_value *bool_obj,
c55a9f58 764 bt_bool *val)
dac5c838
PP
765{
766 enum bt_value_status ret = BT_VALUE_STATUS_OK;
767 struct bt_value_bool *typed_bool_obj = BT_VALUE_TO_BOOL(bool_obj);
768
2f42aa0a
PP
769 if (!bool_obj || !val) {
770 BT_LOGW("Invalid parameter: value object or value is NULL: "
771 "value-addr=%p, raw-value-addr=%p",
772 bool_obj, val);
773 ret = BT_VALUE_STATUS_INVAL;
774 goto end;
775 }
776
777 if (!bt_value_is_bool(bool_obj)) {
778 BT_LOGW("Invalid parameter: value is not a boolean value: addr=%p, "
c4628760
PP
779 "type=%s", bool_obj, bool_obj->type,
780 bt_value_type_string(bool_obj->type));
dac5c838
PP
781 ret = BT_VALUE_STATUS_INVAL;
782 goto end;
783 }
784
785 *val = typed_bool_obj->value;
786
787end:
788 return ret;
789}
790
c55a9f58 791enum bt_value_status bt_value_bool_set(struct bt_value *bool_obj, bt_bool val)
dac5c838
PP
792{
793 enum bt_value_status ret = BT_VALUE_STATUS_OK;
794 struct bt_value_bool *typed_bool_obj = BT_VALUE_TO_BOOL(bool_obj);
795
2f42aa0a
PP
796 if (!bool_obj) {
797 BT_LOGW_STR("Invalid parameter: value object is NULL.");
798 ret = BT_VALUE_STATUS_INVAL;
799 goto end;
800 }
801
802 if (!bt_value_is_bool(bool_obj)) {
803 BT_LOGW("Invalid parameter: value is not a boolean value: addr=%p, "
c4628760
PP
804 "type=%s", bool_obj,
805 bt_value_type_string(bool_obj->type));
dac5c838
PP
806 ret = BT_VALUE_STATUS_INVAL;
807 goto end;
808 }
809
810 if (bool_obj->is_frozen) {
2f42aa0a
PP
811 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
812 bool_obj);
dac5c838
PP
813 ret = BT_VALUE_STATUS_FROZEN;
814 goto end;
815 }
816
817 typed_bool_obj->value = val;
2f42aa0a
PP
818 BT_LOGV("Set boolean value's raw value: value-addr=%p, value=%d",
819 bool_obj, val);
dac5c838
PP
820
821end:
822 return ret;
823}
824
825enum bt_value_status bt_value_integer_get(const struct bt_value *integer_obj,
364747d6 826 int64_t *val)
dac5c838
PP
827{
828 enum bt_value_status ret = BT_VALUE_STATUS_OK;
829 struct bt_value_integer *typed_integer_obj =
830 BT_VALUE_TO_INTEGER(integer_obj);
831
2f42aa0a
PP
832 if (!integer_obj || !val) {
833 BT_LOGW("Invalid parameter: value object or value is NULL: "
834 "value-addr=%p, raw-value-addr=%p",
835 integer_obj, val);
836 ret = BT_VALUE_STATUS_INVAL;
837 goto end;
838 }
839
840 if (!bt_value_is_integer(integer_obj)) {
841 BT_LOGW("Invalid parameter: value is not an integer value: addr=%p, "
c4628760
PP
842 "type=%s", integer_obj,
843 bt_value_type_string(integer_obj->type));
dac5c838
PP
844 ret = BT_VALUE_STATUS_INVAL;
845 goto end;
846 }
847
848 *val = typed_integer_obj->value;
849
850end:
851 return ret;
852}
853
854enum bt_value_status bt_value_integer_set(struct bt_value *integer_obj,
364747d6 855 int64_t val)
dac5c838
PP
856{
857 enum bt_value_status ret = BT_VALUE_STATUS_OK;
858 struct bt_value_integer *typed_integer_obj =
859 BT_VALUE_TO_INTEGER(integer_obj);
860
2f42aa0a
PP
861 if (!integer_obj) {
862 BT_LOGW_STR("Invalid parameter: value object is NULL.");
863 ret = BT_VALUE_STATUS_INVAL;
864 goto end;
865 }
866
867 if (!bt_value_is_integer(integer_obj)) {
868 BT_LOGW("Invalid parameter: value is not an integer value: addr=%p, "
c4628760
PP
869 "type=%s", integer_obj,
870 bt_value_type_string(integer_obj->type));
dac5c838
PP
871 ret = BT_VALUE_STATUS_INVAL;
872 goto end;
873 }
874
875 if (integer_obj->is_frozen) {
2f42aa0a
PP
876 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
877 integer_obj);
dac5c838
PP
878 ret = BT_VALUE_STATUS_FROZEN;
879 goto end;
880 }
881
882 typed_integer_obj->value = val;
2f42aa0a
PP
883 BT_LOGV("Set integer value's raw value: value-addr=%p, value=%" PRId64,
884 integer_obj, val);
dac5c838
PP
885
886end:
887 return ret;
888}
889
890enum bt_value_status bt_value_float_get(const struct bt_value *float_obj,
364747d6 891 double *val)
dac5c838
PP
892{
893 enum bt_value_status ret = BT_VALUE_STATUS_OK;
894 struct bt_value_float *typed_float_obj =
895 BT_VALUE_TO_FLOAT(float_obj);
896
2f42aa0a
PP
897 if (!float_obj || !val) {
898 BT_LOGW("Invalid parameter: value object or value is NULL: "
899 "value-addr=%p, raw-value-addr=%p",
900 float_obj, val);
901 ret = BT_VALUE_STATUS_INVAL;
902 goto end;
903 }
904
905 if (!bt_value_is_float(float_obj)) {
906 BT_LOGW("Invalid parameter: value is not a floating point number value: addr=%p, "
c4628760
PP
907 "type=%s", float_obj,
908 bt_value_type_string(float_obj->type));
dac5c838
PP
909 ret = BT_VALUE_STATUS_INVAL;
910 goto end;
911 }
912
913 *val = typed_float_obj->value;
914
915end:
916 return ret;
917}
918
919enum bt_value_status bt_value_float_set(struct bt_value *float_obj,
364747d6 920 double val)
dac5c838
PP
921{
922 enum bt_value_status ret = BT_VALUE_STATUS_OK;
923 struct bt_value_float *typed_float_obj =
924 BT_VALUE_TO_FLOAT(float_obj);
925
2f42aa0a
PP
926 if (!float_obj) {
927 BT_LOGW_STR("Invalid parameter: value object is NULL.");
928 ret = BT_VALUE_STATUS_INVAL;
929 goto end;
930 }
931
932 if (!bt_value_is_float(float_obj)) {
933 BT_LOGW("Invalid parameter: value is not a floating point number value: addr=%p, "
c4628760
PP
934 "type=%s", float_obj,
935 bt_value_type_string(float_obj->type));
dac5c838
PP
936 ret = BT_VALUE_STATUS_INVAL;
937 goto end;
938 }
939
940 if (float_obj->is_frozen) {
2f42aa0a
PP
941 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
942 float_obj);
dac5c838
PP
943 ret = BT_VALUE_STATUS_FROZEN;
944 goto end;
945 }
946
947 typed_float_obj->value = val;
2f42aa0a
PP
948 BT_LOGV("Set floating point number value's raw value: value-addr=%p, value=%f",
949 float_obj, val);
dac5c838
PP
950
951end:
952 return ret;
953}
954
955enum bt_value_status bt_value_string_get(const struct bt_value *string_obj,
364747d6 956 const char **val)
dac5c838
PP
957{
958 enum bt_value_status ret = BT_VALUE_STATUS_OK;
959 struct bt_value_string *typed_string_obj =
960 BT_VALUE_TO_STRING(string_obj);
961
2f42aa0a
PP
962 if (!string_obj || !val) {
963 BT_LOGW("Invalid parameter: value object or value is NULL: "
964 "value-addr=%p, raw-value-addr=%p",
965 string_obj, val);
966 ret = BT_VALUE_STATUS_INVAL;
967 goto end;
968 }
969
970 if (!bt_value_is_string(string_obj)) {
971 BT_LOGW("Invalid parameter: value is not a string value: addr=%p, "
c4628760
PP
972 "type=%s", string_obj,
973 bt_value_type_string(string_obj->type));
dac5c838
PP
974 ret = BT_VALUE_STATUS_INVAL;
975 goto end;
976 }
977
978 *val = typed_string_obj->gstr->str;
979
980end:
981 return ret;
982}
983
984enum bt_value_status bt_value_string_set(struct bt_value *string_obj,
364747d6 985 const char *val)
dac5c838
PP
986{
987 enum bt_value_status ret = BT_VALUE_STATUS_OK;
988 struct bt_value_string *typed_string_obj =
989 BT_VALUE_TO_STRING(string_obj);
990
2f42aa0a
PP
991 if (!string_obj || !val) {
992 BT_LOGW("Invalid parameter: value object or value is NULL: "
993 "value-addr=%p, raw-value-addr=%p",
994 string_obj, val);
995 ret = BT_VALUE_STATUS_INVAL;
996 goto end;
997 }
998
999 if (!bt_value_is_string(string_obj)) {
1000 BT_LOGW("Invalid parameter: value is not a string value: addr=%p, "
c4628760
PP
1001 "type=%s", string_obj,
1002 bt_value_type_string(string_obj->type));
dac5c838
PP
1003 ret = BT_VALUE_STATUS_INVAL;
1004 goto end;
1005 }
1006
1007 if (string_obj->is_frozen) {
2f42aa0a
PP
1008 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1009 string_obj);
dac5c838
PP
1010 ret = BT_VALUE_STATUS_FROZEN;
1011 goto end;
1012 }
1013
1014 g_string_assign(typed_string_obj->gstr, val);
2f42aa0a
PP
1015 BT_LOGV("Set string value's raw value: value-addr=%p, raw-value-addr=%p",
1016 string_obj, val);
dac5c838
PP
1017
1018end:
1019 return ret;
1020}
1021
544d0515 1022int64_t bt_value_array_size(const struct bt_value *array_obj)
dac5c838 1023{
544d0515 1024 int64_t ret;
dac5c838
PP
1025 struct bt_value_array *typed_array_obj =
1026 BT_VALUE_TO_ARRAY(array_obj);
1027
2f42aa0a
PP
1028 if (!array_obj) {
1029 BT_LOGW_STR("Invalid parameter: value object is NULL.");
9ac68eb1 1030 ret = (int64_t) BT_VALUE_STATUS_INVAL;
dac5c838
PP
1031 goto end;
1032 }
1033
2f42aa0a
PP
1034 if (!bt_value_is_array(array_obj)) {
1035 BT_LOGW("Invalid parameter: value is not an array value: addr=%p, "
c4628760
PP
1036 "type=%s", array_obj,
1037 bt_value_type_string(array_obj->type));
2f42aa0a
PP
1038 ret = BT_VALUE_STATUS_INVAL;
1039 goto end;
1040 }
1041
544d0515 1042 ret = (int64_t) typed_array_obj->garray->len;
dac5c838
PP
1043
1044end:
1045 return ret;
1046}
1047
c55a9f58 1048bt_bool bt_value_array_is_empty(const struct bt_value *array_obj)
dac5c838
PP
1049{
1050 return bt_value_array_size(array_obj) == 0;
1051}
1052
1053struct bt_value *bt_value_array_get(const struct bt_value *array_obj,
2f42aa0a 1054 uint64_t index)
dac5c838
PP
1055{
1056 struct bt_value *ret;
1057 struct bt_value_array *typed_array_obj =
1058 BT_VALUE_TO_ARRAY(array_obj);
1059
2f42aa0a
PP
1060 if (!array_obj) {
1061 BT_LOGW("Invalid parameter: value object is NULL: index=%" PRIu64,
1062 index);
1063 ret = NULL;
1064 goto end;
1065 }
1066
1067 if (!bt_value_is_array(array_obj)) {
1068 BT_LOGW("Invalid parameter: value is not an array value: addr=%p, "
c4628760
PP
1069 "type=%s", array_obj,
1070 bt_value_type_string(array_obj->type));
2f42aa0a
PP
1071 ret = NULL;
1072 goto end;
1073 }
1074
1075 if (index >= typed_array_obj->garray->len) {
1076 BT_LOGW("Invalid parameter: index is out of bounds: "
78c6e1b1
PP
1077 "addr=%p, index=%" PRIu64 ", size=%u",
1078 array_obj, index, typed_array_obj->garray->len);
dac5c838
PP
1079 ret = NULL;
1080 goto end;
1081 }
1082
1083 ret = g_ptr_array_index(typed_array_obj->garray, index);
83509119 1084 bt_get(ret);
dac5c838
PP
1085
1086end:
1087 return ret;
1088}
1089
1090enum bt_value_status bt_value_array_append(struct bt_value *array_obj,
364747d6 1091 struct bt_value *element_obj)
dac5c838
PP
1092{
1093 enum bt_value_status ret = BT_VALUE_STATUS_OK;
1094 struct bt_value_array *typed_array_obj =
1095 BT_VALUE_TO_ARRAY(array_obj);
1096
2f42aa0a
PP
1097 if (!array_obj || !element_obj) {
1098 BT_LOGW("Invalid parameter: array value or element value is NULL: "
1099 "array-value-addr=%p, element-value-addr=%p",
1100 array_obj, element_obj);
1101 ret = BT_VALUE_STATUS_INVAL;
1102 goto end;
1103 }
1104
1105 if (!bt_value_is_array(array_obj)) {
1106 BT_LOGW("Invalid parameter: value is not an array value: addr=%p, "
c4628760
PP
1107 "type=%s", array_obj,
1108 bt_value_type_string(array_obj->type));
dac5c838
PP
1109 ret = BT_VALUE_STATUS_INVAL;
1110 goto end;
1111 }
1112
1113 if (array_obj->is_frozen) {
2f42aa0a
PP
1114 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1115 array_obj);
dac5c838
PP
1116 ret = BT_VALUE_STATUS_FROZEN;
1117 goto end;
1118 }
1119
1120 g_ptr_array_add(typed_array_obj->garray, element_obj);
83509119 1121 bt_get(element_obj);
2f42aa0a
PP
1122 BT_LOGV("Appended element to array value: array-value-addr=%p, "
1123 "element-value-addr=%p, new-size=%u",
1124 array_obj, element_obj, typed_array_obj->garray->len);
dac5c838
PP
1125
1126end:
1127 return ret;
1128}
1129
1130enum bt_value_status bt_value_array_append_bool(struct bt_value *array_obj,
c55a9f58 1131 bt_bool val)
dac5c838
PP
1132{
1133 enum bt_value_status ret;
1134 struct bt_value *bool_obj = NULL;
1135
1136 bool_obj = bt_value_bool_create_init(val);
1137 ret = bt_value_array_append(array_obj, bool_obj);
83509119 1138 bt_put(bool_obj);
dac5c838
PP
1139 return ret;
1140}
1141
1142enum bt_value_status bt_value_array_append_integer(
364747d6 1143 struct bt_value *array_obj, int64_t val)
dac5c838
PP
1144{
1145 enum bt_value_status ret;
1146 struct bt_value *integer_obj = NULL;
1147
1148 integer_obj = bt_value_integer_create_init(val);
1149 ret = bt_value_array_append(array_obj, integer_obj);
83509119 1150 bt_put(integer_obj);
dac5c838
PP
1151 return ret;
1152}
1153
1154enum bt_value_status bt_value_array_append_float(struct bt_value *array_obj,
364747d6 1155 double val)
dac5c838
PP
1156{
1157 enum bt_value_status ret;
1158 struct bt_value *float_obj = NULL;
1159
1160 float_obj = bt_value_float_create_init(val);
1161 ret = bt_value_array_append(array_obj, float_obj);
83509119 1162 bt_put(float_obj);
dac5c838
PP
1163 return ret;
1164}
1165
1166enum bt_value_status bt_value_array_append_string(struct bt_value *array_obj,
364747d6 1167 const char *val)
dac5c838
PP
1168{
1169 enum bt_value_status ret;
1170 struct bt_value *string_obj = NULL;
1171
1172 string_obj = bt_value_string_create_init(val);
1173 ret = bt_value_array_append(array_obj, string_obj);
83509119 1174 bt_put(string_obj);
dac5c838
PP
1175 return ret;
1176}
1177
5b79e8bf 1178enum bt_value_status bt_value_array_append_empty_array(
364747d6 1179 struct bt_value *array_obj)
dac5c838
PP
1180{
1181 enum bt_value_status ret;
1182 struct bt_value *empty_array_obj = NULL;
1183
1184 empty_array_obj = bt_value_array_create();
1185 ret = bt_value_array_append(array_obj, empty_array_obj);
83509119 1186 bt_put(empty_array_obj);
dac5c838
PP
1187 return ret;
1188}
1189
5b79e8bf 1190enum bt_value_status bt_value_array_append_empty_map(struct bt_value *array_obj)
dac5c838
PP
1191{
1192 enum bt_value_status ret;
1193 struct bt_value *map_obj = NULL;
1194
1195 map_obj = bt_value_map_create();
1196 ret = bt_value_array_append(array_obj, map_obj);
83509119 1197 bt_put(map_obj);
dac5c838
PP
1198 return ret;
1199}
1200
1201enum bt_value_status bt_value_array_set(struct bt_value *array_obj,
2f42aa0a 1202 uint64_t index, struct bt_value *element_obj)
dac5c838
PP
1203{
1204 enum bt_value_status ret = BT_VALUE_STATUS_OK;
1205 struct bt_value_array *typed_array_obj =
1206 BT_VALUE_TO_ARRAY(array_obj);
1207
2f42aa0a
PP
1208 if (!array_obj || !element_obj) {
1209 BT_LOGW("Invalid parameter: array value or element value is NULL: "
1210 "index=%" PRIu64 ", array-value-addr=%p, element-value-addr=%p",
1211 index, array_obj, element_obj);
1212 ret = BT_VALUE_STATUS_INVAL;
1213 goto end;
1214 }
1215
1216 if (!bt_value_is_array(array_obj)) {
1217 BT_LOGW("Invalid parameter: value is not an array value: addr=%p, "
c4628760
PP
1218 "type=%s", array_obj,
1219 bt_value_type_string(array_obj->type));
2f42aa0a
PP
1220 ret = BT_VALUE_STATUS_INVAL;
1221 goto end;
1222 }
1223
1224 if (index >= typed_array_obj->garray->len) {
1225 BT_LOGW("Invalid parameter: index is out of bounds: "
78c6e1b1
PP
1226 "addr=%p, index=%" PRIu64 ", size=%u",
1227 array_obj, index, typed_array_obj->garray->len);
dac5c838
PP
1228 ret = BT_VALUE_STATUS_INVAL;
1229 goto end;
1230 }
1231
1232 if (array_obj->is_frozen) {
2f42aa0a
PP
1233 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1234 array_obj);
dac5c838
PP
1235 ret = BT_VALUE_STATUS_FROZEN;
1236 goto end;
1237 }
1238
83509119 1239 bt_put(g_ptr_array_index(typed_array_obj->garray, index));
dac5c838 1240 g_ptr_array_index(typed_array_obj->garray, index) = element_obj;
83509119 1241 bt_get(element_obj);
2f42aa0a
PP
1242 BT_LOGV("Set array value's element: array-value-addr=%p, "
1243 "index=%" PRIu64 ", element-value-addr=%p",
1244 array_obj, index, element_obj);
dac5c838
PP
1245
1246end:
1247 return ret;
1248}
1249
544d0515 1250int64_t bt_value_map_size(const struct bt_value *map_obj)
dac5c838 1251{
544d0515 1252 int64_t ret;
dac5c838
PP
1253 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1254
2f42aa0a
PP
1255 if (!map_obj) {
1256 BT_LOGW_STR("Invalid parameter: value object is NULL.");
1257 ret = (int64_t) BT_VALUE_STATUS_INVAL;
1258 goto end;
1259 }
1260
1261 if (!bt_value_is_map(map_obj)) {
1262 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
c4628760
PP
1263 "type=%s", map_obj,
1264 bt_value_type_string(map_obj->type));
9ac68eb1 1265 ret = (int64_t) BT_VALUE_STATUS_INVAL;
dac5c838
PP
1266 goto end;
1267 }
1268
544d0515 1269 ret = (int64_t) g_hash_table_size(typed_map_obj->ght);
dac5c838
PP
1270
1271end:
1272 return ret;
1273}
1274
c55a9f58 1275bt_bool bt_value_map_is_empty(const struct bt_value *map_obj)
dac5c838
PP
1276{
1277 return bt_value_map_size(map_obj) == 0;
1278}
1279
1280struct bt_value *bt_value_map_get(const struct bt_value *map_obj,
364747d6 1281 const char *key)
dac5c838
PP
1282{
1283 GQuark quark;
1284 struct bt_value *ret;
1285 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1286
2f42aa0a
PP
1287 if (!map_obj || !key) {
1288 BT_LOGW("Invalid parameter: value object or key is NULL: "
1289 "value-addr=%p, key-addr=%p", map_obj, key);
1290 ret = NULL;
1291 goto end;
1292 }
1293
1294 if (!bt_value_is_map(map_obj)) {
1295 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
c4628760
PP
1296 "type=%s", map_obj,
1297 bt_value_type_string(map_obj->type));
dac5c838
PP
1298 ret = NULL;
1299 goto end;
1300 }
1301
1302 quark = g_quark_from_string(key);
1303 ret = g_hash_table_lookup(typed_map_obj->ght, GUINT_TO_POINTER(quark));
dac5c838 1304 if (ret) {
83509119 1305 bt_get(ret);
dac5c838
PP
1306 }
1307
1308end:
1309 return ret;
1310}
1311
c55a9f58 1312bt_bool bt_value_map_has_key(const struct bt_value *map_obj, const char *key)
dac5c838 1313{
c55a9f58 1314 bt_bool ret;
dac5c838
PP
1315 GQuark quark;
1316 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1317
2f42aa0a
PP
1318 if (!map_obj || !key) {
1319 BT_LOGW("Invalid parameter: value object or key is NULL: "
1320 "value-addr=%p, key-addr=%p", map_obj, key);
c55a9f58 1321 ret = BT_FALSE;
2f42aa0a
PP
1322 goto end;
1323 }
1324
1325 if (!bt_value_is_map(map_obj)) {
1326 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
c4628760
PP
1327 "type=%s", map_obj,
1328 bt_value_type_string(map_obj->type));
c55a9f58 1329 ret = BT_FALSE;
dac5c838
PP
1330 goto end;
1331 }
1332
1333 quark = g_quark_from_string(key);
5d5982ab 1334 ret = bt_g_hash_table_contains(typed_map_obj->ght,
dac5c838
PP
1335 GUINT_TO_POINTER(quark));
1336
1337end:
1338 return ret;
1339}
1340
1341enum bt_value_status bt_value_map_insert(struct bt_value *map_obj,
364747d6 1342 const char *key, struct bt_value *element_obj)
dac5c838
PP
1343{
1344 GQuark quark;
1345 enum bt_value_status ret = BT_VALUE_STATUS_OK;
1346 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1347
2f42aa0a
PP
1348 if (!map_obj || !key || !element_obj) {
1349 BT_LOGW("Invalid parameter: map value, key, or element value is NULL: "
1350 "map-value-addr=%p, key-addr=%p, element-value-addr=%p",
1351 map_obj, key, element_obj);
1352 ret = BT_VALUE_STATUS_INVAL;
1353 goto end;
1354 }
1355
1356 if (!bt_value_is_map(map_obj)) {
1357 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
c4628760
PP
1358 "type=%s", map_obj,
1359 bt_value_type_string(map_obj->type));
dac5c838
PP
1360 ret = BT_VALUE_STATUS_INVAL;
1361 goto end;
1362 }
1363
1364 if (map_obj->is_frozen) {
2f42aa0a
PP
1365 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1366 map_obj);
dac5c838
PP
1367 ret = BT_VALUE_STATUS_FROZEN;
1368 goto end;
1369 }
1370
1371 quark = g_quark_from_string(key);
1372 g_hash_table_insert(typed_map_obj->ght,
1373 GUINT_TO_POINTER(quark), element_obj);
83509119 1374 bt_get(element_obj);
2f42aa0a
PP
1375 BT_LOGV("Inserted value into map value: map-value-addr=%p, "
1376 "key=\"%s\", element-value-addr=%p",
1377 map_obj, key, element_obj);
dac5c838
PP
1378
1379end:
1380 return ret;
1381}
1382
1383enum bt_value_status bt_value_map_insert_bool(struct bt_value *map_obj,
c55a9f58 1384 const char *key, bt_bool val)
dac5c838
PP
1385{
1386 enum bt_value_status ret;
1387 struct bt_value *bool_obj = NULL;
1388
1389 bool_obj = bt_value_bool_create_init(val);
1390 ret = bt_value_map_insert(map_obj, key, bool_obj);
83509119 1391 bt_put(bool_obj);
dac5c838
PP
1392 return ret;
1393}
1394
1395enum bt_value_status bt_value_map_insert_integer(struct bt_value *map_obj,
364747d6 1396 const char *key, int64_t val)
dac5c838
PP
1397{
1398 enum bt_value_status ret;
1399 struct bt_value *integer_obj = NULL;
1400
1401 integer_obj = bt_value_integer_create_init(val);
1402 ret = bt_value_map_insert(map_obj, key, integer_obj);
83509119 1403 bt_put(integer_obj);
dac5c838
PP
1404 return ret;
1405}
1406
1407enum bt_value_status bt_value_map_insert_float(struct bt_value *map_obj,
364747d6 1408 const char *key, double val)
dac5c838
PP
1409{
1410 enum bt_value_status ret;
1411 struct bt_value *float_obj = NULL;
1412
1413 float_obj = bt_value_float_create_init(val);
1414 ret = bt_value_map_insert(map_obj, key, float_obj);
83509119 1415 bt_put(float_obj);
dac5c838
PP
1416 return ret;
1417}
1418
1419enum bt_value_status bt_value_map_insert_string(struct bt_value *map_obj,
364747d6 1420 const char *key, const char *val)
dac5c838
PP
1421{
1422 enum bt_value_status ret;
1423 struct bt_value *string_obj = NULL;
1424
1425 string_obj = bt_value_string_create_init(val);
1426 ret = bt_value_map_insert(map_obj, key, string_obj);
83509119 1427 bt_put(string_obj);
dac5c838
PP
1428 return ret;
1429}
1430
5b79e8bf 1431enum bt_value_status bt_value_map_insert_empty_array(struct bt_value *map_obj,
364747d6 1432 const char *key)
dac5c838
PP
1433{
1434 enum bt_value_status ret;
1435 struct bt_value *array_obj = NULL;
1436
1437 array_obj = bt_value_array_create();
1438 ret = bt_value_map_insert(map_obj, key, array_obj);
83509119 1439 bt_put(array_obj);
dac5c838
PP
1440 return ret;
1441}
1442
5b79e8bf 1443enum bt_value_status bt_value_map_insert_empty_map(struct bt_value *map_obj,
364747d6 1444 const char *key)
dac5c838
PP
1445{
1446 enum bt_value_status ret;
1447 struct bt_value *empty_map_obj = NULL;
1448
1449 empty_map_obj = bt_value_map_create();
1450 ret = bt_value_map_insert(map_obj, key, empty_map_obj);
83509119 1451 bt_put(empty_map_obj);
dac5c838
PP
1452 return ret;
1453}
1454
1455enum bt_value_status bt_value_map_foreach(const struct bt_value *map_obj,
364747d6 1456 bt_value_map_foreach_cb cb, void *data)
dac5c838
PP
1457{
1458 enum bt_value_status ret = BT_VALUE_STATUS_OK;
1459 gpointer key, element_obj;
1460 GHashTableIter iter;
1461 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1462
2f42aa0a
PP
1463 if (!map_obj || !cb) {
1464 BT_LOGW("Invalid parameter: map value or callback is NULL: "
1465 "value-addr=%p, cb-addr=%p", map_obj, cb);
1466 ret = BT_VALUE_STATUS_INVAL;
1467 goto end;
1468 }
1469
1470 if (!bt_value_is_map(map_obj)) {
1471 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
c4628760
PP
1472 "type=%s", map_obj,
1473 bt_value_type_string(map_obj->type));
dac5c838
PP
1474 ret = BT_VALUE_STATUS_INVAL;
1475 goto end;
1476 }
1477
1478 g_hash_table_iter_init(&iter, typed_map_obj->ght);
1479
1480 while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
5b44aff2 1481 const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
dac5c838
PP
1482
1483 if (!cb(key_str, element_obj, data)) {
c4628760 1484 BT_LOGV("User cancelled the loop: key=\"%s\", "
2f42aa0a
PP
1485 "value-addr=%p, data=%p",
1486 key_str, element_obj, data);
dac5c838
PP
1487 ret = BT_VALUE_STATUS_CANCELLED;
1488 break;
1489 }
1490 }
1491
1492end:
1493 return ret;
1494}
1495
770750d3
PP
1496struct extend_map_element_data {
1497 struct bt_value *extended_obj;
c55a9f58 1498 bt_bool got_error;
770750d3
PP
1499};
1500
1501static
c55a9f58 1502bt_bool extend_map_element(const char *key,
770750d3
PP
1503 struct bt_value *extension_obj_elem, void *data)
1504{
c55a9f58 1505 bt_bool ret = BT_TRUE;
770750d3
PP
1506
1507 struct extend_map_element_data *extend_data = data;
1508
1509 /* Copy object which is to replace the current one */
1510 struct bt_value *extension_obj_elem_copy =
1511 bt_value_copy(extension_obj_elem);
1512
1513 /* Replace in extended object */
1514 if (bt_value_map_insert(extend_data->extended_obj, key,
1515 extension_obj_elem_copy)) {
2f42aa0a
PP
1516 BT_LOGE("Cannot replace value in extended value: key=\"%s\", "
1517 "extended-value-addr=%p, element-value-addr=%p",
1518 key, extend_data->extended_obj,
1519 extension_obj_elem_copy);
770750d3
PP
1520 goto error;
1521 }
1522
1523 goto end;
1524
1525error:
c55a9f58
PP
1526 ret = BT_FALSE;
1527 extend_data->got_error = BT_TRUE;
770750d3
PP
1528
1529end:
1530 BT_PUT(extension_obj_elem_copy);
770750d3
PP
1531 return ret;
1532}
1533
1534struct bt_value *bt_value_map_extend(struct bt_value *base_map_obj,
1535 struct bt_value *extension_obj)
1536{
1537 struct bt_value *extended_obj = NULL;
1538 struct extend_map_element_data extend_data = { 0 };
1539
2f42aa0a
PP
1540 if (!base_map_obj || !extension_obj) {
1541 BT_LOGW("Invalid parameter: base value or extension value is NULL: "
1542 "base-value-addr=%p, extension-value-addr=%p",
1543 base_map_obj, extension_obj);
1544 goto error;
1545 }
1546
1547 if (!bt_value_is_map(base_map_obj)) {
1548 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
c4628760
PP
1549 "type=%s", base_map_obj,
1550 bt_value_type_string(base_map_obj->type));
770750d3
PP
1551 goto error;
1552 }
1553
2f42aa0a
PP
1554 if (!bt_value_is_map(extension_obj)) {
1555 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
c4628760
PP
1556 "type=%s", extension_obj,
1557 bt_value_type_string(extension_obj->type));
2f42aa0a
PP
1558 goto error;
1559 }
1560
1561 BT_LOGD("Extending map value: base-value-addr=%p, extension-value-addr=%p",
1562 base_map_obj, extension_obj);
1563
770750d3
PP
1564 /* Create copy of base map object to start with */
1565 extended_obj = bt_value_copy(base_map_obj);
1566 if (!extended_obj) {
2f42aa0a
PP
1567 BT_LOGE("Cannot copy base value: base-value-addr=%p",
1568 base_map_obj);
770750d3
PP
1569 goto error;
1570 }
1571
1572 /*
1573 * For each key in the extension map object, replace this key
1574 * in the copied map object.
1575 */
1576 extend_data.extended_obj = extended_obj;
1577
1578 if (bt_value_map_foreach(extension_obj, extend_map_element,
1579 &extend_data)) {
2f42aa0a
PP
1580 BT_LOGE("Cannot iterate on the extension object's elements: ",
1581 "extension-value-addr=%p", extension_obj);
770750d3
PP
1582 goto error;
1583 }
1584
1585 if (extend_data.got_error) {
2f42aa0a
PP
1586 BT_LOGE("Failed to successfully iterate on the extension object's elements: ",
1587 "extension-value-addr=%p", extension_obj);
770750d3
PP
1588 goto error;
1589 }
1590
2f42aa0a
PP
1591 BT_LOGD("Extended map value: extended-value-addr=%p",
1592 extended_obj);
770750d3
PP
1593 goto end;
1594
1595error:
1596 BT_PUT(extended_obj);
1597
1598end:
1599 return extended_obj;
1600}
1601
dac5c838
PP
1602struct bt_value *bt_value_copy(const struct bt_value *object)
1603{
1604 struct bt_value *copy_obj = NULL;
1605
1606 if (!object) {
2f42aa0a 1607 BT_LOGW_STR("Invalid parameter: value object is NULL.");
dac5c838
PP
1608 goto end;
1609 }
1610
2f42aa0a 1611 BT_LOGD("Copying value object: addr=%p", object);
dac5c838 1612 copy_obj = copy_funcs[object->type](object);
2f42aa0a
PP
1613 if (copy_obj) {
1614 BT_LOGD("Copied value object: copy-value-addr=%p",
1615 copy_obj);
1616 } else {
1617 BT_LOGE_STR("Failed to copy value object.");
1618 }
dac5c838
PP
1619
1620end:
1621 return copy_obj;
1622}
1623
c55a9f58 1624bt_bool bt_value_compare(const struct bt_value *object_a,
dac5c838
PP
1625 const struct bt_value *object_b)
1626{
c55a9f58 1627 bt_bool ret = BT_FALSE;
dac5c838
PP
1628
1629 if (!object_a || !object_b) {
2f42aa0a
PP
1630 BT_LOGW("Invalid parameter: value A or value B is NULL: "
1631 "value-a-addr=%p, value-b-addr=%p",
1632 object_a, object_b);
dac5c838
PP
1633 goto end;
1634 }
1635
1636 if (object_a->type != object_b->type) {
2f42aa0a
PP
1637 BT_LOGV("Values are different: type mismatch: "
1638 "value-a-addr=%p, value-b-addr=%p, "
c4628760 1639 "value-a-type=%s, value-b-type=%s",
2f42aa0a 1640 object_a, object_b,
c4628760
PP
1641 bt_value_type_string(object_a->type),
1642 bt_value_type_string(object_b->type));
dac5c838
PP
1643 goto end;
1644 }
1645
1646 ret = compare_funcs[object_a->type](object_a, object_b);
1647
1648end:
1649 return ret;
1650}
This page took 0.104915 seconds and 4 git commands to generate.