configure: re-enable '-Wunused-parameter'
[babeltrace.git] / src / lib / trace-ir / field-class.c
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
5 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 */
7
8 #define BT_LOG_TAG "LIB/FIELD-CLASS"
9 #include "lib/logging.h"
10
11 #include "lib/assert-cond.h"
12 #include <babeltrace2/trace-ir/field-class.h>
13 #include <babeltrace2/trace-ir/field.h>
14 #include <babeltrace2/trace-ir/clock-class.h>
15 #include "lib/object.h"
16 #include "compat/compiler.h"
17 #include "compat/endian.h"
18 #include "common/assert.h"
19 #include "compat/glib.h"
20 #include <float.h>
21 #include <inttypes.h>
22 #include <stdbool.h>
23 #include <stdlib.h>
24
25 #include "clock-class.h"
26 #include "field-class.h"
27 #include "field.h"
28 #include "field-path.h"
29 #include "utils.h"
30 #include "lib/func-status.h"
31 #include "lib/integer-range-set.h"
32 #include "lib/value.h"
33
34 BT_EXPORT
35 enum bt_field_class_type bt_field_class_get_type(
36 const struct bt_field_class *fc)
37 {
38 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
39 return fc->type;
40 }
41
42 static
43 int init_field_class(struct bt_field_class *fc, enum bt_field_class_type type,
44 bt_object_release_func release_func)
45 {
46 int ret = 0;
47
48 BT_ASSERT(fc);
49 BT_ASSERT(release_func);
50 bt_object_init_shared(&fc->base, release_func);
51 fc->type = type;
52 fc->user_attributes = bt_value_map_create();
53 if (!fc->user_attributes) {
54 BT_LIB_LOGE_APPEND_CAUSE(
55 "Failed to create a map value object.");
56 ret = -1;
57 goto end;
58 }
59
60 end:
61 return ret;
62 }
63
64 static
65 void finalize_field_class(struct bt_field_class *fc)
66 {
67 BT_OBJECT_PUT_REF_AND_RESET(fc->user_attributes);
68 }
69
70 static
71 void destroy_bit_array_field_class(struct bt_object *obj)
72 {
73 BT_ASSERT(obj);
74 BT_LIB_LOGD("Destroying bit array field class object: %!+F", obj);
75 finalize_field_class((void *) obj);
76 g_free(obj);
77 }
78
79 BT_EXPORT
80 struct bt_field_class *bt_field_class_bit_array_create(
81 struct bt_trace_class *trace_class, uint64_t length)
82 {
83 struct bt_field_class_bit_array *ba_fc = NULL;
84
85 BT_ASSERT_PRE_NO_ERROR();
86 BT_ASSERT_PRE_TC_NON_NULL(trace_class);
87 BT_ASSERT_PRE("valid-length", length > 0 && length <= 64,
88 "Unsupported length for bit array field class "
89 "(minimum is 1, maximum is 64): length=%" PRIu64, length);
90 BT_LOGD("Creating default bit array field class object.");
91 ba_fc = g_new0(struct bt_field_class_bit_array, 1);
92 if (!ba_fc) {
93 BT_LIB_LOGE_APPEND_CAUSE(
94 "Failed to allocate one bit array field class.");
95 goto error;
96 }
97
98 if (init_field_class((void *) ba_fc, BT_FIELD_CLASS_TYPE_BIT_ARRAY,
99 destroy_bit_array_field_class)) {
100 goto error;
101 }
102
103 ba_fc->length = length;
104 BT_LIB_LOGD("Created bit array field class object: %!+F", ba_fc);
105 goto end;
106
107 error:
108 BT_OBJECT_PUT_REF_AND_RESET(ba_fc);
109
110 end:
111 return (void *) ba_fc;
112 }
113
114 BT_EXPORT
115 uint64_t bt_field_class_bit_array_get_length(const struct bt_field_class *fc)
116 {
117 const struct bt_field_class_bit_array *ba_fc = (const void *) fc;
118
119 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
120 BT_ASSERT_PRE_DEV_FC_HAS_TYPE("field-class", fc, "bit-array",
121 BT_FIELD_CLASS_TYPE_BIT_ARRAY, "Field class");
122 return ba_fc->length;
123 }
124
125 static
126 void destroy_bool_field_class(struct bt_object *obj)
127 {
128 BT_ASSERT(obj);
129 BT_LIB_LOGD("Destroying boolean field class object: %!+F", obj);
130 finalize_field_class((void *) obj);
131 g_free(obj);
132 }
133
134 BT_EXPORT
135 struct bt_field_class *bt_field_class_bool_create(
136 bt_trace_class *trace_class)
137 {
138 struct bt_field_class_bool *bool_fc = NULL;
139
140 BT_ASSERT_PRE_NO_ERROR();
141 BT_ASSERT_PRE_TC_NON_NULL(trace_class);
142 BT_LOGD("Creating default boolean field class object.");
143 bool_fc = g_new0(struct bt_field_class_bool, 1);
144 if (!bool_fc) {
145 BT_LIB_LOGE_APPEND_CAUSE(
146 "Failed to allocate one boolean field class.");
147 goto error;
148 }
149
150 if (init_field_class((void *) bool_fc, BT_FIELD_CLASS_TYPE_BOOL,
151 destroy_bool_field_class)) {
152 goto error;
153 }
154
155 BT_LIB_LOGD("Created boolean field class object: %!+F", bool_fc);
156 goto end;
157
158 error:
159 BT_OBJECT_PUT_REF_AND_RESET(bool_fc);
160
161 end:
162 return (void *) bool_fc;
163 }
164
165 static
166 int init_integer_field_class(struct bt_field_class_integer *fc,
167 enum bt_field_class_type type,
168 bt_object_release_func release_func)
169 {
170 int ret;
171
172 ret = init_field_class((void *) fc, type, release_func);
173 if (ret) {
174 goto end;
175 }
176
177 fc->range = 64;
178 fc->base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
179
180 end:
181 return ret;
182 }
183
184 static
185 void destroy_integer_field_class(struct bt_object *obj)
186 {
187 BT_ASSERT(obj);
188 BT_LIB_LOGD("Destroying integer field class object: %!+F", obj);
189 finalize_field_class((void *) obj);
190 g_free(obj);
191 }
192
193 static inline
194 struct bt_field_class *create_integer_field_class(bt_trace_class *trace_class,
195 enum bt_field_class_type type)
196 {
197 struct bt_field_class_integer *int_fc = NULL;
198
199 BT_ASSERT_PRE_TC_NON_NULL(trace_class);
200 BT_LOGD("Creating default integer field class object: type=%s",
201 bt_common_field_class_type_string(type));
202 int_fc = g_new0(struct bt_field_class_integer, 1);
203 if (!int_fc) {
204 BT_LIB_LOGE_APPEND_CAUSE(
205 "Failed to allocate one integer field class.");
206 goto error;
207 }
208
209 if (init_integer_field_class(int_fc, type,
210 destroy_integer_field_class)) {
211 goto error;
212 }
213
214 BT_LIB_LOGD("Created integer field class object: %!+F", int_fc);
215 goto end;
216
217 error:
218 BT_OBJECT_PUT_REF_AND_RESET(int_fc);
219
220 end:
221 return (void *) int_fc;
222 }
223
224 BT_EXPORT
225 struct bt_field_class *bt_field_class_integer_unsigned_create(
226 bt_trace_class *trace_class)
227 {
228 BT_ASSERT_PRE_NO_ERROR();
229
230 return create_integer_field_class(trace_class,
231 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER);
232 }
233
234 BT_EXPORT
235 struct bt_field_class *bt_field_class_integer_signed_create(
236 bt_trace_class *trace_class)
237 {
238 BT_ASSERT_PRE_NO_ERROR();
239
240 return create_integer_field_class(trace_class,
241 BT_FIELD_CLASS_TYPE_SIGNED_INTEGER);
242 }
243
244 BT_EXPORT
245 uint64_t bt_field_class_integer_get_field_value_range(
246 const struct bt_field_class *fc)
247 {
248 const struct bt_field_class_integer *int_fc = (const void *) fc;
249
250 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
251 BT_ASSERT_PRE_DEV_FC_IS_INT("field-class", fc, "Field class");
252 return int_fc->range;
253 }
254
255 static
256 bool size_is_valid_for_enumeration_field_class(
257 struct bt_field_class *fc __attribute__((unused)),
258 uint64_t size __attribute__((unused)))
259 {
260 // TODO
261 return true;
262 }
263
264 BT_EXPORT
265 void bt_field_class_integer_set_field_value_range(
266 struct bt_field_class *fc, uint64_t size)
267 {
268 struct bt_field_class_integer *int_fc = (void *) fc;
269
270 BT_ASSERT_PRE_FC_NON_NULL(fc);
271 BT_ASSERT_PRE_FC_IS_INT("field-class", fc, "Field class");
272 BT_ASSERT_PRE_DEV_FC_HOT(fc);
273 BT_ASSERT_PRE("valid-n",
274 size >= 1 && size <= 64,
275 "Unsupported size for integer field class's field value range "
276 "(minimum is 1, maximum is 64): size=%" PRIu64, size);
277 BT_ASSERT_PRE("valid-n-for-enumeration-field-class",
278 int_fc->common.type == BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER ||
279 int_fc->common.type == BT_FIELD_CLASS_TYPE_SIGNED_INTEGER ||
280 size_is_valid_for_enumeration_field_class(fc, size),
281 "Invalid field value range for enumeration field class: "
282 "at least one of the current mapping ranges contains values "
283 "which are outside this range: %!+F, size=%" PRIu64, fc, size);
284 int_fc->range = size;
285 BT_LIB_LOGD("Set integer field class's field value range: %!+F", fc);
286 }
287
288 BT_EXPORT
289 enum bt_field_class_integer_preferred_display_base
290 bt_field_class_integer_get_preferred_display_base(const struct bt_field_class *fc)
291 {
292 const struct bt_field_class_integer *int_fc = (const void *) fc;
293
294 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
295 BT_ASSERT_PRE_DEV_FC_IS_INT("field-class", fc, "Field class");
296 return int_fc->base;
297 }
298
299 BT_EXPORT
300 void bt_field_class_integer_set_preferred_display_base(
301 struct bt_field_class *fc,
302 enum bt_field_class_integer_preferred_display_base base)
303 {
304 struct bt_field_class_integer *int_fc = (void *) fc;
305
306 BT_ASSERT_PRE_FC_NON_NULL(fc);
307 BT_ASSERT_PRE_FC_IS_INT("field-class", fc, "Field class");
308 BT_ASSERT_PRE_DEV_FC_HOT(fc);
309 int_fc->base = base;
310 BT_LIB_LOGD("Set integer field class's preferred display base: %!+F", fc);
311 }
312
313 static
314 void finalize_enumeration_field_class_mapping(
315 struct bt_field_class_enumeration_mapping *mapping)
316 {
317 BT_ASSERT(mapping);
318
319 if (mapping->label) {
320 g_string_free(mapping->label, TRUE);
321 mapping->label = NULL;
322 }
323
324 BT_OBJECT_PUT_REF_AND_RESET(mapping->range_set);
325 }
326
327 static
328 void destroy_enumeration_field_class(struct bt_object *obj)
329 {
330 struct bt_field_class_enumeration *fc = (void *) obj;
331
332 BT_ASSERT(fc);
333 BT_LIB_LOGD("Destroying enumeration field class object: %!+F", fc);
334 finalize_field_class((void *) obj);
335
336 if (fc->mappings) {
337 uint64_t i;
338
339 for (i = 0; i < fc->mappings->len; i++) {
340 finalize_enumeration_field_class_mapping(
341 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc, i));
342 }
343
344 g_array_free(fc->mappings, TRUE);
345 fc->mappings = NULL;
346 }
347
348 if (fc->label_buf) {
349 g_ptr_array_free(fc->label_buf, TRUE);
350 fc->label_buf = NULL;
351 }
352
353 g_free(fc);
354 }
355
356 static
357 struct bt_field_class *create_enumeration_field_class(
358 bt_trace_class *trace_class, enum bt_field_class_type type)
359 {
360 struct bt_field_class_enumeration *enum_fc = NULL;
361
362 BT_ASSERT_PRE_TC_NON_NULL(trace_class);
363 BT_LOGD("Creating default enumeration field class object: type=%s",
364 bt_common_field_class_type_string(type));
365 enum_fc = g_new0(struct bt_field_class_enumeration, 1);
366 if (!enum_fc) {
367 BT_LIB_LOGE_APPEND_CAUSE(
368 "Failed to allocate one enumeration field class.");
369 goto error;
370 }
371
372 if (init_integer_field_class((void *) enum_fc, type,
373 destroy_enumeration_field_class)) {
374 goto error;
375 }
376
377 enum_fc->mappings = g_array_new(FALSE, TRUE,
378 sizeof(struct bt_field_class_enumeration_mapping));
379 if (!enum_fc->mappings) {
380 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GArray.");
381 goto error;
382 }
383
384 enum_fc->label_buf = g_ptr_array_new();
385 if (!enum_fc->label_buf) {
386 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GArray.");
387 goto error;
388 }
389
390 BT_LIB_LOGD("Created enumeration field class object: %!+F", enum_fc);
391 goto end;
392
393 error:
394 BT_OBJECT_PUT_REF_AND_RESET(enum_fc);
395
396 end:
397 return (void *) enum_fc;
398 }
399
400 BT_EXPORT
401 struct bt_field_class *bt_field_class_enumeration_unsigned_create(
402 bt_trace_class *trace_class)
403 {
404 BT_ASSERT_PRE_NO_ERROR();
405
406 return create_enumeration_field_class(trace_class,
407 BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION);
408 }
409
410 BT_EXPORT
411 struct bt_field_class *bt_field_class_enumeration_signed_create(
412 bt_trace_class *trace_class)
413 {
414 BT_ASSERT_PRE_NO_ERROR();
415
416 return create_enumeration_field_class(trace_class,
417 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION);
418 }
419
420 BT_EXPORT
421 uint64_t bt_field_class_enumeration_get_mapping_count(
422 const struct bt_field_class *fc)
423 {
424 const struct bt_field_class_enumeration *enum_fc = (const void *) fc;
425
426 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
427 BT_ASSERT_PRE_DEV_FC_IS_ENUM("field-class", fc, "Field class");
428 return (uint64_t) enum_fc->mappings->len;
429 }
430
431 BT_EXPORT
432 const struct bt_field_class_enumeration_unsigned_mapping *
433 bt_field_class_enumeration_unsigned_borrow_mapping_by_index_const(
434 const struct bt_field_class *fc, uint64_t index)
435 {
436 const struct bt_field_class_enumeration *enum_fc = (const void *) fc;
437
438 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
439 BT_ASSERT_PRE_DEV_VALID_INDEX(index, enum_fc->mappings->len);
440 BT_ASSERT_PRE_DEV_FC_HAS_TYPE("field-class", fc, "unsigned-enumeration",
441 BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION, "Field class");
442 return (const void *) BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc, index);
443 }
444
445 BT_EXPORT
446 const struct bt_field_class_enumeration_signed_mapping *
447 bt_field_class_enumeration_signed_borrow_mapping_by_index_const(
448 const struct bt_field_class *fc, uint64_t index)
449 {
450 const struct bt_field_class_enumeration *enum_fc = (const void *) fc;
451
452 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
453 BT_ASSERT_PRE_DEV_VALID_INDEX(index, enum_fc->mappings->len);
454 BT_ASSERT_PRE_DEV_FC_HAS_TYPE("field-class", fc, "signed-enumeration",
455 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION, "Field class");
456 return (const void *) BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc, index);
457 }
458
459 static
460 const struct bt_field_class_enumeration_mapping *
461 borrow_enumeration_field_class_mapping_by_label(
462 const struct bt_field_class_enumeration *fc, const char *label,
463 const char *api_func)
464 {
465 struct bt_field_class_enumeration_mapping *mapping = NULL;
466 uint64_t i;
467
468 BT_ASSERT_DBG(fc);
469 BT_ASSERT_PRE_DEV_NON_NULL_FROM_FUNC(api_func, "label", label,
470 "Label");
471
472 for (i = 0; i < fc->mappings->len; i++) {
473 struct bt_field_class_enumeration_mapping *this_mapping =
474 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc, i);
475
476 if (strcmp(this_mapping->label->str, label) == 0) {
477 mapping = this_mapping;
478 goto end;
479 }
480 }
481
482 end:
483 return mapping;
484 }
485
486 BT_EXPORT
487 const struct bt_field_class_enumeration_signed_mapping *
488 bt_field_class_enumeration_signed_borrow_mapping_by_label_const(
489 const struct bt_field_class *fc, const char *label)
490 {
491 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
492 BT_ASSERT_PRE_DEV_FC_HAS_TYPE("field-class", fc, "signed-enumeration",
493 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION, "Field class");
494 return (const void *) borrow_enumeration_field_class_mapping_by_label(
495 (const void *) fc, label, __func__);
496 }
497
498 BT_EXPORT
499 const struct bt_field_class_enumeration_unsigned_mapping *
500 bt_field_class_enumeration_unsigned_borrow_mapping_by_label_const(
501 const struct bt_field_class *fc, const char *label)
502 {
503 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
504 BT_ASSERT_PRE_DEV_FC_HAS_TYPE("field-class", fc, "unsigned-enumeration",
505 BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION, "Field class");
506 return (const void *) borrow_enumeration_field_class_mapping_by_label(
507 (const void *) fc, label, __func__);
508 }
509
510 BT_EXPORT
511 const char *bt_field_class_enumeration_mapping_get_label(
512 const struct bt_field_class_enumeration_mapping *mapping)
513 {
514 BT_ASSERT_PRE_DEV_NON_NULL("enumeration-field-class-mapping",
515 mapping, "Enumeration field class mapping");
516 return mapping->label->str;
517 }
518
519 BT_EXPORT
520 const struct bt_integer_range_set_unsigned *
521 bt_field_class_enumeration_unsigned_mapping_borrow_ranges_const(
522 const struct bt_field_class_enumeration_unsigned_mapping *u_mapping)
523 {
524 const struct bt_field_class_enumeration_mapping *mapping =
525 (const void *) u_mapping;
526
527 BT_ASSERT_PRE_DEV_NON_NULL("enumeration-field-class-mapping",
528 mapping, "Enumeration field class mapping");
529 return (const void *) mapping->range_set;
530 }
531
532 BT_EXPORT
533 const struct bt_integer_range_set_signed *
534 bt_field_class_enumeration_signed_mapping_borrow_ranges_const(
535 const struct bt_field_class_enumeration_signed_mapping *s_mapping)
536 {
537 const struct bt_field_class_enumeration_mapping *mapping =
538 (const void *) s_mapping;
539
540 BT_ASSERT_PRE_DEV_NON_NULL("enumeration-field-class-mapping",
541 mapping, "Enumeration field class mapping");
542 return (const void *) mapping->range_set;
543 }
544
545 BT_EXPORT
546 enum bt_field_class_enumeration_get_mapping_labels_for_value_status
547 bt_field_class_enumeration_unsigned_get_mapping_labels_for_value(
548 const struct bt_field_class *fc, uint64_t value,
549 bt_field_class_enumeration_mapping_label_array *label_array,
550 uint64_t *count)
551 {
552 const struct bt_field_class_enumeration *enum_fc = (const void *) fc;
553 uint64_t i;
554
555 BT_ASSERT_PRE_DEV_NO_ERROR();
556 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
557 BT_ASSERT_PRE_DEV_NON_NULL("label-array-output", label_array,
558 "Label array (output)");
559 BT_ASSERT_PRE_DEV_NON_NULL("count-output", count, "Count (output)");
560 BT_ASSERT_PRE_DEV_FC_HAS_TYPE("field-class", fc, "unsigned-enumeration",
561 BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION, "Field class");
562 g_ptr_array_set_size(enum_fc->label_buf, 0);
563
564 for (i = 0; i < enum_fc->mappings->len; i++) {
565 uint64_t j;
566 const struct bt_field_class_enumeration_mapping *mapping =
567 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc, i);
568
569 for (j = 0; j < mapping->range_set->ranges->len; j++) {
570 const struct bt_integer_range *range = (const void *)
571 BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(
572 mapping->range_set, j);
573
574 if (value >= range->lower.u &&
575 value <= range->upper.u) {
576 g_ptr_array_add(enum_fc->label_buf,
577 mapping->label->str);
578 break;
579 }
580 }
581 }
582
583 *label_array = (void *) enum_fc->label_buf->pdata;
584 *count = (uint64_t) enum_fc->label_buf->len;
585 return BT_FUNC_STATUS_OK;
586 }
587
588 BT_EXPORT
589 enum bt_field_class_enumeration_get_mapping_labels_for_value_status
590 bt_field_class_enumeration_signed_get_mapping_labels_for_value(
591 const struct bt_field_class *fc, int64_t value,
592 bt_field_class_enumeration_mapping_label_array *label_array,
593 uint64_t *count)
594 {
595 const struct bt_field_class_enumeration *enum_fc = (const void *) fc;
596 uint64_t i;
597
598 BT_ASSERT_PRE_DEV_NO_ERROR();
599 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
600 BT_ASSERT_PRE_DEV_NON_NULL("label-array-output", label_array,
601 "Label array (output)");
602 BT_ASSERT_PRE_DEV_NON_NULL("count-output", count, "Count (output)");
603 BT_ASSERT_PRE_DEV_FC_HAS_TYPE("field-class", fc, "signed-enumeration",
604 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION, "Field class");
605 g_ptr_array_set_size(enum_fc->label_buf, 0);
606
607 for (i = 0; i < enum_fc->mappings->len; i++) {
608 uint64_t j;
609 const struct bt_field_class_enumeration_mapping *mapping =
610 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc, i);
611
612 for (j = 0; j < mapping->range_set->ranges->len; j++) {
613 const struct bt_integer_range *range = (const void *)
614 BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(
615 mapping->range_set, j);
616
617 if (value >= range->lower.i &&
618 value <= range->upper.i) {
619 g_ptr_array_add(enum_fc->label_buf,
620 mapping->label->str);
621 break;
622 }
623 }
624 }
625
626 *label_array = (void *) enum_fc->label_buf->pdata;
627 *count = (uint64_t) enum_fc->label_buf->len;
628 return BT_FUNC_STATUS_OK;
629 }
630
631 static
632 bool enumeration_field_class_has_mapping_with_label(
633 const struct bt_field_class_enumeration *enum_fc,
634 const char *label)
635 {
636 uint64_t i;
637 bool exists = false;
638
639 BT_ASSERT(enum_fc);
640 BT_ASSERT(label);
641
642 for (i = 0; i < enum_fc->mappings->len; i++) {
643 struct bt_field_class_enumeration_mapping *mapping_candidate =
644 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc, i);
645
646 if (strcmp(mapping_candidate->label->str, label) == 0) {
647 exists = true;
648 goto end;
649 }
650 }
651
652 end:
653 return exists;
654 }
655
656 static inline
657 enum bt_field_class_enumeration_add_mapping_status
658 add_mapping_to_enumeration_field_class(struct bt_field_class *fc,
659 const char *label, const struct bt_integer_range_set *range_set,
660 const char *api_func)
661 {
662 enum bt_field_class_enumeration_add_mapping_status status =
663 BT_FUNC_STATUS_OK;
664 struct bt_field_class_enumeration *enum_fc = (void *) fc;
665 struct bt_field_class_enumeration_mapping mapping = { 0 };
666
667 BT_ASSERT_PRE_NO_ERROR_FROM_FUNC(api_func);
668 BT_ASSERT(fc);
669 BT_ASSERT_PRE_NON_NULL_FROM_FUNC(api_func, "label", label, "Label");
670 BT_ASSERT_PRE_INT_RANGE_SET_NON_NULL_FROM_FUNC(api_func, range_set);
671 BT_ASSERT_PRE_FROM_FUNC(api_func,
672 "enumeration-field-class-mapping-label-is-unique",
673 !enumeration_field_class_has_mapping_with_label(
674 enum_fc, label),
675 "Duplicate mapping name in enumeration field class: "
676 "%![enum-fc-]+F, label=\"%s\"", fc, label);
677 mapping.range_set = range_set;
678 bt_object_get_ref(mapping.range_set);
679 mapping.label = g_string_new(label);
680 if (!mapping.label) {
681 finalize_enumeration_field_class_mapping(&mapping);
682 status = BT_FUNC_STATUS_MEMORY_ERROR;
683 goto end;
684 }
685
686 g_array_append_val(enum_fc->mappings, mapping);
687 BT_LIB_LOGD("Added mapping to enumeration field class: "
688 "%![fc-]+F, label=\"%s\"", fc, label);
689
690 end:
691 return status;
692 }
693
694 BT_EXPORT
695 enum bt_field_class_enumeration_add_mapping_status
696 bt_field_class_enumeration_unsigned_add_mapping(
697 struct bt_field_class *fc, const char *label,
698 const struct bt_integer_range_set_unsigned *range_set)
699 {
700 BT_ASSERT_PRE_NO_ERROR();
701 BT_ASSERT_PRE_FC_NON_NULL(fc);
702 BT_ASSERT_PRE_FC_HAS_TYPE("field-class", fc,
703 "unsigned-enumeration-field-class",
704 BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION, "Field class");
705 return add_mapping_to_enumeration_field_class(fc, label,
706 (const void *) range_set, __func__);
707 }
708
709 BT_EXPORT
710 enum bt_field_class_enumeration_add_mapping_status
711 bt_field_class_enumeration_signed_add_mapping(
712 struct bt_field_class *fc, const char *label,
713 const struct bt_integer_range_set_signed *range_set)
714 {
715 BT_ASSERT_PRE_NO_ERROR();
716 BT_ASSERT_PRE_FC_NON_NULL(fc);
717 BT_ASSERT_PRE_FC_HAS_TYPE("field-class", fc,
718 "signed-enumeration-field-class",
719 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION, "Field class");
720 return add_mapping_to_enumeration_field_class(fc, label,
721 (const void *) range_set, __func__);
722 }
723
724 static
725 void destroy_real_field_class(struct bt_object *obj)
726 {
727 BT_ASSERT(obj);
728 BT_LIB_LOGD("Destroying real field class object: %!+F", obj);
729 finalize_field_class((void *) obj);
730 g_free(obj);
731 }
732
733 static
734 struct bt_field_class *create_real_field_class(bt_trace_class *trace_class,
735 enum bt_field_class_type type)
736 {
737 struct bt_field_class_real *real_fc = NULL;
738
739 BT_ASSERT_PRE_TC_NON_NULL(trace_class);
740 BT_LOGD("Creating default real field class object: type=%s",
741 bt_common_field_class_type_string(type));
742 real_fc = g_new0(struct bt_field_class_real, 1);
743 if (!real_fc) {
744 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one real field class.");
745 goto error;
746 }
747
748 if (init_field_class((void *) real_fc, type, destroy_real_field_class)) {
749 goto error;
750 }
751
752 BT_LIB_LOGD("Created real field class object: %!+F", real_fc);
753 goto end;
754
755 error:
756 BT_OBJECT_PUT_REF_AND_RESET(real_fc);
757
758 end:
759 return (void *) real_fc;
760 }
761
762 BT_EXPORT
763 struct bt_field_class *bt_field_class_real_single_precision_create(
764 bt_trace_class *trace_class)
765 {
766 BT_ASSERT_PRE_NO_ERROR();
767
768 return create_real_field_class(trace_class,
769 BT_FIELD_CLASS_TYPE_SINGLE_PRECISION_REAL);
770 }
771
772 BT_EXPORT
773 struct bt_field_class *bt_field_class_real_double_precision_create(
774 bt_trace_class *trace_class)
775 {
776 BT_ASSERT_PRE_NO_ERROR();
777
778 return create_real_field_class(trace_class,
779 BT_FIELD_CLASS_TYPE_DOUBLE_PRECISION_REAL);
780 }
781
782 static
783 int init_named_field_classes_container(
784 struct bt_field_class_named_field_class_container *fc,
785 enum bt_field_class_type type,
786 bt_object_release_func fc_release_func,
787 GDestroyNotify named_fc_destroy_func)
788 {
789 int ret = 0;
790
791 ret = init_field_class((void *) fc, type, fc_release_func);
792 if (ret) {
793 goto end;
794 }
795
796 fc->named_fcs = g_ptr_array_new_with_free_func(named_fc_destroy_func);
797 if (!fc->named_fcs) {
798 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GPtrArray.");
799 ret = -1;
800 goto end;
801 }
802
803 fc->name_to_index = g_hash_table_new(g_str_hash, g_str_equal);
804 if (!fc->name_to_index) {
805 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GHashTable.");
806 ret = -1;
807 goto end;
808 }
809
810 end:
811 return ret;
812 }
813
814 static
815 void finalize_named_field_class(struct bt_named_field_class *named_fc)
816 {
817 BT_ASSERT(named_fc);
818 BT_LIB_LOGD("Finalizing named field class: "
819 "addr=%p, name=\"%s\", %![fc-]+F",
820 named_fc, named_fc->name ? named_fc->name->str : NULL,
821 named_fc->fc);
822 BT_OBJECT_PUT_REF_AND_RESET(named_fc->user_attributes);
823
824 if (named_fc->name) {
825 g_string_free(named_fc->name, TRUE);
826 named_fc->name = NULL;
827 }
828
829 BT_LOGD_STR("Putting named field class's field class.");
830 BT_OBJECT_PUT_REF_AND_RESET(named_fc->fc);
831 }
832
833 static
834 void destroy_named_field_class(gpointer ptr)
835 {
836 struct bt_named_field_class *named_fc = ptr;
837
838 if (ptr) {
839 BT_OBJECT_PUT_REF_AND_RESET(named_fc->user_attributes);
840 finalize_named_field_class(ptr);
841 g_free(ptr);
842 }
843 }
844
845 static
846 void destroy_variant_with_selector_field_option(gpointer ptr)
847 {
848 struct bt_field_class_variant_with_selector_field_option *opt = ptr;
849
850 if (ptr) {
851 finalize_named_field_class(&opt->common);
852 BT_OBJECT_PUT_REF_AND_RESET(opt->range_set);
853 g_free(ptr);
854 }
855 }
856
857 static
858 void finalize_named_field_classes_container(
859 struct bt_field_class_named_field_class_container *fc)
860 {
861 BT_ASSERT(fc);
862
863 if (fc->named_fcs) {
864 g_ptr_array_free(fc->named_fcs, TRUE);
865 fc->named_fcs = NULL;
866
867 }
868
869 if (fc->name_to_index) {
870 g_hash_table_destroy(fc->name_to_index);
871 fc->name_to_index = NULL;
872 }
873 }
874
875 static
876 void destroy_structure_field_class(struct bt_object *obj)
877 {
878 BT_ASSERT(obj);
879 BT_LIB_LOGD("Destroying structure field class object: %!+F", obj);
880 finalize_field_class((void *) obj);
881 finalize_named_field_classes_container((void *) obj);
882 g_free(obj);
883 }
884
885 BT_EXPORT
886 struct bt_field_class *bt_field_class_structure_create(
887 bt_trace_class *trace_class)
888 {
889 int ret;
890 struct bt_field_class_structure *struct_fc = NULL;
891
892 BT_ASSERT_PRE_NO_ERROR();
893 BT_ASSERT_PRE_TC_NON_NULL(trace_class);
894 BT_LOGD_STR("Creating default structure field class object.");
895 struct_fc = g_new0(struct bt_field_class_structure, 1);
896 if (!struct_fc) {
897 BT_LIB_LOGE_APPEND_CAUSE(
898 "Failed to allocate one structure field class.");
899 goto error;
900 }
901
902 ret = init_named_field_classes_container((void *) struct_fc,
903 BT_FIELD_CLASS_TYPE_STRUCTURE, destroy_structure_field_class,
904 destroy_named_field_class);
905 if (ret) {
906 /* init_named_field_classes_container() logs errors */
907 goto error;
908 }
909
910 BT_LIB_LOGD("Created structure field class object: %!+F", struct_fc);
911 goto end;
912
913 error:
914 BT_OBJECT_PUT_REF_AND_RESET(struct_fc);
915
916 end:
917 return (void *) struct_fc;
918 }
919
920 static
921 int init_named_field_class(struct bt_named_field_class *named_fc,
922 const char *name, struct bt_field_class *fc)
923 {
924 int status = BT_FUNC_STATUS_OK;
925
926 BT_ASSERT(named_fc);
927 BT_ASSERT(name);
928 BT_ASSERT(fc);
929 named_fc->name = g_string_new(name);
930 if (!named_fc->name) {
931 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
932 status = BT_FUNC_STATUS_MEMORY_ERROR;
933 goto end;
934 }
935
936 named_fc->user_attributes = bt_value_map_create();
937 if (!named_fc->user_attributes) {
938 BT_LIB_LOGE_APPEND_CAUSE(
939 "Failed to create a map value object.");
940 status = BT_FUNC_STATUS_MEMORY_ERROR;
941 goto end;
942 }
943
944 named_fc->fc = fc;
945 bt_object_get_ref_no_null_check(named_fc->fc);
946
947 end:
948 return status;
949 }
950
951 static
952 struct bt_named_field_class *create_named_field_class(const char *name,
953 struct bt_field_class *fc)
954 {
955 struct bt_named_field_class *named_fc = g_new0(
956 struct bt_named_field_class, 1);
957
958 if (!named_fc) {
959 BT_LIB_LOGE_APPEND_CAUSE(
960 "Failed to allocate a named field class.");
961 goto error;
962 }
963
964 if (init_named_field_class(named_fc, name, fc)) {
965 /* init_named_field_class() logs errors */
966 goto error;
967 }
968
969 goto end;
970
971 error:
972 destroy_named_field_class(named_fc);
973 named_fc = NULL;
974
975 end:
976 return named_fc;
977 }
978
979 static
980 struct bt_field_class_variant_with_selector_field_option *
981 create_variant_with_selector_field_option(
982 const char *name, struct bt_field_class *fc,
983 const struct bt_integer_range_set *range_set)
984 {
985 struct bt_field_class_variant_with_selector_field_option *opt = g_new0(
986 struct bt_field_class_variant_with_selector_field_option, 1);
987
988 BT_ASSERT(range_set);
989
990 if (!opt) {
991 BT_LIB_LOGE_APPEND_CAUSE(
992 "Failed to allocate a named field class.");
993 goto error;
994 }
995
996 if (init_named_field_class(&opt->common, name, fc)) {
997 goto error;
998 }
999
1000 opt->range_set = range_set;
1001 bt_object_get_ref_no_null_check(opt->range_set);
1002 bt_integer_range_set_freeze(range_set);
1003 goto end;
1004
1005 error:
1006 destroy_variant_with_selector_field_option(opt);
1007 opt = NULL;
1008
1009 end:
1010 return opt;
1011 }
1012
1013 static
1014 int append_named_field_class_to_container_field_class(
1015 struct bt_field_class_named_field_class_container *container_fc,
1016 struct bt_named_field_class *named_fc, const char *api_func,
1017 const char *unique_entry_precond_id)
1018 {
1019 BT_ASSERT(container_fc);
1020 BT_ASSERT(named_fc);
1021 BT_ASSERT_PRE_DEV_FC_HOT_FROM_FUNC(api_func, container_fc);
1022 BT_ASSERT_PRE_FROM_FUNC(api_func, unique_entry_precond_id,
1023 !bt_g_hash_table_contains(container_fc->name_to_index,
1024 named_fc->name->str),
1025 "Duplicate member/option name in structure/variant field class: "
1026 "%![container-fc-]+F, name=\"%s\"", container_fc,
1027 named_fc->name->str);
1028
1029 /*
1030 * Freeze the contained field class, but not the named field
1031 * class itself, as it's still possible afterwards to modify
1032 * properties of the member/option object.
1033 */
1034 bt_field_class_freeze(named_fc->fc);
1035 g_ptr_array_add(container_fc->named_fcs, named_fc);
1036 g_hash_table_insert(container_fc->name_to_index, named_fc->name->str,
1037 GUINT_TO_POINTER(container_fc->named_fcs->len - 1));
1038 return BT_FUNC_STATUS_OK;
1039 }
1040
1041 BT_EXPORT
1042 enum bt_field_class_structure_append_member_status
1043 bt_field_class_structure_append_member(
1044 struct bt_field_class *fc, const char *name,
1045 struct bt_field_class *member_fc)
1046 {
1047 enum bt_field_class_structure_append_member_status status;
1048 struct bt_named_field_class *named_fc = NULL;
1049
1050 BT_ASSERT_PRE_NO_ERROR();
1051 BT_ASSERT_PRE_FC_NON_NULL(fc);
1052 BT_ASSERT_PRE_FC_IS_STRUCT("field-class", fc, "Field class");
1053 named_fc = create_named_field_class(name, member_fc);
1054 if (!named_fc) {
1055 /* create_named_field_class() logs errors */
1056 status = BT_FUNC_STATUS_MEMORY_ERROR;
1057 goto end;
1058 }
1059
1060 status = append_named_field_class_to_container_field_class((void *) fc,
1061 named_fc, __func__,
1062 "structure-field-class-member-name-is-unique");
1063 if (status == BT_FUNC_STATUS_OK) {
1064 /* Moved to the container */
1065 named_fc = NULL;
1066 }
1067
1068 end:
1069 return status;
1070 }
1071
1072 BT_EXPORT
1073 uint64_t bt_field_class_structure_get_member_count(
1074 const struct bt_field_class *fc)
1075 {
1076 struct bt_field_class_structure *struct_fc = (void *) fc;
1077
1078 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
1079 BT_ASSERT_PRE_DEV_FC_IS_STRUCT("field-class", fc, "Field class");
1080 return (uint64_t) struct_fc->common.named_fcs->len;
1081 }
1082
1083 static
1084 struct bt_named_field_class *
1085 borrow_named_field_class_from_container_field_class_at_index(
1086 struct bt_field_class_named_field_class_container *fc,
1087 uint64_t index, const char *api_func)
1088 {
1089 BT_ASSERT_DBG(fc);
1090 BT_ASSERT_PRE_DEV_VALID_INDEX_FROM_FUNC(api_func, index,
1091 fc->named_fcs->len);
1092 return fc->named_fcs->pdata[index];
1093 }
1094
1095 BT_EXPORT
1096 const struct bt_field_class_structure_member *
1097 bt_field_class_structure_borrow_member_by_index_const(
1098 const struct bt_field_class *fc, uint64_t index)
1099 {
1100 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
1101 BT_ASSERT_PRE_DEV_FC_IS_STRUCT("field-class", fc, "Field class");
1102 return (const void *)
1103 borrow_named_field_class_from_container_field_class_at_index(
1104 (void *) fc, index, __func__);
1105 }
1106
1107 BT_EXPORT
1108 struct bt_field_class_structure_member *
1109 bt_field_class_structure_borrow_member_by_index(
1110 struct bt_field_class *fc, uint64_t index)
1111 {
1112 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
1113 BT_ASSERT_PRE_DEV_FC_IS_STRUCT("field-class", fc, "Field class");
1114 return (void *)
1115 borrow_named_field_class_from_container_field_class_at_index(
1116 (void *) fc, index, __func__);
1117 }
1118
1119 static
1120 struct bt_named_field_class *
1121 borrow_named_field_class_from_container_field_class_by_name(
1122 struct bt_field_class_named_field_class_container *fc,
1123 const char *name, const char *api_func)
1124 {
1125 struct bt_named_field_class *named_fc = NULL;
1126 gpointer orig_key;
1127 gpointer value;
1128
1129 BT_ASSERT_DBG(fc);
1130 BT_ASSERT_PRE_DEV_NAME_NON_NULL_FROM_FUNC(api_func, name);
1131 if (!g_hash_table_lookup_extended(fc->name_to_index, name, &orig_key,
1132 &value)) {
1133 goto end;
1134 }
1135
1136 named_fc = fc->named_fcs->pdata[GPOINTER_TO_UINT(value)];
1137
1138 end:
1139 return named_fc;
1140 }
1141
1142 BT_EXPORT
1143 const struct bt_field_class_structure_member *
1144 bt_field_class_structure_borrow_member_by_name_const(
1145 const struct bt_field_class *fc, const char *name)
1146 {
1147 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
1148 BT_ASSERT_PRE_DEV_FC_IS_STRUCT("field-class", fc, "Field class");
1149 return (const void *)
1150 borrow_named_field_class_from_container_field_class_by_name(
1151 (void *) fc, name, __func__);
1152 }
1153
1154 BT_EXPORT
1155 struct bt_field_class_structure_member *
1156 bt_field_class_structure_borrow_member_by_name(
1157 struct bt_field_class *fc, const char *name)
1158 {
1159 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
1160 BT_ASSERT_PRE_DEV_FC_IS_STRUCT("field-class", fc, "Field class");
1161 return (void *)
1162 borrow_named_field_class_from_container_field_class_by_name(
1163 (void *) fc, name, __func__);
1164 }
1165
1166 BT_EXPORT
1167 const char *bt_field_class_structure_member_get_name(
1168 const struct bt_field_class_structure_member *member)
1169 {
1170 const struct bt_named_field_class *named_fc = (const void *) member;
1171
1172 BT_ASSERT_PRE_DEV_STRUCT_FC_MEMBER_NON_NULL(member);
1173 return named_fc->name->str;
1174 }
1175
1176 BT_EXPORT
1177 const struct bt_field_class *
1178 bt_field_class_structure_member_borrow_field_class_const(
1179 const struct bt_field_class_structure_member *member)
1180 {
1181 const struct bt_named_field_class *named_fc = (const void *) member;
1182
1183 BT_ASSERT_PRE_DEV_STRUCT_FC_MEMBER_NON_NULL(member);
1184 return named_fc->fc;
1185 }
1186
1187 BT_EXPORT
1188 struct bt_field_class *
1189 bt_field_class_structure_member_borrow_field_class(
1190 struct bt_field_class_structure_member *member)
1191 {
1192 struct bt_named_field_class *named_fc = (void *) member;
1193
1194 BT_ASSERT_PRE_DEV_STRUCT_FC_MEMBER_NON_NULL(member);
1195 return named_fc->fc;
1196 }
1197
1198 static
1199 void destroy_option_field_class(struct bt_object *obj)
1200 {
1201 struct bt_field_class_option *fc = (void *) obj;
1202
1203 BT_ASSERT(fc);
1204 BT_LIB_LOGD("Destroying option field class object: %!+F", fc);
1205 finalize_field_class((void *) obj);
1206 BT_LOGD_STR("Putting content field class.");
1207 BT_OBJECT_PUT_REF_AND_RESET(fc->content_fc);
1208
1209 if (fc->common.type != BT_FIELD_CLASS_TYPE_OPTION_WITHOUT_SELECTOR_FIELD) {
1210 struct bt_field_class_option_with_selector_field *with_sel_fc =
1211 (void *) obj;
1212
1213 BT_LOGD_STR("Putting selector field path.");
1214 BT_OBJECT_PUT_REF_AND_RESET(with_sel_fc->selector_field_path);
1215 BT_LOGD_STR("Putting selector field class.");
1216 BT_OBJECT_PUT_REF_AND_RESET(with_sel_fc->selector_fc);
1217
1218 if (fc->common.type != BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD) {
1219 struct bt_field_class_option_with_selector_field_integer *with_int_sel_fc =
1220 (void *) obj;
1221
1222 BT_LOGD_STR("Putting integer range set.");
1223 BT_OBJECT_PUT_REF_AND_RESET(with_int_sel_fc->range_set);
1224 }
1225 }
1226
1227 g_free(fc);
1228 }
1229
1230 static
1231 struct bt_field_class *create_option_field_class(
1232 struct bt_trace_class *trace_class,
1233 enum bt_field_class_type fc_type,
1234 struct bt_field_class *content_fc,
1235 struct bt_field_class *selector_fc,
1236 const char *api_func)
1237 {
1238 struct bt_field_class_option *opt_fc = NULL;
1239
1240 BT_ASSERT_PRE_NO_ERROR_FROM_FUNC(api_func);
1241 BT_ASSERT_PRE_TC_NON_NULL_FROM_FUNC(api_func, trace_class);
1242 BT_ASSERT_PRE_NON_NULL_FROM_FUNC(api_func, "content-field-class",
1243 content_fc, "Content field class");
1244 BT_LIB_LOGD("Creating option field class: "
1245 "type=%s, %![content-fc-]+F, %![sel-fc-]+F",
1246 bt_common_field_class_type_string(fc_type),
1247 content_fc, selector_fc);
1248
1249 if (fc_type != BT_FIELD_CLASS_TYPE_OPTION_WITHOUT_SELECTOR_FIELD) {
1250 struct bt_field_class_option_with_selector_field *opt_with_sel_fc = NULL;
1251
1252 BT_ASSERT_PRE_NON_NULL_FROM_FUNC(api_func,
1253 "selector-field-class", selector_fc,
1254 "Selector field class");
1255
1256 if (fc_type == BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD) {
1257 BT_ASSERT_PRE_FC_HAS_TYPE_FROM_FUNC(api_func,
1258 "selector-field-class", selector_fc,
1259 "boolean-field-class", BT_FIELD_CLASS_TYPE_BOOL,
1260 "Selector field class");
1261 opt_with_sel_fc = (void *) g_new0(
1262 struct bt_field_class_option_with_selector_field_bool, 1);
1263 } else {
1264 BT_ASSERT_PRE_FC_IS_INT_FROM_FUNC(api_func,
1265 "selector-field-class",
1266 selector_fc, "Selector field class");
1267 opt_with_sel_fc = (void *) g_new0(
1268 struct bt_field_class_option_with_selector_field_integer, 1);
1269 }
1270
1271 if (!opt_with_sel_fc) {
1272 BT_LIB_LOGE_APPEND_CAUSE(
1273 "Failed to allocate one option with selector field class.");
1274 goto error;
1275 }
1276
1277 opt_with_sel_fc->selector_fc = selector_fc;
1278 bt_object_get_ref_no_null_check(opt_with_sel_fc->selector_fc);
1279 opt_fc = (void *) opt_with_sel_fc;
1280 } else {
1281 opt_fc = g_new0(struct bt_field_class_option, 1);
1282 if (!opt_fc) {
1283 BT_LIB_LOGE_APPEND_CAUSE(
1284 "Failed to allocate one option field class.");
1285 goto error;
1286 }
1287 }
1288
1289 BT_ASSERT(opt_fc);
1290
1291 if (init_field_class((void *) opt_fc, fc_type,
1292 destroy_option_field_class)) {
1293 goto error;
1294 }
1295
1296 opt_fc->content_fc = content_fc;
1297 bt_object_get_ref_no_null_check(opt_fc->content_fc);
1298 bt_field_class_freeze(opt_fc->content_fc);
1299
1300 if (selector_fc) {
1301 bt_field_class_freeze(selector_fc);
1302 }
1303
1304 BT_LIB_LOGD("Created option field class object: "
1305 "%![opt-fc-]+F, %![sel-fc-]+F", opt_fc, selector_fc);
1306 goto end;
1307
1308 error:
1309 BT_OBJECT_PUT_REF_AND_RESET(opt_fc);
1310
1311 end:
1312 return (void *) opt_fc;
1313 }
1314
1315 BT_EXPORT
1316 struct bt_field_class *bt_field_class_option_without_selector_create(
1317 struct bt_trace_class *trace_class,
1318 struct bt_field_class *content_fc)
1319 {
1320 return create_option_field_class(trace_class,
1321 BT_FIELD_CLASS_TYPE_OPTION_WITHOUT_SELECTOR_FIELD,
1322 content_fc, NULL, __func__);
1323 }
1324
1325 BT_EXPORT
1326 struct bt_field_class *bt_field_class_option_with_selector_field_bool_create(
1327 struct bt_trace_class *trace_class,
1328 struct bt_field_class *content_fc,
1329 struct bt_field_class *selector_fc)
1330 {
1331 BT_ASSERT_PRE_NO_ERROR();
1332
1333 return create_option_field_class(trace_class,
1334 BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD,
1335 content_fc, selector_fc, __func__);
1336 }
1337
1338 BT_EXPORT
1339 struct bt_field_class *
1340 bt_field_class_option_with_selector_field_integer_unsigned_create(
1341 struct bt_trace_class *trace_class,
1342 struct bt_field_class *content_fc,
1343 struct bt_field_class *selector_fc,
1344 const struct bt_integer_range_set_unsigned *u_range_set)
1345 {
1346 struct bt_field_class_option_with_selector_field_integer *fc;
1347 const struct bt_integer_range_set *range_set =
1348 (const void *) u_range_set;
1349
1350 BT_ASSERT_PRE_NO_ERROR();
1351 BT_ASSERT_PRE_INT_RANGE_SET_NON_NULL(range_set);
1352 BT_ASSERT_PRE_INT_RANGE_SET_NOT_EMPTY(range_set);
1353 fc = (void *) create_option_field_class(trace_class,
1354 BT_FIELD_CLASS_TYPE_OPTION_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD,
1355 content_fc, selector_fc, __func__);
1356
1357 if (!fc) {
1358 goto end;
1359 }
1360
1361 fc->range_set = range_set;
1362 bt_object_get_ref_no_null_check(fc->range_set);
1363 bt_integer_range_set_freeze(range_set);
1364
1365 end:
1366 return (void *) fc;
1367 }
1368
1369 BT_EXPORT
1370 struct bt_field_class *
1371 bt_field_class_option_with_selector_field_integer_signed_create(
1372 struct bt_trace_class *trace_class,
1373 struct bt_field_class *content_fc,
1374 struct bt_field_class *selector_fc,
1375 const struct bt_integer_range_set_signed *i_range_set)
1376 {
1377 struct bt_field_class_option_with_selector_field_integer *fc;
1378 const struct bt_integer_range_set *range_set =
1379 (const void *) i_range_set;
1380
1381 BT_ASSERT_PRE_NO_ERROR();
1382 BT_ASSERT_PRE_INT_RANGE_SET_NON_NULL(range_set);
1383 BT_ASSERT_PRE_INT_RANGE_SET_NOT_EMPTY(range_set);
1384 fc = (void *) create_option_field_class(trace_class,
1385 BT_FIELD_CLASS_TYPE_OPTION_WITH_SIGNED_INTEGER_SELECTOR_FIELD,
1386 content_fc, selector_fc, __func__);
1387
1388 if (!fc) {
1389 goto end;
1390 }
1391
1392 fc->range_set = range_set;
1393 bt_object_get_ref_no_null_check(fc->range_set);
1394 bt_integer_range_set_freeze(range_set);
1395
1396 end:
1397 return (void *) fc;
1398 }
1399
1400 BT_EXPORT
1401 const struct bt_field_class *bt_field_class_option_borrow_field_class_const(
1402 const struct bt_field_class *fc)
1403 {
1404 struct bt_field_class_option *opt_fc = (void *) fc;
1405
1406 BT_ASSERT_PRE_FC_NON_NULL(fc);
1407 BT_ASSERT_PRE_FC_IS_OPTION("field-class", fc, "Field class");
1408 return opt_fc->content_fc;
1409 }
1410
1411 BT_EXPORT
1412 struct bt_field_class *bt_field_class_option_borrow_field_class(
1413 struct bt_field_class *fc)
1414 {
1415 struct bt_field_class_option *opt_fc = (void *) fc;
1416
1417 BT_ASSERT_PRE_FC_NON_NULL(fc);
1418 BT_ASSERT_PRE_FC_IS_OPTION("field-class", fc, "Field class");
1419 return opt_fc->content_fc;
1420 }
1421
1422 BT_EXPORT
1423 const struct bt_field_path *
1424 bt_field_class_option_with_selector_field_borrow_selector_field_path_const(
1425 const struct bt_field_class *fc)
1426 {
1427 const struct bt_field_class_option_with_selector_field *opt_fc =
1428 (const void *) fc;
1429
1430 BT_ASSERT_PRE_FC_NON_NULL(fc);
1431 BT_ASSERT_PRE_FC_IS_OPTION_WITH_SEL("field-class", fc, "Field class");
1432 return opt_fc->selector_field_path;
1433 }
1434
1435 BT_EXPORT
1436 void bt_field_class_option_with_selector_field_bool_set_selector_is_reversed(
1437 struct bt_field_class *fc, bt_bool sel_is_reversed)
1438 {
1439 struct bt_field_class_option_with_selector_field_bool *opt_fc = (void *) fc;
1440
1441 BT_ASSERT_PRE_FC_NON_NULL(fc);
1442 BT_ASSERT_PRE_FC_HAS_TYPE("field-class", fc,
1443 "option-field-class-with-boolean-selector-field",
1444 BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD,
1445 "Field class");
1446 BT_ASSERT_PRE_DEV_FC_HOT(fc);
1447 opt_fc->sel_is_reversed = sel_is_reversed;
1448 }
1449
1450 BT_EXPORT
1451 bt_bool bt_field_class_option_with_selector_field_bool_selector_is_reversed(
1452 const struct bt_field_class *fc)
1453 {
1454 struct bt_field_class_option_with_selector_field_bool *opt_fc = (void *) fc;
1455
1456 BT_ASSERT_PRE_FC_NON_NULL(fc);
1457 BT_ASSERT_PRE_FC_HAS_TYPE("field-class", fc,
1458 "option-field-class-with-boolean-selector-field",
1459 BT_FIELD_CLASS_TYPE_OPTION_WITH_BOOL_SELECTOR_FIELD,
1460 "Field class");
1461 return opt_fc->sel_is_reversed;
1462 }
1463
1464 BT_EXPORT
1465 const struct bt_integer_range_set_unsigned *
1466 bt_field_class_option_with_selector_field_integer_unsigned_borrow_selector_ranges_const(
1467 const struct bt_field_class *fc)
1468 {
1469 struct bt_field_class_option_with_selector_field_integer *opt_fc =
1470 (void *) fc;
1471
1472 BT_ASSERT_PRE_FC_NON_NULL(fc);
1473 BT_ASSERT_PRE_FC_IS_OPTION_WITH_INT_SEL("field-class", fc,
1474 "Field class");
1475 return (const void *) opt_fc->range_set;
1476 }
1477
1478 BT_EXPORT
1479 const struct bt_integer_range_set_signed *
1480 bt_field_class_option_with_selector_field_integer_signed_borrow_selector_ranges_const(
1481 const struct bt_field_class *fc)
1482 {
1483 struct bt_field_class_option_with_selector_field_integer *opt_fc =
1484 (void *) fc;
1485
1486 BT_ASSERT_PRE_FC_NON_NULL(fc);
1487 BT_ASSERT_PRE_FC_IS_OPTION_WITH_INT_SEL("field-class", fc,
1488 "Field class");
1489 return (const void *) opt_fc->range_set;
1490 }
1491
1492 static
1493 void finalize_variant_field_class(struct bt_field_class_variant *var_fc)
1494 {
1495 BT_ASSERT(var_fc);
1496 BT_LIB_LOGD("Finalizing variant field class object: %!+F", var_fc);
1497 finalize_field_class((void *) var_fc);
1498 finalize_named_field_classes_container((void *) var_fc);
1499 }
1500
1501 static
1502 void destroy_variant_field_class(struct bt_object *obj)
1503 {
1504 struct bt_field_class_variant *fc = (void *) obj;
1505
1506 BT_ASSERT(fc);
1507 finalize_variant_field_class(fc);
1508 g_free(fc);
1509 }
1510
1511 static
1512 void destroy_variant_with_selector_field_field_class(struct bt_object *obj)
1513 {
1514 struct bt_field_class_variant_with_selector_field *fc = (void *) obj;
1515
1516 BT_ASSERT(fc);
1517 finalize_variant_field_class(&fc->common);
1518 BT_LOGD_STR("Putting selector field path.");
1519 BT_OBJECT_PUT_REF_AND_RESET(fc->selector_field_path);
1520 BT_LOGD_STR("Putting selector field class.");
1521 BT_OBJECT_PUT_REF_AND_RESET(fc->selector_fc);
1522 g_free(fc);
1523 }
1524
1525 BT_EXPORT
1526 struct bt_field_class *bt_field_class_variant_create(
1527 bt_trace_class *trace_class, bt_field_class *selector_fc)
1528 {
1529 int ret;
1530 struct bt_field_class_variant *var_fc = NULL;
1531 struct bt_field_class_variant_with_selector_field *var_with_sel_fc = NULL;
1532 enum bt_field_class_type fc_type;
1533
1534 BT_ASSERT_PRE_NO_ERROR();
1535 BT_ASSERT_PRE_TC_NON_NULL(trace_class);
1536
1537 if (selector_fc) {
1538 BT_ASSERT_PRE_FC_IS_INT("selector-field-class", selector_fc,
1539 "Selector field class");
1540 }
1541
1542 BT_LIB_LOGD("Creating default variant field class: %![sel-fc-]+F",
1543 selector_fc);
1544
1545 if (selector_fc) {
1546 var_with_sel_fc = g_new0(
1547 struct bt_field_class_variant_with_selector_field, 1);
1548 if (!var_with_sel_fc) {
1549 BT_LIB_LOGE_APPEND_CAUSE(
1550 "Failed to allocate one variant field class with selector.");
1551 goto error;
1552 }
1553
1554 if (bt_field_class_type_is(selector_fc->type,
1555 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER)) {
1556 fc_type = BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD;
1557 } else {
1558 fc_type = BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD;
1559 }
1560
1561 ret = init_named_field_classes_container(
1562 (void *) var_with_sel_fc, fc_type,
1563 destroy_variant_with_selector_field_field_class,
1564 destroy_variant_with_selector_field_option);
1565 if (ret) {
1566 /* init_named_field_classes_container() logs errors */
1567 goto error;
1568 }
1569
1570 var_with_sel_fc->selector_fc = selector_fc;
1571 bt_object_get_ref_no_null_check(var_with_sel_fc->selector_fc);
1572 bt_field_class_freeze(selector_fc);
1573 var_fc = (void *) var_with_sel_fc;
1574 BT_LIB_LOGD("Created default variant field class with selector object: "
1575 "%![var-fc-]+F, %![sel-fc-]+F", var_fc, selector_fc);
1576 } else {
1577 var_fc = g_new0(struct bt_field_class_variant, 1);
1578 if (!var_fc) {
1579 BT_LIB_LOGE_APPEND_CAUSE(
1580 "Failed to allocate one variant field class without selector.");
1581 goto error;
1582 }
1583
1584 ret = init_named_field_classes_container((void *) var_fc,
1585 BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR_FIELD,
1586 destroy_variant_field_class, destroy_named_field_class);
1587 if (ret) {
1588 /* init_named_field_classes_container() logs errors */
1589 goto error;
1590 }
1591 BT_LIB_LOGD("Created default variant field class without selector object: "
1592 "%![var-fc-]+F", var_fc);
1593 }
1594
1595 BT_ASSERT(var_fc);
1596 goto end;
1597
1598 error:
1599 BT_OBJECT_PUT_REF_AND_RESET(var_fc);
1600 BT_OBJECT_PUT_REF_AND_RESET(var_with_sel_fc);
1601
1602 end:
1603 return (void *) var_fc;
1604 }
1605
1606 #define VAR_FC_OPT_NAME_IS_UNIQUE_ID \
1607 "variant-field-class-option-name-is-unique"
1608
1609 BT_EXPORT
1610 enum bt_field_class_variant_without_selector_append_option_status
1611 bt_field_class_variant_without_selector_append_option(struct bt_field_class *fc,
1612 const char *name, struct bt_field_class *option_fc)
1613 {
1614 enum bt_field_class_variant_without_selector_append_option_status status;
1615 struct bt_named_field_class *named_fc = NULL;
1616
1617 BT_ASSERT_PRE_NO_ERROR();
1618 BT_ASSERT_PRE_FC_NON_NULL(fc);
1619 BT_ASSERT_PRE_NAME_NON_NULL(name);
1620 BT_ASSERT_PRE_NON_NULL("option-field-class", option_fc,
1621 "Option field class");
1622 BT_ASSERT_PRE_FC_HAS_TYPE("field-class", fc,
1623 "variant-field-class-without-selector-field",
1624 BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR_FIELD,
1625 "Field class");
1626 named_fc = create_named_field_class(name, option_fc);
1627 if (!named_fc) {
1628 /* create_named_field_class() logs errors */
1629 status = BT_FUNC_STATUS_MEMORY_ERROR;
1630 goto end;
1631 }
1632
1633 status = append_named_field_class_to_container_field_class((void *) fc,
1634 named_fc, __func__, VAR_FC_OPT_NAME_IS_UNIQUE_ID);
1635 if (status == BT_FUNC_STATUS_OK) {
1636 /* Moved to the container */
1637 named_fc = NULL;
1638 }
1639
1640 end:
1641 if (named_fc) {
1642 destroy_named_field_class(named_fc);
1643 }
1644
1645 return status;
1646 }
1647
1648 static
1649 int ranges_overlap(GPtrArray *var_fc_opts, const struct bt_integer_range_set *range_set,
1650 bool is_signed, bool *has_overlap)
1651 {
1652 int status = BT_FUNC_STATUS_OK;
1653 struct bt_integer_range_set *full_range_set;
1654 uint64_t i;
1655
1656 *has_overlap = false;
1657
1658 /*
1659 * Build a single range set with all the ranges and test for
1660 * overlaps.
1661 */
1662 if (is_signed) {
1663 full_range_set = (void *) bt_integer_range_set_signed_create();
1664 } else {
1665 full_range_set = (void *) bt_integer_range_set_unsigned_create();
1666 }
1667
1668 if (!full_range_set) {
1669 BT_LOGE_STR("Failed to create a range set.");
1670 status = BT_FUNC_STATUS_MEMORY_ERROR;
1671 goto end;
1672 }
1673
1674 /* Add existing option ranges */
1675 for (i = 0; i < var_fc_opts->len; i++) {
1676 struct bt_field_class_variant_with_selector_field_option *opt =
1677 var_fc_opts->pdata[i];
1678 uint64_t j;
1679
1680 for (j = 0; j < opt->range_set->ranges->len; j++) {
1681 struct bt_integer_range *range = BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(
1682 opt->range_set, j);
1683
1684 if (is_signed) {
1685 status = bt_integer_range_set_signed_add_range(
1686 (void *) full_range_set, range->lower.i,
1687 range->upper.i);
1688 } else {
1689 status = bt_integer_range_set_unsigned_add_range(
1690 (void *) full_range_set, range->lower.u,
1691 range->upper.u);
1692 }
1693
1694 if (status) {
1695 goto end;
1696 }
1697 }
1698 }
1699
1700 /* Add new ranges */
1701 for (i = 0; i < range_set->ranges->len; i++) {
1702 struct bt_integer_range *range = BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(
1703 range_set, i);
1704
1705 if (is_signed) {
1706 status = bt_integer_range_set_signed_add_range(
1707 (void *) full_range_set, range->lower.i,
1708 range->upper.i);
1709 } else {
1710 status = bt_integer_range_set_unsigned_add_range(
1711 (void *) full_range_set, range->lower.u,
1712 range->upper.u);
1713 }
1714
1715 if (status) {
1716 goto end;
1717 }
1718 }
1719
1720 /* Check overlaps */
1721 if (is_signed) {
1722 *has_overlap = bt_integer_range_set_signed_has_overlaps(full_range_set);
1723 } else {
1724 *has_overlap = bt_integer_range_set_unsigned_has_overlaps(
1725 full_range_set);
1726 }
1727
1728 end:
1729 bt_object_put_ref(full_range_set);
1730 return status;
1731 }
1732
1733 static
1734 int append_option_to_variant_with_selector_field_field_class(
1735 struct bt_field_class *fc, const char *name,
1736 struct bt_field_class *option_fc,
1737 const struct bt_integer_range_set *range_set,
1738 enum bt_field_class_type expected_type,
1739 const char *api_func)
1740 {
1741 int status;
1742 struct bt_field_class_variant_with_selector_field *var_fc = (void *) fc;
1743 struct bt_field_class_variant_with_selector_field_option *opt = NULL;
1744 bool has_overlap;
1745
1746 BT_ASSERT(fc);
1747 BT_ASSERT_PRE_NAME_NON_NULL_FROM_FUNC(api_func, name);
1748 BT_ASSERT_PRE_NON_NULL_FROM_FUNC(api_func, "option-field-class",
1749 option_fc, "Option field class");
1750 BT_ASSERT_PRE_INT_RANGE_SET_NON_NULL_FROM_FUNC(api_func, range_set);
1751 BT_ASSERT_PRE_INT_RANGE_SET_NOT_EMPTY_FROM_FUNC(api_func, range_set);
1752 status = ranges_overlap(var_fc->common.common.named_fcs, range_set,
1753 expected_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD,
1754 &has_overlap);
1755 if (status) {
1756 /* ranges_overlap() logs errors */
1757 goto end;
1758 }
1759
1760 BT_ASSERT_PRE_FROM_FUNC(api_func, "ranges-do-not-overlap",
1761 !has_overlap,
1762 "Integer range set's ranges and existing ranges have an overlap: "
1763 "%!+R", range_set);
1764 opt = create_variant_with_selector_field_option(name, option_fc, range_set);
1765 if (!opt) {
1766 /* create_variant_with_selector_field_option() logs errors */
1767 status = BT_FUNC_STATUS_MEMORY_ERROR;
1768 goto end;
1769 }
1770
1771 status = append_named_field_class_to_container_field_class((void *) fc,
1772 &opt->common, __func__, VAR_FC_OPT_NAME_IS_UNIQUE_ID);
1773 if (status == BT_FUNC_STATUS_OK) {
1774 /* Moved to the container */
1775 opt = NULL;
1776 }
1777
1778 end:
1779 if (opt) {
1780 destroy_variant_with_selector_field_option(opt);
1781 }
1782
1783 return status;
1784 }
1785
1786 BT_EXPORT
1787 enum bt_field_class_variant_with_selector_field_integer_append_option_status
1788 bt_field_class_variant_with_selector_field_integer_unsigned_append_option(
1789 struct bt_field_class *fc, const char *name,
1790 struct bt_field_class *option_fc,
1791 const struct bt_integer_range_set_unsigned *range_set)
1792 {
1793 BT_ASSERT_PRE_NO_ERROR();
1794 BT_ASSERT_PRE_FC_NON_NULL(fc);
1795 BT_ASSERT_PRE_FC_HAS_TYPE("field-class", fc,
1796 "variant-field-class-with-unsigned-integer-selector-field",
1797 BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD,
1798 "Field class");
1799 return append_option_to_variant_with_selector_field_field_class(fc,
1800 name, option_fc, (const void *) range_set,
1801 BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD,
1802 __func__);
1803 }
1804
1805 BT_EXPORT
1806 enum bt_field_class_variant_with_selector_field_integer_append_option_status
1807 bt_field_class_variant_with_selector_field_integer_signed_append_option(
1808 struct bt_field_class *fc, const char *name,
1809 struct bt_field_class *option_fc,
1810 const struct bt_integer_range_set_signed *range_set)
1811 {
1812 BT_ASSERT_PRE_NO_ERROR();
1813 BT_ASSERT_PRE_FC_NON_NULL(fc);
1814 BT_ASSERT_PRE_FC_HAS_TYPE("field-class", fc,
1815 "variant-field-class-with-signed-integer-selector-field",
1816 BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD,
1817 "Field class");
1818 return append_option_to_variant_with_selector_field_field_class(fc,
1819 name, option_fc, (const void *) range_set,
1820 BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD,
1821 __func__);
1822 }
1823
1824 BT_EXPORT
1825 uint64_t bt_field_class_variant_get_option_count(const struct bt_field_class *fc)
1826 {
1827 const struct bt_field_class_variant *var_fc = (const void *) fc;
1828
1829 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
1830 BT_ASSERT_PRE_DEV_FC_IS_VARIANT("field-class", fc, "Field class");
1831 return (uint64_t) var_fc->common.named_fcs->len;
1832 }
1833
1834 BT_EXPORT
1835 const struct bt_field_class_variant_option *
1836 bt_field_class_variant_borrow_option_by_name_const(
1837 const struct bt_field_class *fc, const char *name)
1838 {
1839 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
1840 BT_ASSERT_PRE_DEV_FC_IS_VARIANT("field-class", fc, "Field class");
1841 return (const void *)
1842 borrow_named_field_class_from_container_field_class_by_name(
1843 (void *) fc, name, __func__);
1844 }
1845
1846 BT_EXPORT
1847 const struct bt_field_class_variant_option *
1848 bt_field_class_variant_borrow_option_by_index_const(
1849 const struct bt_field_class *fc, uint64_t index)
1850 {
1851 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
1852 BT_ASSERT_PRE_DEV_FC_IS_VARIANT("field-class", fc, "Field class");
1853 return (const void *)
1854 borrow_named_field_class_from_container_field_class_at_index(
1855 (void *) fc, index, __func__);
1856 }
1857
1858 BT_EXPORT
1859 struct bt_field_class_variant_option *
1860 bt_field_class_variant_borrow_option_by_name(
1861 struct bt_field_class *fc, const char *name)
1862 {
1863 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
1864 BT_ASSERT_PRE_DEV_FC_IS_VARIANT("field-class", fc, "Field class");
1865 return (void *)
1866 borrow_named_field_class_from_container_field_class_by_name(
1867 (void *) fc, name, __func__);
1868 }
1869
1870 BT_EXPORT
1871 struct bt_field_class_variant_option *
1872 bt_field_class_variant_borrow_option_by_index(
1873 struct bt_field_class *fc, uint64_t index)
1874 {
1875 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
1876 BT_ASSERT_PRE_DEV_FC_IS_VARIANT("field-class", fc, "Field class");
1877 return (void *)
1878 borrow_named_field_class_from_container_field_class_at_index(
1879 (void *) fc, index, __func__);
1880 }
1881
1882 BT_EXPORT
1883 const struct bt_field_class_variant_with_selector_field_integer_unsigned_option *
1884 bt_field_class_variant_with_selector_field_integer_unsigned_borrow_option_by_name_const(
1885 const struct bt_field_class *fc, const char *name)
1886 {
1887 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
1888 BT_ASSERT_PRE_DEV_FC_HAS_TYPE("field-class", fc,
1889 "variant-field-class-with-unsigned-integer-selector-field",
1890 BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD,
1891 "Field class");
1892 return (const void *)
1893 borrow_named_field_class_from_container_field_class_by_name(
1894 (void *) fc, name, __func__);
1895 }
1896
1897 BT_EXPORT
1898 const struct bt_field_class_variant_with_selector_field_integer_unsigned_option *
1899 bt_field_class_variant_with_selector_field_integer_unsigned_borrow_option_by_index_const(
1900 const struct bt_field_class *fc, uint64_t index)
1901 {
1902 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
1903 BT_ASSERT_PRE_DEV_FC_HAS_TYPE("field-class", fc,
1904 "variant-field-class-with-unsigned-integer-selector-field",
1905 BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_INTEGER_SELECTOR_FIELD,
1906 "Field class");
1907 return (const void *)
1908 borrow_named_field_class_from_container_field_class_at_index(
1909 (void *) fc, index, __func__);
1910 }
1911
1912 BT_EXPORT
1913 const struct bt_field_class_variant_with_selector_field_integer_signed_option *
1914 bt_field_class_variant_with_selector_field_integer_signed_borrow_option_by_name_const(
1915 const struct bt_field_class *fc, const char *name)
1916 {
1917 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
1918 BT_ASSERT_PRE_DEV_FC_HAS_TYPE("field-class", fc,
1919 "variant-field-class-with-signed-integer-selector-field",
1920 BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD,
1921 "Field class");
1922 return (const void *)
1923 borrow_named_field_class_from_container_field_class_by_name(
1924 (void *) fc, name, __func__);
1925 }
1926
1927 BT_EXPORT
1928 const struct bt_field_class_variant_with_selector_field_integer_signed_option *
1929 bt_field_class_variant_with_selector_field_integer_signed_borrow_option_by_index_const(
1930 const struct bt_field_class *fc, uint64_t index)
1931 {
1932 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
1933 BT_ASSERT_PRE_DEV_FC_HAS_TYPE("field-class", fc,
1934 "variant-field-class-with-signed-integer-selector-field",
1935 BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_INTEGER_SELECTOR_FIELD,
1936 "Field class");
1937 return (const void *)
1938 borrow_named_field_class_from_container_field_class_at_index(
1939 (void *) fc, index, __func__);
1940 }
1941
1942 BT_EXPORT
1943 const char *bt_field_class_variant_option_get_name(
1944 const struct bt_field_class_variant_option *option)
1945 {
1946 const struct bt_named_field_class *named_fc = (const void *) option;
1947
1948 BT_ASSERT_PRE_DEV_VAR_FC_OPT_NON_NULL(option);
1949 return named_fc->name->str;
1950 }
1951
1952 BT_EXPORT
1953 const struct bt_field_class *
1954 bt_field_class_variant_option_borrow_field_class_const(
1955 const struct bt_field_class_variant_option *option)
1956 {
1957 const struct bt_named_field_class *named_fc = (const void *) option;
1958
1959 BT_ASSERT_PRE_DEV_VAR_FC_OPT_NON_NULL(option);
1960 return named_fc->fc;
1961 }
1962
1963 BT_EXPORT
1964 struct bt_field_class *
1965 bt_field_class_variant_option_borrow_field_class(
1966 struct bt_field_class_variant_option *option)
1967 {
1968 struct bt_named_field_class *named_fc = (void *) option;
1969
1970 BT_ASSERT_PRE_DEV_VAR_FC_OPT_NON_NULL(option);
1971 return named_fc->fc;
1972 }
1973
1974 BT_EXPORT
1975 const struct bt_integer_range_set_unsigned *
1976 bt_field_class_variant_with_selector_field_integer_unsigned_option_borrow_ranges_const(
1977 const struct bt_field_class_variant_with_selector_field_integer_unsigned_option *option)
1978 {
1979 const struct bt_field_class_variant_with_selector_field_option *opt =
1980 (const void *) option;
1981
1982 BT_ASSERT_PRE_DEV_VAR_FC_OPT_NON_NULL(option);
1983 return (const void *) opt->range_set;
1984 }
1985
1986 BT_EXPORT
1987 const struct bt_integer_range_set_signed *
1988 bt_field_class_variant_with_selector_field_integer_signed_option_borrow_ranges_const(
1989 const struct bt_field_class_variant_with_selector_field_integer_signed_option *option)
1990 {
1991 const struct bt_field_class_variant_with_selector_field_option *opt =
1992 (const void *) option;
1993
1994 BT_ASSERT_PRE_DEV_VAR_FC_OPT_NON_NULL(option);
1995 return (const void *) opt->range_set;
1996 }
1997
1998 BT_EXPORT
1999 const struct bt_field_path *
2000 bt_field_class_variant_with_selector_field_borrow_selector_field_path_const(
2001 const struct bt_field_class *fc)
2002 {
2003 const struct bt_field_class_variant_with_selector_field *var_fc =
2004 (const void *) fc;
2005
2006 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
2007 BT_ASSERT_PRE_DEV_FC_IS_VARIANT_WITH_SEL("field-class", fc,
2008 "Field class");
2009 return var_fc->selector_field_path;
2010 }
2011
2012 static
2013 int init_array_field_class(struct bt_field_class_array *fc,
2014 enum bt_field_class_type type, bt_object_release_func release_func,
2015 struct bt_field_class *element_fc)
2016 {
2017 int ret;
2018
2019 BT_ASSERT(element_fc);
2020 ret = init_field_class((void *) fc, type, release_func);
2021 if (ret) {
2022 goto end;
2023 }
2024
2025 fc->element_fc = element_fc;
2026 bt_object_get_ref_no_null_check(fc->element_fc);
2027 bt_field_class_freeze(element_fc);
2028
2029 end:
2030 return ret;
2031 }
2032
2033 static
2034 void finalize_array_field_class(struct bt_field_class_array *array_fc)
2035 {
2036 BT_ASSERT(array_fc);
2037 BT_LOGD_STR("Putting element field class.");
2038 finalize_field_class((void *) array_fc);
2039 BT_OBJECT_PUT_REF_AND_RESET(array_fc->element_fc);
2040 }
2041
2042 static
2043 void destroy_static_array_field_class(struct bt_object *obj)
2044 {
2045 BT_ASSERT(obj);
2046 BT_LIB_LOGD("Destroying static array field class object: %!+F", obj);
2047 finalize_array_field_class((void *) obj);
2048 g_free(obj);
2049 }
2050
2051 BT_EXPORT
2052 struct bt_field_class *
2053 bt_field_class_array_static_create(bt_trace_class *trace_class,
2054 struct bt_field_class *element_fc, uint64_t length)
2055 {
2056 struct bt_field_class_array_static *array_fc = NULL;
2057
2058 BT_ASSERT_PRE_NO_ERROR();
2059 BT_ASSERT_PRE_TC_NON_NULL(trace_class);
2060 BT_ASSERT_PRE_NON_NULL("element-field-class", element_fc,
2061 "Element field class");
2062 BT_LOGD_STR("Creating default static array field class object.");
2063 array_fc = g_new0(struct bt_field_class_array_static, 1);
2064 if (!array_fc) {
2065 BT_LIB_LOGE_APPEND_CAUSE(
2066 "Failed to allocate one static array field class.");
2067 goto error;
2068 }
2069
2070 if (init_array_field_class((void *) array_fc,
2071 BT_FIELD_CLASS_TYPE_STATIC_ARRAY,
2072 destroy_static_array_field_class, element_fc)) {
2073 goto error;
2074 }
2075
2076 array_fc->length = length;
2077 BT_LIB_LOGD("Created static array field class object: %!+F", array_fc);
2078 goto end;
2079
2080 error:
2081 BT_OBJECT_PUT_REF_AND_RESET(array_fc);
2082
2083 end:
2084 return (void *) array_fc;
2085 }
2086
2087 BT_EXPORT
2088 const struct bt_field_class *
2089 bt_field_class_array_borrow_element_field_class_const(
2090 const struct bt_field_class *fc)
2091 {
2092 const struct bt_field_class_array *array_fc = (const void *) fc;
2093
2094 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
2095 BT_ASSERT_PRE_DEV_FC_IS_ARRAY("field-class", fc, "Field class");
2096 return array_fc->element_fc;
2097 }
2098
2099 BT_EXPORT
2100 struct bt_field_class *
2101 bt_field_class_array_borrow_element_field_class(struct bt_field_class *fc)
2102 {
2103 struct bt_field_class_array *array_fc = (void *) fc;
2104
2105 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
2106 BT_ASSERT_PRE_DEV_FC_IS_ARRAY("field-class", fc, "Field class");
2107 return array_fc->element_fc;
2108 }
2109
2110 BT_EXPORT
2111 uint64_t bt_field_class_array_static_get_length(const struct bt_field_class *fc)
2112 {
2113 const struct bt_field_class_array_static *array_fc = (const void *) fc;
2114
2115 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
2116 BT_ASSERT_PRE_DEV_FC_HAS_TYPE("field-class", fc,
2117 "static-array-field-class", BT_FIELD_CLASS_TYPE_STATIC_ARRAY,
2118 "Field class");
2119 return (uint64_t) array_fc->length;
2120 }
2121
2122 static
2123 void destroy_dynamic_array_field_class(struct bt_object *obj)
2124 {
2125 struct bt_field_class_array_dynamic *fc = (void *) obj;
2126
2127 BT_ASSERT(fc);
2128 BT_LIB_LOGD("Destroying dynamic array field class object: %!+F", fc);
2129 finalize_array_field_class((void *) fc);
2130 BT_LOGD_STR("Putting length field path.");
2131 BT_OBJECT_PUT_REF_AND_RESET(fc->length_field_path);
2132 BT_LOGD_STR("Putting length field class.");
2133 BT_OBJECT_PUT_REF_AND_RESET(fc->length_fc);
2134 g_free(fc);
2135 }
2136
2137 BT_EXPORT
2138 struct bt_field_class *bt_field_class_array_dynamic_create(
2139 struct bt_trace_class *trace_class,
2140 struct bt_field_class *element_fc,
2141 struct bt_field_class *length_fc)
2142 {
2143 struct bt_field_class_array_dynamic *array_fc = NULL;
2144
2145 BT_ASSERT_PRE_NO_ERROR();
2146 BT_ASSERT_PRE_TC_NON_NULL(trace_class);
2147 BT_ASSERT_PRE_NON_NULL("element-field-class", element_fc,
2148 "Element field class");
2149 BT_LOGD_STR("Creating default dynamic array field class object.");
2150 array_fc = g_new0(struct bt_field_class_array_dynamic, 1);
2151 if (!array_fc) {
2152 BT_LIB_LOGE_APPEND_CAUSE(
2153 "Failed to allocate one dynamic array field class.");
2154 goto error;
2155 }
2156
2157 if (init_array_field_class((void *) array_fc,
2158 length_fc ?
2159 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD :
2160 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITHOUT_LENGTH_FIELD,
2161 destroy_dynamic_array_field_class, element_fc)) {
2162 goto error;
2163 }
2164
2165 if (length_fc) {
2166 BT_ASSERT_PRE_FC_IS_UNSIGNED_INT("length-field-class",
2167 length_fc, "Length field class");
2168 array_fc->length_fc = length_fc;
2169 bt_object_get_ref_no_null_check(array_fc->length_fc);
2170 bt_field_class_freeze(length_fc);
2171 }
2172
2173 BT_LIB_LOGD("Created dynamic array field class object: %!+F", array_fc);
2174 goto end;
2175
2176 error:
2177 BT_OBJECT_PUT_REF_AND_RESET(array_fc);
2178
2179 end:
2180 return (void *) array_fc;
2181 }
2182
2183 BT_EXPORT
2184 const struct bt_field_path *
2185 bt_field_class_array_dynamic_with_length_field_borrow_length_field_path_const(
2186 const struct bt_field_class *fc)
2187 {
2188 const struct bt_field_class_array_dynamic *seq_fc = (const void *) fc;
2189
2190 BT_ASSERT_PRE_NO_ERROR();
2191 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
2192 BT_ASSERT_PRE_FC_HAS_TYPE("field-class", fc,
2193 "dynamic-array-field-class-with-length-field",
2194 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD,
2195 "Field class");
2196 return seq_fc->length_field_path;
2197 }
2198
2199 static
2200 void destroy_string_field_class(struct bt_object *obj)
2201 {
2202 BT_ASSERT(obj);
2203 BT_LIB_LOGD("Destroying string field class object: %!+F", obj);
2204 finalize_field_class((void *) obj);
2205 g_free(obj);
2206 }
2207
2208 BT_EXPORT
2209 struct bt_field_class *bt_field_class_string_create(bt_trace_class *trace_class)
2210 {
2211 struct bt_field_class_string *string_fc = NULL;
2212
2213 BT_ASSERT_PRE_NO_ERROR();
2214 BT_ASSERT_PRE_TC_NON_NULL(trace_class);
2215 BT_LOGD_STR("Creating default string field class object.");
2216 string_fc = g_new0(struct bt_field_class_string, 1);
2217 if (!string_fc) {
2218 BT_LIB_LOGE_APPEND_CAUSE(
2219 "Failed to allocate one string field class.");
2220 goto error;
2221 }
2222
2223 if (init_field_class((void *) string_fc, BT_FIELD_CLASS_TYPE_STRING,
2224 destroy_string_field_class)) {
2225 goto error;
2226 }
2227
2228 BT_LIB_LOGD("Created string field class object: %!+F", string_fc);
2229 goto end;
2230
2231 error:
2232 BT_OBJECT_PUT_REF_AND_RESET(string_fc);
2233
2234 end:
2235 return (void *) string_fc;
2236 }
2237
2238 void _bt_field_class_freeze(const struct bt_field_class *c_fc)
2239 {
2240 struct bt_field_class *fc = (void *) c_fc;
2241
2242 /*
2243 * Element/member/option field classes are frozen when added to
2244 * their owner.
2245 */
2246 BT_ASSERT(fc);
2247 bt_value_freeze(fc->user_attributes);
2248 fc->frozen = true;
2249
2250 if (fc->type == BT_FIELD_CLASS_TYPE_STRUCTURE ||
2251 bt_field_class_type_is(fc->type,
2252 BT_FIELD_CLASS_TYPE_VARIANT)) {
2253 struct bt_field_class_named_field_class_container *container_fc =
2254 (void *) fc;
2255 uint64_t i;
2256
2257 for (i = 0; i < container_fc->named_fcs->len; i++) {
2258 bt_named_field_class_freeze(
2259 container_fc->named_fcs->pdata[i]);
2260 }
2261 }
2262 }
2263
2264 void _bt_named_field_class_freeze(const struct bt_named_field_class *named_fc)
2265 {
2266 BT_ASSERT(named_fc);
2267 BT_ASSERT(named_fc->fc->frozen);
2268 BT_LIB_LOGD("Freezing named field class's user attributes: %!+v",
2269 named_fc->user_attributes);
2270 bt_value_freeze(named_fc->user_attributes);
2271 ((struct bt_named_field_class *) named_fc)->frozen = true;
2272 }
2273
2274 void bt_field_class_make_part_of_trace_class(const struct bt_field_class *c_fc)
2275 {
2276 struct bt_field_class *fc = (void *) c_fc;
2277
2278 BT_ASSERT(fc);
2279 BT_ASSERT_PRE("field-class-is-not-part-of-trace-class",
2280 !fc->part_of_trace_class,
2281 "Field class is already part of a trace class: %!+F", fc);
2282 fc->part_of_trace_class = true;
2283
2284 if (fc->type == BT_FIELD_CLASS_TYPE_STRUCTURE ||
2285 bt_field_class_type_is(fc->type,
2286 BT_FIELD_CLASS_TYPE_VARIANT)) {
2287 struct bt_field_class_named_field_class_container *container_fc =
2288 (void *) fc;
2289 uint64_t i;
2290
2291 for (i = 0; i < container_fc->named_fcs->len; i++) {
2292 struct bt_named_field_class *named_fc =
2293 container_fc->named_fcs->pdata[i];
2294
2295 bt_field_class_make_part_of_trace_class(named_fc->fc);
2296 }
2297 } else if (bt_field_class_type_is(fc->type,
2298 BT_FIELD_CLASS_TYPE_ARRAY)) {
2299 struct bt_field_class_array *array_fc = (void *) fc;
2300
2301 bt_field_class_make_part_of_trace_class(array_fc->element_fc);
2302 }
2303 }
2304
2305 BT_EXPORT
2306 const struct bt_value *bt_field_class_borrow_user_attributes_const(
2307 const struct bt_field_class *fc)
2308 {
2309 BT_ASSERT_PRE_DEV_FC_NON_NULL(fc);
2310 return fc->user_attributes;
2311 }
2312
2313 BT_EXPORT
2314 struct bt_value *bt_field_class_borrow_user_attributes(
2315 struct bt_field_class *field_class)
2316 {
2317 return (void *) bt_field_class_borrow_user_attributes_const(
2318 (void *) field_class);
2319 }
2320
2321
2322 BT_EXPORT
2323 void bt_field_class_set_user_attributes(
2324 struct bt_field_class *fc,
2325 const struct bt_value *user_attributes)
2326 {
2327 BT_ASSERT_PRE_FC_NON_NULL(fc);
2328 BT_ASSERT_PRE_USER_ATTRS_NON_NULL(user_attributes);
2329 BT_ASSERT_PRE_USER_ATTRS_IS_MAP(user_attributes);
2330 BT_ASSERT_PRE_DEV_FC_HOT(fc);
2331 bt_object_put_ref_no_null_check(fc->user_attributes);
2332 fc->user_attributes = (void *) user_attributes;
2333 bt_object_get_ref_no_null_check(fc->user_attributes);
2334 }
2335
2336 static
2337 const struct bt_value *bt_named_field_class_borrow_user_attributes_const(
2338 const struct bt_named_field_class *named_fc)
2339 {
2340 return named_fc->user_attributes;
2341 }
2342
2343 static
2344 void set_named_field_class_user_attributes(
2345 struct bt_named_field_class *named_fc,
2346 const struct bt_value *user_attributes, const char *api_func)
2347 {
2348 BT_ASSERT_PRE_USER_ATTRS_NON_NULL_FROM_FUNC(api_func, user_attributes);
2349 BT_ASSERT_PRE_USER_ATTRS_NON_NULL_FROM_FUNC(api_func, user_attributes);
2350 bt_object_put_ref_no_null_check(named_fc->user_attributes);
2351 named_fc->user_attributes = (void *) user_attributes;
2352 bt_object_get_ref_no_null_check(named_fc->user_attributes);
2353 }
2354
2355 BT_EXPORT
2356 const struct bt_value *
2357 bt_field_class_structure_member_borrow_user_attributes_const(
2358 const struct bt_field_class_structure_member *member)
2359 {
2360 BT_ASSERT_PRE_STRUCT_FC_MEMBER_NON_NULL(member);
2361 return bt_named_field_class_borrow_user_attributes_const(
2362 (const void *) member);
2363 }
2364
2365 BT_EXPORT
2366 struct bt_value *
2367 bt_field_class_structure_member_borrow_user_attributes(
2368 struct bt_field_class_structure_member *member)
2369 {
2370 BT_ASSERT_PRE_STRUCT_FC_MEMBER_NON_NULL(member);
2371 return (void *) bt_named_field_class_borrow_user_attributes_const(
2372 (void *) member);
2373 }
2374
2375 BT_EXPORT
2376 void bt_field_class_structure_member_set_user_attributes(
2377 struct bt_field_class_structure_member *member,
2378 const struct bt_value *user_attributes)
2379 {
2380 BT_ASSERT_PRE_STRUCT_FC_MEMBER_NON_NULL(member);
2381 BT_ASSERT_PRE_DEV_HOT("structure-field-class-member",
2382 (struct bt_named_field_class *) member,
2383 "Structure field class member", ".");
2384 set_named_field_class_user_attributes((void *) member,
2385 user_attributes, __func__);
2386 }
2387
2388 BT_EXPORT
2389 const struct bt_value *bt_field_class_variant_option_borrow_user_attributes_const(
2390 const struct bt_field_class_variant_option *option)
2391 {
2392 BT_ASSERT_PRE_VAR_FC_OPT_NON_NULL(option);
2393 return bt_named_field_class_borrow_user_attributes_const(
2394 (const void *) option);
2395 }
2396
2397 BT_EXPORT
2398 struct bt_value *bt_field_class_variant_option_borrow_user_attributes(
2399 struct bt_field_class_variant_option *option)
2400 {
2401 BT_ASSERT_PRE_VAR_FC_OPT_NON_NULL(option);
2402 return (void *) bt_named_field_class_borrow_user_attributes_const(
2403 (void *) option);
2404 }
2405
2406 BT_EXPORT
2407 void bt_field_class_variant_option_set_user_attributes(
2408 struct bt_field_class_variant_option *option,
2409 const struct bt_value *user_attributes)
2410 {
2411 BT_ASSERT_PRE_VAR_FC_OPT_NON_NULL(option);
2412 BT_ASSERT_PRE_DEV_HOT("variant-field-class-option",
2413 (struct bt_named_field_class *) option,
2414 "Variant field class option", ".");
2415 set_named_field_class_user_attributes((void *) option,
2416 user_attributes, __func__);
2417 }
2418
2419 BT_EXPORT
2420 void bt_field_class_get_ref(const struct bt_field_class *field_class)
2421 {
2422 bt_object_get_ref(field_class);
2423 }
2424
2425 BT_EXPORT
2426 void bt_field_class_put_ref(const struct bt_field_class *field_class)
2427 {
2428 bt_object_put_ref(field_class);
2429 }
This page took 0.081307 seconds and 4 git commands to generate.