Rename: bt_put(), bt_get() -> bt_object_put_ref(), bt_object_get_ref()
[babeltrace.git] / lib / trace-ir / field-classes.c
1 /*
2 * field-classes.c
3 *
4 * Babeltrace trace IR - Event Types
5 *
6 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 *
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
29 #define BT_LOG_TAG "FIELD-CLASSES"
30 #include <babeltrace/lib-logging-internal.h>
31
32 #include <babeltrace/assert-pre-internal.h>
33 #include <babeltrace/trace-ir/field-classes-internal.h>
34 #include <babeltrace/trace-ir/field-path-internal.h>
35 #include <babeltrace/trace-ir/fields-internal.h>
36 #include <babeltrace/trace-ir/fields.h>
37 #include <babeltrace/trace-ir/utils-internal.h>
38 #include <babeltrace/object.h>
39 #include <babeltrace/trace-ir/clock-class.h>
40 #include <babeltrace/trace-ir/clock-class-internal.h>
41 #include <babeltrace/object-internal.h>
42 #include <babeltrace/object.h>
43 #include <babeltrace/compiler-internal.h>
44 #include <babeltrace/endian-internal.h>
45 #include <babeltrace/assert-internal.h>
46 #include <babeltrace/compat/glib-internal.h>
47 #include <float.h>
48 #include <inttypes.h>
49 #include <stdlib.h>
50
51 enum bt_field_class_type bt_field_class_get_type(struct bt_field_class *fc)
52 {
53 BT_ASSERT_PRE_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(bt_field_class_has_known_type(fc));
63 BT_ASSERT(release_func);
64 bt_object_init_shared(&fc->base, release_func);
65 fc->type = type;
66 }
67
68 static
69 void init_integer_field_class(struct bt_field_class_integer *fc,
70 enum bt_field_class_type type,
71 bt_object_release_func release_func)
72 {
73 init_field_class((void *) fc, type, release_func);
74 fc->range = 64;
75 fc->base = BT_FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL;
76 }
77
78 static
79 void destroy_integer_field_class(struct bt_object *obj)
80 {
81 BT_ASSERT(obj);
82 BT_LIB_LOGD("Destroying integer field classe object: %!+F", obj);
83 g_free(obj);
84 }
85
86 static inline
87 struct bt_field_class *create_integer_field_class(enum bt_field_class_type type)
88 {
89 struct bt_field_class_integer *int_fc = NULL;
90
91 BT_LOGD("Creating default integer field classe object: type=%s",
92 bt_common_field_class_type_string(type));
93 int_fc = g_new0(struct bt_field_class_integer, 1);
94 if (!int_fc) {
95 BT_LOGE_STR("Failed to allocate one integer field classe.");
96 goto error;
97 }
98
99 init_integer_field_class(int_fc, type, destroy_integer_field_class);
100 BT_LIB_LOGD("Created integer field classe object: %!+F", int_fc);
101 goto end;
102
103 error:
104 BT_OBJECT_PUT_REF_AND_RESET(int_fc);
105
106 end:
107 return (void *) int_fc;
108 }
109
110 struct bt_field_class *bt_field_class_unsigned_integer_create(void)
111 {
112 return create_integer_field_class(BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER);
113 }
114
115 struct bt_field_class *bt_field_class_signed_integer_create(void)
116 {
117 return create_integer_field_class(BT_FIELD_CLASS_TYPE_SIGNED_INTEGER);
118 }
119
120 uint64_t bt_field_class_integer_get_field_value_range(
121 struct bt_field_class *fc)
122 {
123 struct bt_field_class_integer *int_fc = (void *) fc;
124
125 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
126 BT_ASSERT_PRE_FC_IS_INT(fc, "Field class");
127 return int_fc->range;
128 }
129
130 BT_ASSERT_PRE_FUNC
131 static
132 bool size_is_valid_for_enumeration_field_class(struct bt_field_class *fc,
133 uint64_t size)
134 {
135 // TODO
136 return true;
137 }
138
139 int bt_field_class_integer_set_field_value_range(
140 struct bt_field_class *fc, uint64_t size)
141 {
142 struct bt_field_class_integer *int_fc = (void *) fc;
143
144 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
145 BT_ASSERT_PRE_FC_IS_INT(fc, "Field class");
146 BT_ASSERT_PRE_FC_HOT(fc, "Field class");
147 BT_ASSERT_PRE(size <= 64,
148 "Unsupported size for integer field classe's field value range "
149 "(maximum is 64): size=%" PRIu64, size);
150 BT_ASSERT_PRE(
151 int_fc->common.type == BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER ||
152 int_fc->common.type == BT_FIELD_CLASS_TYPE_SIGNED_INTEGER ||
153 size_is_valid_for_enumeration_field_class(fc, size),
154 "Invalid field value range for enumeration field classe: "
155 "at least one of the current mapping ranges contains values "
156 "which are outside this range: %!+F, size=%" PRIu64, fc, size);
157 int_fc->range = size;
158 BT_LIB_LOGV("Set integer field classe's field value range: %!+F", fc);
159 return 0;
160 }
161
162 enum bt_field_class_integer_preferred_display_base
163 bt_field_class_integer_get_preferred_display_base(struct bt_field_class *fc)
164 {
165 struct bt_field_class_integer *int_fc = (void *) fc;
166
167 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
168 BT_ASSERT_PRE_FC_IS_INT(fc, "Field class");
169 return int_fc->base;
170 }
171
172 int bt_field_class_integer_set_preferred_display_base(struct bt_field_class *fc,
173 enum bt_field_class_integer_preferred_display_base base)
174 {
175 struct bt_field_class_integer *int_fc = (void *) fc;
176
177 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
178 BT_ASSERT_PRE_FC_IS_INT(fc, "Field class");
179 BT_ASSERT_PRE_FC_HOT(fc, "Field class");
180 int_fc->base = base;
181 BT_LIB_LOGV("Set integer field classe's preferred display base: %!+F", fc);
182 return 0;
183 }
184
185 static
186 void finalize_enumeration_field_class_mapping(
187 struct bt_field_class_enumeration_mapping *mapping)
188 {
189 BT_ASSERT(mapping);
190
191 if (mapping->label) {
192 g_string_free(mapping->label, TRUE);
193 }
194
195 if (mapping->ranges) {
196 g_array_free(mapping->ranges, TRUE);
197 }
198 }
199
200 static
201 void destroy_enumeration_field_class(struct bt_object *obj)
202 {
203 struct bt_field_class_enumeration *fc = (void *) obj;
204
205 BT_ASSERT(fc);
206 BT_LIB_LOGD("Destroying enumeration field classe object: %!+F", fc);
207
208 if (fc->mappings) {
209 uint64_t i;
210
211 for (i = 0; i < fc->mappings->len; i++) {
212 finalize_enumeration_field_class_mapping(
213 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc, i));
214 }
215
216 g_array_free(fc->mappings, TRUE);
217 }
218
219 if (fc->label_buf) {
220 g_ptr_array_free(fc->label_buf, TRUE);
221 }
222
223 g_free(fc);
224 }
225
226 static
227 struct bt_field_class *create_enumeration_field_class(enum bt_field_class_type type)
228 {
229 struct bt_field_class_enumeration *enum_fc = NULL;
230
231 BT_LOGD("Creating default enumeration field classe object: type=%s",
232 bt_common_field_class_type_string(type));
233 enum_fc = g_new0(struct bt_field_class_enumeration, 1);
234 if (!enum_fc) {
235 BT_LOGE_STR("Failed to allocate one enumeration field classe.");
236 goto error;
237 }
238
239 init_integer_field_class((void *) enum_fc, type,
240 destroy_enumeration_field_class);
241 enum_fc->mappings = g_array_new(FALSE, TRUE,
242 sizeof(struct bt_field_class_enumeration_mapping));
243 if (!enum_fc->mappings) {
244 BT_LOGE_STR("Failed to allocate a GArray.");
245 goto error;
246 }
247
248 enum_fc->label_buf = g_ptr_array_new();
249 if (!enum_fc->label_buf) {
250 BT_LOGE_STR("Failed to allocate a GArray.");
251 goto error;
252 }
253
254 BT_LIB_LOGD("Created enumeration field classe object: %!+F", enum_fc);
255 goto end;
256
257 error:
258 BT_OBJECT_PUT_REF_AND_RESET(enum_fc);
259
260 end:
261 return (void *) enum_fc;
262 }
263
264 struct bt_field_class *bt_field_class_unsigned_enumeration_create(void)
265 {
266 return create_enumeration_field_class(
267 BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION);
268 }
269
270 struct bt_field_class *bt_field_class_signed_enumeration_create(void)
271 {
272 return create_enumeration_field_class(
273 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION);
274 }
275
276 uint64_t bt_field_class_enumeration_get_mapping_count(struct bt_field_class *fc)
277 {
278 struct bt_field_class_enumeration *enum_fc = (void *) fc;
279
280 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
281 BT_ASSERT_PRE_FC_IS_ENUM(fc, "Field class");
282 return (uint64_t) enum_fc->mappings->len;
283 }
284
285 void bt_field_class_unsigned_enumeration_borrow_mapping_by_index(
286 struct bt_field_class *fc, uint64_t index,
287 const char **name,
288 struct bt_field_class_unsigned_enumeration_mapping_ranges **ranges)
289 {
290 struct bt_field_class_enumeration *enum_fc = (void *) fc;
291 struct bt_field_class_enumeration_mapping *mapping;
292
293 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
294 BT_ASSERT_PRE_NON_NULL(name, "Name (output)");
295 BT_ASSERT_PRE_NON_NULL(ranges, "Ranges (output)");
296 BT_ASSERT_PRE_VALID_INDEX(index, enum_fc->mappings->len);
297 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION,
298 "Field class");
299 mapping = BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc, index);
300 *name = mapping->label->str;
301 *ranges = (void *) mapping;
302 }
303
304 void bt_field_class_signed_enumeration_borrow_mapping_by_index(
305 struct bt_field_class *fc, uint64_t index,
306 const char **name,
307 struct bt_field_class_signed_enumeration_mapping_ranges **ranges)
308 {
309 struct bt_field_class_enumeration *enum_fc = (void *) fc;
310 struct bt_field_class_enumeration_mapping *mapping;
311
312 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
313 BT_ASSERT_PRE_NON_NULL(name, "Name (output)");
314 BT_ASSERT_PRE_NON_NULL(ranges, "Ranges (output)");
315 BT_ASSERT_PRE_VALID_INDEX(index, enum_fc->mappings->len);
316 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION,
317 "Field class");
318 mapping = BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(fc, index);
319 *name = mapping->label->str;
320 *ranges = (void *) mapping;
321 }
322
323 static inline
324 uint64_t get_enumeration_field_class_mapping_range_count(
325 struct bt_field_class_enumeration_mapping *mapping)
326 {
327 BT_ASSERT_PRE_NON_NULL(mapping, "Ranges");
328 return (uint64_t) mapping->ranges->len;
329 }
330
331 uint64_t bt_field_class_unsigned_enumeration_mapping_ranges_get_range_count(
332 struct bt_field_class_unsigned_enumeration_mapping_ranges *ranges)
333 {
334 return get_enumeration_field_class_mapping_range_count((void *) ranges);
335 }
336
337 uint64_t bt_field_class_signed_enumeration_mapping_ranges_get_range_count(
338 struct bt_field_class_signed_enumeration_mapping_ranges *ranges)
339 {
340 return get_enumeration_field_class_mapping_range_count((void *) ranges);
341 }
342
343 static inline
344 void get_enumeration_field_class_mapping_range_at_index(
345 struct bt_field_class_enumeration_mapping *mapping,
346 uint64_t index, uint64_t *lower, uint64_t *upper)
347 {
348 struct bt_field_class_enumeration_mapping_range *range;
349
350 BT_ASSERT_PRE_NON_NULL(mapping, "Ranges");
351 BT_ASSERT_PRE_NON_NULL(lower, "Range's lower (output)");
352 BT_ASSERT_PRE_NON_NULL(upper, "Range's upper (output)");
353 BT_ASSERT_PRE_VALID_INDEX(index, mapping->ranges->len);
354 range = BT_FIELD_CLASS_ENUM_MAPPING_RANGE_AT_INDEX(mapping, index);
355 *lower = range->lower.u;
356 *upper = range->upper.u;
357 }
358
359 void bt_field_class_unsigned_enumeration_mapping_ranges_get_range_by_index(
360 struct bt_field_class_unsigned_enumeration_mapping_ranges *ranges,
361 uint64_t index, uint64_t *lower, uint64_t *upper)
362 {
363 get_enumeration_field_class_mapping_range_at_index((void *) ranges,
364 index, lower, upper);
365 }
366
367 void bt_field_class_signed_enumeration_mapping_ranges_get_range_by_index(
368 struct bt_field_class_unsigned_enumeration_mapping_ranges *ranges,
369 uint64_t index, int64_t *lower, int64_t *upper)
370 {
371 get_enumeration_field_class_mapping_range_at_index((void *) ranges,
372 index, (uint64_t *) lower, (uint64_t *) upper);
373 }
374
375
376
377 int bt_field_class_unsigned_enumeration_get_mapping_labels_by_value(
378 struct bt_field_class *fc, uint64_t value,
379 bt_field_class_enumeration_mapping_label_array *label_array,
380 uint64_t *count)
381 {
382 struct bt_field_class_enumeration *enum_fc = (void *) fc;
383 uint64_t i;
384
385 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
386 BT_ASSERT_PRE_NON_NULL(label_array, "Label array (output)");
387 BT_ASSERT_PRE_NON_NULL(count, "Count (output)");
388 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION,
389 "Field class");
390 g_ptr_array_set_size(enum_fc->label_buf, 0);
391
392 for (i = 0; i < enum_fc->mappings->len; i++) {
393 uint64_t j;
394 struct bt_field_class_enumeration_mapping *mapping =
395 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc, i);
396
397 for (j = 0; j < mapping->ranges->len; j++) {
398 struct bt_field_class_enumeration_mapping_range *range =
399 BT_FIELD_CLASS_ENUM_MAPPING_RANGE_AT_INDEX(
400 mapping, j);
401
402 if (value >= range->lower.u &&
403 value <= range->upper.u) {
404 g_ptr_array_add(enum_fc->label_buf,
405 mapping->label->str);
406 break;
407 }
408 }
409 }
410
411 *label_array = (void *) enum_fc->label_buf->pdata;
412 *count = (uint64_t) enum_fc->label_buf->len;
413 return 0;
414 }
415
416 int bt_field_class_signed_enumeration_get_mapping_labels_by_value(
417 struct bt_field_class *fc, int64_t value,
418 bt_field_class_enumeration_mapping_label_array *label_array,
419 uint64_t *count)
420 {
421 struct bt_field_class_enumeration *enum_fc = (void *) fc;
422 uint64_t i;
423
424 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
425 BT_ASSERT_PRE_NON_NULL(label_array, "Label array (output)");
426 BT_ASSERT_PRE_NON_NULL(count, "Count (output)");
427 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION,
428 "Field class");
429 g_ptr_array_set_size(enum_fc->label_buf, 0);
430
431 for (i = 0; i < enum_fc->mappings->len; i++) {
432 uint64_t j;
433 struct bt_field_class_enumeration_mapping *mapping =
434 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc, i);
435
436 for (j = 0; j < mapping->ranges->len; j++) {
437 struct bt_field_class_enumeration_mapping_range *range =
438 BT_FIELD_CLASS_ENUM_MAPPING_RANGE_AT_INDEX(
439 mapping, j);
440
441 if (value >= range->lower.i &&
442 value <= range->upper.i) {
443 g_ptr_array_add(enum_fc->label_buf,
444 mapping->label->str);
445 break;
446 }
447 }
448 }
449
450 *label_array = (void *) enum_fc->label_buf->pdata;
451 *count = (uint64_t) enum_fc->label_buf->len;
452 return 0;
453 }
454
455 static inline
456 int add_mapping_to_enumeration_field_class(struct bt_field_class *fc,
457 const char *label, uint64_t lower, uint64_t upper)
458 {
459 int ret = 0;
460 uint64_t i;
461 struct bt_field_class_enumeration *enum_fc = (void *) fc;
462 struct bt_field_class_enumeration_mapping *mapping = NULL;
463 struct bt_field_class_enumeration_mapping_range *range;
464
465 BT_ASSERT(fc);
466 BT_ASSERT_PRE_NON_NULL(label, "Label");
467
468 /* Find existing mapping identified by this label */
469 for (i = 0; i < enum_fc->mappings->len; i++) {
470 struct bt_field_class_enumeration_mapping *mapping_candidate =
471 BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc, i);
472
473 if (strcmp(mapping_candidate->label->str, label) == 0) {
474 mapping = mapping_candidate;
475 break;
476 }
477 }
478
479 if (!mapping) {
480 /* Create new mapping for this label */
481 g_array_set_size(enum_fc->mappings, enum_fc->mappings->len + 1);
482 mapping = BT_FIELD_CLASS_ENUM_MAPPING_AT_INDEX(enum_fc,
483 enum_fc->mappings->len - 1);
484 mapping->ranges = g_array_new(FALSE, TRUE,
485 sizeof(struct bt_field_class_enumeration_mapping_range));
486 if (!mapping->ranges) {
487 finalize_enumeration_field_class_mapping(mapping);
488 g_array_set_size(enum_fc->mappings,
489 enum_fc->mappings->len - 1);
490 ret = -1;
491 goto end;
492 }
493
494 mapping->label = g_string_new(label);
495 if (!mapping->label) {
496 finalize_enumeration_field_class_mapping(mapping);
497 g_array_set_size(enum_fc->mappings,
498 enum_fc->mappings->len - 1);
499 ret = -1;
500 goto end;
501 }
502 }
503
504 /* Add range */
505 BT_ASSERT(mapping);
506 g_array_set_size(mapping->ranges, mapping->ranges->len + 1);
507 range = BT_FIELD_CLASS_ENUM_MAPPING_RANGE_AT_INDEX(mapping,
508 mapping->ranges->len - 1);
509 range->lower.u = lower;
510 range->upper.u = upper;
511 BT_LIB_LOGV("Added mapping to enumeration field classe: "
512 "%![fc-]+F, label=\"%s\", lower-unsigned=%" PRIu64 ", "
513 "upper-unsigned=%" PRIu64, fc, label, lower, upper);
514
515 end:
516 return ret;
517 }
518
519 int bt_field_class_unsigned_enumeration_map_range(
520 struct bt_field_class *fc, const char *label,
521 uint64_t range_lower, uint64_t range_upper)
522 {
523 struct bt_field_class_enumeration *enum_fc = (void *) fc;
524
525 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
526 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION,
527 "Field class");
528 BT_ASSERT_PRE(range_lower <= range_upper,
529 "Range's upper bound is less than lower bound: "
530 "upper=%" PRIu64 ", lower=%" PRIu64,
531 range_lower, range_upper);
532 BT_ASSERT_PRE(bt_util_value_is_in_range_unsigned(enum_fc->common.range,
533 range_lower),
534 "Range's lower bound is outside the enumeration field classe's value range: "
535 "%![fc-]+F, lower=%" PRIu64, fc, range_lower);
536 BT_ASSERT_PRE(bt_util_value_is_in_range_unsigned(enum_fc->common.range,
537 range_upper),
538 "Range's upper bound is outside the enumeration field classe's value range: "
539 "%![fc-]+F, upper=%" PRIu64, fc, range_upper);
540 return add_mapping_to_enumeration_field_class(fc, label, range_lower,
541 range_upper);
542 }
543
544 int bt_field_class_signed_enumeration_map_range(
545 struct bt_field_class *fc, const char *label,
546 int64_t range_lower, int64_t range_upper)
547 {
548 struct bt_field_class_enumeration *enum_fc = (void *) fc;
549
550 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
551 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION,
552 "Field class");
553 BT_ASSERT_PRE(range_lower <= range_upper,
554 "Range's upper bound is less than lower bound: "
555 "upper=%" PRId64 ", lower=%" PRId64,
556 range_lower, range_upper);
557 BT_ASSERT_PRE(bt_util_value_is_in_range_signed(enum_fc->common.range,
558 range_lower),
559 "Range's lower bound is outside the enumeration field classe's value range: "
560 "%![fc-]+F, lower=%" PRId64, fc, range_lower);
561 BT_ASSERT_PRE(bt_util_value_is_in_range_signed(enum_fc->common.range,
562 range_upper),
563 "Range's upper bound is outside the enumeration field classe's value range: "
564 "%![fc-]+F, upper=%" PRId64, fc, range_upper);
565 return add_mapping_to_enumeration_field_class(fc, label, range_lower,
566 range_upper);
567 }
568
569 static
570 void destroy_real_field_class(struct bt_object *obj)
571 {
572 BT_ASSERT(obj);
573 BT_LIB_LOGD("Destroying real field classe object: %!+F", obj);
574 g_free(obj);
575 }
576
577 struct bt_field_class *bt_field_class_real_create(void)
578 {
579 struct bt_field_class_real *real_fc = NULL;
580
581 BT_LOGD_STR("Creating default real field classe object.");
582 real_fc = g_new0(struct bt_field_class_real, 1);
583 if (!real_fc) {
584 BT_LOGE_STR("Failed to allocate one real field classe.");
585 goto error;
586 }
587
588 init_field_class((void *) real_fc, BT_FIELD_CLASS_TYPE_REAL,
589 destroy_real_field_class);
590 BT_LIB_LOGD("Created real field classe object: %!+F", real_fc);
591 goto end;
592
593 error:
594 BT_OBJECT_PUT_REF_AND_RESET(real_fc);
595
596 end:
597 return (void *) real_fc;
598 }
599
600 bt_bool bt_field_class_real_is_single_precision(struct bt_field_class *fc)
601 {
602 struct bt_field_class_real *real_fc = (void *) fc;
603
604 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
605 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_REAL, "Field class");
606 return real_fc->is_single_precision;
607 }
608
609 int bt_field_class_real_set_is_single_precision(struct bt_field_class *fc,
610 bt_bool is_single_precision)
611 {
612 struct bt_field_class_real *real_fc = (void *) fc;
613
614 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
615 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_REAL, "Field class");
616 BT_ASSERT_PRE_FC_HOT(fc, "Field class");
617 real_fc->is_single_precision = (bool) is_single_precision;
618 BT_LIB_LOGV("Set real field classe's \"is single precision\" property: "
619 "%!+F", fc);
620 return 0;
621 }
622
623 static
624 int init_named_field_classes_container(
625 struct bt_field_class_named_field_class_container *fc,
626 enum bt_field_class_type type, bt_object_release_func release_func)
627 {
628 int ret = 0;
629
630 init_field_class((void *) fc, type, release_func);
631 fc->named_fcs = g_array_new(FALSE, TRUE,
632 sizeof(struct bt_named_field_class));
633 if (!fc->named_fcs) {
634 BT_LOGE_STR("Failed to allocate a GArray.");
635 ret = -1;
636 goto end;
637 }
638
639 fc->name_to_index = g_hash_table_new(g_str_hash, g_str_equal);
640 if (!fc->name_to_index) {
641 BT_LOGE_STR("Failed to allocate a GHashTable.");
642 ret = -1;
643 goto end;
644 }
645
646 end:
647 return ret;
648 }
649
650 static
651 void finalize_named_field_class(struct bt_named_field_class *named_fc)
652 {
653 BT_ASSERT(named_fc);
654 BT_LIB_LOGD("Finalizing named field classe: "
655 "addr=%p, name=\"%s\", %![fc-]+F",
656 named_fc, named_fc->name ? named_fc->name->str : NULL,
657 named_fc->fc);
658
659 if (named_fc->name) {
660 g_string_free(named_fc->name, TRUE);
661 }
662
663 BT_LOGD_STR("Putting named field classe's field classe.");
664 bt_object_put_ref(named_fc->fc);
665 }
666
667 static
668 void finalize_named_field_classes_container(
669 struct bt_field_class_named_field_class_container *fc)
670 {
671 uint64_t i;
672
673 BT_ASSERT(fc);
674
675 if (fc->named_fcs) {
676 for (i = 0; i < fc->named_fcs->len; i++) {
677 finalize_named_field_class(
678 &g_array_index(fc->named_fcs,
679 struct bt_named_field_class, i));
680 }
681
682 g_array_free(fc->named_fcs, TRUE);
683 }
684
685 if (fc->name_to_index) {
686 g_hash_table_destroy(fc->name_to_index);
687 }
688 }
689
690 static
691 void destroy_structure_field_class(struct bt_object *obj)
692 {
693 BT_ASSERT(obj);
694 BT_LIB_LOGD("Destroying string field classe object: %!+F", obj);
695 finalize_named_field_classes_container((void *) obj);
696 g_free(obj);
697 }
698
699 struct bt_field_class *bt_field_class_structure_create(void)
700 {
701 int ret;
702 struct bt_field_class_structure *struct_fc = NULL;
703
704 BT_LOGD_STR("Creating default structure field classe object.");
705 struct_fc = g_new0(struct bt_field_class_structure, 1);
706 if (!struct_fc) {
707 BT_LOGE_STR("Failed to allocate one structure field classe.");
708 goto error;
709 }
710
711 ret = init_named_field_classes_container((void *) struct_fc,
712 BT_FIELD_CLASS_TYPE_STRUCTURE, destroy_structure_field_class);
713 if (ret) {
714 goto error;
715 }
716
717 BT_LIB_LOGD("Created structure field classe object: %!+F", struct_fc);
718 goto end;
719
720 error:
721 BT_OBJECT_PUT_REF_AND_RESET(struct_fc);
722
723 end:
724 return (void *) struct_fc;
725 }
726
727 static
728 int append_named_field_class_to_container_field_class(
729 struct bt_field_class_named_field_class_container *container_fc,
730 const char *name, struct bt_field_class *fc)
731 {
732 int ret = 0;
733 struct bt_named_field_class *named_fc;
734 GString *name_str;
735
736 BT_ASSERT(container_fc);
737 BT_ASSERT_PRE_FC_HOT(container_fc, "Field class");
738 BT_ASSERT_PRE_NON_NULL(name, "Name");
739 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
740 BT_ASSERT_PRE(!bt_g_hash_table_contains(container_fc->name_to_index,
741 name),
742 "Duplicate member/option name in structure/variant field classe: "
743 "%![container-fc-]+F, name=\"%s\"", container_fc, name);
744 name_str = g_string_new(name);
745 if (!name_str) {
746 BT_LOGE_STR("Failed to allocate a GString.");
747 ret = -1;
748 goto end;
749 }
750
751 g_array_set_size(container_fc->named_fcs,
752 container_fc->named_fcs->len + 1);
753 named_fc = &g_array_index(container_fc->named_fcs,
754 struct bt_named_field_class, container_fc->named_fcs->len - 1);
755 named_fc->name = name_str;
756 named_fc->fc = bt_object_get_ref(fc);
757 g_hash_table_insert(container_fc->name_to_index, named_fc->name->str,
758 GUINT_TO_POINTER(container_fc->named_fcs->len - 1));
759 bt_field_class_freeze(fc);
760
761 end:
762 return ret;
763 }
764
765 int bt_field_class_structure_append_member(struct bt_field_class *fc,
766 const char *name, struct bt_field_class *member_fc)
767 {
768 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
769 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_STRUCTURE, "Field class");
770 return append_named_field_class_to_container_field_class((void *) fc,
771 name, member_fc);
772 }
773
774 uint64_t bt_field_class_structure_get_member_count(struct bt_field_class *fc)
775 {
776 struct bt_field_class_structure *struct_fc = (void *) fc;
777
778 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
779 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_STRUCTURE, "Field class");
780 return (uint64_t) struct_fc->common.named_fcs->len;
781 }
782
783 static
784 void borrow_named_field_class_from_container_field_class_at_index(
785 struct bt_field_class_named_field_class_container *fc,
786 uint64_t index, const char **name,
787 struct bt_field_class **out_fc)
788 {
789 struct bt_named_field_class *named_fc;
790
791 BT_ASSERT(fc);
792 BT_ASSERT_PRE_NON_NULL(name, "Name");
793 BT_ASSERT_PRE_NON_NULL(out_fc, "Field class (output)");
794 BT_ASSERT_PRE_VALID_INDEX(index, fc->named_fcs->len);
795 named_fc = BT_FIELD_CLASS_NAMED_FC_AT_INDEX(fc, index);
796 *name = named_fc->name->str;
797 *out_fc = named_fc->fc;
798 }
799
800 void bt_field_class_structure_borrow_member_by_index(
801 struct bt_field_class *fc, uint64_t index,
802 const char **name, struct bt_field_class **out_fc)
803 {
804 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
805 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_STRUCTURE, "Field class");
806 borrow_named_field_class_from_container_field_class_at_index((void *) fc,
807 index, name, out_fc);
808 }
809
810 static
811 struct bt_field_class *borrow_field_class_from_container_field_class_by_name(
812 struct bt_field_class_named_field_class_container *fc,
813 const char *name)
814 {
815 struct bt_field_class *ret_fc = NULL;
816 struct bt_named_field_class *named_fc;
817 gpointer orig_key;
818 gpointer value;
819
820 BT_ASSERT(fc);
821 BT_ASSERT_PRE_NON_NULL(name, "Name");
822 if (!g_hash_table_lookup_extended(fc->name_to_index, name, &orig_key,
823 &value)) {
824 goto end;
825 }
826
827 named_fc = BT_FIELD_CLASS_NAMED_FC_AT_INDEX(fc,
828 GPOINTER_TO_UINT(value));
829 ret_fc = named_fc->fc;
830
831 end:
832 return ret_fc;
833 }
834
835 struct bt_field_class *bt_field_class_structure_borrow_member_field_class_by_name(
836 struct bt_field_class *fc, const char *name)
837 {
838 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
839 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_STRUCTURE, "Field class");
840 return borrow_field_class_from_container_field_class_by_name((void *) fc,
841 name);
842 }
843
844 static
845 void destroy_variant_field_class(struct bt_object *obj)
846 {
847 struct bt_field_class_variant *fc = (void *) obj;
848
849 BT_ASSERT(fc);
850 BT_LIB_LOGD("Destroying variant field classe object: %!+F", fc);
851 finalize_named_field_classes_container((void *) fc);
852 BT_LOGD_STR("Putting selector field path.");
853 bt_object_put_ref(fc->selector_field_path);
854 g_free(fc);
855 }
856
857 struct bt_field_class *bt_field_class_variant_create(void)
858 {
859 int ret;
860 struct bt_field_class_variant *var_fc = NULL;
861
862 BT_LOGD_STR("Creating default variant field classe object.");
863 var_fc = g_new0(struct bt_field_class_variant, 1);
864 if (!var_fc) {
865 BT_LOGE_STR("Failed to allocate one variant field classe.");
866 goto error;
867 }
868
869 ret = init_named_field_classes_container((void *) var_fc,
870 BT_FIELD_CLASS_TYPE_VARIANT, destroy_variant_field_class);
871 if (ret) {
872 goto error;
873 }
874
875 BT_LIB_LOGD("Created variant field classe object: %!+F", var_fc);
876 goto end;
877
878 error:
879 BT_OBJECT_PUT_REF_AND_RESET(var_fc);
880
881 end:
882 return (void *) var_fc;
883 }
884
885 int bt_field_class_variant_set_selector_field_class(
886 struct bt_field_class *fc, struct bt_field_class *selector_fc)
887 {
888 struct bt_field_class_variant *var_fc = (void *) fc;
889
890 BT_ASSERT_PRE_NON_NULL(fc, "Variant field classe");
891 BT_ASSERT_PRE_NON_NULL(selector_fc, "Selector field classe");
892 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_VARIANT, "Field class");
893 BT_ASSERT_PRE_FC_IS_ENUM(selector_fc, "Selector field classe");
894 BT_ASSERT_PRE_FC_HOT(fc, "Variant field classe");
895 var_fc->selector_fc = selector_fc;
896 bt_field_class_freeze(selector_fc);
897 return 0;
898 }
899
900 int bt_field_class_variant_append_option(struct bt_field_class *fc,
901 const char *name, struct bt_field_class *option_fc)
902 {
903 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
904 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_VARIANT, "Field class");
905 return append_named_field_class_to_container_field_class((void *) fc,
906 name, option_fc);
907 }
908
909 struct bt_field_class *bt_field_class_variant_borrow_option_field_class_by_name(
910 struct bt_field_class *fc, const char *name)
911 {
912 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
913 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_VARIANT, "Field class");
914 return borrow_field_class_from_container_field_class_by_name((void *) fc,
915 name);
916 }
917
918 uint64_t bt_field_class_variant_get_option_count(struct bt_field_class *fc)
919 {
920 struct bt_field_class_variant *var_fc = (void *) fc;
921
922 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
923 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_VARIANT, "Field class");
924 return (uint64_t) var_fc->common.named_fcs->len;
925 }
926
927 void bt_field_class_variant_borrow_option_by_index(
928 struct bt_field_class *fc, uint64_t index,
929 const char **name, struct bt_field_class **out_fc)
930 {
931 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
932 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_VARIANT, "Field class");
933 borrow_named_field_class_from_container_field_class_at_index((void *) fc,
934 index, name, out_fc);
935 }
936
937 struct bt_field_path *bt_field_class_variant_borrow_selector_field_path(
938 struct bt_field_class *fc)
939 {
940 struct bt_field_class_variant *var_fc = (void *) fc;
941
942 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
943 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_VARIANT,
944 "Field class");
945 return var_fc->selector_field_path;
946 }
947
948 static
949 void init_array_field_class(struct bt_field_class_array *fc,
950 enum bt_field_class_type type, bt_object_release_func release_func,
951 struct bt_field_class *element_fc)
952 {
953 BT_ASSERT(element_fc);
954 init_field_class((void *) fc, type, release_func);
955 fc->element_fc = bt_object_get_ref(element_fc);
956 bt_field_class_freeze(element_fc);
957 }
958
959 static
960 void finalize_array_field_class(struct bt_field_class_array *array_fc)
961 {
962 BT_ASSERT(array_fc);
963 BT_LOGD_STR("Putting element field classe.");
964 bt_object_put_ref(array_fc->element_fc);
965 }
966
967 static
968 void destroy_static_array_field_class(struct bt_object *obj)
969 {
970 BT_ASSERT(obj);
971 BT_LIB_LOGD("Destroying static array field classe object: %!+F", obj);
972 finalize_array_field_class((void *) obj);
973 g_free(obj);
974 }
975
976 struct bt_field_class *bt_field_class_static_array_create(
977 struct bt_field_class *element_fc, uint64_t length)
978 {
979 struct bt_field_class_static_array *array_fc = NULL;
980
981 BT_ASSERT_PRE_NON_NULL(element_fc, "Element field classe");
982 BT_LOGD_STR("Creating default static array field classe object.");
983 array_fc = g_new0(struct bt_field_class_static_array, 1);
984 if (!array_fc) {
985 BT_LOGE_STR("Failed to allocate one static array field classe.");
986 goto error;
987 }
988
989 init_array_field_class((void *) array_fc, BT_FIELD_CLASS_TYPE_STATIC_ARRAY,
990 destroy_static_array_field_class, element_fc);
991 array_fc->length = length;
992 BT_LIB_LOGD("Created static array field classe object: %!+F", array_fc);
993 goto end;
994
995 error:
996 BT_OBJECT_PUT_REF_AND_RESET(array_fc);
997
998 end:
999 return (void *) array_fc;
1000 }
1001
1002 struct bt_field_class *bt_field_class_array_borrow_element_field_class(
1003 struct bt_field_class *fc)
1004 {
1005 struct bt_field_class_array *array_fc = (void *) fc;
1006
1007 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
1008 BT_ASSERT_PRE_FC_IS_ARRAY(fc, "Field class");
1009 return array_fc->element_fc;
1010 }
1011
1012 uint64_t bt_field_class_static_array_get_length(struct bt_field_class *fc)
1013 {
1014 struct bt_field_class_static_array *array_fc = (void *) fc;
1015
1016 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
1017 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_STATIC_ARRAY,
1018 "Field class");
1019 return (uint64_t) array_fc->length;
1020 }
1021
1022 static
1023 void destroy_dynamic_array_field_class(struct bt_object *obj)
1024 {
1025 struct bt_field_class_dynamic_array *fc = (void *) obj;
1026
1027 BT_ASSERT(fc);
1028 BT_LIB_LOGD("Destroying dynamic array field classe object: %!+F", fc);
1029 finalize_array_field_class((void *) fc);
1030 BT_LOGD_STR("Putting length field path.");
1031 bt_object_put_ref(fc->length_field_path);
1032 g_free(fc);
1033 }
1034
1035 struct bt_field_class *bt_field_class_dynamic_array_create(
1036 struct bt_field_class *element_fc)
1037 {
1038 struct bt_field_class_dynamic_array *array_fc = NULL;
1039
1040 BT_ASSERT_PRE_NON_NULL(element_fc, "Element field classe");
1041 BT_LOGD_STR("Creating default dynamic array field classe object.");
1042 array_fc = g_new0(struct bt_field_class_dynamic_array, 1);
1043 if (!array_fc) {
1044 BT_LOGE_STR("Failed to allocate one dynamic array field classe.");
1045 goto error;
1046 }
1047
1048 init_array_field_class((void *) array_fc, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY,
1049 destroy_dynamic_array_field_class, element_fc);
1050 BT_LIB_LOGD("Created dynamic array field classe object: %!+F", array_fc);
1051 goto end;
1052
1053 error:
1054 BT_OBJECT_PUT_REF_AND_RESET(array_fc);
1055
1056 end:
1057 return (void *) array_fc;
1058 }
1059
1060 int bt_field_class_dynamic_array_set_length_field_class(struct bt_field_class *fc,
1061 struct bt_field_class *length_fc)
1062 {
1063 struct bt_field_class_dynamic_array *array_fc = (void *) fc;
1064
1065 BT_ASSERT_PRE_NON_NULL(fc, "Dynamic array field classe");
1066 BT_ASSERT_PRE_NON_NULL(length_fc, "Length field classe");
1067 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY,
1068 "Field class");
1069 BT_ASSERT_PRE_FC_IS_UNSIGNED_INT(length_fc, "Length field classe");
1070 BT_ASSERT_PRE_FC_HOT(fc, "Dynamic array field classe");
1071 array_fc->length_fc = length_fc;
1072 bt_field_class_freeze(length_fc);
1073 return 0;
1074 }
1075
1076 struct bt_field_path *bt_field_class_dynamic_array_borrow_length_field_path(
1077 struct bt_field_class *fc)
1078 {
1079 struct bt_field_class_dynamic_array *seq_fc = (void *) fc;
1080
1081 BT_ASSERT_PRE_NON_NULL(fc, "Field class");
1082 BT_ASSERT_PRE_FC_HAS_ID(fc, BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY,
1083 "Field class");
1084 return seq_fc->length_field_path;
1085 }
1086
1087 static
1088 void destroy_string_field_class(struct bt_object *obj)
1089 {
1090 BT_ASSERT(obj);
1091 BT_LIB_LOGD("Destroying string field classe object: %!+F", obj);
1092 g_free(obj);
1093 }
1094
1095 struct bt_field_class *bt_field_class_string_create(void)
1096 {
1097 struct bt_field_class_string *string_fc = NULL;
1098
1099 BT_LOGD_STR("Creating default string field classe object.");
1100 string_fc = g_new0(struct bt_field_class_string, 1);
1101 if (!string_fc) {
1102 BT_LOGE_STR("Failed to allocate one string field classe.");
1103 goto error;
1104 }
1105
1106 init_field_class((void *) string_fc, BT_FIELD_CLASS_TYPE_STRING,
1107 destroy_string_field_class);
1108 BT_LIB_LOGD("Created string field classe object: %!+F", string_fc);
1109 goto end;
1110
1111 error:
1112 BT_OBJECT_PUT_REF_AND_RESET(string_fc);
1113
1114 end:
1115 return (void *) string_fc;
1116 }
1117
1118 BT_HIDDEN
1119 void _bt_field_class_freeze(struct bt_field_class *fc)
1120 {
1121 /*
1122 * Element/member/option field classes are frozen when added to
1123 * their owner.
1124 */
1125 BT_ASSERT(fc);
1126 fc->frozen = true;
1127 }
1128
1129 BT_HIDDEN
1130 void _bt_field_class_make_part_of_trace(struct bt_field_class *fc)
1131 {
1132 BT_ASSERT(fc);
1133 BT_ASSERT_PRE(!fc->part_of_trace,
1134 "Field class is already part of a trace: %!+F", fc);
1135 fc->part_of_trace = true;
1136
1137 switch (fc->type) {
1138 case BT_FIELD_CLASS_TYPE_STRUCTURE:
1139 case BT_FIELD_CLASS_TYPE_VARIANT:
1140 {
1141 struct bt_field_class_named_field_class_container *container_fc =
1142 (void *) fc;
1143 uint64_t i;
1144
1145 for (i = 0; i < container_fc->named_fcs->len; i++) {
1146 struct bt_named_field_class *named_fc =
1147 BT_FIELD_CLASS_NAMED_FC_AT_INDEX(
1148 container_fc, i);
1149
1150 bt_field_class_make_part_of_trace(named_fc->fc);
1151 }
1152
1153 break;
1154 }
1155 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY:
1156 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY:
1157 {
1158 struct bt_field_class_array *array_fc = (void *) fc;
1159
1160 bt_field_class_make_part_of_trace(array_fc->element_fc);
1161 break;
1162 }
1163 default:
1164 break;
1165 }
1166 }
This page took 0.052886 seconds and 4 git commands to generate.