Commit | Line | Data |
---|---|---|
347829f5 PP |
1 | /* |
2 | * objects.c: basic object system | |
3 | * | |
4 | * Babeltrace Library | |
5 | * | |
6 | * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation | |
7 | * Copyright (c) 2015 Philippe Proulx <pproulx@efficios.com> | |
8 | * | |
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
10 | * of this software and associated documentation files (the "Software"), to deal | |
11 | * in the Software without restriction, including without limitation the rights | |
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
13 | * copies of the Software, and to permit persons to whom the Software is | |
14 | * furnished to do so, subject to the following conditions: | |
15 | * | |
16 | * The above copyright notice and this permission notice shall be included in | |
17 | * all copies or substantial portions of the Software. | |
18 | * | |
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
25 | * SOFTWARE. | |
26 | */ | |
27 | ||
28 | #include <stdlib.h> | |
29 | #include <string.h> | |
30 | #include <assert.h> | |
31 | #include <string.h> | |
32 | #include <babeltrace/ctf-writer/ref-internal.h> | |
33 | #include <babeltrace/compiler.h> | |
34 | #include <glib.h> | |
35 | #include <babeltrace/objects.h> | |
36 | ||
37 | #define BT_OBJECT_FROM_CONCRETE(_concrete) ((struct bt_object *) (_concrete)) | |
38 | #define BT_OBJECT_TO_BOOL(_base) ((struct bt_object_bool *) (_base)) | |
39 | #define BT_OBJECT_TO_INTEGER(_base) ((struct bt_object_integer *) (_base)) | |
40 | #define BT_OBJECT_TO_FLOAT(_base) ((struct bt_object_float *) (_base)) | |
41 | #define BT_OBJECT_TO_STRING(_base) ((struct bt_object_string *) (_base)) | |
42 | #define BT_OBJECT_TO_ARRAY(_base) ((struct bt_object_array *) (_base)) | |
43 | #define BT_OBJECT_TO_MAP(_base) ((struct bt_object_map *) (_base)) | |
44 | ||
45 | struct bt_object { | |
46 | enum bt_object_type type; | |
47 | struct bt_ctf_ref ref_count; | |
48 | }; | |
49 | ||
50 | static | |
51 | struct bt_object bt_object_null_instance = { | |
52 | .type = BT_OBJECT_TYPE_NULL, | |
53 | }; | |
54 | ||
55 | struct bt_object *bt_object_null = &bt_object_null_instance; | |
56 | ||
57 | struct bt_object_bool { | |
58 | struct bt_object base; | |
59 | bool value; | |
60 | }; | |
61 | ||
62 | struct bt_object_integer { | |
63 | struct bt_object base; | |
64 | int64_t value; | |
65 | }; | |
66 | ||
67 | struct bt_object_float { | |
68 | struct bt_object base; | |
69 | double value; | |
70 | }; | |
71 | ||
72 | struct bt_object_string { | |
73 | struct bt_object base; | |
74 | GString *gstr; | |
75 | }; | |
76 | ||
77 | struct bt_object_array { | |
78 | struct bt_object base; | |
a22a5f1b | 79 | GPtrArray *garray; |
347829f5 PP |
80 | }; |
81 | ||
82 | struct bt_object_map { | |
83 | struct bt_object base; | |
84 | GHashTable *ght; | |
85 | }; | |
86 | ||
87 | static | |
88 | void bt_object_string_destroy(struct bt_object *object) | |
89 | { | |
e196f486 | 90 | g_string_free(BT_OBJECT_TO_STRING(object)->gstr, TRUE); |
347829f5 PP |
91 | } |
92 | ||
93 | static | |
94 | void bt_object_array_destroy(struct bt_object *object) | |
95 | { | |
a22a5f1b PP |
96 | /* |
97 | * Pointer array's registered value destructor will take care | |
98 | * of putting each contained object. | |
99 | */ | |
100 | g_ptr_array_free(BT_OBJECT_TO_ARRAY(object)->garray, TRUE); | |
347829f5 PP |
101 | } |
102 | ||
103 | static | |
104 | void bt_object_map_destroy(struct bt_object *object) | |
105 | { | |
347829f5 PP |
106 | /* |
107 | * Hash table's registered value destructor will take care of | |
108 | * putting each contained object. Keys are GQuarks and cannot | |
109 | * be destroyed anyway. | |
110 | */ | |
e196f486 | 111 | g_hash_table_destroy(BT_OBJECT_TO_MAP(object)->ght); |
347829f5 PP |
112 | } |
113 | ||
114 | static | |
115 | void (* const destroy_funcs[])(struct bt_object *) = { | |
116 | [BT_OBJECT_TYPE_NULL] = NULL, | |
117 | [BT_OBJECT_TYPE_BOOL] = NULL, | |
118 | [BT_OBJECT_TYPE_INTEGER] = NULL, | |
119 | [BT_OBJECT_TYPE_FLOAT] = NULL, | |
120 | [BT_OBJECT_TYPE_STRING] = bt_object_string_destroy, | |
121 | [BT_OBJECT_TYPE_ARRAY] = bt_object_array_destroy, | |
122 | [BT_OBJECT_TYPE_MAP] = bt_object_map_destroy, | |
123 | }; | |
124 | ||
125 | static | |
126 | struct bt_object *bt_object_null_copy(const struct bt_object *null_obj) | |
127 | { | |
128 | return bt_object_null; | |
129 | } | |
130 | ||
131 | static | |
132 | struct bt_object *bt_object_bool_copy(const struct bt_object *bool_obj) | |
133 | { | |
134 | return bt_object_bool_create_init(BT_OBJECT_TO_BOOL(bool_obj)->value); | |
135 | } | |
136 | ||
137 | static | |
138 | struct bt_object *bt_object_integer_copy(const struct bt_object *integer_obj) | |
139 | { | |
140 | return bt_object_integer_create_init( | |
141 | BT_OBJECT_TO_INTEGER(integer_obj)->value); | |
142 | } | |
143 | ||
144 | static | |
145 | struct bt_object *bt_object_float_copy(const struct bt_object *float_obj) | |
146 | { | |
147 | return bt_object_float_create_init( | |
148 | BT_OBJECT_TO_FLOAT(float_obj)->value); | |
149 | } | |
150 | ||
151 | static | |
152 | struct bt_object *bt_object_string_copy(const struct bt_object *string_obj) | |
153 | { | |
154 | return bt_object_string_create_init( | |
155 | BT_OBJECT_TO_STRING(string_obj)->gstr->str); | |
156 | } | |
157 | ||
158 | static | |
159 | struct bt_object *bt_object_array_copy(const struct bt_object *array_obj) | |
160 | { | |
161 | int x; | |
162 | int ret; | |
163 | struct bt_object *copy_obj; | |
164 | struct bt_object_array *typed_array_obj; | |
165 | ||
166 | typed_array_obj = BT_OBJECT_TO_ARRAY(array_obj); | |
167 | copy_obj = bt_object_array_create(); | |
168 | ||
169 | if (!copy_obj) { | |
170 | goto end; | |
171 | } | |
172 | ||
173 | for (x = 0; x < typed_array_obj->garray->len; ++x) { | |
174 | struct bt_object *element_obj_copy; | |
175 | struct bt_object *element_obj = | |
176 | bt_object_array_get(array_obj, x); | |
177 | ||
178 | if (!element_obj) { | |
179 | BT_OBJECT_PUT(copy_obj); | |
180 | goto end; | |
181 | } | |
182 | ||
183 | element_obj_copy = bt_object_copy(element_obj); | |
184 | BT_OBJECT_PUT(element_obj); | |
185 | ||
186 | if (!element_obj_copy) { | |
187 | BT_OBJECT_PUT(copy_obj); | |
188 | goto end; | |
189 | } | |
190 | ||
191 | ret = bt_object_array_append(copy_obj, element_obj_copy); | |
192 | BT_OBJECT_PUT(element_obj_copy); | |
193 | ||
194 | if (ret) { | |
195 | BT_OBJECT_PUT(copy_obj); | |
196 | goto end; | |
197 | } | |
198 | } | |
199 | ||
200 | end: | |
201 | return copy_obj; | |
202 | } | |
203 | ||
204 | static | |
205 | struct bt_object *bt_object_map_copy(const struct bt_object *map_obj) | |
206 | { | |
207 | int ret; | |
208 | GHashTableIter iter; | |
209 | gpointer key, element_obj; | |
210 | struct bt_object *copy_obj; | |
211 | struct bt_object *element_obj_copy; | |
212 | struct bt_object_map *typed_map_obj; | |
213 | ||
214 | typed_map_obj = BT_OBJECT_TO_MAP(map_obj); | |
215 | copy_obj = bt_object_map_create(); | |
216 | ||
217 | if (!copy_obj) { | |
218 | goto end; | |
219 | } | |
220 | ||
221 | g_hash_table_iter_init(&iter, typed_map_obj->ght); | |
222 | ||
223 | while (g_hash_table_iter_next(&iter, &key, &element_obj)) { | |
224 | const char *key_str = g_quark_to_string((unsigned long) key); | |
225 | ||
226 | element_obj_copy = bt_object_copy(element_obj); | |
227 | ||
228 | if (!element_obj_copy) { | |
229 | BT_OBJECT_PUT(copy_obj); | |
230 | goto end; | |
231 | } | |
232 | ||
233 | ret = bt_object_map_insert(copy_obj, key_str, element_obj_copy); | |
234 | BT_OBJECT_PUT(element_obj_copy); | |
235 | ||
236 | if (ret) { | |
237 | BT_OBJECT_PUT(copy_obj); | |
238 | goto end; | |
239 | } | |
240 | } | |
241 | ||
242 | end: | |
243 | return copy_obj; | |
244 | } | |
245 | ||
246 | static | |
247 | struct bt_object *(* const copy_funcs[])(const struct bt_object *) = { | |
248 | [BT_OBJECT_TYPE_NULL] = bt_object_null_copy, | |
249 | [BT_OBJECT_TYPE_BOOL] = bt_object_bool_copy, | |
250 | [BT_OBJECT_TYPE_INTEGER] = bt_object_integer_copy, | |
251 | [BT_OBJECT_TYPE_FLOAT] = bt_object_float_copy, | |
252 | [BT_OBJECT_TYPE_STRING] = bt_object_string_copy, | |
253 | [BT_OBJECT_TYPE_ARRAY] = bt_object_array_copy, | |
254 | [BT_OBJECT_TYPE_MAP] = bt_object_map_copy, | |
255 | }; | |
256 | ||
257 | static | |
258 | bool bt_object_null_compare(const struct bt_object *object_a, | |
259 | const struct bt_object *object_b) | |
260 | { | |
261 | /* | |
262 | * Always true since bt_object_compare() already checks if both | |
263 | * object_a and object_b have the same type, and in the case of | |
264 | * null objects, they're always the same if it is so. | |
265 | */ | |
266 | return true; | |
267 | } | |
268 | ||
269 | static | |
270 | bool bt_object_bool_compare(const struct bt_object *object_a, | |
271 | const struct bt_object *object_b) | |
272 | { | |
273 | return BT_OBJECT_TO_BOOL(object_a)->value == | |
274 | BT_OBJECT_TO_BOOL(object_b)->value; | |
275 | } | |
276 | ||
277 | static | |
278 | bool bt_object_integer_compare(const struct bt_object *object_a, | |
279 | const struct bt_object *object_b) | |
280 | { | |
281 | return BT_OBJECT_TO_INTEGER(object_a)->value == | |
282 | BT_OBJECT_TO_INTEGER(object_b)->value; | |
283 | } | |
284 | ||
285 | static | |
286 | bool bt_object_float_compare(const struct bt_object *object_a, | |
287 | const struct bt_object *object_b) | |
288 | { | |
289 | return BT_OBJECT_TO_FLOAT(object_a)->value == | |
290 | BT_OBJECT_TO_FLOAT(object_b)->value; | |
291 | } | |
292 | ||
293 | static | |
294 | bool bt_object_string_compare(const struct bt_object *object_a, | |
295 | const struct bt_object *object_b) | |
296 | { | |
297 | return !strcmp(BT_OBJECT_TO_STRING(object_a)->gstr->str, | |
298 | BT_OBJECT_TO_STRING(object_b)->gstr->str); | |
299 | } | |
300 | ||
301 | static | |
302 | bool bt_object_array_compare(const struct bt_object *object_a, | |
303 | const struct bt_object *object_b) | |
304 | { | |
305 | int x; | |
306 | bool ret = true; | |
307 | const struct bt_object_array *array_obj_a = | |
308 | BT_OBJECT_TO_ARRAY(object_a); | |
309 | ||
310 | if (bt_object_array_size(object_a) != bt_object_array_size(object_b)) { | |
311 | ret = false; | |
312 | goto end; | |
313 | } | |
314 | ||
315 | for (x = 0; x < array_obj_a->garray->len; ++x) { | |
316 | struct bt_object *element_obj_a; | |
317 | struct bt_object *element_obj_b; | |
318 | ||
319 | element_obj_a = bt_object_array_get(object_a, x); | |
320 | element_obj_b = bt_object_array_get(object_b, x); | |
321 | ||
322 | if (!bt_object_compare(element_obj_a, element_obj_b)) { | |
323 | BT_OBJECT_PUT(element_obj_a); | |
324 | BT_OBJECT_PUT(element_obj_b); | |
325 | ret = false; | |
326 | goto end; | |
327 | } | |
328 | ||
329 | BT_OBJECT_PUT(element_obj_a); | |
330 | BT_OBJECT_PUT(element_obj_b); | |
331 | } | |
332 | ||
333 | end: | |
334 | return ret; | |
335 | } | |
336 | ||
337 | static | |
338 | bool bt_object_map_compare(const struct bt_object *object_a, | |
339 | const struct bt_object *object_b) | |
340 | { | |
341 | bool ret = true; | |
342 | GHashTableIter iter; | |
343 | gpointer key, element_obj_a; | |
344 | const struct bt_object_map *map_obj_a = BT_OBJECT_TO_MAP(object_a); | |
345 | ||
346 | if (bt_object_map_size(object_a) != bt_object_map_size(object_b)) { | |
347 | ret = false; | |
348 | goto end; | |
349 | } | |
350 | ||
351 | g_hash_table_iter_init(&iter, map_obj_a->ght); | |
352 | ||
353 | while (g_hash_table_iter_next(&iter, &key, &element_obj_a)) { | |
354 | struct bt_object *element_obj_b; | |
355 | const char *key_str = g_quark_to_string((unsigned long) key); | |
356 | ||
357 | element_obj_b = bt_object_map_get(object_b, key_str); | |
358 | ||
359 | if (!bt_object_compare(element_obj_a, element_obj_b)) { | |
360 | BT_OBJECT_PUT(element_obj_b); | |
361 | ret = false; | |
362 | goto end; | |
363 | } | |
364 | ||
365 | BT_OBJECT_PUT(element_obj_b); | |
366 | } | |
367 | ||
368 | end: | |
369 | return ret; | |
370 | } | |
371 | ||
372 | static | |
373 | bool (* const compare_funcs[])(const struct bt_object *, | |
374 | const struct bt_object *) = { | |
375 | [BT_OBJECT_TYPE_NULL] = bt_object_null_compare, | |
376 | [BT_OBJECT_TYPE_BOOL] = bt_object_bool_compare, | |
377 | [BT_OBJECT_TYPE_INTEGER] = bt_object_integer_compare, | |
378 | [BT_OBJECT_TYPE_FLOAT] = bt_object_float_compare, | |
379 | [BT_OBJECT_TYPE_STRING] = bt_object_string_compare, | |
380 | [BT_OBJECT_TYPE_ARRAY] = bt_object_array_compare, | |
381 | [BT_OBJECT_TYPE_MAP] = bt_object_map_compare, | |
382 | }; | |
383 | ||
384 | static | |
385 | void bt_object_destroy(struct bt_ctf_ref *ref_count) | |
386 | { | |
387 | struct bt_object *object; | |
388 | ||
389 | object = container_of(ref_count, struct bt_object, ref_count); | |
390 | assert(object->type != BT_OBJECT_TYPE_UNKNOWN); | |
391 | ||
392 | if (bt_object_is_null(object)) { | |
393 | return; | |
394 | } | |
395 | ||
396 | if (destroy_funcs[object->type]) { | |
397 | destroy_funcs[object->type](object); | |
398 | } | |
399 | ||
400 | g_free(object); | |
401 | } | |
402 | ||
403 | void bt_object_get(struct bt_object *object) | |
404 | { | |
405 | if (!object) { | |
406 | goto skip; | |
407 | } | |
408 | ||
409 | bt_ctf_ref_get(&object->ref_count); | |
410 | ||
411 | skip: | |
412 | return; | |
413 | } | |
414 | ||
415 | void bt_object_put(struct bt_object *object) | |
416 | { | |
417 | if (!object) { | |
418 | goto skip; | |
419 | } | |
420 | ||
421 | bt_ctf_ref_put(&object->ref_count, bt_object_destroy); | |
422 | ||
423 | skip: | |
424 | return; | |
425 | } | |
426 | ||
427 | enum bt_object_type bt_object_get_type(const struct bt_object *object) | |
428 | { | |
429 | if (!object) { | |
430 | return BT_OBJECT_TYPE_UNKNOWN; | |
431 | } | |
432 | ||
433 | return object->type; | |
434 | } | |
435 | ||
436 | static | |
437 | struct bt_object bt_object_create_base(enum bt_object_type type) | |
438 | { | |
439 | struct bt_object base; | |
440 | ||
441 | base.type = type; | |
442 | bt_ctf_ref_init(&base.ref_count); | |
443 | ||
444 | return base; | |
445 | } | |
446 | ||
447 | struct bt_object *bt_object_bool_create_init(bool val) | |
448 | { | |
449 | struct bt_object_bool *bool_obj; | |
450 | ||
451 | bool_obj = g_new0(struct bt_object_bool, 1); | |
452 | ||
453 | if (!bool_obj) { | |
454 | goto end; | |
455 | } | |
456 | ||
457 | bool_obj->base = bt_object_create_base(BT_OBJECT_TYPE_BOOL); | |
458 | bool_obj->value = val; | |
459 | ||
460 | end: | |
461 | return BT_OBJECT_FROM_CONCRETE(bool_obj); | |
462 | } | |
463 | ||
464 | struct bt_object *bt_object_bool_create(void) | |
465 | { | |
466 | return bt_object_bool_create_init(false); | |
467 | } | |
468 | ||
469 | struct bt_object *bt_object_integer_create_init(int64_t val) | |
470 | { | |
471 | struct bt_object_integer *integer_obj; | |
472 | ||
473 | integer_obj = g_new0(struct bt_object_integer, 1); | |
474 | ||
475 | if (!integer_obj) { | |
476 | goto end; | |
477 | } | |
478 | ||
479 | integer_obj->base = bt_object_create_base(BT_OBJECT_TYPE_INTEGER); | |
480 | integer_obj->value = val; | |
481 | ||
482 | end: | |
483 | return BT_OBJECT_FROM_CONCRETE(integer_obj); | |
484 | } | |
485 | ||
486 | struct bt_object *bt_object_integer_create(void) | |
487 | { | |
488 | return bt_object_integer_create_init(0); | |
489 | } | |
490 | ||
491 | struct bt_object *bt_object_float_create_init(double val) | |
492 | { | |
493 | struct bt_object_float *float_obj; | |
494 | ||
495 | float_obj = g_new0(struct bt_object_float, 1); | |
496 | ||
497 | if (!float_obj) { | |
498 | goto end; | |
499 | } | |
500 | ||
501 | float_obj->base = bt_object_create_base(BT_OBJECT_TYPE_FLOAT); | |
502 | float_obj->value = val; | |
503 | ||
504 | end: | |
505 | return BT_OBJECT_FROM_CONCRETE(float_obj); | |
506 | } | |
507 | ||
508 | struct bt_object *bt_object_float_create(void) | |
509 | { | |
510 | return bt_object_float_create_init(0.); | |
511 | } | |
512 | ||
513 | struct bt_object *bt_object_string_create_init(const char *val) | |
514 | { | |
515 | struct bt_object_string *string_obj = NULL; | |
516 | ||
517 | if (!val) { | |
518 | goto end; | |
519 | } | |
520 | ||
521 | string_obj = g_new0(struct bt_object_string, 1); | |
522 | ||
523 | if (!string_obj) { | |
524 | goto end; | |
525 | } | |
526 | ||
527 | string_obj->base = bt_object_create_base(BT_OBJECT_TYPE_STRING); | |
528 | string_obj->gstr = g_string_new(val); | |
529 | ||
530 | if (!string_obj->gstr) { | |
531 | g_free(string_obj); | |
532 | string_obj = NULL; | |
533 | goto end; | |
534 | } | |
535 | ||
536 | end: | |
537 | return BT_OBJECT_FROM_CONCRETE(string_obj); | |
538 | } | |
539 | ||
540 | struct bt_object *bt_object_string_create(void) | |
541 | { | |
542 | return bt_object_string_create_init(""); | |
543 | } | |
544 | ||
545 | struct bt_object *bt_object_array_create(void) | |
546 | { | |
547 | struct bt_object_array *array_obj; | |
548 | ||
549 | array_obj = g_new0(struct bt_object_array, 1); | |
550 | ||
551 | if (!array_obj) { | |
552 | goto end; | |
553 | } | |
554 | ||
555 | array_obj->base = bt_object_create_base(BT_OBJECT_TYPE_ARRAY); | |
a22a5f1b PP |
556 | array_obj->garray = g_ptr_array_new_full(0, |
557 | (GDestroyNotify) bt_object_put); | |
347829f5 PP |
558 | |
559 | if (!array_obj->garray) { | |
560 | g_free(array_obj); | |
561 | array_obj = NULL; | |
562 | goto end; | |
563 | } | |
564 | ||
565 | end: | |
566 | return BT_OBJECT_FROM_CONCRETE(array_obj); | |
567 | } | |
568 | ||
569 | struct bt_object *bt_object_map_create(void) | |
570 | { | |
571 | struct bt_object_map *map_obj; | |
572 | ||
573 | map_obj = g_new0(struct bt_object_map, 1); | |
574 | ||
575 | if (!map_obj) { | |
576 | goto end; | |
577 | } | |
578 | ||
579 | map_obj->base = bt_object_create_base(BT_OBJECT_TYPE_MAP); | |
580 | map_obj->ght = g_hash_table_new_full(g_direct_hash, g_direct_equal, | |
581 | NULL, (GDestroyNotify) bt_object_put); | |
582 | ||
583 | if (!map_obj->ght) { | |
584 | g_free(map_obj); | |
585 | map_obj = NULL; | |
586 | goto end; | |
587 | } | |
588 | ||
589 | end: | |
590 | return BT_OBJECT_FROM_CONCRETE(map_obj); | |
591 | } | |
592 | ||
593 | int bt_object_bool_get(const struct bt_object *bool_obj, bool *val) | |
594 | { | |
595 | int ret = 0; | |
596 | struct bt_object_bool *typed_bool_obj = BT_OBJECT_TO_BOOL(bool_obj); | |
597 | ||
598 | if (!bool_obj || !bt_object_is_bool(bool_obj)) { | |
599 | ret = -1; | |
600 | goto end; | |
601 | } | |
602 | ||
603 | *val = typed_bool_obj->value; | |
604 | ||
605 | end: | |
606 | return ret; | |
607 | } | |
608 | ||
609 | int bt_object_bool_set(struct bt_object *bool_obj, bool val) | |
610 | { | |
611 | int ret = 0; | |
612 | struct bt_object_bool *typed_bool_obj = BT_OBJECT_TO_BOOL(bool_obj); | |
613 | ||
614 | if (!bool_obj || !bt_object_is_bool(bool_obj)) { | |
615 | ret = -1; | |
616 | goto end; | |
617 | } | |
618 | ||
619 | typed_bool_obj->value = val; | |
620 | ||
621 | end: | |
622 | return ret; | |
623 | } | |
624 | ||
625 | int bt_object_integer_get(const struct bt_object *integer_obj, int64_t *val) | |
626 | { | |
627 | int ret = 0; | |
628 | struct bt_object_integer *typed_integer_obj = | |
629 | BT_OBJECT_TO_INTEGER(integer_obj); | |
630 | ||
631 | if (!integer_obj || !bt_object_is_integer(integer_obj)) { | |
632 | ret = -1; | |
633 | goto end; | |
634 | } | |
635 | ||
636 | *val = typed_integer_obj->value; | |
637 | ||
638 | end: | |
639 | return ret; | |
640 | } | |
641 | ||
642 | int bt_object_integer_set(struct bt_object *integer_obj, int64_t val) | |
643 | { | |
644 | int ret = 0; | |
645 | struct bt_object_integer *typed_integer_obj = | |
646 | BT_OBJECT_TO_INTEGER(integer_obj); | |
647 | ||
648 | if (!integer_obj || !bt_object_is_integer(integer_obj)) { | |
649 | ret = -1; | |
650 | goto end; | |
651 | } | |
652 | ||
653 | typed_integer_obj->value = val; | |
654 | ||
655 | end: | |
656 | return ret; | |
657 | } | |
658 | ||
659 | int bt_object_float_get(const struct bt_object *float_obj, double *val) | |
660 | { | |
661 | int ret = 0; | |
662 | struct bt_object_float *typed_float_obj = | |
663 | BT_OBJECT_TO_FLOAT(float_obj); | |
664 | ||
665 | if (!float_obj || !bt_object_is_float(float_obj)) { | |
666 | ret = -1; | |
667 | goto end; | |
668 | } | |
669 | ||
670 | *val = typed_float_obj->value; | |
671 | ||
672 | end: | |
673 | return ret; | |
674 | } | |
675 | ||
676 | int bt_object_float_set(struct bt_object *float_obj, double val) | |
677 | { | |
678 | int ret = 0; | |
679 | struct bt_object_float *typed_float_obj = | |
680 | BT_OBJECT_TO_FLOAT(float_obj); | |
681 | ||
682 | if (!float_obj || !bt_object_is_float(float_obj)) { | |
683 | ret = -1; | |
684 | goto end; | |
685 | } | |
686 | ||
687 | typed_float_obj->value = val; | |
688 | ||
689 | end: | |
690 | return ret; | |
691 | } | |
692 | ||
693 | const char *bt_object_string_get(const struct bt_object *string_obj) | |
694 | { | |
695 | const char *ret; | |
696 | struct bt_object_string *typed_string_obj = | |
697 | BT_OBJECT_TO_STRING(string_obj); | |
698 | ||
699 | if (!string_obj || !bt_object_is_string(string_obj)) { | |
700 | ret = NULL; | |
701 | goto end; | |
702 | } | |
703 | ||
704 | ret = typed_string_obj->gstr->str; | |
705 | ||
706 | end: | |
707 | return ret; | |
708 | } | |
709 | ||
710 | int bt_object_string_set(struct bt_object *string_obj, const char *val) | |
711 | { | |
712 | int ret = 0; | |
713 | struct bt_object_string *typed_string_obj = | |
714 | BT_OBJECT_TO_STRING(string_obj); | |
715 | ||
716 | if (!string_obj || !bt_object_is_string(string_obj) || !val) { | |
717 | ret = -1; | |
718 | goto end; | |
719 | } | |
720 | ||
721 | g_string_assign(typed_string_obj->gstr, val); | |
722 | ||
723 | end: | |
724 | return ret; | |
725 | } | |
726 | ||
727 | int bt_object_array_size(const struct bt_object *array_obj) | |
728 | { | |
729 | int ret = 0; | |
730 | struct bt_object_array *typed_array_obj = | |
731 | BT_OBJECT_TO_ARRAY(array_obj); | |
732 | ||
733 | if (!array_obj || !bt_object_is_array(array_obj)) { | |
734 | ret = -1; | |
735 | goto end; | |
736 | } | |
737 | ||
738 | ret = (int) typed_array_obj->garray->len; | |
739 | ||
740 | end: | |
741 | return ret; | |
742 | } | |
743 | ||
744 | bool bt_object_array_is_empty(const struct bt_object *array_obj) | |
745 | { | |
746 | return bt_object_array_size(array_obj) == 0; | |
747 | } | |
748 | ||
749 | struct bt_object *bt_object_array_get(const struct bt_object *array_obj, | |
750 | size_t index) | |
751 | { | |
752 | struct bt_object *ret; | |
753 | struct bt_object_array *typed_array_obj = | |
754 | BT_OBJECT_TO_ARRAY(array_obj); | |
755 | ||
756 | if (!array_obj || !bt_object_is_array(array_obj) || | |
757 | index >= typed_array_obj->garray->len) { | |
758 | ret = NULL; | |
759 | goto end; | |
760 | } | |
761 | ||
a22a5f1b | 762 | ret = g_ptr_array_index(typed_array_obj->garray, index); |
347829f5 PP |
763 | bt_object_get(ret); |
764 | ||
765 | end: | |
766 | return ret; | |
767 | } | |
768 | ||
769 | int bt_object_array_append(struct bt_object *array_obj, | |
770 | struct bt_object *element_obj) | |
771 | { | |
772 | int ret = 0; | |
773 | struct bt_object_array *typed_array_obj = | |
774 | BT_OBJECT_TO_ARRAY(array_obj); | |
775 | ||
776 | if (!array_obj || !bt_object_is_array(array_obj) || !element_obj) { | |
777 | ret = -1; | |
778 | goto end; | |
779 | } | |
780 | ||
a22a5f1b | 781 | g_ptr_array_add(typed_array_obj->garray, element_obj); |
347829f5 PP |
782 | bt_object_get(element_obj); |
783 | ||
784 | end: | |
785 | return ret; | |
786 | } | |
787 | ||
788 | int bt_object_array_append_bool(struct bt_object *array_obj, bool val) | |
789 | { | |
790 | int ret; | |
791 | struct bt_object *bool_obj = NULL; | |
792 | ||
793 | bool_obj = bt_object_bool_create_init(val); | |
794 | ret = bt_object_array_append(array_obj, bool_obj); | |
795 | bt_object_put(bool_obj); | |
796 | ||
797 | return ret; | |
798 | } | |
799 | ||
800 | int bt_object_array_append_integer(struct bt_object *array_obj, int64_t val) | |
801 | { | |
802 | int ret; | |
803 | struct bt_object *integer_obj = NULL; | |
804 | ||
805 | integer_obj = bt_object_integer_create_init(val); | |
806 | ret = bt_object_array_append(array_obj, integer_obj); | |
807 | bt_object_put(integer_obj); | |
808 | ||
809 | return ret; | |
810 | } | |
811 | ||
812 | int bt_object_array_append_float(struct bt_object *array_obj, double val) | |
813 | { | |
814 | int ret; | |
815 | struct bt_object *float_obj = NULL; | |
816 | ||
817 | float_obj = bt_object_float_create_init(val); | |
818 | ret = bt_object_array_append(array_obj, float_obj); | |
819 | bt_object_put(float_obj); | |
820 | ||
821 | return ret; | |
822 | } | |
823 | ||
824 | int bt_object_array_append_string(struct bt_object *array_obj, const char *val) | |
825 | { | |
826 | int ret; | |
827 | struct bt_object *string_obj = NULL; | |
828 | ||
829 | string_obj = bt_object_string_create_init(val); | |
830 | ret = bt_object_array_append(array_obj, string_obj); | |
831 | bt_object_put(string_obj); | |
832 | ||
833 | return ret; | |
834 | } | |
835 | ||
836 | int bt_object_array_append_array(struct bt_object *array_obj) | |
837 | { | |
838 | int ret; | |
839 | struct bt_object *empty_array_obj = NULL; | |
840 | ||
841 | empty_array_obj = bt_object_array_create(); | |
842 | ret = bt_object_array_append(array_obj, empty_array_obj); | |
843 | bt_object_put(empty_array_obj); | |
844 | ||
845 | return ret; | |
846 | } | |
847 | ||
848 | int bt_object_array_append_map(struct bt_object *array_obj) | |
849 | { | |
850 | int ret; | |
851 | struct bt_object *map_obj = NULL; | |
852 | ||
853 | map_obj = bt_object_map_create(); | |
854 | ret = bt_object_array_append(array_obj, map_obj); | |
855 | bt_object_put(map_obj); | |
856 | ||
857 | return ret; | |
858 | } | |
859 | ||
860 | int bt_object_map_size(const struct bt_object *map_obj) | |
861 | { | |
862 | int ret; | |
863 | struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj); | |
864 | ||
865 | if (!map_obj || !bt_object_is_map(map_obj)) { | |
866 | ret = -1; | |
867 | goto end; | |
868 | } | |
869 | ||
870 | ret = (int) g_hash_table_size(typed_map_obj->ght); | |
871 | ||
872 | end: | |
873 | return ret; | |
874 | } | |
875 | ||
876 | bool bt_object_map_is_empty(const struct bt_object *map_obj) | |
877 | { | |
878 | return bt_object_map_size(map_obj) == 0; | |
879 | } | |
880 | ||
881 | struct bt_object *bt_object_map_get(const struct bt_object *map_obj, | |
882 | const char *key) | |
883 | { | |
884 | GQuark quark; | |
885 | struct bt_object *ret; | |
886 | struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj); | |
887 | ||
888 | if (!map_obj || !bt_object_is_map(map_obj) || !key) { | |
889 | ret = NULL; | |
890 | goto end; | |
891 | } | |
892 | ||
893 | quark = g_quark_from_string(key); | |
894 | ret = g_hash_table_lookup(typed_map_obj->ght, GUINT_TO_POINTER(quark)); | |
895 | ||
896 | if (ret) { | |
897 | bt_object_get(ret); | |
898 | } | |
899 | ||
900 | end: | |
901 | return ret; | |
902 | } | |
903 | ||
904 | bool bt_object_map_has_key(const struct bt_object *map_obj, const char *key) | |
905 | { | |
906 | bool ret; | |
907 | GQuark quark; | |
908 | struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj); | |
909 | ||
910 | if (!map_obj || !bt_object_is_map(map_obj) || !key) { | |
911 | ret = false; | |
912 | goto end; | |
913 | } | |
914 | ||
915 | quark = g_quark_from_string(key); | |
916 | ret = g_hash_table_contains(typed_map_obj->ght, | |
917 | GUINT_TO_POINTER(quark)); | |
918 | ||
919 | end: | |
920 | return ret; | |
921 | } | |
922 | ||
923 | int bt_object_map_insert(struct bt_object *map_obj, const char *key, | |
924 | struct bt_object *element_obj) | |
925 | { | |
926 | int ret = 0; | |
927 | GQuark quark; | |
928 | struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj); | |
929 | ||
930 | if (!map_obj || !bt_object_is_map(map_obj) || !key || !element_obj) { | |
931 | ret = -1; | |
932 | goto end; | |
933 | } | |
934 | ||
935 | quark = g_quark_from_string(key); | |
936 | g_hash_table_insert(typed_map_obj->ght, | |
937 | GUINT_TO_POINTER(quark), element_obj); | |
938 | bt_object_get(element_obj); | |
939 | ||
940 | end: | |
941 | return ret; | |
942 | } | |
943 | ||
944 | int bt_object_map_insert_bool(struct bt_object *map_obj, | |
945 | const char *key, bool val) | |
946 | { | |
947 | int ret; | |
948 | struct bt_object *bool_obj = NULL; | |
949 | ||
950 | bool_obj = bt_object_bool_create_init(val); | |
951 | ret = bt_object_map_insert(map_obj, key, bool_obj); | |
952 | bt_object_put(bool_obj); | |
953 | ||
954 | return ret; | |
955 | } | |
956 | ||
957 | int bt_object_map_insert_integer(struct bt_object *map_obj, | |
958 | const char *key, int64_t val) | |
959 | { | |
960 | int ret; | |
961 | struct bt_object *integer_obj = NULL; | |
962 | ||
963 | integer_obj = bt_object_integer_create_init(val); | |
964 | ret = bt_object_map_insert(map_obj, key, integer_obj); | |
965 | bt_object_put(integer_obj); | |
966 | ||
967 | return ret; | |
968 | } | |
969 | ||
970 | int bt_object_map_insert_float(struct bt_object *map_obj, | |
971 | const char *key, double val) | |
972 | { | |
973 | int ret; | |
974 | struct bt_object *float_obj = NULL; | |
975 | ||
976 | float_obj = bt_object_float_create_init(val); | |
977 | ret = bt_object_map_insert(map_obj, key, float_obj); | |
978 | bt_object_put(float_obj); | |
979 | ||
980 | return ret; | |
981 | } | |
982 | ||
983 | int bt_object_map_insert_string(struct bt_object *map_obj, | |
984 | const char *key, const char *val) | |
985 | { | |
986 | int ret; | |
987 | struct bt_object *string_obj = NULL; | |
988 | ||
989 | string_obj = bt_object_string_create_init(val); | |
990 | ret = bt_object_map_insert(map_obj, key, string_obj); | |
991 | bt_object_put(string_obj); | |
992 | ||
993 | return ret; | |
994 | } | |
995 | ||
996 | int bt_object_map_insert_array(struct bt_object *map_obj, | |
997 | const char *key) | |
998 | { | |
999 | int ret; | |
1000 | struct bt_object *array_obj = NULL; | |
1001 | ||
1002 | array_obj = bt_object_array_create(); | |
1003 | ret = bt_object_map_insert(map_obj, key, array_obj); | |
1004 | bt_object_put(array_obj); | |
1005 | ||
1006 | return ret; | |
1007 | } | |
1008 | ||
1009 | int bt_object_map_insert_map(struct bt_object *map_obj, | |
1010 | const char *key) | |
1011 | { | |
1012 | int ret; | |
1013 | struct bt_object *empty_map_obj = NULL; | |
1014 | ||
1015 | empty_map_obj = bt_object_map_create(); | |
1016 | ret = bt_object_map_insert(map_obj, key, empty_map_obj); | |
1017 | bt_object_put(empty_map_obj); | |
1018 | ||
1019 | return ret; | |
1020 | } | |
1021 | ||
1022 | int bt_object_map_foreach(const struct bt_object *map_obj, | |
1023 | bt_object_map_foreach_cb cb, void *data) | |
1024 | { | |
1025 | int ret = 0; | |
1026 | gpointer key, element_obj; | |
1027 | GHashTableIter iter; | |
1028 | struct bt_object_map *typed_map_obj = BT_OBJECT_TO_MAP(map_obj); | |
1029 | ||
1030 | if (!map_obj || !bt_object_is_map(map_obj) || !cb) { | |
1031 | ret = -1; | |
1032 | goto end; | |
1033 | } | |
1034 | ||
1035 | g_hash_table_iter_init(&iter, typed_map_obj->ght); | |
1036 | ||
1037 | while (g_hash_table_iter_next(&iter, &key, &element_obj)) { | |
1038 | const char *key_str = g_quark_to_string((unsigned long) key); | |
1039 | ||
1040 | if (!cb(key_str, element_obj, data)) { | |
1041 | break; | |
1042 | } | |
1043 | } | |
1044 | ||
1045 | end: | |
1046 | return ret; | |
1047 | } | |
1048 | ||
1049 | struct bt_object *bt_object_copy(const struct bt_object *object) | |
1050 | { | |
1051 | struct bt_object *copy_obj = NULL; | |
1052 | ||
1053 | if (!object) { | |
1054 | goto end; | |
1055 | } | |
1056 | ||
1057 | copy_obj = copy_funcs[object->type](object); | |
1058 | ||
1059 | end: | |
1060 | return copy_obj; | |
1061 | } | |
1062 | ||
1063 | bool bt_object_compare(const struct bt_object *object_a, | |
1064 | const struct bt_object *object_b) | |
1065 | { | |
1066 | bool ret = false; | |
1067 | ||
1068 | if (!object_a || !object_b) { | |
1069 | goto end; | |
1070 | } | |
1071 | ||
1072 | if (object_a->type != object_b->type) { | |
1073 | goto end; | |
1074 | } | |
1075 | ||
1076 | ret = compare_funcs[object_a->type](object_a, object_b); | |
1077 | ||
1078 | end: | |
1079 | return ret; | |
1080 | } |