lib: update copyrights
[babeltrace.git] / lib / value.c
CommitLineData
dac5c838 1/*
e2f7325d 2 * Copyright (c) 2015-2018 Philippe Proulx <pproulx@efficios.com>
dac5c838
PP
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
0f5e83e5 23#define BT_LOG_TAG "VALUES"
40547d22 24#include <babeltrace/lib-logging-internal.h>
0f5e83e5 25
dac5c838
PP
26#include <stdlib.h>
27#include <string.h>
dac5c838 28#include <string.h>
2f42aa0a 29#include <inttypes.h>
3d9990ac 30#include <babeltrace/compiler-internal.h>
da91b29a 31#include <babeltrace/common-internal.h>
65300d60 32#include <babeltrace/object.h>
c6bd8523
PP
33#include <babeltrace/value-const.h>
34#include <babeltrace/value.h>
3d9990ac 35#include <babeltrace/compat/glib-internal.h>
c55a9f58 36#include <babeltrace/types.h>
0f5e83e5 37#include <babeltrace/object-internal.h>
c6bd8523 38#include <babeltrace/value-internal.h>
f6ccaed9
PP
39#include <babeltrace/assert-internal.h>
40#include <babeltrace/assert-pre-internal.h>
2f42aa0a 41
dac5c838
PP
42#define BT_VALUE_FROM_CONCRETE(_concrete) ((struct bt_value *) (_concrete))
43#define BT_VALUE_TO_BOOL(_base) ((struct bt_value_bool *) (_base))
44#define BT_VALUE_TO_INTEGER(_base) ((struct bt_value_integer *) (_base))
a373bf69 45#define BT_VALUE_TO_REAL(_base) ((struct bt_value_real *) (_base))
dac5c838
PP
46#define BT_VALUE_TO_STRING(_base) ((struct bt_value_string *) (_base))
47#define BT_VALUE_TO_ARRAY(_base) ((struct bt_value_array *) (_base))
48#define BT_VALUE_TO_MAP(_base) ((struct bt_value_map *) (_base))
49
f6ccaed9 50#define BT_ASSERT_PRE_VALUE_IS_TYPE(_value, _type) \
da91b29a 51 BT_ASSERT_PRE(((struct bt_value *) (_value))->type == (_type), \
f6ccaed9 52 "Value has the wrong type ID: expected-type=%s, " \
da91b29a 53 "%![value-]+v", bt_common_value_type_string(_type), \
f6ccaed9
PP
54 (_value))
55
56#define BT_ASSERT_PRE_VALUE_HOT(_value, _name) \
da91b29a
PP
57 BT_ASSERT_PRE_HOT(((struct bt_value *) (_value)), (_name), \
58 ": %!+v", (_value))
f6ccaed9
PP
59
60#define BT_ASSERT_PRE_VALUE_INDEX_IN_BOUNDS(_index, _count) \
61 BT_ASSERT_PRE((_index) < (_count), \
62 "Index is out of bound: " \
63 "index=%" PRIu64 ", count=%u", (_index), (_count));
64
dac5c838 65struct bt_value {
83509119 66 struct bt_object base;
dac5c838 67 enum bt_value_type type;
f6ccaed9 68 bt_bool frozen;
dac5c838
PP
69};
70
3fea54f6
PP
71static
72void bt_value_null_instance_release_func(struct bt_object *obj)
73{
74 BT_LOGW("Releasing the null value singleton: addr=%p", obj);
75}
76
dac5c838
PP
77static
78struct bt_value bt_value_null_instance = {
f685129c 79 .base = {
312c056a 80 .is_shared = true,
3fea54f6
PP
81 .ref_count = 1,
82 .release_func = bt_value_null_instance_release_func,
83 .spec_release_func = NULL,
84 .parent_is_owner_listener_func = NULL,
85 .parent = NULL,
f685129c 86 },
dac5c838 87 .type = BT_VALUE_TYPE_NULL,
f6ccaed9 88 .frozen = BT_TRUE,
dac5c838
PP
89};
90
91struct bt_value *bt_value_null = &bt_value_null_instance;
92
93struct bt_value_bool {
94 struct bt_value base;
c55a9f58 95 bt_bool value;
dac5c838
PP
96};
97
98struct bt_value_integer {
99 struct bt_value base;
100 int64_t value;
101};
102
a373bf69 103struct bt_value_real {
dac5c838
PP
104 struct bt_value base;
105 double value;
106};
107
108struct bt_value_string {
109 struct bt_value base;
110 GString *gstr;
111};
112
113struct bt_value_array {
114 struct bt_value base;
115 GPtrArray *garray;
116};
117
118struct bt_value_map {
119 struct bt_value base;
120 GHashTable *ght;
121};
122
123static
83509119 124void bt_value_destroy(struct bt_object *obj);
dac5c838
PP
125
126static
127void bt_value_string_destroy(struct bt_value *object)
128{
129 g_string_free(BT_VALUE_TO_STRING(object)->gstr, TRUE);
238b7404 130 BT_VALUE_TO_STRING(object)->gstr = NULL;
dac5c838
PP
131}
132
133static
134void bt_value_array_destroy(struct bt_value *object)
135{
136 /*
137 * Pointer array's registered value destructor will take care
138 * of putting each contained object.
139 */
140 g_ptr_array_free(BT_VALUE_TO_ARRAY(object)->garray, TRUE);
238b7404 141 BT_VALUE_TO_ARRAY(object)->garray = NULL;
dac5c838
PP
142}
143
144static
145void bt_value_map_destroy(struct bt_value *object)
146{
147 /*
148 * Hash table's registered value destructor will take care of
149 * putting each contained object. Keys are GQuarks and cannot
150 * be destroyed anyway.
151 */
152 g_hash_table_destroy(BT_VALUE_TO_MAP(object)->ght);
238b7404 153 BT_VALUE_TO_MAP(object)->ght = NULL;
dac5c838
PP
154}
155
156static
157void (* const destroy_funcs[])(struct bt_value *) = {
158 [BT_VALUE_TYPE_NULL] = NULL,
159 [BT_VALUE_TYPE_BOOL] = NULL,
160 [BT_VALUE_TYPE_INTEGER] = NULL,
a373bf69 161 [BT_VALUE_TYPE_REAL] = NULL,
dac5c838
PP
162 [BT_VALUE_TYPE_STRING] = bt_value_string_destroy,
163 [BT_VALUE_TYPE_ARRAY] = bt_value_array_destroy,
164 [BT_VALUE_TYPE_MAP] = bt_value_map_destroy,
165};
166
167static
05e21286 168struct bt_value *bt_value_null_copy(const struct bt_value *null_obj)
dac5c838 169{
da91b29a 170 return (void *) bt_value_null;
dac5c838
PP
171}
172
173static
05e21286 174struct bt_value *bt_value_bool_copy(const struct bt_value *bool_obj)
dac5c838 175{
05e21286 176 return bt_value_bool_create_init(
601b0d3c 177 BT_VALUE_TO_BOOL(bool_obj)->value);
dac5c838
PP
178}
179
180static
05e21286 181struct bt_value *bt_value_integer_copy(
da91b29a 182 const struct bt_value *integer_obj)
dac5c838 183{
05e21286 184 return bt_value_integer_create_init(
dac5c838
PP
185 BT_VALUE_TO_INTEGER(integer_obj)->value);
186}
187
188static
05e21286 189struct bt_value *bt_value_real_copy(const struct bt_value *real_obj)
dac5c838 190{
05e21286 191 return bt_value_real_create_init(
a373bf69 192 BT_VALUE_TO_REAL(real_obj)->value);
dac5c838
PP
193}
194
195static
05e21286 196struct bt_value *bt_value_string_copy(const struct bt_value *string_obj)
dac5c838 197{
05e21286 198 return bt_value_string_create_init(
dac5c838
PP
199 BT_VALUE_TO_STRING(string_obj)->gstr->str);
200}
201
202static
05e21286 203struct bt_value *bt_value_array_copy(const struct bt_value *array_obj)
dac5c838
PP
204{
205 int i;
206 int ret;
05e21286 207 struct bt_value *copy_obj;
dac5c838
PP
208 struct bt_value_array *typed_array_obj;
209
2f42aa0a 210 BT_LOGD("Copying array value: addr=%p", array_obj);
dac5c838 211 typed_array_obj = BT_VALUE_TO_ARRAY(array_obj);
05e21286 212 copy_obj = bt_value_array_create();
dac5c838 213 if (!copy_obj) {
2f42aa0a 214 BT_LOGE_STR("Cannot create empty array value.");
dac5c838
PP
215 goto end;
216 }
217
218 for (i = 0; i < typed_array_obj->garray->len; ++i) {
05e21286
PP
219 struct bt_value *element_obj_copy = NULL;
220 const struct bt_value *element_obj =
221 bt_value_array_borrow_element_by_index_const(
601b0d3c 222 array_obj, i);
dac5c838 223
f6ccaed9 224 BT_ASSERT(element_obj);
40b59ed9
PP
225 BT_LOGD("Copying array value's element: element-addr=%p, "
226 "index=%d", element_obj, i);
6be5a99e 227 ret = bt_value_copy(element_obj, &element_obj_copy);
601b0d3c 228 if (ret) {
2f42aa0a
PP
229 BT_LOGE("Cannot copy array value's element: "
230 "array-addr=%p, index=%d",
231 array_obj, i);
65300d60 232 BT_OBJECT_PUT_REF_AND_RESET(copy_obj);
dac5c838
PP
233 goto end;
234 }
235
601b0d3c 236 BT_ASSERT(element_obj_copy);
05e21286 237 ret = bt_value_array_append_element(copy_obj,
da91b29a 238 (void *) element_obj_copy);
65300d60 239 BT_OBJECT_PUT_REF_AND_RESET(element_obj_copy);
dac5c838 240 if (ret) {
2f42aa0a
PP
241 BT_LOGE("Cannot append to array value: addr=%p",
242 array_obj);
65300d60 243 BT_OBJECT_PUT_REF_AND_RESET(copy_obj);
dac5c838
PP
244 goto end;
245 }
246 }
247
a704fb0b
PP
248 BT_LOGD("Copied array value: original-addr=%p, copy-addr=%p",
249 array_obj, copy_obj);
2f42aa0a 250
dac5c838
PP
251end:
252 return copy_obj;
253}
254
255static
05e21286 256struct bt_value *bt_value_map_copy(const struct bt_value *map_obj)
dac5c838
PP
257{
258 int ret;
259 GHashTableIter iter;
260 gpointer key, element_obj;
05e21286
PP
261 struct bt_value *copy_obj;
262 struct bt_value *element_obj_copy = NULL;
dac5c838
PP
263 struct bt_value_map *typed_map_obj;
264
2f42aa0a 265 BT_LOGD("Copying map value: addr=%p", map_obj);
dac5c838 266 typed_map_obj = BT_VALUE_TO_MAP(map_obj);
05e21286 267 copy_obj = bt_value_map_create();
dac5c838
PP
268 if (!copy_obj) {
269 goto end;
270 }
271
272 g_hash_table_iter_init(&iter, typed_map_obj->ght);
273
274 while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
5b44aff2 275 const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
dac5c838 276
f6ccaed9 277 BT_ASSERT(key_str);
40b59ed9
PP
278 BT_LOGD("Copying map value's element: element-addr=%p, "
279 "key=\"%s\"", element_obj, key_str);
6be5a99e 280 ret = bt_value_copy(element_obj, &element_obj_copy);
601b0d3c 281 if (ret) {
2f42aa0a
PP
282 BT_LOGE("Cannot copy map value's element: "
283 "map-addr=%p, key=\"%s\"",
284 map_obj, key_str);
65300d60 285 BT_OBJECT_PUT_REF_AND_RESET(copy_obj);
dac5c838
PP
286 goto end;
287 }
288
601b0d3c 289 BT_ASSERT(element_obj_copy);
05e21286 290 ret = bt_value_map_insert_entry(copy_obj, key_str,
da91b29a 291 (void *) element_obj_copy);
65300d60 292 BT_OBJECT_PUT_REF_AND_RESET(element_obj_copy);
dac5c838 293 if (ret) {
2f42aa0a
PP
294 BT_LOGE("Cannot insert into map value: addr=%p, key=\"%s\"",
295 map_obj, key_str);
65300d60 296 BT_OBJECT_PUT_REF_AND_RESET(copy_obj);
dac5c838
PP
297 goto end;
298 }
299 }
300
2f42aa0a
PP
301 BT_LOGD("Copied map value: addr=%p", map_obj);
302
dac5c838
PP
303end:
304 return copy_obj;
305}
306
307static
05e21286 308struct bt_value *(* const copy_funcs[])(const struct bt_value *) = {
dac5c838
PP
309 [BT_VALUE_TYPE_NULL] = bt_value_null_copy,
310 [BT_VALUE_TYPE_BOOL] = bt_value_bool_copy,
311 [BT_VALUE_TYPE_INTEGER] = bt_value_integer_copy,
a373bf69 312 [BT_VALUE_TYPE_REAL] = bt_value_real_copy,
dac5c838
PP
313 [BT_VALUE_TYPE_STRING] = bt_value_string_copy,
314 [BT_VALUE_TYPE_ARRAY] = bt_value_array_copy,
315 [BT_VALUE_TYPE_MAP] = bt_value_map_copy,
316};
317
318static
c55a9f58 319bt_bool bt_value_null_compare(const struct bt_value *object_a,
dac5c838
PP
320 const struct bt_value *object_b)
321{
322 /*
c55a9f58 323 * Always BT_TRUE since bt_value_compare() already checks if both
dac5c838
PP
324 * object_a and object_b have the same type, and in the case of
325 * null value objects, they're always the same if it is so.
326 */
c55a9f58 327 return BT_TRUE;
dac5c838
PP
328}
329
330static
c55a9f58 331bt_bool bt_value_bool_compare(const struct bt_value *object_a,
dac5c838
PP
332 const struct bt_value *object_b)
333{
40b59ed9
PP
334 if (BT_VALUE_TO_BOOL(object_a)->value !=
335 BT_VALUE_TO_BOOL(object_b)->value) {
336 BT_LOGV("Boolean value objects are different: "
337 "bool-a-val=%d, bool-b-val=%d",
338 BT_VALUE_TO_BOOL(object_a)->value,
339 BT_VALUE_TO_BOOL(object_b)->value);
340 return BT_FALSE;
341 }
342
343 return BT_TRUE;
dac5c838
PP
344}
345
346static
c55a9f58 347bt_bool bt_value_integer_compare(const struct bt_value *object_a,
dac5c838
PP
348 const struct bt_value *object_b)
349{
40b59ed9
PP
350 if (BT_VALUE_TO_INTEGER(object_a)->value !=
351 BT_VALUE_TO_INTEGER(object_b)->value) {
352 BT_LOGV("Integer value objects are different: "
353 "int-a-val=%" PRId64 ", int-b-val=%" PRId64,
354 BT_VALUE_TO_INTEGER(object_a)->value,
355 BT_VALUE_TO_INTEGER(object_b)->value);
356 return BT_FALSE;
357 }
358
359 return BT_TRUE;
dac5c838
PP
360}
361
362static
a373bf69 363bt_bool bt_value_real_compare(const struct bt_value *object_a,
dac5c838
PP
364 const struct bt_value *object_b)
365{
a373bf69
PP
366 if (BT_VALUE_TO_REAL(object_a)->value !=
367 BT_VALUE_TO_REAL(object_b)->value) {
368 BT_LOGV("Real number value objects are different: "
369 "real-a-val=%f, real-b-val=%f",
370 BT_VALUE_TO_REAL(object_a)->value,
371 BT_VALUE_TO_REAL(object_b)->value);
40b59ed9
PP
372 return BT_FALSE;
373 }
374
375 return BT_TRUE;
dac5c838
PP
376}
377
378static
c55a9f58 379bt_bool bt_value_string_compare(const struct bt_value *object_a,
dac5c838
PP
380 const struct bt_value *object_b)
381{
40b59ed9
PP
382 if (strcmp(BT_VALUE_TO_STRING(object_a)->gstr->str,
383 BT_VALUE_TO_STRING(object_b)->gstr->str) != 0) {
384 BT_LOGV("String value objects are different: "
385 "string-a-val=\"%s\", string-b-val=\"%s\"",
386 BT_VALUE_TO_STRING(object_a)->gstr->str,
387 BT_VALUE_TO_STRING(object_b)->gstr->str);
388 return BT_FALSE;
389 }
390
391 return BT_TRUE;
dac5c838
PP
392}
393
394static
c55a9f58 395bt_bool bt_value_array_compare(const struct bt_value *object_a,
dac5c838
PP
396 const struct bt_value *object_b)
397{
398 int i;
c55a9f58 399 bt_bool ret = BT_TRUE;
dac5c838
PP
400 const struct bt_value_array *array_obj_a =
401 BT_VALUE_TO_ARRAY(object_a);
402
da91b29a
PP
403 if (bt_value_array_get_size(object_a) !=
404 bt_value_array_get_size(object_b)) {
2f42aa0a
PP
405 BT_LOGV("Array values are different: size mismatch "
406 "value-a-addr=%p, value-b-addr=%p, "
407 "value-a-size=%" PRId64 ", value-b-size=%" PRId64,
408 object_a, object_b,
07208d85
PP
409 bt_value_array_get_size(object_a),
410 bt_value_array_get_size(object_b));
c55a9f58 411 ret = BT_FALSE;
dac5c838
PP
412 goto end;
413 }
414
415 for (i = 0; i < array_obj_a->garray->len; ++i) {
05e21286
PP
416 const struct bt_value *element_obj_a;
417 const struct bt_value *element_obj_b;
dac5c838 418
05e21286 419 element_obj_a = bt_value_array_borrow_element_by_index_const(
da91b29a 420 object_a, i);
05e21286 421 element_obj_b = bt_value_array_borrow_element_by_index_const(
da91b29a 422 object_b, i);
dac5c838
PP
423
424 if (!bt_value_compare(element_obj_a, element_obj_b)) {
2f42aa0a
PP
425 BT_LOGV("Array values's elements are different: "
426 "value-a-addr=%p, value-b-addr=%p, index=%d",
32e87ceb 427 element_obj_a, element_obj_b, i);
c55a9f58 428 ret = BT_FALSE;
dac5c838
PP
429 goto end;
430 }
dac5c838
PP
431 }
432
433end:
434 return ret;
435}
436
437static
c55a9f58 438bt_bool bt_value_map_compare(const struct bt_value *object_a,
dac5c838
PP
439 const struct bt_value *object_b)
440{
c55a9f58 441 bt_bool ret = BT_TRUE;
dac5c838
PP
442 GHashTableIter iter;
443 gpointer key, element_obj_a;
444 const struct bt_value_map *map_obj_a = BT_VALUE_TO_MAP(object_a);
445
601b0d3c
PP
446 if (bt_value_map_get_size(object_a) !=
447 bt_value_map_get_size(object_b)) {
2f42aa0a
PP
448 BT_LOGV("Map values are different: size mismatch "
449 "value-a-addr=%p, value-b-addr=%p, "
450 "value-a-size=%" PRId64 ", value-b-size=%" PRId64,
451 object_a, object_b,
07208d85
PP
452 bt_value_map_get_size(object_a),
453 bt_value_map_get_size(object_b));
c55a9f58 454 ret = BT_FALSE;
dac5c838
PP
455 goto end;
456 }
457
458 g_hash_table_iter_init(&iter, map_obj_a->ght);
459
460 while (g_hash_table_iter_next(&iter, &key, &element_obj_a)) {
05e21286 461 const struct bt_value *element_obj_b;
5b44aff2 462 const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
dac5c838 463
05e21286 464 element_obj_b = bt_value_map_borrow_entry_value_const(object_b,
da91b29a 465 key_str);
dac5c838
PP
466
467 if (!bt_value_compare(element_obj_a, element_obj_b)) {
2f42aa0a
PP
468 BT_LOGV("Map values's elements are different: "
469 "value-a-addr=%p, value-b-addr=%p, key=\"%s\"",
470 element_obj_a, element_obj_b, key_str);
c55a9f58 471 ret = BT_FALSE;
dac5c838
PP
472 goto end;
473 }
dac5c838
PP
474 }
475
476end:
477 return ret;
478}
479
480static
c55a9f58 481bt_bool (* const compare_funcs[])(const struct bt_value *,
dac5c838
PP
482 const struct bt_value *) = {
483 [BT_VALUE_TYPE_NULL] = bt_value_null_compare,
484 [BT_VALUE_TYPE_BOOL] = bt_value_bool_compare,
485 [BT_VALUE_TYPE_INTEGER] = bt_value_integer_compare,
a373bf69 486 [BT_VALUE_TYPE_REAL] = bt_value_real_compare,
dac5c838 487 [BT_VALUE_TYPE_STRING] = bt_value_string_compare,
40b59ed9 488 [BT_VALUE_TYPE_ARRAY] = bt_value_array_compare,
dac5c838
PP
489 [BT_VALUE_TYPE_MAP] = bt_value_map_compare,
490};
491
f6ccaed9 492static
dac5c838
PP
493void bt_value_null_freeze(struct bt_value *object)
494{
495}
496
f6ccaed9 497static
dac5c838
PP
498void bt_value_generic_freeze(struct bt_value *object)
499{
f6ccaed9 500 object->frozen = BT_TRUE;
dac5c838
PP
501}
502
f6ccaed9 503static
dac5c838
PP
504void bt_value_array_freeze(struct bt_value *object)
505{
506 int i;
507 struct bt_value_array *typed_array_obj =
508 BT_VALUE_TO_ARRAY(object);
509
510 for (i = 0; i < typed_array_obj->garray->len; ++i) {
f6ccaed9 511 bt_value_freeze(g_ptr_array_index(typed_array_obj->garray, i));
dac5c838
PP
512 }
513
514 bt_value_generic_freeze(object);
515}
516
f6ccaed9 517static
dac5c838
PP
518void bt_value_map_freeze(struct bt_value *object)
519{
520 GHashTableIter iter;
521 gpointer key, element_obj;
522 const struct bt_value_map *map_obj = BT_VALUE_TO_MAP(object);
523
524 g_hash_table_iter_init(&iter, map_obj->ght);
525
526 while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
527 bt_value_freeze(element_obj);
528 }
529
530 bt_value_generic_freeze(object);
531}
532
533static
534void (* const freeze_funcs[])(struct bt_value *) = {
535 [BT_VALUE_TYPE_NULL] = bt_value_null_freeze,
536 [BT_VALUE_TYPE_BOOL] = bt_value_generic_freeze,
537 [BT_VALUE_TYPE_INTEGER] = bt_value_generic_freeze,
a373bf69 538 [BT_VALUE_TYPE_REAL] = bt_value_generic_freeze,
dac5c838
PP
539 [BT_VALUE_TYPE_STRING] = bt_value_generic_freeze,
540 [BT_VALUE_TYPE_ARRAY] = bt_value_array_freeze,
541 [BT_VALUE_TYPE_MAP] = bt_value_map_freeze,
542};
543
544static
83509119 545void bt_value_destroy(struct bt_object *obj)
dac5c838 546{
83509119 547 struct bt_value *value;
dac5c838 548
83509119 549 value = container_of(obj, struct bt_value, base);
2f42aa0a
PP
550 BT_LOGD("Destroying value: addr=%p", value);
551
83509119 552 if (bt_value_is_null(value)) {
2f42aa0a 553 BT_LOGD_STR("Not destroying the null value singleton.");
dac5c838
PP
554 return;
555 }
556
83509119
JG
557 if (destroy_funcs[value->type]) {
558 destroy_funcs[value->type](value);
dac5c838
PP
559 }
560
83509119 561 g_free(value);
dac5c838
PP
562}
563
f6ccaed9 564BT_HIDDEN
05e21286 565enum bt_value_status _bt_value_freeze(const struct bt_value *c_object)
dac5c838 566{
05e21286 567 const struct bt_value *object = (void *) c_object;
dac5c838
PP
568 enum bt_value_status ret = BT_VALUE_STATUS_OK;
569
f6ccaed9 570 BT_ASSERT(object);
dac5c838 571
f6ccaed9 572 if (object->frozen) {
2f42aa0a
PP
573 goto end;
574 }
575
576 BT_LOGD("Freezing value: addr=%p", object);
05e21286 577 freeze_funcs[object->type]((void *) object);
dac5c838
PP
578
579end:
580 return ret;
581}
582
dac5c838
PP
583enum bt_value_type bt_value_get_type(const struct bt_value *object)
584{
f6ccaed9 585 BT_ASSERT_PRE_NON_NULL(object, "Value object");
dac5c838
PP
586 return object->type;
587}
588
589static
590struct bt_value bt_value_create_base(enum bt_value_type type)
591{
3fea54f6 592 struct bt_value value;
dac5c838 593
3fea54f6
PP
594 value.type = type;
595 value.frozen = BT_FALSE;
596 bt_object_init_shared(&value.base, bt_value_destroy);
597 return value;
dac5c838
PP
598}
599
05e21286 600struct bt_value *bt_value_bool_create_init(bt_bool val)
dac5c838
PP
601{
602 struct bt_value_bool *bool_obj;
603
2f42aa0a 604 BT_LOGD("Creating boolean value object: val=%d", val);
dac5c838 605 bool_obj = g_new0(struct bt_value_bool, 1);
dac5c838 606 if (!bool_obj) {
2f42aa0a 607 BT_LOGE_STR("Failed to allocate one boolean value object.");
dac5c838
PP
608 goto end;
609 }
610
611 bool_obj->base = bt_value_create_base(BT_VALUE_TYPE_BOOL);
612 bool_obj->value = val;
2f42aa0a 613 BT_LOGD("Created boolean value object: addr=%p", bool_obj);
dac5c838
PP
614
615end:
da91b29a 616 return (void *) BT_VALUE_FROM_CONCRETE(bool_obj);
dac5c838
PP
617}
618
05e21286 619struct bt_value *bt_value_bool_create(void)
dac5c838 620{
05e21286 621 return bt_value_bool_create_init(BT_FALSE);
dac5c838
PP
622}
623
05e21286 624struct bt_value *bt_value_integer_create_init(int64_t val)
dac5c838
PP
625{
626 struct bt_value_integer *integer_obj;
627
2f42aa0a 628 BT_LOGD("Creating integer value object: val=%" PRId64, val);
dac5c838 629 integer_obj = g_new0(struct bt_value_integer, 1);
dac5c838 630 if (!integer_obj) {
2f42aa0a 631 BT_LOGE_STR("Failed to allocate one integer value object.");
dac5c838
PP
632 goto end;
633 }
634
635 integer_obj->base = bt_value_create_base(BT_VALUE_TYPE_INTEGER);
636 integer_obj->value = val;
2f42aa0a
PP
637 BT_LOGD("Created integer value object: addr=%p",
638 integer_obj);
dac5c838
PP
639
640end:
da91b29a 641 return (void *) BT_VALUE_FROM_CONCRETE(integer_obj);
dac5c838
PP
642}
643
05e21286 644struct bt_value *bt_value_integer_create(void)
dac5c838 645{
05e21286 646 return bt_value_integer_create_init(0);
dac5c838
PP
647}
648
05e21286 649struct bt_value *bt_value_real_create_init(double val)
dac5c838 650{
a373bf69 651 struct bt_value_real *real_obj;
dac5c838 652
a373bf69
PP
653 BT_LOGD("Creating real number value object: val=%f", val);
654 real_obj = g_new0(struct bt_value_real, 1);
655 if (!real_obj) {
656 BT_LOGE_STR("Failed to allocate one real number value object.");
dac5c838
PP
657 goto end;
658 }
659
a373bf69
PP
660 real_obj->base = bt_value_create_base(BT_VALUE_TYPE_REAL);
661 real_obj->value = val;
662 BT_LOGD("Created real number value object: addr=%p",
663 real_obj);
dac5c838
PP
664
665end:
da91b29a 666 return (void *) BT_VALUE_FROM_CONCRETE(real_obj);
dac5c838
PP
667}
668
05e21286 669struct bt_value *bt_value_real_create(void)
dac5c838 670{
05e21286 671 return bt_value_real_create_init(0.);
dac5c838
PP
672}
673
05e21286 674struct bt_value *bt_value_string_create_init(const char *val)
dac5c838
PP
675{
676 struct bt_value_string *string_obj = NULL;
677
678 if (!val) {
2f42aa0a 679 BT_LOGW_STR("Invalid parameter: value is NULL.");
dac5c838
PP
680 goto end;
681 }
682
003c7749 683 BT_LOGD("Creating string value object: val-len=%zu", strlen(val));
dac5c838 684 string_obj = g_new0(struct bt_value_string, 1);
dac5c838 685 if (!string_obj) {
2f42aa0a 686 BT_LOGE_STR("Failed to allocate one string object.");
dac5c838
PP
687 goto end;
688 }
689
690 string_obj->base = bt_value_create_base(BT_VALUE_TYPE_STRING);
691 string_obj->gstr = g_string_new(val);
dac5c838 692 if (!string_obj->gstr) {
2f42aa0a 693 BT_LOGE_STR("Failed to allocate a GString.");
dac5c838
PP
694 g_free(string_obj);
695 string_obj = NULL;
696 goto end;
697 }
698
2f42aa0a
PP
699 BT_LOGD("Created string value object: addr=%p",
700 string_obj);
701
dac5c838 702end:
da91b29a 703 return (void *) BT_VALUE_FROM_CONCRETE(string_obj);
dac5c838
PP
704}
705
05e21286 706struct bt_value *bt_value_string_create(void)
dac5c838 707{
05e21286 708 return bt_value_string_create_init("");
dac5c838
PP
709}
710
05e21286 711struct bt_value *bt_value_array_create(void)
dac5c838
PP
712{
713 struct bt_value_array *array_obj;
714
2f42aa0a 715 BT_LOGD_STR("Creating empty array value object.");
dac5c838 716 array_obj = g_new0(struct bt_value_array, 1);
dac5c838 717 if (!array_obj) {
2f42aa0a 718 BT_LOGE_STR("Failed to allocate one array object.");
dac5c838
PP
719 goto end;
720 }
721
722 array_obj->base = bt_value_create_base(BT_VALUE_TYPE_ARRAY);
5d5982ab 723 array_obj->garray = bt_g_ptr_array_new_full(0,
65300d60 724 (GDestroyNotify) bt_object_put_ref);
dac5c838 725 if (!array_obj->garray) {
2f42aa0a 726 BT_LOGE_STR("Failed to allocate a GPtrArray.");
dac5c838
PP
727 g_free(array_obj);
728 array_obj = NULL;
729 goto end;
730 }
731
2f42aa0a
PP
732 BT_LOGD("Created array value object: addr=%p",
733 array_obj);
734
dac5c838 735end:
da91b29a 736 return (void *) BT_VALUE_FROM_CONCRETE(array_obj);
dac5c838
PP
737}
738
05e21286 739struct bt_value *bt_value_map_create(void)
dac5c838
PP
740{
741 struct bt_value_map *map_obj;
742
2f42aa0a 743 BT_LOGD_STR("Creating empty map value object.");
dac5c838 744 map_obj = g_new0(struct bt_value_map, 1);
dac5c838 745 if (!map_obj) {
2f42aa0a 746 BT_LOGE_STR("Failed to allocate one map object.");
dac5c838
PP
747 goto end;
748 }
749
750 map_obj->base = bt_value_create_base(BT_VALUE_TYPE_MAP);
751 map_obj->ght = g_hash_table_new_full(g_direct_hash, g_direct_equal,
65300d60 752 NULL, (GDestroyNotify) bt_object_put_ref);
dac5c838 753 if (!map_obj->ght) {
2f42aa0a 754 BT_LOGE_STR("Failed to allocate a GHashTable.");
dac5c838
PP
755 g_free(map_obj);
756 map_obj = NULL;
757 goto end;
758 }
759
2f42aa0a
PP
760 BT_LOGD("Created map value object: addr=%p",
761 map_obj);
762
dac5c838 763end:
da91b29a 764 return (void *) BT_VALUE_FROM_CONCRETE(map_obj);
dac5c838
PP
765}
766
601b0d3c 767bt_bool bt_value_bool_get(const struct bt_value *bool_obj)
dac5c838 768{
f6ccaed9 769 BT_ASSERT_PRE_NON_NULL(bool_obj, "Value object");
f6ccaed9 770 BT_ASSERT_PRE_VALUE_IS_TYPE(bool_obj, BT_VALUE_TYPE_BOOL);
601b0d3c 771 return BT_VALUE_TO_BOOL(bool_obj)->value;
dac5c838
PP
772}
773
05e21286 774void bt_value_bool_set(struct bt_value *bool_obj, bt_bool val)
dac5c838 775{
f6ccaed9
PP
776 BT_ASSERT_PRE_NON_NULL(bool_obj, "Value object");
777 BT_ASSERT_PRE_VALUE_IS_TYPE(bool_obj, BT_VALUE_TYPE_BOOL);
778 BT_ASSERT_PRE_VALUE_HOT(bool_obj, "Value object");
779 BT_VALUE_TO_BOOL(bool_obj)->value = val;
2f42aa0a
PP
780 BT_LOGV("Set boolean value's raw value: value-addr=%p, value=%d",
781 bool_obj, val);
dac5c838
PP
782}
783
601b0d3c 784int64_t bt_value_integer_get(const struct bt_value *integer_obj)
dac5c838 785{
f6ccaed9 786 BT_ASSERT_PRE_NON_NULL(integer_obj, "Value object");
f6ccaed9 787 BT_ASSERT_PRE_VALUE_IS_TYPE(integer_obj, BT_VALUE_TYPE_INTEGER);
601b0d3c 788 return BT_VALUE_TO_INTEGER(integer_obj)->value;
dac5c838
PP
789}
790
05e21286 791void bt_value_integer_set(struct bt_value *integer_obj,
364747d6 792 int64_t val)
dac5c838 793{
f6ccaed9
PP
794 BT_ASSERT_PRE_NON_NULL(integer_obj, "Value object");
795 BT_ASSERT_PRE_VALUE_IS_TYPE(integer_obj, BT_VALUE_TYPE_INTEGER);
796 BT_ASSERT_PRE_VALUE_HOT(integer_obj, "Value object");
797 BT_VALUE_TO_INTEGER(integer_obj)->value = val;
2f42aa0a
PP
798 BT_LOGV("Set integer value's raw value: value-addr=%p, value=%" PRId64,
799 integer_obj, val);
dac5c838
PP
800}
801
601b0d3c 802double bt_value_real_get(const struct bt_value *real_obj)
dac5c838 803{
a373bf69 804 BT_ASSERT_PRE_NON_NULL(real_obj, "Value object");
a373bf69 805 BT_ASSERT_PRE_VALUE_IS_TYPE(real_obj, BT_VALUE_TYPE_REAL);
601b0d3c 806 return BT_VALUE_TO_REAL(real_obj)->value;
dac5c838
PP
807}
808
05e21286 809void bt_value_real_set(struct bt_value *real_obj, double val)
dac5c838 810{
a373bf69
PP
811 BT_ASSERT_PRE_NON_NULL(real_obj, "Value object");
812 BT_ASSERT_PRE_VALUE_IS_TYPE(real_obj, BT_VALUE_TYPE_REAL);
813 BT_ASSERT_PRE_VALUE_HOT(real_obj, "Value object");
814 BT_VALUE_TO_REAL(real_obj)->value = val;
815 BT_LOGV("Set real number value's raw value: value-addr=%p, value=%f",
816 real_obj, val);
dac5c838
PP
817}
818
601b0d3c 819const char *bt_value_string_get(const struct bt_value *string_obj)
dac5c838 820{
f6ccaed9 821 BT_ASSERT_PRE_NON_NULL(string_obj, "Value object");
f6ccaed9 822 BT_ASSERT_PRE_VALUE_IS_TYPE(string_obj, BT_VALUE_TYPE_STRING);
601b0d3c 823 return BT_VALUE_TO_STRING(string_obj)->gstr->str;
dac5c838
PP
824}
825
05e21286
PP
826enum bt_value_status bt_value_string_set(
827 struct bt_value *string_obj, const char *val)
dac5c838 828{
f6ccaed9 829 BT_ASSERT_PRE_NON_NULL(string_obj, "Value object");
f6ccaed9
PP
830 BT_ASSERT_PRE_VALUE_IS_TYPE(string_obj, BT_VALUE_TYPE_STRING);
831 BT_ASSERT_PRE_VALUE_HOT(string_obj, "Value object");
832 g_string_assign(BT_VALUE_TO_STRING(string_obj)->gstr, val);
2f42aa0a
PP
833 BT_LOGV("Set string value's raw value: value-addr=%p, raw-value-addr=%p",
834 string_obj, val);
f6ccaed9 835 return BT_VALUE_STATUS_OK;
dac5c838
PP
836}
837
601b0d3c 838uint64_t bt_value_array_get_size(const struct bt_value *array_obj)
dac5c838 839{
f6ccaed9
PP
840 BT_ASSERT_PRE_NON_NULL(array_obj, "Value object");
841 BT_ASSERT_PRE_VALUE_IS_TYPE(array_obj, BT_VALUE_TYPE_ARRAY);
601b0d3c 842 return (uint64_t) BT_VALUE_TO_ARRAY(array_obj)->garray->len;
dac5c838
PP
843}
844
da91b29a 845struct bt_value *bt_value_array_borrow_element_by_index(
05e21286 846 struct bt_value *array_obj, uint64_t index)
dac5c838 847{
dac5c838
PP
848 struct bt_value_array *typed_array_obj =
849 BT_VALUE_TO_ARRAY(array_obj);
850
f6ccaed9
PP
851 BT_ASSERT_PRE_NON_NULL(array_obj, "Value object");
852 BT_ASSERT_PRE_VALUE_IS_TYPE(array_obj, BT_VALUE_TYPE_ARRAY);
853 BT_ASSERT_PRE_VALUE_INDEX_IN_BOUNDS(index,
854 typed_array_obj->garray->len);
094ff7c0 855 return g_ptr_array_index(typed_array_obj->garray, index);
dac5c838
PP
856}
857
05e21286
PP
858const struct bt_value *bt_value_array_borrow_element_by_index_const(
859 const struct bt_value *array_obj,
da91b29a
PP
860 uint64_t index)
861{
05e21286 862 return bt_value_array_borrow_element_by_index(
da91b29a
PP
863 (void *) array_obj, index);
864}
865
05e21286
PP
866enum bt_value_status bt_value_array_append_element(
867 struct bt_value *array_obj,
364747d6 868 struct bt_value *element_obj)
dac5c838 869{
dac5c838
PP
870 struct bt_value_array *typed_array_obj =
871 BT_VALUE_TO_ARRAY(array_obj);
872
f6ccaed9
PP
873 BT_ASSERT_PRE_NON_NULL(array_obj, "Array value object");
874 BT_ASSERT_PRE_NON_NULL(element_obj, "Element value object");
875 BT_ASSERT_PRE_VALUE_IS_TYPE(array_obj, BT_VALUE_TYPE_ARRAY);
876 BT_ASSERT_PRE_VALUE_HOT(array_obj, "Array value object");
dac5c838 877 g_ptr_array_add(typed_array_obj->garray, element_obj);
65300d60 878 bt_object_get_ref(element_obj);
2f42aa0a
PP
879 BT_LOGV("Appended element to array value: array-value-addr=%p, "
880 "element-value-addr=%p, new-size=%u",
881 array_obj, element_obj, typed_array_obj->garray->len);
f6ccaed9 882 return BT_VALUE_STATUS_OK;
dac5c838
PP
883}
884
05e21286
PP
885enum bt_value_status bt_value_array_append_bool_element(
886 struct bt_value *array_obj, bt_bool val)
dac5c838
PP
887{
888 enum bt_value_status ret;
05e21286 889 struct bt_value *bool_obj = NULL;
dac5c838 890
05e21286
PP
891 bool_obj = bt_value_bool_create_init(val);
892 ret = bt_value_array_append_element(array_obj,
da91b29a 893 (void *) bool_obj);
65300d60 894 bt_object_put_ref(bool_obj);
dac5c838
PP
895 return ret;
896}
897
05e21286
PP
898enum bt_value_status bt_value_array_append_integer_element(
899 struct bt_value *array_obj, int64_t val)
dac5c838
PP
900{
901 enum bt_value_status ret;
05e21286 902 struct bt_value *integer_obj = NULL;
dac5c838 903
05e21286
PP
904 integer_obj = bt_value_integer_create_init(val);
905 ret = bt_value_array_append_element(array_obj,
da91b29a 906 (void *) integer_obj);
65300d60 907 bt_object_put_ref(integer_obj);
dac5c838
PP
908 return ret;
909}
910
05e21286
PP
911enum bt_value_status bt_value_array_append_real_element(
912 struct bt_value *array_obj, double val)
dac5c838
PP
913{
914 enum bt_value_status ret;
05e21286 915 struct bt_value *real_obj = NULL;
dac5c838 916
05e21286
PP
917 real_obj = bt_value_real_create_init(val);
918 ret = bt_value_array_append_element(array_obj,
da91b29a 919 (void *) real_obj);
65300d60 920 bt_object_put_ref(real_obj);
dac5c838
PP
921 return ret;
922}
923
05e21286
PP
924enum bt_value_status bt_value_array_append_string_element(
925 struct bt_value *array_obj, const char *val)
dac5c838
PP
926{
927 enum bt_value_status ret;
05e21286 928 struct bt_value *string_obj = NULL;
dac5c838 929
05e21286
PP
930 string_obj = bt_value_string_create_init(val);
931 ret = bt_value_array_append_element(array_obj,
da91b29a 932 (void *) string_obj);
65300d60 933 bt_object_put_ref(string_obj);
dac5c838
PP
934 return ret;
935}
936
05e21286
PP
937enum bt_value_status bt_value_array_append_empty_array_element(
938 struct bt_value *array_obj)
dac5c838
PP
939{
940 enum bt_value_status ret;
05e21286 941 struct bt_value *empty_array_obj = NULL;
dac5c838 942
05e21286
PP
943 empty_array_obj = bt_value_array_create();
944 ret = bt_value_array_append_element(array_obj,
da91b29a 945 (void *) empty_array_obj);
65300d60 946 bt_object_put_ref(empty_array_obj);
dac5c838
PP
947 return ret;
948}
949
05e21286
PP
950enum bt_value_status bt_value_array_append_empty_map_element(
951 struct bt_value *array_obj)
dac5c838
PP
952{
953 enum bt_value_status ret;
05e21286 954 struct bt_value *map_obj = NULL;
dac5c838 955
05e21286
PP
956 map_obj = bt_value_map_create();
957 ret = bt_value_array_append_element(array_obj,
da91b29a 958 (void *) map_obj);
65300d60 959 bt_object_put_ref(map_obj);
dac5c838
PP
960 return ret;
961}
962
05e21286
PP
963enum bt_value_status bt_value_array_set_element_by_index(
964 struct bt_value *array_obj, uint64_t index,
da91b29a 965 struct bt_value *element_obj)
dac5c838 966{
dac5c838
PP
967 struct bt_value_array *typed_array_obj =
968 BT_VALUE_TO_ARRAY(array_obj);
969
f6ccaed9
PP
970 BT_ASSERT_PRE_NON_NULL(array_obj, "Array value object");
971 BT_ASSERT_PRE_NON_NULL(element_obj, "Element value object");
972 BT_ASSERT_PRE_VALUE_IS_TYPE(array_obj, BT_VALUE_TYPE_ARRAY);
973 BT_ASSERT_PRE_VALUE_HOT(array_obj, "Array value object");
974 BT_ASSERT_PRE_VALUE_INDEX_IN_BOUNDS(index,
975 typed_array_obj->garray->len);
65300d60 976 bt_object_put_ref(g_ptr_array_index(typed_array_obj->garray, index));
dac5c838 977 g_ptr_array_index(typed_array_obj->garray, index) = element_obj;
65300d60 978 bt_object_get_ref(element_obj);
2f42aa0a
PP
979 BT_LOGV("Set array value's element: array-value-addr=%p, "
980 "index=%" PRIu64 ", element-value-addr=%p",
981 array_obj, index, element_obj);
f6ccaed9 982 return BT_VALUE_STATUS_OK;
dac5c838
PP
983}
984
601b0d3c 985uint64_t bt_value_map_get_size(const struct bt_value *map_obj)
dac5c838 986{
f6ccaed9
PP
987 BT_ASSERT_PRE_NON_NULL(map_obj, "Value object");
988 BT_ASSERT_PRE_VALUE_IS_TYPE(map_obj, BT_VALUE_TYPE_MAP);
601b0d3c 989 return (uint64_t) g_hash_table_size(BT_VALUE_TO_MAP(map_obj)->ght);
dac5c838
PP
990}
991
05e21286 992struct bt_value *bt_value_map_borrow_entry_value(struct bt_value *map_obj,
364747d6 993 const char *key)
dac5c838 994{
f6ccaed9
PP
995 BT_ASSERT_PRE_NON_NULL(map_obj, "Value object");
996 BT_ASSERT_PRE_NON_NULL(key, "Key");
997 BT_ASSERT_PRE_VALUE_IS_TYPE(map_obj, BT_VALUE_TYPE_MAP);
094ff7c0
PP
998 return g_hash_table_lookup(BT_VALUE_TO_MAP(map_obj)->ght,
999 GUINT_TO_POINTER(g_quark_from_string(key)));
dac5c838
PP
1000}
1001
05e21286
PP
1002const struct bt_value *bt_value_map_borrow_entry_value_const(
1003 const struct bt_value *map_obj, const char *key)
da91b29a 1004{
05e21286 1005 return bt_value_map_borrow_entry_value((void *) map_obj, key);
da91b29a
PP
1006}
1007
07208d85 1008bt_bool bt_value_map_has_entry(const struct bt_value *map_obj, const char *key)
dac5c838 1009{
f6ccaed9
PP
1010 BT_ASSERT_PRE_NON_NULL(map_obj, "Value object");
1011 BT_ASSERT_PRE_NON_NULL(key, "Key");
1012 BT_ASSERT_PRE_VALUE_IS_TYPE(map_obj, BT_VALUE_TYPE_MAP);
1013 return bt_g_hash_table_contains(BT_VALUE_TO_MAP(map_obj)->ght,
1014 GUINT_TO_POINTER(g_quark_from_string(key)));
dac5c838
PP
1015}
1016
05e21286
PP
1017enum bt_value_status bt_value_map_insert_entry(
1018 struct bt_value *map_obj,
364747d6 1019 const char *key, struct bt_value *element_obj)
dac5c838 1020{
f6ccaed9
PP
1021 BT_ASSERT_PRE_NON_NULL(map_obj, "Map value object");
1022 BT_ASSERT_PRE_NON_NULL(key, "Key");
1023 BT_ASSERT_PRE_NON_NULL(element_obj, "Element value object");
1024 BT_ASSERT_PRE_VALUE_IS_TYPE(map_obj, BT_VALUE_TYPE_MAP);
1025 BT_ASSERT_PRE_VALUE_HOT(map_obj, "Map value object");
1026 g_hash_table_insert(BT_VALUE_TO_MAP(map_obj)->ght,
1027 GUINT_TO_POINTER(g_quark_from_string(key)), element_obj);
65300d60 1028 bt_object_get_ref(element_obj);
2f42aa0a
PP
1029 BT_LOGV("Inserted value into map value: map-value-addr=%p, "
1030 "key=\"%s\", element-value-addr=%p",
1031 map_obj, key, element_obj);
f6ccaed9 1032 return BT_VALUE_STATUS_OK;
dac5c838
PP
1033}
1034
05e21286
PP
1035enum bt_value_status bt_value_map_insert_bool_entry(
1036 struct bt_value *map_obj, const char *key, bt_bool val)
dac5c838
PP
1037{
1038 enum bt_value_status ret;
05e21286 1039 struct bt_value *bool_obj = NULL;
dac5c838 1040
05e21286
PP
1041 bool_obj = bt_value_bool_create_init(val);
1042 ret = bt_value_map_insert_entry(map_obj, key,
da91b29a 1043 (void *) bool_obj);
65300d60 1044 bt_object_put_ref(bool_obj);
dac5c838
PP
1045 return ret;
1046}
1047
05e21286
PP
1048enum bt_value_status bt_value_map_insert_integer_entry(
1049 struct bt_value *map_obj, const char *key, int64_t val)
dac5c838
PP
1050{
1051 enum bt_value_status ret;
05e21286 1052 struct bt_value *integer_obj = NULL;
dac5c838 1053
05e21286
PP
1054 integer_obj = bt_value_integer_create_init(val);
1055 ret = bt_value_map_insert_entry(map_obj, key,
da91b29a 1056 (void *) integer_obj);
65300d60 1057 bt_object_put_ref(integer_obj);
dac5c838
PP
1058 return ret;
1059}
1060
05e21286
PP
1061enum bt_value_status bt_value_map_insert_real_entry(
1062 struct bt_value *map_obj, const char *key, double val)
dac5c838
PP
1063{
1064 enum bt_value_status ret;
05e21286 1065 struct bt_value *real_obj = NULL;
dac5c838 1066
05e21286
PP
1067 real_obj = bt_value_real_create_init(val);
1068 ret = bt_value_map_insert_entry(map_obj, key,
da91b29a 1069 (void *) real_obj);
65300d60 1070 bt_object_put_ref(real_obj);
dac5c838
PP
1071 return ret;
1072}
1073
05e21286
PP
1074enum bt_value_status bt_value_map_insert_string_entry(
1075 struct bt_value *map_obj, const char *key,
601b0d3c 1076 const char *val)
dac5c838
PP
1077{
1078 enum bt_value_status ret;
05e21286 1079 struct bt_value *string_obj = NULL;
dac5c838 1080
05e21286
PP
1081 string_obj = bt_value_string_create_init(val);
1082 ret = bt_value_map_insert_entry(map_obj, key,
da91b29a 1083 (void *) string_obj);
65300d60 1084 bt_object_put_ref(string_obj);
dac5c838
PP
1085 return ret;
1086}
1087
05e21286
PP
1088enum bt_value_status bt_value_map_insert_empty_array_entry(
1089 struct bt_value *map_obj, const char *key)
dac5c838
PP
1090{
1091 enum bt_value_status ret;
05e21286 1092 struct bt_value *array_obj = NULL;
dac5c838 1093
05e21286
PP
1094 array_obj = bt_value_array_create();
1095 ret = bt_value_map_insert_entry(map_obj, key,
da91b29a 1096 (void *) array_obj);
65300d60 1097 bt_object_put_ref(array_obj);
dac5c838
PP
1098 return ret;
1099}
1100
05e21286
PP
1101enum bt_value_status bt_value_map_insert_empty_map_entry(
1102 struct bt_value *map_obj, const char *key)
dac5c838
PP
1103{
1104 enum bt_value_status ret;
05e21286 1105 struct bt_value *empty_map_obj = NULL;
dac5c838 1106
05e21286
PP
1107 empty_map_obj = bt_value_map_create();
1108 ret = bt_value_map_insert_entry(map_obj, key,
da91b29a 1109 (void *) empty_map_obj);
65300d60 1110 bt_object_put_ref(empty_map_obj);
dac5c838
PP
1111 return ret;
1112}
1113
05e21286 1114enum bt_value_status bt_value_map_foreach_entry(struct bt_value *map_obj,
40f4ba76 1115 bt_value_map_foreach_entry_func func, void *data)
dac5c838
PP
1116{
1117 enum bt_value_status ret = BT_VALUE_STATUS_OK;
1118 gpointer key, element_obj;
1119 GHashTableIter iter;
1120 struct bt_value_map *typed_map_obj = BT_VALUE_TO_MAP(map_obj);
1121
f6ccaed9 1122 BT_ASSERT_PRE_NON_NULL(map_obj, "Value object");
40f4ba76 1123 BT_ASSERT_PRE_NON_NULL(func, "Callback");
f6ccaed9 1124 BT_ASSERT_PRE_VALUE_IS_TYPE(map_obj, BT_VALUE_TYPE_MAP);
dac5c838
PP
1125 g_hash_table_iter_init(&iter, typed_map_obj->ght);
1126
1127 while (g_hash_table_iter_next(&iter, &key, &element_obj)) {
5b44aff2 1128 const char *key_str = g_quark_to_string(GPOINTER_TO_UINT(key));
dac5c838 1129
40f4ba76 1130 if (!func(key_str, element_obj, data)) {
f6ccaed9 1131 BT_LOGV("User canceled the loop: key=\"%s\", "
2f42aa0a
PP
1132 "value-addr=%p, data=%p",
1133 key_str, element_obj, data);
f6ccaed9 1134 ret = BT_VALUE_STATUS_CANCELED;
dac5c838
PP
1135 break;
1136 }
1137 }
1138
dac5c838
PP
1139 return ret;
1140}
1141
05e21286
PP
1142enum bt_value_status bt_value_map_foreach_entry_const(
1143 const struct bt_value *map_obj,
40f4ba76 1144 bt_value_map_foreach_entry_const_func func, void *data)
da91b29a
PP
1145{
1146 return bt_value_map_foreach_entry((void *) map_obj,
40f4ba76 1147 (bt_value_map_foreach_entry_func) func, data);
da91b29a
PP
1148}
1149
770750d3 1150struct extend_map_element_data {
05e21286 1151 struct bt_value *extended_obj;
601b0d3c 1152 enum bt_value_status status;
770750d3
PP
1153};
1154
1155static
c55a9f58 1156bt_bool extend_map_element(const char *key,
05e21286 1157 const struct bt_value *extension_obj_elem, void *data)
770750d3 1158{
c55a9f58 1159 bt_bool ret = BT_TRUE;
770750d3 1160 struct extend_map_element_data *extend_data = data;
05e21286 1161 struct bt_value *extension_obj_elem_copy = NULL;
770750d3
PP
1162
1163 /* Copy object which is to replace the current one */
6be5a99e
PP
1164 extend_data->status = bt_value_copy(extension_obj_elem,
1165 &extension_obj_elem_copy);
601b0d3c
PP
1166 if (extend_data->status) {
1167 BT_LOGE("Cannot copy map element: addr=%p",
1168 extension_obj_elem);
1169 goto error;
1170 }
1171
1172 BT_ASSERT(extension_obj_elem_copy);
770750d3
PP
1173
1174 /* Replace in extended object */
05e21286 1175 extend_data->status = bt_value_map_insert_entry(
601b0d3c
PP
1176 extend_data->extended_obj, key,
1177 (void *) extension_obj_elem_copy);
1178 if (extend_data->status) {
2f42aa0a
PP
1179 BT_LOGE("Cannot replace value in extended value: key=\"%s\", "
1180 "extended-value-addr=%p, element-value-addr=%p",
1181 key, extend_data->extended_obj,
1182 extension_obj_elem_copy);
770750d3
PP
1183 goto error;
1184 }
1185
1186 goto end;
1187
1188error:
601b0d3c 1189 BT_ASSERT(extend_data->status != BT_VALUE_STATUS_OK);
c55a9f58 1190 ret = BT_FALSE;
770750d3
PP
1191
1192end:
65300d60 1193 BT_OBJECT_PUT_REF_AND_RESET(extension_obj_elem_copy);
770750d3
PP
1194 return ret;
1195}
1196
601b0d3c 1197enum bt_value_status bt_value_map_extend(
70991d9f 1198 const struct bt_value *base_map_obj,
35294e83
PP
1199 const struct bt_value *extension_obj,
1200 struct bt_value **extended_map_obj)
770750d3 1201{
601b0d3c
PP
1202 struct extend_map_element_data extend_data = {
1203 .extended_obj = NULL,
1204 .status = BT_VALUE_STATUS_OK,
1205 };
770750d3 1206
f6ccaed9
PP
1207 BT_ASSERT_PRE_NON_NULL(base_map_obj, "Base value object");
1208 BT_ASSERT_PRE_NON_NULL(extension_obj, "Extension value object");
601b0d3c
PP
1209 BT_ASSERT_PRE_NON_NULL(extended_map_obj,
1210 "Extended value object (output)");
f6ccaed9
PP
1211 BT_ASSERT_PRE_VALUE_IS_TYPE(base_map_obj, BT_VALUE_TYPE_MAP);
1212 BT_ASSERT_PRE_VALUE_IS_TYPE(extension_obj, BT_VALUE_TYPE_MAP);
2f42aa0a
PP
1213 BT_LOGD("Extending map value: base-value-addr=%p, extension-value-addr=%p",
1214 base_map_obj, extension_obj);
601b0d3c 1215 *extended_map_obj = NULL;
2f42aa0a 1216
770750d3 1217 /* Create copy of base map object to start with */
6be5a99e 1218 extend_data.status = bt_value_copy(base_map_obj, extended_map_obj);
601b0d3c 1219 if (extend_data.status) {
2f42aa0a
PP
1220 BT_LOGE("Cannot copy base value: base-value-addr=%p",
1221 base_map_obj);
770750d3
PP
1222 goto error;
1223 }
1224
601b0d3c
PP
1225 BT_ASSERT(extended_map_obj);
1226
770750d3
PP
1227 /*
1228 * For each key in the extension map object, replace this key
1229 * in the copied map object.
1230 */
601b0d3c 1231 extend_data.extended_obj = *extended_map_obj;
770750d3 1232
05e21286 1233 if (bt_value_map_foreach_entry_const(extension_obj, extend_map_element,
770750d3 1234 &extend_data)) {
32e87ceb 1235 BT_LOGE("Cannot iterate on the extension object's elements: "
2f42aa0a 1236 "extension-value-addr=%p", extension_obj);
770750d3
PP
1237 goto error;
1238 }
1239
601b0d3c 1240 if (extend_data.status) {
32e87ceb 1241 BT_LOGE("Failed to successfully iterate on the extension object's elements: "
2f42aa0a 1242 "extension-value-addr=%p", extension_obj);
770750d3
PP
1243 goto error;
1244 }
1245
2f42aa0a 1246 BT_LOGD("Extended map value: extended-value-addr=%p",
601b0d3c 1247 *extended_map_obj);
770750d3
PP
1248 goto end;
1249
1250error:
601b0d3c
PP
1251 BT_OBJECT_PUT_REF_AND_RESET(*extended_map_obj);
1252 *extended_map_obj = NULL;
770750d3
PP
1253
1254end:
601b0d3c 1255 return extend_data.status;
770750d3
PP
1256}
1257
6be5a99e
PP
1258enum bt_value_status bt_value_copy(const struct bt_value *object,
1259 struct bt_value **copy_obj)
dac5c838 1260{
601b0d3c 1261 enum bt_value_status status = BT_VALUE_STATUS_OK;
dac5c838 1262
f6ccaed9 1263 BT_ASSERT_PRE_NON_NULL(object, "Value object");
601b0d3c 1264 BT_ASSERT_PRE_NON_NULL(copy_obj, "Value object copy (output)");
2f42aa0a 1265 BT_LOGD("Copying value object: addr=%p", object);
601b0d3c
PP
1266 *copy_obj = copy_funcs[object->type](object);
1267 if (*copy_obj) {
2f42aa0a
PP
1268 BT_LOGD("Copied value object: copy-value-addr=%p",
1269 copy_obj);
1270 } else {
601b0d3c
PP
1271 status = BT_VALUE_STATUS_NOMEM;
1272 *copy_obj = NULL;
2f42aa0a
PP
1273 BT_LOGE_STR("Failed to copy value object.");
1274 }
dac5c838 1275
601b0d3c 1276 return status;
dac5c838
PP
1277}
1278
c55a9f58 1279bt_bool bt_value_compare(const struct bt_value *object_a,
dac5c838
PP
1280 const struct bt_value *object_b)
1281{
c55a9f58 1282 bt_bool ret = BT_FALSE;
dac5c838 1283
f6ccaed9
PP
1284 BT_ASSERT_PRE_NON_NULL(object_a, "Value object A");
1285 BT_ASSERT_PRE_NON_NULL(object_b, "Value object B");
dac5c838
PP
1286
1287 if (object_a->type != object_b->type) {
2f42aa0a
PP
1288 BT_LOGV("Values are different: type mismatch: "
1289 "value-a-addr=%p, value-b-addr=%p, "
c4628760 1290 "value-a-type=%s, value-b-type=%s",
2f42aa0a 1291 object_a, object_b,
da91b29a
PP
1292 bt_common_value_type_string(object_a->type),
1293 bt_common_value_type_string(object_b->type));
dac5c838
PP
1294 goto end;
1295 }
1296
1297 ret = compare_funcs[object_a->type](object_a, object_b);
1298
1299end:
1300 return ret;
1301}
This page took 0.109551 seconds and 4 git commands to generate.