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