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