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