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