lib/values.c: add more verbose/debug logging
[babeltrace.git] / lib / values.c
1 /*
2 * Values.c: value objects
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
28 #define BT_LOG_TAG "VALUES"
29 #include <babeltrace/lib-logging-internal.h>
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <assert.h>
34 #include <string.h>
35 #include <inttypes.h>
36 #include <babeltrace/compiler-internal.h>
37 #include <babeltrace/ref.h>
38 #include <babeltrace/values.h>
39 #include <babeltrace/compat/glib-internal.h>
40 #include <babeltrace/types.h>
41 #include <babeltrace/object-internal.h>
42 #include <babeltrace/values-internal.h>
43
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
52 struct bt_value {
53 struct bt_object base;
54 enum bt_value_type type;
55 bt_bool is_frozen;
56 };
57
58 static
59 struct bt_value bt_value_null_instance = {
60 .base = {
61 .ref_count = {
62 .count = 1,
63 .release = NULL,
64 },
65 .release = NULL,
66 .parent = NULL,
67 },
68 .type = BT_VALUE_TYPE_NULL,
69 .is_frozen = BT_TRUE,
70 };
71
72 struct bt_value *bt_value_null = &bt_value_null_instance;
73
74 struct bt_value_bool {
75 struct bt_value base;
76 bt_bool value;
77 };
78
79 struct bt_value_integer {
80 struct bt_value base;
81 int64_t value;
82 };
83
84 struct bt_value_float {
85 struct bt_value base;
86 double value;
87 };
88
89 struct bt_value_string {
90 struct bt_value base;
91 GString *gstr;
92 };
93
94 struct bt_value_array {
95 struct bt_value base;
96 GPtrArray *garray;
97 };
98
99 struct bt_value_map {
100 struct bt_value base;
101 GHashTable *ght;
102 };
103
104 static
105 void bt_value_destroy(struct bt_object *obj);
106
107 static
108 void bt_value_string_destroy(struct bt_value *object)
109 {
110 g_string_free(BT_VALUE_TO_STRING(object)->gstr, TRUE);
111 }
112
113 static
114 void 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
123 static
124 void 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
134 static
135 void (* 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
145 static
146 struct bt_value *bt_value_null_copy(const struct bt_value *null_obj)
147 {
148 return bt_value_null;
149 }
150
151 static
152 struct 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
157 static
158 struct 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
164 static
165 struct 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
171 static
172 struct 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
178 static
179 struct 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
186 BT_LOGD("Copying array value: addr=%p", array_obj);
187 typed_array_obj = BT_VALUE_TO_ARRAY(array_obj);
188 copy_obj = bt_value_array_create();
189
190 if (!copy_obj) {
191 BT_LOGE_STR("Cannot create empty array value.");
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
199 assert(element_obj);
200 BT_LOGD("Copying array value's element: element-addr=%p, "
201 "index=%d", element_obj, i);
202 element_obj_copy = bt_value_copy(element_obj);
203 BT_PUT(element_obj);
204 if (!element_obj_copy) {
205 BT_LOGE("Cannot copy array value's element: "
206 "array-addr=%p, index=%d",
207 array_obj, i);
208 BT_PUT(copy_obj);
209 goto end;
210 }
211
212 ret = bt_value_array_append(copy_obj, element_obj_copy);
213 BT_PUT(element_obj_copy);
214 if (ret) {
215 BT_LOGE("Cannot append to array value: addr=%p",
216 array_obj);
217 BT_PUT(copy_obj);
218 goto end;
219 }
220 }
221
222 BT_LOGD("Copied array value: original-addr=%p, copy-addr=%p",
223 array_obj, copy_obj);
224
225 end:
226 return copy_obj;
227 }
228
229 static
230 struct 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
239 BT_LOGD("Copying map value: addr=%p", map_obj);
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)) {
250 const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
251
252 assert(key_str);
253 BT_LOGD("Copying map value's element: element-addr=%p, "
254 "key=\"%s\"", element_obj, key_str);
255 element_obj_copy = bt_value_copy(element_obj);
256 if (!element_obj_copy) {
257 BT_LOGE("Cannot copy map value's element: "
258 "map-addr=%p, key=\"%s\"",
259 map_obj, key_str);
260 BT_PUT(copy_obj);
261 goto end;
262 }
263
264 ret = bt_value_map_insert(copy_obj, key_str, element_obj_copy);
265 BT_PUT(element_obj_copy);
266 if (ret) {
267 BT_LOGE("Cannot insert into map value: addr=%p, key=\"%s\"",
268 map_obj, key_str);
269 BT_PUT(copy_obj);
270 goto end;
271 }
272 }
273
274 BT_LOGD("Copied map value: addr=%p", map_obj);
275
276 end:
277 return copy_obj;
278 }
279
280 static
281 struct 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
291 static
292 bt_bool bt_value_null_compare(const struct bt_value *object_a,
293 const struct bt_value *object_b)
294 {
295 /*
296 * Always BT_TRUE since bt_value_compare() already checks if both
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 */
300 return BT_TRUE;
301 }
302
303 static
304 bt_bool bt_value_bool_compare(const struct bt_value *object_a,
305 const struct bt_value *object_b)
306 {
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;
317 }
318
319 static
320 bt_bool bt_value_integer_compare(const struct bt_value *object_a,
321 const struct bt_value *object_b)
322 {
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;
333 }
334
335 static
336 bt_bool bt_value_float_compare(const struct bt_value *object_a,
337 const struct bt_value *object_b)
338 {
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;
349 }
350
351 static
352 bt_bool bt_value_string_compare(const struct bt_value *object_a,
353 const struct bt_value *object_b)
354 {
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;
365 }
366
367 static
368 bt_bool bt_value_array_compare(const struct bt_value *object_a,
369 const struct bt_value *object_b)
370 {
371 int i;
372 bt_bool ret = BT_TRUE;
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)) {
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));
383 ret = BT_FALSE;
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)) {
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);
398 BT_PUT(element_obj_a);
399 BT_PUT(element_obj_b);
400 ret = BT_FALSE;
401 goto end;
402 }
403
404 BT_PUT(element_obj_a);
405 BT_PUT(element_obj_b);
406 }
407
408 end:
409 return ret;
410 }
411
412 static
413 bt_bool bt_value_map_compare(const struct bt_value *object_a,
414 const struct bt_value *object_b)
415 {
416 bt_bool ret = BT_TRUE;
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)) {
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));
428 ret = BT_FALSE;
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;
436 const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
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)) {
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);
444 BT_PUT(element_obj_b);
445 ret = BT_FALSE;
446 goto end;
447 }
448
449 BT_PUT(element_obj_b);
450 }
451
452 end:
453 return ret;
454 }
455
456 static
457 bt_bool (* const compare_funcs[])(const struct bt_value *,
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,
462 [BT_VALUE_TYPE_FLOAT] = bt_value_float_compare,
463 [BT_VALUE_TYPE_STRING] = bt_value_string_compare,
464 [BT_VALUE_TYPE_ARRAY] = bt_value_array_compare,
465 [BT_VALUE_TYPE_MAP] = bt_value_map_compare,
466 };
467
468 void bt_value_null_freeze(struct bt_value *object)
469 {
470 }
471
472 void bt_value_generic_freeze(struct bt_value *object)
473 {
474 object->is_frozen = BT_TRUE;
475 }
476
477 void 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
493 void 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
508 static
509 void (* 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
519 static
520 void bt_value_destroy(struct bt_object *obj)
521 {
522 struct bt_value *value;
523
524 value = container_of(obj, struct bt_value, base);
525 assert(value->type != BT_VALUE_TYPE_UNKNOWN);
526 BT_LOGD("Destroying value: addr=%p", value);
527
528 if (bt_value_is_null(value)) {
529 BT_LOGD_STR("Not destroying the null value singleton.");
530 return;
531 }
532
533 if (destroy_funcs[value->type]) {
534 destroy_funcs[value->type](value);
535 }
536
537 g_free(value);
538 }
539
540 enum 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) {
545 BT_LOGW_STR("Invalid parameter: value object is NULL.");
546 ret = BT_VALUE_STATUS_INVAL;
547 goto end;
548 }
549
550 if (object->is_frozen) {
551 goto end;
552 }
553
554 BT_LOGD("Freezing value: addr=%p", object);
555 freeze_funcs[object->type](object);
556
557 end:
558 return ret;
559 }
560
561 bt_bool bt_value_is_frozen(const struct bt_value *object)
562 {
563 return object && object->is_frozen;
564 }
565
566 enum bt_value_type bt_value_get_type(const struct bt_value *object)
567 {
568 if (!object) {
569 BT_LOGW_STR("Invalid parameter: value object is NULL.");
570 return BT_VALUE_TYPE_UNKNOWN;
571 }
572
573 return object->type;
574 }
575
576 static
577 struct bt_value bt_value_create_base(enum bt_value_type type)
578 {
579 struct bt_value base;
580
581 base.type = type;
582 base.is_frozen = BT_FALSE;
583 bt_object_init(&base, bt_value_destroy);
584 return base;
585 }
586
587 struct bt_value *bt_value_bool_create_init(bt_bool val)
588 {
589 struct bt_value_bool *bool_obj;
590
591 BT_LOGD("Creating boolean value object: val=%d", val);
592 bool_obj = g_new0(struct bt_value_bool, 1);
593
594 if (!bool_obj) {
595 BT_LOGE_STR("Failed to allocate one boolean value object.");
596 goto end;
597 }
598
599 bool_obj->base = bt_value_create_base(BT_VALUE_TYPE_BOOL);
600 bool_obj->value = val;
601 BT_LOGD("Created boolean value object: addr=%p", bool_obj);
602
603 end:
604 return BT_VALUE_FROM_CONCRETE(bool_obj);
605 }
606
607 struct bt_value *bt_value_bool_create(void)
608 {
609 return bt_value_bool_create_init(BT_FALSE);
610 }
611
612 struct bt_value *bt_value_integer_create_init(int64_t val)
613 {
614 struct bt_value_integer *integer_obj;
615
616 BT_LOGD("Creating integer value object: val=%" PRId64, val);
617 integer_obj = g_new0(struct bt_value_integer, 1);
618
619 if (!integer_obj) {
620 BT_LOGE_STR("Failed to allocate one integer value object.");
621 goto end;
622 }
623
624 integer_obj->base = bt_value_create_base(BT_VALUE_TYPE_INTEGER);
625 integer_obj->value = val;
626 BT_LOGD("Created integer value object: addr=%p",
627 integer_obj);
628
629 end:
630 return BT_VALUE_FROM_CONCRETE(integer_obj);
631 }
632
633 struct bt_value *bt_value_integer_create(void)
634 {
635 return bt_value_integer_create_init(0);
636 }
637
638 struct bt_value *bt_value_float_create_init(double val)
639 {
640 struct bt_value_float *float_obj;
641
642 BT_LOGD("Creating floating point number value object: val=%f", val);
643 float_obj = g_new0(struct bt_value_float, 1);
644
645 if (!float_obj) {
646 BT_LOGE_STR("Failed to allocate one floating point number value object.");
647 goto end;
648 }
649
650 float_obj->base = bt_value_create_base(BT_VALUE_TYPE_FLOAT);
651 float_obj->value = val;
652 BT_LOGD("Created floating point number value object: addr=%p",
653 float_obj);
654
655 end:
656 return BT_VALUE_FROM_CONCRETE(float_obj);
657 }
658
659 struct bt_value *bt_value_float_create(void)
660 {
661 return bt_value_float_create_init(0.);
662 }
663
664 struct bt_value *bt_value_string_create_init(const char *val)
665 {
666 struct bt_value_string *string_obj = NULL;
667
668 if (!val) {
669 BT_LOGW_STR("Invalid parameter: value is NULL.");
670 goto end;
671 }
672
673 BT_LOGD("Creating string value object: val-len=%u", strlen(val));
674 string_obj = g_new0(struct bt_value_string, 1);
675
676 if (!string_obj) {
677 BT_LOGE_STR("Failed to allocate one string object.");
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) {
685 BT_LOGE_STR("Failed to allocate a GString.");
686 g_free(string_obj);
687 string_obj = NULL;
688 goto end;
689 }
690
691 BT_LOGD("Created string value object: addr=%p",
692 string_obj);
693
694 end:
695 return BT_VALUE_FROM_CONCRETE(string_obj);
696 }
697
698 struct bt_value *bt_value_string_create(void)
699 {
700 return bt_value_string_create_init("");
701 }
702
703 struct bt_value *bt_value_array_create(void)
704 {
705 struct bt_value_array *array_obj;
706
707 BT_LOGD_STR("Creating empty array value object.");
708 array_obj = g_new0(struct bt_value_array, 1);
709
710 if (!array_obj) {
711 BT_LOGE_STR("Failed to allocate one array object.");
712 goto end;
713 }
714
715 array_obj->base = bt_value_create_base(BT_VALUE_TYPE_ARRAY);
716 array_obj->garray = bt_g_ptr_array_new_full(0,
717 (GDestroyNotify) bt_put);
718
719 if (!array_obj->garray) {
720 BT_LOGE_STR("Failed to allocate a GPtrArray.");
721 g_free(array_obj);
722 array_obj = NULL;
723 goto end;
724 }
725
726 BT_LOGD("Created array value object: addr=%p",
727 array_obj);
728
729 end:
730 return BT_VALUE_FROM_CONCRETE(array_obj);
731 }
732
733 struct bt_value *bt_value_map_create(void)
734 {
735 struct bt_value_map *map_obj;
736
737 BT_LOGD_STR("Creating empty map value object.");
738 map_obj = g_new0(struct bt_value_map, 1);
739
740 if (!map_obj) {
741 BT_LOGE_STR("Failed to allocate one map object.");
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,
747 NULL, (GDestroyNotify) bt_put);
748
749 if (!map_obj->ght) {
750 BT_LOGE_STR("Failed to allocate a GHashTable.");
751 g_free(map_obj);
752 map_obj = NULL;
753 goto end;
754 }
755
756 BT_LOGD("Created map value object: addr=%p",
757 map_obj);
758
759 end:
760 return BT_VALUE_FROM_CONCRETE(map_obj);
761 }
762
763 enum bt_value_status bt_value_bool_get(const struct bt_value *bool_obj,
764 bt_bool *val)
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
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, "
779 "type=%s", bool_obj, bool_obj->type,
780 bt_value_type_string(bool_obj->type));
781 ret = BT_VALUE_STATUS_INVAL;
782 goto end;
783 }
784
785 *val = typed_bool_obj->value;
786
787 end:
788 return ret;
789 }
790
791 enum bt_value_status bt_value_bool_set(struct bt_value *bool_obj, bt_bool val)
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
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, "
804 "type=%s", bool_obj,
805 bt_value_type_string(bool_obj->type));
806 ret = BT_VALUE_STATUS_INVAL;
807 goto end;
808 }
809
810 if (bool_obj->is_frozen) {
811 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
812 bool_obj);
813 ret = BT_VALUE_STATUS_FROZEN;
814 goto end;
815 }
816
817 typed_bool_obj->value = val;
818 BT_LOGV("Set boolean value's raw value: value-addr=%p, value=%d",
819 bool_obj, val);
820
821 end:
822 return ret;
823 }
824
825 enum bt_value_status bt_value_integer_get(const struct bt_value *integer_obj,
826 int64_t *val)
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
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, "
842 "type=%s", integer_obj,
843 bt_value_type_string(integer_obj->type));
844 ret = BT_VALUE_STATUS_INVAL;
845 goto end;
846 }
847
848 *val = typed_integer_obj->value;
849
850 end:
851 return ret;
852 }
853
854 enum bt_value_status bt_value_integer_set(struct bt_value *integer_obj,
855 int64_t val)
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
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, "
869 "type=%s", integer_obj,
870 bt_value_type_string(integer_obj->type));
871 ret = BT_VALUE_STATUS_INVAL;
872 goto end;
873 }
874
875 if (integer_obj->is_frozen) {
876 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
877 integer_obj);
878 ret = BT_VALUE_STATUS_FROZEN;
879 goto end;
880 }
881
882 typed_integer_obj->value = val;
883 BT_LOGV("Set integer value's raw value: value-addr=%p, value=%" PRId64,
884 integer_obj, val);
885
886 end:
887 return ret;
888 }
889
890 enum bt_value_status bt_value_float_get(const struct bt_value *float_obj,
891 double *val)
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
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, "
907 "type=%s", float_obj,
908 bt_value_type_string(float_obj->type));
909 ret = BT_VALUE_STATUS_INVAL;
910 goto end;
911 }
912
913 *val = typed_float_obj->value;
914
915 end:
916 return ret;
917 }
918
919 enum bt_value_status bt_value_float_set(struct bt_value *float_obj,
920 double val)
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
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, "
934 "type=%s", float_obj,
935 bt_value_type_string(float_obj->type));
936 ret = BT_VALUE_STATUS_INVAL;
937 goto end;
938 }
939
940 if (float_obj->is_frozen) {
941 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
942 float_obj);
943 ret = BT_VALUE_STATUS_FROZEN;
944 goto end;
945 }
946
947 typed_float_obj->value = val;
948 BT_LOGV("Set floating point number value's raw value: value-addr=%p, value=%f",
949 float_obj, val);
950
951 end:
952 return ret;
953 }
954
955 enum bt_value_status bt_value_string_get(const struct bt_value *string_obj,
956 const char **val)
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
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, "
972 "type=%s", string_obj,
973 bt_value_type_string(string_obj->type));
974 ret = BT_VALUE_STATUS_INVAL;
975 goto end;
976 }
977
978 *val = typed_string_obj->gstr->str;
979
980 end:
981 return ret;
982 }
983
984 enum bt_value_status bt_value_string_set(struct bt_value *string_obj,
985 const char *val)
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
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, "
1001 "type=%s", string_obj,
1002 bt_value_type_string(string_obj->type));
1003 ret = BT_VALUE_STATUS_INVAL;
1004 goto end;
1005 }
1006
1007 if (string_obj->is_frozen) {
1008 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1009 string_obj);
1010 ret = BT_VALUE_STATUS_FROZEN;
1011 goto end;
1012 }
1013
1014 g_string_assign(typed_string_obj->gstr, val);
1015 BT_LOGV("Set string value's raw value: value-addr=%p, raw-value-addr=%p",
1016 string_obj, val);
1017
1018 end:
1019 return ret;
1020 }
1021
1022 int64_t bt_value_array_size(const struct bt_value *array_obj)
1023 {
1024 int64_t ret;
1025 struct bt_value_array *typed_array_obj =
1026 BT_VALUE_TO_ARRAY(array_obj);
1027
1028 if (!array_obj) {
1029 BT_LOGW_STR("Invalid parameter: value object is NULL.");
1030 ret = (int64_t) BT_VALUE_STATUS_INVAL;
1031 goto end;
1032 }
1033
1034 if (!bt_value_is_array(array_obj)) {
1035 BT_LOGW("Invalid parameter: value is not an array value: addr=%p, "
1036 "type=%s", array_obj,
1037 bt_value_type_string(array_obj->type));
1038 ret = BT_VALUE_STATUS_INVAL;
1039 goto end;
1040 }
1041
1042 ret = (int64_t) typed_array_obj->garray->len;
1043
1044 end:
1045 return ret;
1046 }
1047
1048 bt_bool bt_value_array_is_empty(const struct bt_value *array_obj)
1049 {
1050 return bt_value_array_size(array_obj) == 0;
1051 }
1052
1053 struct bt_value *bt_value_array_get(const struct bt_value *array_obj,
1054 uint64_t index)
1055 {
1056 struct bt_value *ret;
1057 struct bt_value_array *typed_array_obj =
1058 BT_VALUE_TO_ARRAY(array_obj);
1059
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, "
1069 "type=%s", array_obj,
1070 bt_value_type_string(array_obj->type));
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: "
1077 "addr=%p, index=%" PRIu64 ", size=%u",
1078 array_obj, index, typed_array_obj->garray->len);
1079 ret = NULL;
1080 goto end;
1081 }
1082
1083 ret = g_ptr_array_index(typed_array_obj->garray, index);
1084 bt_get(ret);
1085
1086 end:
1087 return ret;
1088 }
1089
1090 enum bt_value_status bt_value_array_append(struct bt_value *array_obj,
1091 struct bt_value *element_obj)
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
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, "
1107 "type=%s", array_obj,
1108 bt_value_type_string(array_obj->type));
1109 ret = BT_VALUE_STATUS_INVAL;
1110 goto end;
1111 }
1112
1113 if (array_obj->is_frozen) {
1114 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1115 array_obj);
1116 ret = BT_VALUE_STATUS_FROZEN;
1117 goto end;
1118 }
1119
1120 g_ptr_array_add(typed_array_obj->garray, element_obj);
1121 bt_get(element_obj);
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);
1125
1126 end:
1127 return ret;
1128 }
1129
1130 enum bt_value_status bt_value_array_append_bool(struct bt_value *array_obj,
1131 bt_bool val)
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);
1138 bt_put(bool_obj);
1139 return ret;
1140 }
1141
1142 enum bt_value_status bt_value_array_append_integer(
1143 struct bt_value *array_obj, int64_t val)
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);
1150 bt_put(integer_obj);
1151 return ret;
1152 }
1153
1154 enum bt_value_status bt_value_array_append_float(struct bt_value *array_obj,
1155 double val)
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);
1162 bt_put(float_obj);
1163 return ret;
1164 }
1165
1166 enum bt_value_status bt_value_array_append_string(struct bt_value *array_obj,
1167 const char *val)
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);
1174 bt_put(string_obj);
1175 return ret;
1176 }
1177
1178 enum bt_value_status bt_value_array_append_empty_array(
1179 struct bt_value *array_obj)
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);
1186 bt_put(empty_array_obj);
1187 return ret;
1188 }
1189
1190 enum bt_value_status bt_value_array_append_empty_map(struct bt_value *array_obj)
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);
1197 bt_put(map_obj);
1198 return ret;
1199 }
1200
1201 enum bt_value_status bt_value_array_set(struct bt_value *array_obj,
1202 uint64_t index, struct bt_value *element_obj)
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
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, "
1218 "type=%s", array_obj,
1219 bt_value_type_string(array_obj->type));
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: "
1226 "addr=%p, index=%" PRIu64 ", size=%u",
1227 array_obj, index, typed_array_obj->garray->len);
1228 ret = BT_VALUE_STATUS_INVAL;
1229 goto end;
1230 }
1231
1232 if (array_obj->is_frozen) {
1233 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1234 array_obj);
1235 ret = BT_VALUE_STATUS_FROZEN;
1236 goto end;
1237 }
1238
1239 bt_put(g_ptr_array_index(typed_array_obj->garray, index));
1240 g_ptr_array_index(typed_array_obj->garray, index) = element_obj;
1241 bt_get(element_obj);
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);
1245
1246 end:
1247 return ret;
1248 }
1249
1250 int64_t bt_value_map_size(const struct bt_value *map_obj)
1251 {
1252 int64_t ret;
1253 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1254
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, "
1263 "type=%s", map_obj,
1264 bt_value_type_string(map_obj->type));
1265 ret = (int64_t) BT_VALUE_STATUS_INVAL;
1266 goto end;
1267 }
1268
1269 ret = (int64_t) g_hash_table_size(typed_map_obj->ght);
1270
1271 end:
1272 return ret;
1273 }
1274
1275 bt_bool bt_value_map_is_empty(const struct bt_value *map_obj)
1276 {
1277 return bt_value_map_size(map_obj) == 0;
1278 }
1279
1280 struct bt_value *bt_value_map_get(const struct bt_value *map_obj,
1281 const char *key)
1282 {
1283 GQuark quark;
1284 struct bt_value *ret;
1285 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1286
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, "
1296 "type=%s", map_obj,
1297 bt_value_type_string(map_obj->type));
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));
1304 if (ret) {
1305 bt_get(ret);
1306 }
1307
1308 end:
1309 return ret;
1310 }
1311
1312 bt_bool bt_value_map_has_key(const struct bt_value *map_obj, const char *key)
1313 {
1314 bt_bool ret;
1315 GQuark quark;
1316 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1317
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);
1321 ret = BT_FALSE;
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, "
1327 "type=%s", map_obj,
1328 bt_value_type_string(map_obj->type));
1329 ret = BT_FALSE;
1330 goto end;
1331 }
1332
1333 quark = g_quark_from_string(key);
1334 ret = bt_g_hash_table_contains(typed_map_obj->ght,
1335 GUINT_TO_POINTER(quark));
1336
1337 end:
1338 return ret;
1339 }
1340
1341 enum bt_value_status bt_value_map_insert(struct bt_value *map_obj,
1342 const char *key, struct bt_value *element_obj)
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
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, "
1358 "type=%s", map_obj,
1359 bt_value_type_string(map_obj->type));
1360 ret = BT_VALUE_STATUS_INVAL;
1361 goto end;
1362 }
1363
1364 if (map_obj->is_frozen) {
1365 BT_LOGW("Invalid parameter: value is frozen: addr=%p",
1366 map_obj);
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);
1374 bt_get(element_obj);
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);
1378
1379 end:
1380 return ret;
1381 }
1382
1383 enum bt_value_status bt_value_map_insert_bool(struct bt_value *map_obj,
1384 const char *key, bt_bool val)
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);
1391 bt_put(bool_obj);
1392 return ret;
1393 }
1394
1395 enum bt_value_status bt_value_map_insert_integer(struct bt_value *map_obj,
1396 const char *key, int64_t val)
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);
1403 bt_put(integer_obj);
1404 return ret;
1405 }
1406
1407 enum bt_value_status bt_value_map_insert_float(struct bt_value *map_obj,
1408 const char *key, double val)
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);
1415 bt_put(float_obj);
1416 return ret;
1417 }
1418
1419 enum bt_value_status bt_value_map_insert_string(struct bt_value *map_obj,
1420 const char *key, const char *val)
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);
1427 bt_put(string_obj);
1428 return ret;
1429 }
1430
1431 enum bt_value_status bt_value_map_insert_empty_array(struct bt_value *map_obj,
1432 const char *key)
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);
1439 bt_put(array_obj);
1440 return ret;
1441 }
1442
1443 enum bt_value_status bt_value_map_insert_empty_map(struct bt_value *map_obj,
1444 const char *key)
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);
1451 bt_put(empty_map_obj);
1452 return ret;
1453 }
1454
1455 enum bt_value_status bt_value_map_foreach(const struct bt_value *map_obj,
1456 bt_value_map_foreach_cb cb, void *data)
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
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, "
1472 "type=%s", map_obj,
1473 bt_value_type_string(map_obj->type));
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)) {
1481 const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
1482
1483 if (!cb(key_str, element_obj, data)) {
1484 BT_LOGV("User cancelled the loop: key=\"%s\", "
1485 "value-addr=%p, data=%p",
1486 key_str, element_obj, data);
1487 ret = BT_VALUE_STATUS_CANCELLED;
1488 break;
1489 }
1490 }
1491
1492 end:
1493 return ret;
1494 }
1495
1496 struct extend_map_element_data {
1497 struct bt_value *extended_obj;
1498 bt_bool got_error;
1499 };
1500
1501 static
1502 bt_bool extend_map_element(const char *key,
1503 struct bt_value *extension_obj_elem, void *data)
1504 {
1505 bt_bool ret = BT_TRUE;
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)) {
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);
1520 goto error;
1521 }
1522
1523 goto end;
1524
1525 error:
1526 ret = BT_FALSE;
1527 extend_data->got_error = BT_TRUE;
1528
1529 end:
1530 BT_PUT(extension_obj_elem_copy);
1531 return ret;
1532 }
1533
1534 struct 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
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, "
1549 "type=%s", base_map_obj,
1550 bt_value_type_string(base_map_obj->type));
1551 goto error;
1552 }
1553
1554 if (!bt_value_is_map(extension_obj)) {
1555 BT_LOGW("Invalid parameter: value is not a map value: addr=%p, "
1556 "type=%s", extension_obj,
1557 bt_value_type_string(extension_obj->type));
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
1564 /* Create copy of base map object to start with */
1565 extended_obj = bt_value_copy(base_map_obj);
1566 if (!extended_obj) {
1567 BT_LOGE("Cannot copy base value: base-value-addr=%p",
1568 base_map_obj);
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)) {
1580 BT_LOGE("Cannot iterate on the extension object's elements: ",
1581 "extension-value-addr=%p", extension_obj);
1582 goto error;
1583 }
1584
1585 if (extend_data.got_error) {
1586 BT_LOGE("Failed to successfully iterate on the extension object's elements: ",
1587 "extension-value-addr=%p", extension_obj);
1588 goto error;
1589 }
1590
1591 BT_LOGD("Extended map value: extended-value-addr=%p",
1592 extended_obj);
1593 goto end;
1594
1595 error:
1596 BT_PUT(extended_obj);
1597
1598 end:
1599 return extended_obj;
1600 }
1601
1602 struct bt_value *bt_value_copy(const struct bt_value *object)
1603 {
1604 struct bt_value *copy_obj = NULL;
1605
1606 if (!object) {
1607 BT_LOGW_STR("Invalid parameter: value object is NULL.");
1608 goto end;
1609 }
1610
1611 BT_LOGD("Copying value object: addr=%p", object);
1612 copy_obj = copy_funcs[object->type](object);
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 }
1619
1620 end:
1621 return copy_obj;
1622 }
1623
1624 bt_bool bt_value_compare(const struct bt_value *object_a,
1625 const struct bt_value *object_b)
1626 {
1627 bt_bool ret = BT_FALSE;
1628
1629 if (!object_a || !object_b) {
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);
1633 goto end;
1634 }
1635
1636 if (object_a->type != object_b->type) {
1637 BT_LOGV("Values are different: type mismatch: "
1638 "value-a-addr=%p, value-b-addr=%p, "
1639 "value-a-type=%s, value-b-type=%s",
1640 object_a, object_b,
1641 bt_value_type_string(object_a->type),
1642 bt_value_type_string(object_b->type));
1643 goto end;
1644 }
1645
1646 ret = compare_funcs[object_a->type](object_a, object_b);
1647
1648 end:
1649 return ret;
1650 }
This page took 0.064366 seconds and 5 git commands to generate.