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