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