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