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