fb2e99ec75b095556f6035ae543755e72cdef229
[babeltrace.git] / src / lib / trace-ir / field-class.c
1 /*
2 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
3 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #define BT_LOG_TAG "LIB/FIELD-CLASS"
25 #include "lib/logging.h"
26
27 #include "lib/assert-pre.h"
28 #include <babeltrace2/trace-ir/field-class.h>
29 #include <babeltrace2/trace-ir/field-class-const.h>
30 #include <babeltrace2/trace-ir/field-const.h>
31 #include <babeltrace2/trace-ir/field.h>
32 #include <babeltrace2/trace-ir/clock-class.h>
33 #include "lib/object.h"
34 #include "compat/compiler.h"
35 #include "compat/endian.h"
36 #include "common/assert.h"
37 #include "compat/glib.h"
38 #include <float.h>
39 #include <inttypes.h>
40 #include <stdlib.h>
41
42 #include "clock-class.h"
43 #include "field-class.h"
44 #include "field.h"
45 #include "field-path.h"
46 #include "utils.h"
47 #include "lib/func-status.h"
48 #include "lib/integer-range-set.h"
49
50 enum bt_field_class_type bt_field_class_get_type(
51 const struct bt_field_class *fc)
52 {
53 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
54 return fc->type;
55 }
56
57 static
58 void init_field_class(struct bt_field_class *fc, enum bt_field_class_type type,
59 bt_object_release_func release_func)
60 {
61 BT_ASSERT(fc);
62 BT_ASSERT(release_func);
63 bt_object_init_shared(&fc->base, release_func);
64 fc->type = type;
65 }
66
67 static
68 void init_integer_field_class(struct bt_field_class_integer *fc,
69 enum bt_field_class_type type,
70 bt_object_release_func release_func)
71 {
72 init_field_class((void *) fc, type, release_func);
73 fc->range = 64;
74 fc->base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
75 }
76
77 static
78 void destroy_integer_field_class(struct bt_object *obj)
79 {
80 BT_ASSERT(obj);
81 BT_LIB_LOGD("Destroying integer field class object: %!+F", obj);
82 g_free(obj);
83 }
84
85 static inline
86 struct bt_field_class *create_integer_field_class(bt_trace_class *trace_class,
87 enum bt_field_class_type type)
88 {
89 struct bt_field_class_integer *int_fc = NULL;
90
91 BT_ASSERT_PRE_NON_NULL(trace_class, "Trace class");
92 BT_LOGD("Creating default integer field class object: type=%s",
93 bt_common_field_class_type_string(type));
94 int_fc = g_new0(struct bt_field_class_integer, 1);
95 if (!int_fc) {
96 BT_LIB_LOGE_APPEND_CAUSE(
97 "Failed to allocate one integer field class.");
98 goto error;
99 }
100
101 init_integer_field_class(int_fc, type, destroy_integer_field_class);
102 BT_LIB_LOGD("Created integer field class object: %!+F", int_fc);
103 goto end;
104
105 error:
106 BT_OBJECT_PUT_REF_AND_RESET(int_fc);
107
108 end:
109 return (void *) int_fc;
110 }
111
112 struct bt_field_class *bt_field_class_unsigned_integer_create(
113 bt_trace_class *trace_class)
114 {
115 return create_integer_field_class(trace_class,
116 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER);
117 }
118
119 struct bt_field_class *bt_field_class_signed_integer_create(
120 bt_trace_class *trace_class)
121 {
122 return create_integer_field_class(trace_class,
123 BT_FIELD_CLASS_TYPE_SIGNED_INTEGER);
124 }
125
126 uint64_t bt_field_class_integer_get_field_value_range(
127 const struct bt_field_class *fc)
128 {
129 const struct bt_field_class_integer *int_fc = (const void *) fc;
130
131 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
132 BT_ASSERT_PRE_DEV_FC_IS_INT(fc, "Field class");
133 return int_fc->range;
134 }
135
136 BT_ASSERT_PRE_FUNC
137 static
138 bool size_is_valid_for_enumeration_field_class(struct bt_field_class *fc,
139 uint64_t size)
140 {
141 // TODO
142 return true;
143 }
144
145 void bt_field_class_integer_set_field_value_range(
146 struct bt_field_class *fc, uint64_t size)
147 {
148 struct bt_field_class_integer *int_fc = (void *) fc;
149
150 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
151 BT_ASSERT_PRE_FC_IS_INT(fc, "Field class");
152 BT_ASSERT_PRE_DEV_FC_HOT(fc, "Field class");
153 BT_ASSERT_PRE(size <= 64,
154 "Unsupported size for integer field class's field value range "
155 "(maximum is 64): size=%" PRIu64, size);
156 BT_ASSERT_PRE(
157 int_fc->common.type == BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER ||
158 int_fc->common.type == BT_FIELD_CLASS_TYPE_SIGNED_INTEGER ||
159 size_is_valid_for_enumeration_field_class(fc, size),
160 "Invalid field value range for enumeration field class: "
161 "at least one of the current mapping ranges contains values "
162 "which are outside this range: %!+F, size=%" PRIu64, fc, size);
163 int_fc->range = size;
164 BT_LIB_LOGD("Set integer field class's field value range: %!+F", fc);
165 }
166
167 enum bt_field_class_integer_preferred_display_base
168 bt_field_class_integer_get_preferred_display_base(const struct bt_field_class *fc)
169 {
170 const struct bt_field_class_integer *int_fc = (const void *) fc;
171
172 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
173 BT_ASSERT_PRE_DEV_FC_IS_INT(fc, "Field class");
174 return int_fc->base;
175 }
176
177 void bt_field_class_integer_set_preferred_display_base(
178 struct bt_field_class *fc,
179 enum bt_field_class_integer_preferred_display_base base)
180 {
181 struct bt_field_class_integer *int_fc = (void *) fc;
182
183 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
184 BT_ASSERT_PRE_FC_IS_INT(fc, "Field class");
185 BT_ASSERT_PRE_DEV_FC_HOT(fc, "Field class");
186 int_fc->base = base;
187 BT_LIB_LOGD("Set integer field class's preferred display base: %!+F", fc);
188 }
189
190 static
191 void finalize_enumeration_field_class_mapping(
192 struct bt_field_class_enumeration_mapping *mapping)
193 {
194 BT_ASSERT(mapping);
195
196 if (mapping->label) {
197 g_string_free(mapping->label, TRUE);
198 mapping->label = NULL;
199 }
200
201 BT_OBJECT_PUT_REF_AND_RESET(mapping->range_set);
202 }
203
204 static
205 void destroy_enumeration_field_class(struct bt_object *obj)
206 {
207 struct bt_field_class_enumeration *fc = (void *) obj;
208
209 BT_ASSERT(fc);
210 BT_LIB_LOGD("Destroying enumeration field class object: %!+F", fc);
211
212 if (fc->mappings) {
213 uint64_t i;
214
215 for (i = 0; i < fc->mappings->len; i++) {
216 finalize_enumeration_field_class_mapping(
217 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc, i));
218 }
219
220 g_array_free(fc->mappings, TRUE);
221 fc->mappings = NULL;
222 }
223
224 if (fc->label_buf) {
225 g_ptr_array_free(fc->label_buf, TRUE);
226 fc->label_buf = NULL;
227 }
228
229 g_free(fc);
230 }
231
232 static
233 struct bt_field_class *create_enumeration_field_class(
234 bt_trace_class *trace_class, enum bt_field_class_type type)
235 {
236 struct bt_field_class_enumeration *enum_fc = NULL;
237
238 BT_ASSERT_PRE_NON_NULL(trace_class, "Trace class");
239 BT_LOGD("Creating default enumeration field class object: type=%s",
240 bt_common_field_class_type_string(type));
241 enum_fc = g_new0(struct bt_field_class_enumeration, 1);
242 if (!enum_fc) {
243 BT_LIB_LOGE_APPEND_CAUSE(
244 "Failed to allocate one enumeration field class.");
245 goto error;
246 }
247
248 init_integer_field_class((void *) enum_fc, type,
249 destroy_enumeration_field_class);
250 enum_fc->mappings = g_array_new(FALSE, TRUE,
251 sizeof(struct bt_field_class_enumeration_mapping));
252 if (!enum_fc->mappings) {
253 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GArray.");
254 goto error;
255 }
256
257 enum_fc->label_buf = g_ptr_array_new();
258 if (!enum_fc->label_buf) {
259 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GArray.");
260 goto error;
261 }
262
263 BT_LIB_LOGD("Created enumeration field class object: %!+F", enum_fc);
264 goto end;
265
266 error:
267 BT_OBJECT_PUT_REF_AND_RESET(enum_fc);
268
269 end:
270 return (void *) enum_fc;
271 }
272
273 struct bt_field_class *bt_field_class_unsigned_enumeration_create(
274 bt_trace_class *trace_class)
275 {
276 return create_enumeration_field_class(trace_class,
277 BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION);
278 }
279
280 struct bt_field_class *bt_field_class_signed_enumeration_create(
281 bt_trace_class *trace_class)
282 {
283 return create_enumeration_field_class(trace_class,
284 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION);
285 }
286
287 uint64_t bt_field_class_enumeration_get_mapping_count(
288 const struct bt_field_class *fc)
289 {
290 const struct bt_field_class_enumeration *enum_fc = (const void *) fc;
291
292 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
293 BT_ASSERT_PRE_DEV_FC_IS_ENUM(fc, "Field class");
294 return (uint64_t) enum_fc->mappings->len;
295 }
296
297 const struct bt_field_class_unsigned_enumeration_mapping *
298 bt_field_class_unsigned_enumeration_borrow_mapping_by_index_const(
299 const struct bt_field_class *fc, uint64_t index)
300 {
301 const struct bt_field_class_enumeration *enum_fc = (const void *) fc;
302
303 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
304 BT_ASSERT_PRE_DEV_VALID_INDEX(index, enum_fc->mappings->len);
305 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION,
306 "Field class");
307 return (const void *) BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc, index);
308 }
309
310 const struct bt_field_class_signed_enumeration_mapping *
311 bt_field_class_signed_enumeration_borrow_mapping_by_index_const(
312 const struct bt_field_class *fc, uint64_t index)
313 {
314 const struct bt_field_class_enumeration *enum_fc = (const void *) fc;
315
316 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
317 BT_ASSERT_PRE_DEV_VALID_INDEX(index, enum_fc->mappings->len);
318 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION,
319 "Field class");
320 return (const void *) BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc, index);
321 }
322
323 static
324 const struct bt_field_class_enumeration_mapping *
325 borrow_enumeration_field_class_mapping_by_label(
326 const struct bt_field_class_enumeration *fc, const char *label)
327 {
328 struct bt_field_class_enumeration_mapping *mapping = NULL;
329 uint64_t i;
330
331 BT_ASSERT(fc);
332 BT_ASSERT_PRE_DEV_NON_NULL(label, "Label");
333
334 for (i = 0; i < fc->mappings->len; i++) {
335 struct bt_field_class_enumeration_mapping *this_mapping =
336 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc, i);
337
338 if (strcmp(this_mapping->label->str, label) == 0) {
339 mapping = this_mapping;
340 goto end;
341 }
342 }
343
344 end:
345 return mapping;
346 }
347
348 const struct bt_field_class_signed_enumeration_mapping *
349 bt_field_class_signed_enumeration_borrow_mapping_by_label_const(
350 const struct bt_field_class *fc, const char *label)
351 {
352 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
353 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION,
354 "Field class");
355 return (const void *) borrow_enumeration_field_class_mapping_by_label(
356 (const void *) fc, label);
357 }
358
359 const struct bt_field_class_unsigned_enumeration_mapping *
360 bt_field_class_unsigned_enumeration_borrow_mapping_by_label_const(
361 const struct bt_field_class *fc, const char *label)
362 {
363 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
364 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc,
365 BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION, "Field class");
366 return (const void *) borrow_enumeration_field_class_mapping_by_label(
367 (const void *) fc, label);
368 }
369
370 const char *bt_field_class_enumeration_mapping_get_label(
371 const struct bt_field_class_enumeration_mapping *mapping)
372 {
373 BT_ASSERT_PRE_DEV_NON_NULL(mapping, "Enumeration field class mapping");
374 return mapping->label->str;
375 }
376
377 const struct bt_integer_range_set_unsigned *
378 bt_field_class_unsigned_enumeration_mapping_borrow_ranges_const(
379 const struct bt_field_class_unsigned_enumeration_mapping *u_mapping)
380 {
381 const struct bt_field_class_enumeration_mapping *mapping =
382 (const void *) u_mapping;
383
384 BT_ASSERT_PRE_DEV_NON_NULL(mapping, "Enumeration field class mapping");
385 return (const void *) mapping->range_set;
386 }
387
388 const struct bt_integer_range_set_signed *
389 bt_field_class_signed_enumeration_mapping_borrow_ranges_const(
390 const struct bt_field_class_signed_enumeration_mapping *s_mapping)
391 {
392 const struct bt_field_class_enumeration_mapping *mapping =
393 (const void *) s_mapping;
394
395 BT_ASSERT_PRE_DEV_NON_NULL(mapping, "Enumeration field class mapping");
396 return (const void *) mapping->range_set;
397 }
398
399 enum bt_field_class_enumeration_get_mapping_labels_for_value_status
400 bt_field_class_unsigned_enumeration_get_mapping_labels_for_value(
401 const struct bt_field_class *fc, uint64_t value,
402 bt_field_class_enumeration_mapping_label_array *label_array,
403 uint64_t *count)
404 {
405 const struct bt_field_class_enumeration *enum_fc = (const void *) fc;
406 uint64_t i;
407
408 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
409 BT_ASSERT_PRE_DEV_NON_NULL(label_array, "Label array (output)");
410 BT_ASSERT_PRE_DEV_NON_NULL(count, "Count (output)");
411 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION,
412 "Field class");
413 g_ptr_array_set_size(enum_fc->label_buf, 0);
414
415 for (i = 0; i < enum_fc->mappings->len; i++) {
416 uint64_t j;
417 const struct bt_field_class_enumeration_mapping *mapping =
418 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc, i);
419
420 for (j = 0; j < mapping->range_set->ranges->len; j++) {
421 const struct bt_integer_range *range = (const void *)
422 BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(
423 mapping->range_set, j);
424
425 if (value >= range->lower.u &&
426 value <= range->upper.u) {
427 g_ptr_array_add(enum_fc->label_buf,
428 mapping->label->str);
429 break;
430 }
431 }
432 }
433
434 *label_array = (void *) enum_fc->label_buf->pdata;
435 *count = (uint64_t) enum_fc->label_buf->len;
436 return BT_FUNC_STATUS_OK;
437 }
438
439 enum bt_field_class_enumeration_get_mapping_labels_for_value_status
440 bt_field_class_signed_enumeration_get_mapping_labels_for_value(
441 const struct bt_field_class *fc, int64_t value,
442 bt_field_class_enumeration_mapping_label_array *label_array,
443 uint64_t *count)
444 {
445 const struct bt_field_class_enumeration *enum_fc = (const void *) fc;
446 uint64_t i;
447
448 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
449 BT_ASSERT_PRE_DEV_NON_NULL(label_array, "Label array (output)");
450 BT_ASSERT_PRE_DEV_NON_NULL(count, "Count (output)");
451 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION,
452 "Field class");
453 g_ptr_array_set_size(enum_fc->label_buf, 0);
454
455 for (i = 0; i < enum_fc->mappings->len; i++) {
456 uint64_t j;
457 const struct bt_field_class_enumeration_mapping *mapping =
458 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc, i);
459
460 for (j = 0; j < mapping->range_set->ranges->len; j++) {
461 const struct bt_integer_range *range = (const void *)
462 BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(
463 mapping->range_set, j);
464
465 if (value >= range->lower.i &&
466 value <= range->upper.i) {
467 g_ptr_array_add(enum_fc->label_buf,
468 mapping->label->str);
469 break;
470 }
471 }
472 }
473
474 *label_array = (void *) enum_fc->label_buf->pdata;
475 *count = (uint64_t) enum_fc->label_buf->len;
476 return BT_FUNC_STATUS_OK;
477 }
478
479 static
480 bool enumeration_field_class_has_mapping_with_label(
481 const struct bt_field_class_enumeration *enum_fc,
482 const char *label)
483 {
484 uint64_t i;
485 bool exists = false;
486
487 BT_ASSERT(enum_fc);
488 BT_ASSERT(label);
489
490 for (i = 0; i < enum_fc->mappings->len; i++) {
491 struct bt_field_class_enumeration_mapping *mapping_candidate =
492 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc, i);
493
494 if (strcmp(mapping_candidate->label->str, label) == 0) {
495 exists = true;
496 goto end;
497 }
498 }
499
500 end:
501 return exists;
502 }
503
504 static inline
505 enum bt_field_class_enumeration_add_mapping_status
506 add_mapping_to_enumeration_field_class(struct bt_field_class *fc,
507 const char *label, const struct bt_integer_range_set *range_set)
508 {
509 enum bt_field_class_enumeration_add_mapping_status status =
510 BT_FUNC_STATUS_OK;
511 struct bt_field_class_enumeration *enum_fc = (void *) fc;
512 struct bt_field_class_enumeration_mapping mapping = { 0 };
513
514 BT_ASSERT(fc);
515 BT_ASSERT_PRE_NON_NULL(label, "Label");
516 BT_ASSERT_PRE_NON_NULL(range_set, "Range set");
517 BT_ASSERT_PRE(!enumeration_field_class_has_mapping_with_label(
518 enum_fc, label),
519 "Duplicate mapping name in enumeration field class: "
520 "%![enum-fc-]+F, label=\"%s\"", fc, label);
521 mapping.range_set = range_set;
522 bt_object_get_ref(mapping.range_set);
523 mapping.label = g_string_new(label);
524 if (!mapping.label) {
525 finalize_enumeration_field_class_mapping(&mapping);
526 status = BT_FUNC_STATUS_MEMORY_ERROR;
527 goto end;
528 }
529
530 g_array_append_val(enum_fc->mappings, mapping);
531 BT_LIB_LOGD("Added mapping to enumeration field class: "
532 "%![fc-]+F, label=\"%s\"", fc, label);
533
534 end:
535 return status;
536 }
537
538 enum bt_field_class_enumeration_add_mapping_status
539 bt_field_class_unsigned_enumeration_add_mapping(
540 struct bt_field_class *fc, const char *label,
541 const struct bt_integer_range_set_unsigned *range_set)
542 {
543 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
544 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION,
545 "Field class");
546 return add_mapping_to_enumeration_field_class(fc, label,
547 (const void *) range_set);
548 }
549
550 enum bt_field_class_enumeration_add_mapping_status
551 bt_field_class_signed_enumeration_add_mapping(
552 struct bt_field_class *fc, const char *label,
553 const struct bt_integer_range_set_signed *range_set)
554 {
555 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
556 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION,
557 "Field class");
558 return add_mapping_to_enumeration_field_class(fc, label,
559 (const void *) range_set);
560 }
561
562 static
563 void destroy_real_field_class(struct bt_object *obj)
564 {
565 BT_ASSERT(obj);
566 BT_LIB_LOGD("Destroying real field class object: %!+F", obj);
567 g_free(obj);
568 }
569
570 struct bt_field_class *bt_field_class_real_create(bt_trace_class *trace_class)
571 {
572 struct bt_field_class_real *real_fc = NULL;
573
574 BT_ASSERT_PRE_NON_NULL(trace_class, "Trace class");
575 BT_LOGD_STR("Creating default real field class object.");
576 real_fc = g_new0(struct bt_field_class_real, 1);
577 if (!real_fc) {
578 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one real field class.");
579 goto error;
580 }
581
582 init_field_class((void *) real_fc, BT_FIELD_CLASS_TYPE_REAL,
583 destroy_real_field_class);
584 BT_LIB_LOGD("Created real field class object: %!+F", real_fc);
585 goto end;
586
587 error:
588 BT_OBJECT_PUT_REF_AND_RESET(real_fc);
589
590 end:
591 return (void *) real_fc;
592 }
593
594 bt_bool bt_field_class_real_is_single_precision(const struct bt_field_class *fc)
595 {
596 const struct bt_field_class_real *real_fc = (const void *) fc;
597
598 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
599 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_REAL, "Field class");
600 return real_fc->is_single_precision;
601 }
602
603 void bt_field_class_real_set_is_single_precision(struct bt_field_class *fc,
604 bt_bool is_single_precision)
605 {
606 struct bt_field_class_real *real_fc = (void *) fc;
607
608 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
609 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_REAL, "Field class");
610 BT_ASSERT_PRE_DEV_FC_HOT(fc, "Field class");
611 real_fc->is_single_precision = (bool) is_single_precision;
612 BT_LIB_LOGD("Set real field class's \"is single precision\" property: "
613 "%!+F", fc);
614 }
615
616 static
617 int init_named_field_classes_container(
618 struct bt_field_class_named_field_class_container *fc,
619 enum bt_field_class_type type,
620 bt_object_release_func fc_release_func,
621 GDestroyNotify named_fc_destroy_func)
622 {
623 int ret = 0;
624
625 init_field_class((void *) fc, type, fc_release_func);
626 fc->named_fcs = g_ptr_array_new_with_free_func(named_fc_destroy_func);
627 if (!fc->named_fcs) {
628 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GPtrArray.");
629 ret = -1;
630 goto end;
631 }
632
633 fc->name_to_index = g_hash_table_new(g_str_hash, g_str_equal);
634 if (!fc->name_to_index) {
635 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GHashTable.");
636 ret = -1;
637 goto end;
638 }
639
640 end:
641 return ret;
642 }
643
644 static
645 void finalize_named_field_class(struct bt_named_field_class *named_fc)
646 {
647 BT_ASSERT(named_fc);
648 BT_LIB_LOGD("Finalizing named field class: "
649 "addr=%p, name=\"%s\", %![fc-]+F",
650 named_fc, named_fc->name ? named_fc->name->str : NULL,
651 named_fc->fc);
652
653 if (named_fc->name) {
654 g_string_free(named_fc->name, TRUE);
655 named_fc->name = NULL;
656 }
657
658 BT_LOGD_STR("Putting named field class's field class.");
659 BT_OBJECT_PUT_REF_AND_RESET(named_fc->fc);
660 }
661
662 static
663 void destroy_named_field_class(gpointer ptr)
664 {
665 if (ptr) {
666 finalize_named_field_class(ptr);
667 g_free(ptr);
668 }
669 }
670
671 static
672 void destroy_variant_with_selector_option(gpointer ptr)
673 {
674 struct bt_field_class_variant_with_selector_option *opt = ptr;
675
676 if (ptr) {
677 finalize_named_field_class(&opt->common);
678 BT_OBJECT_PUT_REF_AND_RESET(opt->range_set);
679 g_free(ptr);
680 }
681 }
682
683 static
684 void finalize_named_field_classes_container(
685 struct bt_field_class_named_field_class_container *fc)
686 {
687 BT_ASSERT(fc);
688
689 if (fc->named_fcs) {
690 g_ptr_array_free(fc->named_fcs, TRUE);
691 fc->named_fcs = NULL;
692
693 }
694
695 if (fc->name_to_index) {
696 g_hash_table_destroy(fc->name_to_index);
697 fc->name_to_index = NULL;
698 }
699 }
700
701 static
702 void destroy_structure_field_class(struct bt_object *obj)
703 {
704 BT_ASSERT(obj);
705 BT_LIB_LOGD("Destroying structure field class object: %!+F", obj);
706 finalize_named_field_classes_container((void *) obj);
707 g_free(obj);
708 }
709
710 struct bt_field_class *bt_field_class_structure_create(
711 bt_trace_class *trace_class)
712 {
713 int ret;
714 struct bt_field_class_structure *struct_fc = NULL;
715
716 BT_ASSERT_PRE_NON_NULL(trace_class, "Trace class");
717 BT_LOGD_STR("Creating default structure field class object.");
718 struct_fc = g_new0(struct bt_field_class_structure, 1);
719 if (!struct_fc) {
720 BT_LIB_LOGE_APPEND_CAUSE(
721 "Failed to allocate one structure field class.");
722 goto error;
723 }
724
725 ret = init_named_field_classes_container((void *) struct_fc,
726 BT_FIELD_CLASS_TYPE_STRUCTURE, destroy_structure_field_class,
727 destroy_named_field_class);
728 if (ret) {
729 /* init_named_field_classes_container() logs errors */
730 goto error;
731 }
732
733 BT_LIB_LOGD("Created structure field class object: %!+F", struct_fc);
734 goto end;
735
736 error:
737 BT_OBJECT_PUT_REF_AND_RESET(struct_fc);
738
739 end:
740 return (void *) struct_fc;
741 }
742
743 static
744 int init_named_field_class(struct bt_named_field_class *named_fc,
745 const char *name, struct bt_field_class *fc)
746 {
747 int status = BT_FUNC_STATUS_OK;
748
749 BT_ASSERT(named_fc);
750 BT_ASSERT(name);
751 BT_ASSERT(fc);
752 named_fc->name = g_string_new(name);
753 if (!named_fc->name) {
754 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
755 status = BT_FUNC_STATUS_MEMORY_ERROR;
756 goto end;
757 }
758
759 named_fc->fc = fc;
760 bt_object_get_no_null_check(named_fc->fc);
761 bt_named_field_class_freeze(named_fc);
762
763 end:
764 return status;
765 }
766
767 static
768 struct bt_named_field_class *create_named_field_class(const char *name,
769 struct bt_field_class *fc)
770 {
771 struct bt_named_field_class *named_fc = g_new0(
772 struct bt_named_field_class, 1);
773
774 if (!named_fc) {
775 BT_LIB_LOGE_APPEND_CAUSE(
776 "Failed to allocate a named field class.");
777 goto error;
778 }
779
780 if (init_named_field_class(named_fc, name, fc)) {
781 /* init_named_field_class() logs errors */
782 goto error;
783 }
784
785 goto end;
786
787 error:
788 destroy_named_field_class(named_fc);
789 named_fc = NULL;
790
791 end:
792 return named_fc;
793 }
794
795 static
796 struct bt_field_class_variant_with_selector_option *
797 create_variant_with_selector_option(
798 const char *name, struct bt_field_class *fc,
799 const struct bt_integer_range_set *range_set)
800 {
801 struct bt_field_class_variant_with_selector_option *opt = g_new0(
802 struct bt_field_class_variant_with_selector_option, 1);
803
804 BT_ASSERT(range_set);
805
806 if (!opt) {
807 BT_LIB_LOGE_APPEND_CAUSE(
808 "Failed to allocate a named field class.");
809 goto error;
810 }
811
812 if (init_named_field_class(&opt->common, name, fc)) {
813 goto error;
814 }
815
816 opt->range_set = range_set;
817 bt_object_get_no_null_check(opt->range_set);
818 bt_integer_range_set_freeze(range_set);
819 goto end;
820
821 error:
822 destroy_variant_with_selector_option(opt);
823 opt = NULL;
824
825 end:
826 return opt;
827 }
828
829 static
830 int append_named_field_class_to_container_field_class(
831 struct bt_field_class_named_field_class_container *container_fc,
832 struct bt_named_field_class *named_fc)
833 {
834 BT_ASSERT(container_fc);
835 BT_ASSERT(named_fc);
836 BT_ASSERT_PRE_DEV_FC_HOT(container_fc, "Field class");
837 BT_ASSERT_PRE(!bt_g_hash_table_contains(container_fc->name_to_index,
838 named_fc->name->str),
839 "Duplicate member/option name in structure/variant field class: "
840 "%![container-fc-]+F, name=\"%s\"", container_fc,
841 named_fc->name->str);
842 g_ptr_array_add(container_fc->named_fcs, named_fc);
843 g_hash_table_insert(container_fc->name_to_index, named_fc->name->str,
844 GUINT_TO_POINTER(container_fc->named_fcs->len - 1));
845 return BT_FUNC_STATUS_OK;
846 }
847
848 enum bt_field_class_structure_append_member_status
849 bt_field_class_structure_append_member(
850 struct bt_field_class *fc, const char *name,
851 struct bt_field_class *member_fc)
852 {
853 enum bt_field_class_structure_append_member_status status;
854 struct bt_named_field_class *named_fc = NULL;
855
856 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
857 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_STRUCTURE,
858 "Field class");
859 named_fc = create_named_field_class(name, member_fc);
860 if (!named_fc) {
861 /* create_named_field_class() logs errors */
862 status = BT_FUNC_STATUS_MEMORY_ERROR;
863 goto end;
864 }
865
866 status = append_named_field_class_to_container_field_class((void *) fc,
867 named_fc);
868 if (status == BT_FUNC_STATUS_OK) {
869 /* Moved to the container */
870 named_fc = NULL;
871 }
872
873 end:
874 return status;
875 }
876
877 uint64_t bt_field_class_structure_get_member_count(
878 const struct bt_field_class *fc)
879 {
880 struct bt_field_class_structure *struct_fc = (void *) fc;
881
882 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
883 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_STRUCTURE,
884 "Field class");
885 return (uint64_t) struct_fc->common.named_fcs->len;
886 }
887
888 static
889 struct bt_named_field_class *
890 borrow_named_field_class_from_container_field_class_at_index(
891 struct bt_field_class_named_field_class_container *fc,
892 uint64_t index)
893 {
894 BT_ASSERT(fc);
895 BT_ASSERT_PRE_DEV_VALID_INDEX(index, fc->named_fcs->len);
896 return fc->named_fcs->pdata[index];
897 }
898
899 const struct bt_field_class_structure_member *
900 bt_field_class_structure_borrow_member_by_index_const(
901 const struct bt_field_class *fc, uint64_t index)
902 {
903 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
904 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_STRUCTURE,
905 "Field class");
906 return (const void *)
907 borrow_named_field_class_from_container_field_class_at_index(
908 (void *) fc, index);
909 }
910
911 struct bt_field_class_structure_member *
912 bt_field_class_structure_borrow_member_by_index(
913 struct bt_field_class *fc, uint64_t index)
914 {
915 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
916 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_STRUCTURE,
917 "Field class");
918 return (void *)
919 borrow_named_field_class_from_container_field_class_at_index(
920 (void *) fc, index);
921 }
922
923 static
924 struct bt_named_field_class *
925 borrow_named_field_class_from_container_field_class_by_name(
926 struct bt_field_class_named_field_class_container *fc,
927 const char *name)
928 {
929 struct bt_named_field_class *named_fc = NULL;
930 gpointer orig_key;
931 gpointer value;
932
933 BT_ASSERT(fc);
934 BT_ASSERT_PRE_DEV_NON_NULL(name, "Name");
935 if (!g_hash_table_lookup_extended(fc->name_to_index, name, &orig_key,
936 &value)) {
937 goto end;
938 }
939
940 named_fc = fc->named_fcs->pdata[GPOINTER_TO_UINT(value)];
941
942 end:
943 return named_fc;
944 }
945
946 const struct bt_field_class_structure_member *
947 bt_field_class_structure_borrow_member_by_name_const(
948 const struct bt_field_class *fc, const char *name)
949 {
950 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
951 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_STRUCTURE,
952 "Field class");
953 return (const void *)
954 borrow_named_field_class_from_container_field_class_by_name(
955 (void *) fc, name);
956 }
957
958 struct bt_field_class_structure_member *
959 bt_field_class_structure_borrow_member_by_name(
960 struct bt_field_class *fc, const char *name)
961 {
962 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
963 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_STRUCTURE,
964 "Field class");
965 return (void *)
966 borrow_named_field_class_from_container_field_class_by_name(
967 (void *) fc, name);
968 }
969
970 const char *bt_field_class_structure_member_get_name(
971 const struct bt_field_class_structure_member *member)
972 {
973 const struct bt_named_field_class *named_fc = (const void *) member;
974
975 BT_ASSERT_PRE_DEV_NON_NULL(member, "Structure field class member");
976 return named_fc->name->str;
977 }
978
979 const struct bt_field_class *
980 bt_field_class_structure_member_borrow_field_class_const(
981 const struct bt_field_class_structure_member *member)
982 {
983 const struct bt_named_field_class *named_fc = (const void *) member;
984
985 BT_ASSERT_PRE_DEV_NON_NULL(member, "Structure field class member");
986 return named_fc->fc;
987 }
988
989 static
990 void finalize_variant_field_class(struct bt_field_class_variant *var_fc)
991 {
992 BT_ASSERT(var_fc);
993 BT_LIB_LOGD("Finalizing variant field class object: %!+F", var_fc);
994 finalize_named_field_classes_container((void *) var_fc);
995 }
996
997 static
998 void destroy_variant_field_class(struct bt_object *obj)
999 {
1000 struct bt_field_class_variant *fc = (void *) obj;
1001
1002 BT_ASSERT(fc);
1003 finalize_variant_field_class(fc);
1004 g_free(fc);
1005 }
1006
1007 static
1008 void destroy_variant_with_selector_field_class(struct bt_object *obj)
1009 {
1010 struct bt_field_class_variant_with_selector *fc = (void *) obj;
1011
1012 BT_ASSERT(fc);
1013 finalize_variant_field_class(&fc->common);
1014 BT_LOGD_STR("Putting selector field path.");
1015 BT_OBJECT_PUT_REF_AND_RESET(fc->selector_field_path);
1016 BT_LOGD_STR("Putting selector field class.");
1017 BT_OBJECT_PUT_REF_AND_RESET(fc->selector_fc);
1018 g_free(fc);
1019 }
1020
1021 struct bt_field_class *bt_field_class_variant_create(
1022 bt_trace_class *trace_class, bt_field_class *selector_fc)
1023 {
1024 int ret;
1025 struct bt_field_class_variant *var_fc = NULL;
1026 struct bt_field_class_variant_with_selector *var_with_sel_fc = NULL;
1027 enum bt_field_class_type fc_type;
1028
1029 BT_ASSERT_PRE_NON_NULL(trace_class, "Trace class");
1030
1031 if (selector_fc) {
1032 BT_ASSERT_PRE_FC_IS_INT(selector_fc, "Selector field class");
1033 }
1034
1035 BT_LIB_LOGD("Creating default variant field class: %![sel-fc-]+F",
1036 selector_fc);
1037
1038 if (selector_fc) {
1039 var_with_sel_fc = g_new0(
1040 struct bt_field_class_variant_with_selector, 1);
1041 if (!var_with_sel_fc) {
1042 BT_LIB_LOGE_APPEND_CAUSE(
1043 "Failed to allocate one variant field class with selector.");
1044 goto error;
1045 }
1046
1047 if (selector_fc->type == BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER ||
1048 selector_fc->type == BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION) {
1049 fc_type = BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR;
1050 } else {
1051 fc_type = BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR;
1052 }
1053
1054 ret = init_named_field_classes_container(
1055 (void *) var_with_sel_fc, fc_type,
1056 destroy_variant_with_selector_field_class,
1057 destroy_variant_with_selector_option);
1058 if (ret) {
1059 /* init_named_field_classes_container() logs errors */
1060 goto error;
1061 }
1062
1063 var_with_sel_fc->selector_fc = selector_fc;
1064 bt_object_get_no_null_check(var_with_sel_fc->selector_fc);
1065 bt_field_class_freeze(selector_fc);
1066 var_fc = (void *) var_with_sel_fc;
1067 } else {
1068 var_fc = g_new0(struct bt_field_class_variant, 1);
1069 if (!var_fc) {
1070 BT_LIB_LOGE_APPEND_CAUSE(
1071 "Failed to allocate one variant field class without selector.");
1072 goto error;
1073 }
1074
1075 ret = init_named_field_classes_container((void *) var_fc,
1076 BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR,
1077 destroy_variant_field_class, destroy_named_field_class);
1078 if (ret) {
1079 /* init_named_field_classes_container() logs errors */
1080 goto error;
1081 }
1082 }
1083
1084 BT_ASSERT(var_fc);
1085 BT_LIB_LOGD("Created default variant field class with selector object: "
1086 "%![var-fc-]+F, %![sel-fc-]+F", var_fc, selector_fc);
1087 goto end;
1088
1089 error:
1090 BT_OBJECT_PUT_REF_AND_RESET(var_fc);
1091
1092 end:
1093 return (void *) var_fc;
1094 }
1095
1096 enum bt_field_class_variant_without_selector_append_option_status
1097 bt_field_class_variant_without_selector_append_option(struct bt_field_class *fc,
1098 const char *name, struct bt_field_class *option_fc)
1099 {
1100 enum bt_field_class_variant_without_selector_append_option_status status;
1101 struct bt_named_field_class *named_fc = NULL;
1102
1103 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
1104 BT_ASSERT_PRE_NON_NULL(name, "Name");
1105 BT_ASSERT_PRE_NON_NULL(option_fc, "Option field class");
1106 BT_ASSERT_PRE_FC_HAS_ID(fc,
1107 BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR, "Field class");
1108 named_fc = create_named_field_class(name, option_fc);
1109 if (!named_fc) {
1110 /* create_named_field_class() logs errors */
1111 status = BT_FUNC_STATUS_MEMORY_ERROR;
1112 goto end;
1113 }
1114
1115 status = append_named_field_class_to_container_field_class((void *) fc,
1116 named_fc);
1117 if (status == BT_FUNC_STATUS_OK) {
1118 /* Moved to the container */
1119 named_fc = NULL;
1120 }
1121
1122 end:
1123 if (named_fc) {
1124 destroy_named_field_class(named_fc);
1125 }
1126
1127 return status;
1128 }
1129
1130 static
1131 int ranges_overlap(GPtrArray *var_fc_opts, const struct bt_integer_range_set *range_set,
1132 bool is_signed, bool *has_overlap)
1133 {
1134 int status = BT_FUNC_STATUS_OK;
1135 struct bt_integer_range_set *full_range_set;
1136 uint64_t i;
1137
1138 *has_overlap = false;
1139
1140 /*
1141 * Build a single range set with all the ranges and test for
1142 * overlaps.
1143 */
1144 if (is_signed) {
1145 full_range_set = (void *) bt_integer_range_set_signed_create();
1146 } else {
1147 full_range_set = (void *) bt_integer_range_set_unsigned_create();
1148 }
1149
1150 if (!full_range_set) {
1151 BT_LOGE_STR("Failed to create a range set.");
1152 status = BT_FUNC_STATUS_MEMORY_ERROR;
1153 goto end;
1154 }
1155
1156 /* Add existing option ranges */
1157 for (i = 0; i < var_fc_opts->len; i++) {
1158 struct bt_field_class_variant_with_selector_option *opt =
1159 var_fc_opts->pdata[i];
1160 uint64_t j;
1161
1162 for (j = 0; j < opt->range_set->ranges->len; j++) {
1163 struct bt_integer_range *range = BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(
1164 opt->range_set, j);
1165
1166 if (is_signed) {
1167 status = bt_integer_range_set_signed_add_range(
1168 (void *) full_range_set, range->lower.i,
1169 range->upper.i);
1170 } else {
1171 status = bt_integer_range_set_unsigned_add_range(
1172 (void *) full_range_set, range->lower.u,
1173 range->upper.u);
1174 }
1175
1176 if (status) {
1177 goto end;
1178 }
1179 }
1180 }
1181
1182 /* Add new ranges */
1183 for (i = 0; i < range_set->ranges->len; i++) {
1184 struct bt_integer_range *range = BT_INTEGER_RANGE_SET_RANGE_AT_INDEX(
1185 range_set, i);
1186
1187 if (is_signed) {
1188 status = bt_integer_range_set_signed_add_range(
1189 (void *) full_range_set, range->lower.i,
1190 range->upper.i);
1191 } else {
1192 status = bt_integer_range_set_unsigned_add_range(
1193 (void *) full_range_set, range->lower.u,
1194 range->upper.u);
1195 }
1196
1197 if (status) {
1198 goto end;
1199 }
1200 }
1201
1202 /* Check overlaps */
1203 if (is_signed) {
1204 *has_overlap = bt_integer_range_set_signed_has_overlaps(full_range_set);
1205 } else {
1206 *has_overlap = bt_integer_range_set_unsigned_has_overlaps(
1207 full_range_set);
1208 }
1209
1210 end:
1211 bt_object_put_ref(full_range_set);
1212 return status;
1213 }
1214
1215 static
1216 int append_option_to_variant_with_selector_field_class(
1217 struct bt_field_class *fc, const char *name,
1218 struct bt_field_class *option_fc,
1219 const struct bt_integer_range_set *range_set,
1220 enum bt_field_class_type expected_type)
1221 {
1222 int status;
1223 struct bt_field_class_variant_with_selector *var_fc = (void *) fc;
1224 struct bt_field_class_variant_with_selector_option *opt = NULL;
1225 bool has_overlap;
1226
1227 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
1228 BT_ASSERT_PRE_NON_NULL(name, "Name");
1229 BT_ASSERT_PRE_NON_NULL(option_fc, "Option field class");
1230 BT_ASSERT_PRE_NON_NULL(range_set, "Range set");
1231 BT_ASSERT_PRE_FC_HAS_ID(fc, expected_type, "Field class");
1232 BT_ASSERT_PRE(range_set->ranges->len > 0,
1233 "Range set is empty: addr=%p", range_set);
1234 status = ranges_overlap(var_fc->common.common.named_fcs, range_set,
1235 expected_type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR,
1236 &has_overlap);
1237 if (status) {
1238 /* ranges_overlap() logs errors */
1239 goto end;
1240 }
1241
1242 BT_ASSERT_PRE(!has_overlap,
1243 "Range set's ranges and existing ranges have an overlap: "
1244 "addr=%p", range_set);
1245 opt = create_variant_with_selector_option(name, option_fc, range_set);
1246 if (!opt) {
1247 /* create_variant_with_selector_option() logs errors */
1248 status = BT_FUNC_STATUS_MEMORY_ERROR;
1249 goto end;
1250 }
1251
1252 status = append_named_field_class_to_container_field_class((void *) fc,
1253 &opt->common);
1254 if (status == BT_FUNC_STATUS_OK) {
1255 /* Moved to the container */
1256 opt = NULL;
1257 }
1258
1259 end:
1260 if (opt) {
1261 destroy_variant_with_selector_option(opt);
1262 }
1263
1264 return status;
1265 }
1266
1267 enum bt_field_class_variant_with_selector_append_option_status
1268 bt_field_class_variant_with_unsigned_selector_append_option(
1269 struct bt_field_class *fc, const char *name,
1270 struct bt_field_class *option_fc,
1271 const struct bt_integer_range_set_unsigned *range_set)
1272 {
1273 return append_option_to_variant_with_selector_field_class(fc,
1274 name, option_fc, (const void *) range_set,
1275 BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR);
1276 }
1277
1278 enum bt_field_class_variant_with_selector_append_option_status
1279 bt_field_class_variant_with_signed_selector_append_option(
1280 struct bt_field_class *fc, const char *name,
1281 struct bt_field_class *option_fc,
1282 const struct bt_integer_range_set_signed *range_set)
1283 {
1284 return append_option_to_variant_with_selector_field_class(fc,
1285 name, option_fc, (const void *) range_set,
1286 BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR);
1287 }
1288
1289 uint64_t bt_field_class_variant_get_option_count(const struct bt_field_class *fc)
1290 {
1291 const struct bt_field_class_variant *var_fc = (const void *) fc;
1292
1293 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
1294 BT_ASSERT_PRE_DEV_FC_IS_VARIANT(fc, "Field class");
1295 return (uint64_t) var_fc->common.named_fcs->len;
1296 }
1297
1298 const struct bt_field_class_variant_option *
1299 bt_field_class_variant_borrow_option_by_name_const(
1300 const struct bt_field_class *fc, const char *name)
1301 {
1302 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
1303 BT_ASSERT_PRE_DEV_FC_IS_VARIANT(fc, "Field class");
1304 return (const void *)
1305 borrow_named_field_class_from_container_field_class_by_name(
1306 (void *) fc, name);
1307 }
1308
1309 const struct bt_field_class_variant_option *
1310 bt_field_class_variant_borrow_option_by_index_const(
1311 const struct bt_field_class *fc, uint64_t index)
1312 {
1313 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
1314 BT_ASSERT_PRE_DEV_FC_IS_VARIANT(fc, "Field class");
1315 return (const void *)
1316 borrow_named_field_class_from_container_field_class_at_index(
1317 (void *) fc, index);
1318 }
1319
1320 const struct bt_field_class_variant_with_unsigned_selector_option *
1321 bt_field_class_variant_with_unsigned_selector_borrow_option_by_name_const(
1322 const struct bt_field_class *fc, const char *name)
1323 {
1324 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
1325 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc,
1326 BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR,
1327 "Field class");
1328 return (const void *)
1329 borrow_named_field_class_from_container_field_class_by_name(
1330 (void *) fc, name);
1331 }
1332
1333 const struct bt_field_class_variant_with_unsigned_selector_option *
1334 bt_field_class_variant_with_unsigned_selector_borrow_option_by_index_const(
1335 const struct bt_field_class *fc, uint64_t index)
1336 {
1337 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
1338 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc,
1339 BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR,
1340 "Field class");
1341 return (const void *)
1342 borrow_named_field_class_from_container_field_class_at_index(
1343 (void *) fc, index);
1344 }
1345
1346 const struct bt_field_class_variant_with_signed_selector_option *
1347 bt_field_class_variant_with_signed_selector_borrow_option_by_name_const(
1348 const struct bt_field_class *fc, const char *name)
1349 {
1350 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
1351 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc,
1352 BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR,
1353 "Field class");
1354 return (const void *)
1355 borrow_named_field_class_from_container_field_class_by_name(
1356 (void *) fc, name);
1357 }
1358
1359 const struct bt_field_class_variant_with_signed_selector_option *
1360 bt_field_class_variant_with_signed_selector_borrow_option_by_index_const(
1361 const struct bt_field_class *fc, uint64_t index)
1362 {
1363 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
1364 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc,
1365 BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR,
1366 "Field class");
1367 return (const void *)
1368 borrow_named_field_class_from_container_field_class_at_index(
1369 (void *) fc, index);
1370 }
1371
1372 const char *bt_field_class_variant_option_get_name(
1373 const struct bt_field_class_variant_option *option)
1374 {
1375 const struct bt_named_field_class *named_fc = (const void *) option;
1376
1377 BT_ASSERT_PRE_DEV_NON_NULL(option, "Variant field class option");
1378 return named_fc->name->str;
1379 }
1380
1381 const struct bt_field_class *
1382 bt_field_class_variant_option_borrow_field_class_const(
1383 const struct bt_field_class_variant_option *option)
1384 {
1385 const struct bt_named_field_class *named_fc = (const void *) option;
1386
1387 BT_ASSERT_PRE_DEV_NON_NULL(option, "Variant field class option");
1388 return named_fc->fc;
1389 }
1390
1391 const struct bt_integer_range_set_unsigned *
1392 bt_field_class_variant_with_unsigned_selector_option_borrow_ranges_const(
1393 const struct bt_field_class_variant_with_unsigned_selector_option *option)
1394 {
1395 const struct bt_field_class_variant_with_selector_option *opt =
1396 (const void *) option;
1397
1398 BT_ASSERT_PRE_DEV_NON_NULL(option, "Variant field class option");
1399 return (const void *) opt->range_set;
1400 }
1401
1402 const struct bt_integer_range_set_signed *
1403 bt_field_class_variant_with_signed_selector_option_borrow_ranges_const(
1404 const struct bt_field_class_variant_with_signed_selector_option *option)
1405 {
1406 const struct bt_field_class_variant_with_selector_option *opt =
1407 (const void *) option;
1408
1409 BT_ASSERT_PRE_DEV_NON_NULL(option, "Variant field class option");
1410 return (const void *) opt->range_set;
1411 }
1412
1413 const struct bt_field_path *
1414 bt_field_class_variant_with_selector_borrow_selector_field_path_const(
1415 const struct bt_field_class *fc)
1416 {
1417 const struct bt_field_class_variant_with_selector *var_fc =
1418 (const void *) fc;
1419
1420 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
1421 BT_ASSERT_PRE_DEV_FC_IS_VARIANT_WITH_SEL(fc, "Field class");
1422 return var_fc->selector_field_path;
1423 }
1424
1425 static
1426 void init_array_field_class(struct bt_field_class_array *fc,
1427 enum bt_field_class_type type, bt_object_release_func release_func,
1428 struct bt_field_class *element_fc)
1429 {
1430 BT_ASSERT(element_fc);
1431 init_field_class((void *) fc, type, release_func);
1432 fc->element_fc = element_fc;
1433 bt_object_get_no_null_check(fc->element_fc);
1434 bt_field_class_freeze(element_fc);
1435 }
1436
1437 static
1438 void finalize_array_field_class(struct bt_field_class_array *array_fc)
1439 {
1440 BT_ASSERT(array_fc);
1441 BT_LOGD_STR("Putting element field class.");
1442 BT_OBJECT_PUT_REF_AND_RESET(array_fc->element_fc);
1443 }
1444
1445 static
1446 void destroy_static_array_field_class(struct bt_object *obj)
1447 {
1448 BT_ASSERT(obj);
1449 BT_LIB_LOGD("Destroying static array field class object: %!+F", obj);
1450 finalize_array_field_class((void *) obj);
1451 g_free(obj);
1452 }
1453
1454 struct bt_field_class *
1455 bt_field_class_static_array_create(bt_trace_class *trace_class,
1456 struct bt_field_class *element_fc, uint64_t length)
1457 {
1458 struct bt_field_class_static_array *array_fc = NULL;
1459
1460 BT_ASSERT_PRE_NON_NULL(trace_class, "Trace class");
1461 BT_ASSERT_PRE_NON_NULL(element_fc, "Element field class");
1462 BT_LOGD_STR("Creating default static array field class object.");
1463 array_fc = g_new0(struct bt_field_class_static_array, 1);
1464 if (!array_fc) {
1465 BT_LIB_LOGE_APPEND_CAUSE(
1466 "Failed to allocate one static array field class.");
1467 goto error;
1468 }
1469
1470 init_array_field_class((void *) array_fc, BT_FIELD_CLASS_TYPE_STATIC_ARRAY,
1471 destroy_static_array_field_class, element_fc);
1472 array_fc->length = length;
1473 BT_LIB_LOGD("Created static array field class object: %!+F", array_fc);
1474 goto end;
1475
1476 error:
1477 BT_OBJECT_PUT_REF_AND_RESET(array_fc);
1478
1479 end:
1480 return (void *) array_fc;
1481 }
1482
1483 const struct bt_field_class *
1484 bt_field_class_array_borrow_element_field_class_const(
1485 const struct bt_field_class *fc)
1486 {
1487 const struct bt_field_class_array *array_fc = (const void *) fc;
1488
1489 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
1490 BT_ASSERT_PRE_DEV_FC_IS_ARRAY(fc, "Field class");
1491 return array_fc->element_fc;
1492 }
1493
1494 struct bt_field_class *
1495 bt_field_class_array_borrow_element_field_class(struct bt_field_class *fc)
1496 {
1497 struct bt_field_class_array *array_fc = (void *) fc;
1498
1499 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
1500 BT_ASSERT_PRE_DEV_FC_IS_ARRAY(fc, "Field class");
1501 return array_fc->element_fc;
1502 }
1503
1504 uint64_t bt_field_class_static_array_get_length(const struct bt_field_class *fc)
1505 {
1506 const struct bt_field_class_static_array *array_fc = (const void *) fc;
1507
1508 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
1509 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_STATIC_ARRAY,
1510 "Field class");
1511 return (uint64_t) array_fc->length;
1512 }
1513
1514 static
1515 void destroy_dynamic_array_field_class(struct bt_object *obj)
1516 {
1517 struct bt_field_class_dynamic_array *fc = (void *) obj;
1518
1519 BT_ASSERT(fc);
1520 BT_LIB_LOGD("Destroying dynamic array field class object: %!+F", fc);
1521 finalize_array_field_class((void *) fc);
1522 BT_LOGD_STR("Putting length field path.");
1523 BT_OBJECT_PUT_REF_AND_RESET(fc->length_field_path);
1524 BT_LOGD_STR("Putting length field class.");
1525 BT_OBJECT_PUT_REF_AND_RESET(fc->length_fc);
1526 g_free(fc);
1527 }
1528
1529 struct bt_field_class *bt_field_class_dynamic_array_create(
1530 bt_trace_class *trace_class,
1531 struct bt_field_class *element_fc)
1532 {
1533 struct bt_field_class_dynamic_array *array_fc = NULL;
1534
1535 BT_ASSERT_PRE_NON_NULL(trace_class, "Trace class");
1536 BT_ASSERT_PRE_NON_NULL(element_fc, "Element field class");
1537 BT_LOGD_STR("Creating default dynamic array field class object.");
1538 array_fc = g_new0(struct bt_field_class_dynamic_array, 1);
1539 if (!array_fc) {
1540 BT_LIB_LOGE_APPEND_CAUSE(
1541 "Failed to allocate one dynamic array field class.");
1542 goto error;
1543 }
1544
1545 init_array_field_class((void *) array_fc,
1546 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY,
1547 destroy_dynamic_array_field_class, element_fc);
1548 BT_LIB_LOGD("Created dynamic array field class object: %!+F", array_fc);
1549 goto end;
1550
1551 error:
1552 BT_OBJECT_PUT_REF_AND_RESET(array_fc);
1553
1554 end:
1555 return (void *) array_fc;
1556 }
1557
1558 enum bt_field_class_dynamic_array_set_length_field_class_status
1559 bt_field_class_dynamic_array_set_length_field_class(
1560 struct bt_field_class *fc,
1561 struct bt_field_class *length_fc)
1562 {
1563 struct bt_field_class_dynamic_array *array_fc = (void *) fc;
1564
1565 BT_ASSERT_PRE_NON_NULL(fc, "Dynamic array field class");
1566 BT_ASSERT_PRE_NON_NULL(length_fc, "Length field class");
1567 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY,
1568 "Field class");
1569 BT_ASSERT_PRE_FC_IS_UNSIGNED_INT(length_fc, "Length field class");
1570 BT_ASSERT_PRE_DEV_FC_HOT(fc, "Dynamic array field class");
1571 array_fc->length_fc = length_fc;
1572 bt_object_get_no_null_check(array_fc->length_fc);
1573 bt_field_class_freeze(length_fc);
1574 return BT_FUNC_STATUS_OK;
1575 }
1576
1577 const struct bt_field_path *
1578 bt_field_class_dynamic_array_borrow_length_field_path_const(
1579 const struct bt_field_class *fc)
1580 {
1581 const struct bt_field_class_dynamic_array *seq_fc = (const void *) fc;
1582
1583 BT_ASSERT_PRE_DEV_NON_NULL(fc, "Field class");
1584 BT_ASSERT_PRE_DEV_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY,
1585 "Field class");
1586 return seq_fc->length_field_path;
1587 }
1588
1589 static
1590 void destroy_string_field_class(struct bt_object *obj)
1591 {
1592 BT_ASSERT(obj);
1593 BT_LIB_LOGD("Destroying string field class object: %!+F", obj);
1594 g_free(obj);
1595 }
1596
1597 struct bt_field_class *bt_field_class_string_create(bt_trace_class *trace_class)
1598 {
1599 struct bt_field_class_string *string_fc = NULL;
1600
1601 BT_ASSERT_PRE_NON_NULL(trace_class, "Trace class");
1602 BT_LOGD_STR("Creating default string field class object.");
1603 string_fc = g_new0(struct bt_field_class_string, 1);
1604 if (!string_fc) {
1605 BT_LIB_LOGE_APPEND_CAUSE(
1606 "Failed to allocate one string field class.");
1607 goto error;
1608 }
1609
1610 init_field_class((void *) string_fc, BT_FIELD_CLASS_TYPE_STRING,
1611 destroy_string_field_class);
1612 BT_LIB_LOGD("Created string field class object: %!+F", string_fc);
1613 goto end;
1614
1615 error:
1616 BT_OBJECT_PUT_REF_AND_RESET(string_fc);
1617
1618 end:
1619 return (void *) string_fc;
1620 }
1621
1622 BT_HIDDEN
1623 void _bt_field_class_freeze(const struct bt_field_class *c_fc)
1624 {
1625 struct bt_field_class *fc = (void *) c_fc;
1626
1627 /*
1628 * Element/member/option field classes are frozen when added to
1629 * their owner.
1630 */
1631 BT_ASSERT(fc);
1632 fc->frozen = true;
1633
1634 switch (fc->type) {
1635 case BT_FIELD_CLASS_TYPE_STRUCTURE:
1636 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR:
1637 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR:
1638 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR:
1639 {
1640 struct bt_field_class_named_field_class_container *container_fc =
1641 (void *) fc;
1642 uint64_t i;
1643
1644 for (i = 0; i < container_fc->named_fcs->len; i++) {
1645 bt_named_field_class_freeze(
1646 container_fc->named_fcs->pdata[i]);
1647 }
1648
1649 break;
1650 }
1651 default:
1652 break;
1653 }
1654 }
1655
1656 BT_HIDDEN
1657 void _bt_named_field_class_freeze(const struct bt_named_field_class *named_fc)
1658 {
1659 BT_ASSERT(named_fc);
1660 ((struct bt_named_field_class *) named_fc)->frozen = true;
1661 bt_field_class_freeze(named_fc->fc);
1662 }
1663
1664 BT_HIDDEN
1665 void bt_field_class_make_part_of_trace_class(const struct bt_field_class *c_fc)
1666 {
1667 struct bt_field_class *fc = (void *) c_fc;
1668
1669 BT_ASSERT(fc);
1670 BT_ASSERT_PRE(!fc->part_of_trace_class,
1671 "Field class is already part of a trace: %!+F", fc);
1672 fc->part_of_trace_class = true;
1673
1674 switch (fc->type) {
1675 case BT_FIELD_CLASS_TYPE_STRUCTURE:
1676 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR:
1677 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR:
1678 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR:
1679 {
1680 struct bt_field_class_named_field_class_container *container_fc =
1681 (void *) fc;
1682 uint64_t i;
1683
1684 for (i = 0; i < container_fc->named_fcs->len; i++) {
1685 struct bt_named_field_class *named_fc =
1686 container_fc->named_fcs->pdata[i];
1687
1688 bt_field_class_make_part_of_trace_class(named_fc->fc);
1689 }
1690
1691 break;
1692 }
1693 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY:
1694 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY:
1695 {
1696 struct bt_field_class_array *array_fc = (void *) fc;
1697
1698 bt_field_class_make_part_of_trace_class(array_fc->element_fc);
1699 break;
1700 }
1701 default:
1702 break;
1703 }
1704 }
1705
1706 void bt_field_class_get_ref(const struct bt_field_class *field_class)
1707 {
1708 bt_object_get_ref(field_class);
1709 }
1710
1711 void bt_field_class_put_ref(const struct bt_field_class *field_class)
1712 {
1713 bt_object_put_ref(field_class);
1714 }
This page took 0.132593 seconds and 3 git commands to generate.