lib: decouple variant FC option names from selector FC mapping names
[babeltrace.git] / src / lib / trace-ir / field.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"
25 #include "lib/logging.h"
26
27 #include "lib/assert-pre.h"
28 #include <babeltrace2/trace-ir/field.h>
29 #include <babeltrace2/trace-ir/field-const.h>
30 #include "lib/object.h"
31 #include "compat/compiler.h"
32 #include "compat/fcntl.h"
33 #include "common/align.h"
34 #include "common/assert.h"
35 #include <inttypes.h>
36
37 #include "field.h"
38 #include "field-class.h"
39 #include "lib/func-status.h"
40
41 static
42 void reset_single_field(struct bt_field *field);
43
44 static
45 void reset_array_field(struct bt_field *field);
46
47 static
48 void reset_structure_field(struct bt_field *field);
49
50 static
51 void reset_variant_field(struct bt_field *field);
52
53 static
54 void set_single_field_is_frozen(struct bt_field *field, bool is_frozen);
55
56 static
57 void set_array_field_is_frozen(struct bt_field *field, bool is_frozen);
58
59 static
60 void set_structure_field_is_frozen(struct bt_field *field, bool is_frozen);
61
62 static
63 void set_variant_field_is_frozen(struct bt_field *field, bool is_frozen);
64
65 static
66 bool single_field_is_set(const struct bt_field *field);
67
68 static
69 bool array_field_is_set(const struct bt_field *field);
70
71 static
72 bool structure_field_is_set(const struct bt_field *field);
73
74 static
75 bool variant_field_is_set(const struct bt_field *field);
76
77 static
78 struct bt_field_methods integer_field_methods = {
79 .set_is_frozen = set_single_field_is_frozen,
80 .is_set = single_field_is_set,
81 .reset = reset_single_field,
82 };
83
84 static
85 struct bt_field_methods real_field_methods = {
86 .set_is_frozen = set_single_field_is_frozen,
87 .is_set = single_field_is_set,
88 .reset = reset_single_field,
89 };
90
91 static
92 struct bt_field_methods string_field_methods = {
93 .set_is_frozen = set_single_field_is_frozen,
94 .is_set = single_field_is_set,
95 .reset = reset_single_field,
96 };
97
98 static
99 struct bt_field_methods structure_field_methods = {
100 .set_is_frozen = set_structure_field_is_frozen,
101 .is_set = structure_field_is_set,
102 .reset = reset_structure_field,
103 };
104
105 static
106 struct bt_field_methods array_field_methods = {
107 .set_is_frozen = set_array_field_is_frozen,
108 .is_set = array_field_is_set,
109 .reset = reset_array_field,
110 };
111
112 static
113 struct bt_field_methods variant_field_methods = {
114 .set_is_frozen = set_variant_field_is_frozen,
115 .is_set = variant_field_is_set,
116 .reset = reset_variant_field,
117 };
118
119 static
120 struct bt_field *create_integer_field(struct bt_field_class *);
121
122 static
123 struct bt_field *create_real_field(struct bt_field_class *);
124
125 static
126 struct bt_field *create_string_field(struct bt_field_class *);
127
128 static
129 struct bt_field *create_structure_field(struct bt_field_class *);
130
131 static
132 struct bt_field *create_static_array_field(struct bt_field_class *);
133
134 static
135 struct bt_field *create_dynamic_array_field(struct bt_field_class *);
136
137 static
138 struct bt_field *create_variant_field(struct bt_field_class *);
139
140 static
141 struct bt_field *(* const field_create_funcs[])(struct bt_field_class *) = {
142 [BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER] = create_integer_field,
143 [BT_FIELD_CLASS_TYPE_SIGNED_INTEGER] = create_integer_field,
144 [BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION] = create_integer_field,
145 [BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION] = create_integer_field,
146 [BT_FIELD_CLASS_TYPE_REAL] = create_real_field,
147 [BT_FIELD_CLASS_TYPE_STRING] = create_string_field,
148 [BT_FIELD_CLASS_TYPE_STRUCTURE] = create_structure_field,
149 [BT_FIELD_CLASS_TYPE_STATIC_ARRAY] = create_static_array_field,
150 [BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY] = create_dynamic_array_field,
151 [BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR] = create_variant_field,
152 [BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR] = create_variant_field,
153 [BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR] = create_variant_field,
154 };
155
156 static
157 void destroy_integer_field(struct bt_field *field);
158
159 static
160 void destroy_real_field(struct bt_field *field);
161
162 static
163 void destroy_string_field(struct bt_field *field);
164
165 static
166 void destroy_structure_field(struct bt_field *field);
167
168 static
169 void destroy_array_field(struct bt_field *field);
170
171 static
172 void destroy_variant_field(struct bt_field *field);
173
174 static
175 void (* const field_destroy_funcs[])(struct bt_field *) = {
176 [BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER] = destroy_integer_field,
177 [BT_FIELD_CLASS_TYPE_SIGNED_INTEGER] = destroy_integer_field,
178 [BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION] = destroy_integer_field,
179 [BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION] = destroy_integer_field,
180 [BT_FIELD_CLASS_TYPE_REAL] = destroy_real_field,
181 [BT_FIELD_CLASS_TYPE_STRING] = destroy_string_field,
182 [BT_FIELD_CLASS_TYPE_STRUCTURE] = destroy_structure_field,
183 [BT_FIELD_CLASS_TYPE_STATIC_ARRAY] = destroy_array_field,
184 [BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY] = destroy_array_field,
185 [BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR] = destroy_variant_field,
186 [BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR] = destroy_variant_field,
187 [BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR] = destroy_variant_field,
188 };
189
190 struct bt_field_class *bt_field_borrow_class(const struct bt_field *field)
191 {
192 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
193 return field->class;
194 }
195
196 const struct bt_field_class *bt_field_borrow_class_const(
197 const struct bt_field *field)
198 {
199 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
200 return field->class;
201 }
202
203 enum bt_field_class_type bt_field_get_class_type(const struct bt_field *field)
204 {
205 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
206 return field->class->type;
207 }
208
209 BT_HIDDEN
210 struct bt_field *bt_field_create(struct bt_field_class *fc)
211 {
212 struct bt_field *field = NULL;
213
214 BT_ASSERT(fc);
215 field = field_create_funcs[fc->type](fc);
216 if (!field) {
217 BT_LIB_LOGE_APPEND_CAUSE("Cannot create field object from field class: "
218 "%![fc-]+F", fc);
219 goto end;
220 }
221
222 end:
223 return field;
224 }
225
226 static inline
227 void init_field(struct bt_field *field, struct bt_field_class *fc,
228 struct bt_field_methods *methods)
229 {
230 BT_ASSERT(field);
231 BT_ASSERT(fc);
232 bt_object_init_unique(&field->base);
233 field->methods = methods;
234 field->class = fc;
235 bt_object_get_no_null_check(fc);
236 }
237
238 static
239 struct bt_field *create_integer_field(struct bt_field_class *fc)
240 {
241 struct bt_field_integer *int_field;
242
243 BT_LIB_LOGD("Creating integer field object: %![fc-]+F", fc);
244 int_field = g_new0(struct bt_field_integer, 1);
245 if (!int_field) {
246 BT_LIB_LOGE_APPEND_CAUSE(
247 "Failed to allocate one integer field.");
248 goto end;
249 }
250
251 init_field((void *) int_field, fc, &integer_field_methods);
252 BT_LIB_LOGD("Created integer field object: %!+f", int_field);
253
254 end:
255 return (void *) int_field;
256 }
257
258 static
259 struct bt_field *create_real_field(struct bt_field_class *fc)
260 {
261 struct bt_field_real *real_field;
262
263 BT_LIB_LOGD("Creating real field object: %![fc-]+F", fc);
264 real_field = g_new0(struct bt_field_real, 1);
265 if (!real_field) {
266 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one real field.");
267 goto end;
268 }
269
270 init_field((void *) real_field, fc, &real_field_methods);
271 BT_LIB_LOGD("Created real field object: %!+f", real_field);
272
273 end:
274 return (void *) real_field;
275 }
276
277 static
278 struct bt_field *create_string_field(struct bt_field_class *fc)
279 {
280 struct bt_field_string *string_field;
281
282 BT_LIB_LOGD("Creating string field object: %![fc-]+F", fc);
283 string_field = g_new0(struct bt_field_string, 1);
284 if (!string_field) {
285 BT_LIB_LOGE_APPEND_CAUSE(
286 "Failed to allocate one string field.");
287 goto end;
288 }
289
290 init_field((void *) string_field, fc, &string_field_methods);
291 string_field->buf = g_array_sized_new(FALSE, FALSE,
292 sizeof(char), 1);
293 if (!string_field->buf) {
294 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GArray.");
295 BT_OBJECT_PUT_REF_AND_RESET(string_field);
296 goto end;
297 }
298
299 g_array_index(string_field->buf, char, 0) = '\0';
300 BT_LIB_LOGD("Created string field object: %!+f", string_field);
301
302 end:
303 return (void *) string_field;
304 }
305
306 static inline
307 int create_fields_from_named_field_classes(
308 struct bt_field_class_named_field_class_container *fc,
309 GPtrArray **fields)
310 {
311 int ret = 0;
312 uint64_t i;
313
314 *fields = g_ptr_array_new_with_free_func(
315 (GDestroyNotify) bt_field_destroy);
316 if (!*fields) {
317 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GPtrArray.");
318 ret = -1;
319 goto end;
320 }
321
322 g_ptr_array_set_size(*fields, fc->named_fcs->len);
323
324 for (i = 0; i < fc->named_fcs->len; i++) {
325 struct bt_field *field;
326 struct bt_named_field_class *named_fc = fc->named_fcs->pdata[i];
327
328 field = bt_field_create(named_fc->fc);
329 if (!field) {
330 BT_LIB_LOGE_APPEND_CAUSE(
331 "Failed to create structure member or variant option field: "
332 "name=\"%s\", %![fc-]+F",
333 named_fc->name->str, named_fc->fc);
334 ret = -1;
335 goto end;
336 }
337
338 g_ptr_array_index(*fields, i) = field;
339 }
340
341 end:
342 return ret;
343 }
344
345 static
346 struct bt_field *create_structure_field(struct bt_field_class *fc)
347 {
348 struct bt_field_structure *struct_field;
349
350 BT_LIB_LOGD("Creating structure field object: %![fc-]+F", fc);
351 struct_field = g_new0(struct bt_field_structure, 1);
352 if (!struct_field) {
353 BT_LIB_LOGE_APPEND_CAUSE(
354 "Failed to allocate one structure field.");
355 goto end;
356 }
357
358 init_field((void *) struct_field, fc, &structure_field_methods);
359
360 if (create_fields_from_named_field_classes((void *) fc,
361 &struct_field->fields)) {
362 BT_LIB_LOGE_APPEND_CAUSE(
363 "Cannot create structure member fields: %![fc-]+F", fc);
364 BT_OBJECT_PUT_REF_AND_RESET(struct_field);
365 goto end;
366 }
367
368 BT_LIB_LOGD("Created structure field object: %!+f", struct_field);
369
370 end:
371 return (void *) struct_field;
372 }
373
374 static
375 struct bt_field *create_variant_field(struct bt_field_class *fc)
376 {
377 struct bt_field_variant *var_field;
378
379 BT_LIB_LOGD("Creating variant field object: %![fc-]+F", fc);
380 var_field = g_new0(struct bt_field_variant, 1);
381 if (!var_field) {
382 BT_LIB_LOGE_APPEND_CAUSE(
383 "Failed to allocate one variant field.");
384 goto end;
385 }
386
387 init_field((void *) var_field, fc, &variant_field_methods);
388
389 if (create_fields_from_named_field_classes((void *) fc,
390 &var_field->fields)) {
391 BT_LIB_LOGE_APPEND_CAUSE("Cannot create variant member fields: "
392 "%![fc-]+F", fc);
393 BT_OBJECT_PUT_REF_AND_RESET(var_field);
394 goto end;
395 }
396
397 BT_LIB_LOGD("Created variant field object: %!+f", var_field);
398
399 end:
400 return (void *) var_field;
401 }
402
403 static inline
404 int init_array_field_fields(struct bt_field_array *array_field)
405 {
406 int ret = 0;
407 uint64_t i;
408 struct bt_field_class_array *array_fc;
409
410 BT_ASSERT(array_field);
411 array_fc = (void *) array_field->common.class;
412 array_field->fields = g_ptr_array_sized_new(array_field->length);
413 if (!array_field->fields) {
414 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GPtrArray.");
415 ret = -1;
416 goto end;
417 }
418
419 g_ptr_array_set_free_func(array_field->fields,
420 (GDestroyNotify) bt_field_destroy);
421 g_ptr_array_set_size(array_field->fields, array_field->length);
422
423 for (i = 0; i < array_field->length; i++) {
424 array_field->fields->pdata[i] = bt_field_create(
425 array_fc->element_fc);
426 if (!array_field->fields->pdata[i]) {
427 BT_LIB_LOGE_APPEND_CAUSE(
428 "Cannot create array field's element field: "
429 "index=%" PRIu64 ", %![fc-]+F", i, array_fc);
430 ret = -1;
431 goto end;
432 }
433 }
434
435 end:
436 return ret;
437 }
438
439 static
440 struct bt_field *create_static_array_field(struct bt_field_class *fc)
441 {
442 struct bt_field_class_static_array *array_fc = (void *) fc;
443 struct bt_field_array *array_field;
444
445 BT_LIB_LOGD("Creating static array field object: %![fc-]+F", fc);
446 array_field = g_new0(struct bt_field_array, 1);
447 if (!array_field) {
448 BT_LIB_LOGE_APPEND_CAUSE(
449 "Failed to allocate one static array field.");
450 goto end;
451 }
452
453 init_field((void *) array_field, fc, &array_field_methods);
454 array_field->length = array_fc->length;
455
456 if (init_array_field_fields(array_field)) {
457 BT_LIB_LOGE_APPEND_CAUSE("Cannot create static array fields: "
458 "%![fc-]+F", fc);
459 BT_OBJECT_PUT_REF_AND_RESET(array_field);
460 goto end;
461 }
462
463 BT_LIB_LOGD("Created static array field object: %!+f", array_field);
464
465 end:
466 return (void *) array_field;
467 }
468
469 static
470 struct bt_field *create_dynamic_array_field(struct bt_field_class *fc)
471 {
472 struct bt_field_array *array_field;
473
474 BT_LIB_LOGD("Creating dynamic array field object: %![fc-]+F", fc);
475 array_field = g_new0(struct bt_field_array, 1);
476 if (!array_field) {
477 BT_LIB_LOGE_APPEND_CAUSE(
478 "Failed to allocate one dynamic array field.");
479 goto end;
480 }
481
482 init_field((void *) array_field, fc, &array_field_methods);
483
484 if (init_array_field_fields(array_field)) {
485 BT_LIB_LOGE_APPEND_CAUSE("Cannot create dynamic array fields: "
486 "%![fc-]+F", fc);
487 BT_OBJECT_PUT_REF_AND_RESET(array_field);
488 goto end;
489 }
490
491 BT_LIB_LOGD("Created dynamic array field object: %!+f", array_field);
492
493 end:
494 return (void *) array_field;
495 }
496
497 int64_t bt_field_signed_integer_get_value(const struct bt_field *field)
498 {
499 const struct bt_field_integer *int_field = (const void *) field;
500
501 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
502 BT_ASSERT_PRE_DEV_FIELD_IS_SET(field, "Field");
503 BT_ASSERT_PRE_DEV_FIELD_IS_SIGNED_INT(field, "Field");
504 return int_field->value.i;
505 }
506
507 void bt_field_signed_integer_set_value(struct bt_field *field, int64_t value)
508 {
509 struct bt_field_integer *int_field = (void *) field;
510
511 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
512 BT_ASSERT_PRE_DEV_FIELD_IS_SIGNED_INT(field, "Field");
513 BT_ASSERT_PRE_DEV_FIELD_HOT(field, "Field");
514 BT_ASSERT_PRE_DEV(bt_util_value_is_in_range_signed(
515 ((struct bt_field_class_integer *) field->class)->range, value),
516 "Value is out of bounds: value=%" PRId64 ", %![field-]+f, "
517 "%![fc-]+F", value, field, field->class);
518 int_field->value.i = value;
519 bt_field_set_single(field, true);
520 }
521
522 uint64_t bt_field_unsigned_integer_get_value(const struct bt_field *field)
523 {
524 const struct bt_field_integer *int_field = (const void *) field;
525
526 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
527 BT_ASSERT_PRE_DEV_FIELD_IS_SET(field, "Field");
528 BT_ASSERT_PRE_DEV_FIELD_IS_UNSIGNED_INT(field, "Field");
529 return int_field->value.u;
530 }
531
532 void bt_field_unsigned_integer_set_value(struct bt_field *field, uint64_t value)
533 {
534 struct bt_field_integer *int_field = (void *) field;
535
536 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
537 BT_ASSERT_PRE_DEV_FIELD_IS_UNSIGNED_INT(field, "Field");
538 BT_ASSERT_PRE_DEV_FIELD_HOT(field, "Field");
539 BT_ASSERT_PRE_DEV(bt_util_value_is_in_range_unsigned(
540 ((struct bt_field_class_integer *) field->class)->range, value),
541 "Value is out of bounds: value=%" PRIu64 ", %![field-]+f, "
542 "%![fc-]+F", value, field, field->class);
543 int_field->value.u = value;
544 bt_field_set_single(field, true);
545 }
546
547 double bt_field_real_get_value(const struct bt_field *field)
548 {
549 const struct bt_field_real *real_field = (const void *) field;
550
551 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
552 BT_ASSERT_PRE_DEV_FIELD_IS_SET(field, "Field");
553 BT_ASSERT_PRE_DEV_FIELD_HAS_CLASS_TYPE(field, BT_FIELD_CLASS_TYPE_REAL, "Field");
554 return real_field->value;
555 }
556
557 void bt_field_real_set_value(struct bt_field *field, double value)
558 {
559 struct bt_field_real *real_field = (void *) field;
560
561 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
562 BT_ASSERT_PRE_DEV_FIELD_HAS_CLASS_TYPE(field, BT_FIELD_CLASS_TYPE_REAL, "Field");
563 BT_ASSERT_PRE_DEV_FIELD_HOT(field, "Field");
564 BT_ASSERT_PRE_DEV(
565 !((struct bt_field_class_real *) field->class)->is_single_precision ||
566 (double) (float) value == value,
567 "Invalid value for a single-precision real number: value=%f, "
568 "%![fc-]+F", value, field->class);
569 real_field->value = value;
570 bt_field_set_single(field, true);
571 }
572
573 enum bt_field_enumeration_get_mapping_labels_status
574 bt_field_unsigned_enumeration_get_mapping_labels(
575 const struct bt_field *field,
576 bt_field_class_enumeration_mapping_label_array *label_array,
577 uint64_t *count)
578 {
579 const struct bt_field_integer *int_field = (const void *) field;
580
581 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
582 BT_ASSERT_PRE_DEV_NON_NULL(label_array, "Label array (output)");
583 BT_ASSERT_PRE_DEV_NON_NULL(label_array, "Count (output)");
584 BT_ASSERT_PRE_DEV_FIELD_IS_SET(field, "Field");
585 BT_ASSERT_PRE_DEV_FIELD_HAS_CLASS_TYPE(field,
586 BT_FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION, "Field");
587 return (int)
588 bt_field_class_unsigned_enumeration_get_mapping_labels_for_value(
589 field->class, int_field->value.u, label_array, count);
590 }
591
592 enum bt_field_enumeration_get_mapping_labels_status
593 bt_field_signed_enumeration_get_mapping_labels(
594 const struct bt_field *field,
595 bt_field_class_enumeration_mapping_label_array *label_array,
596 uint64_t *count)
597 {
598 const struct bt_field_integer *int_field = (const void *) field;
599
600 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
601 BT_ASSERT_PRE_DEV_NON_NULL(label_array, "Label array (output)");
602 BT_ASSERT_PRE_DEV_NON_NULL(label_array, "Count (output)");
603 BT_ASSERT_PRE_DEV_FIELD_IS_SET(field, "Field");
604 BT_ASSERT_PRE_DEV_FIELD_HAS_CLASS_TYPE(field,
605 BT_FIELD_CLASS_TYPE_SIGNED_ENUMERATION, "Field");
606 return (int)
607 bt_field_class_signed_enumeration_get_mapping_labels_for_value(
608 field->class, int_field->value.i, label_array, count);
609 }
610
611 const char *bt_field_string_get_value(const struct bt_field *field)
612 {
613 const struct bt_field_string *string_field = (const void *) field;
614
615 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
616 BT_ASSERT_PRE_DEV_FIELD_IS_SET(field, "Field");
617 BT_ASSERT_PRE_DEV_FIELD_HAS_CLASS_TYPE(field, BT_FIELD_CLASS_TYPE_STRING,
618 "Field");
619 return (const char *) string_field->buf->data;
620 }
621
622 uint64_t bt_field_string_get_length(const struct bt_field *field)
623 {
624 const struct bt_field_string *string_field = (const void *) field;
625
626 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
627 BT_ASSERT_PRE_DEV_FIELD_IS_SET(field, "Field");
628 BT_ASSERT_PRE_DEV_FIELD_HAS_CLASS_TYPE(field, BT_FIELD_CLASS_TYPE_STRING,
629 "Field");
630 return string_field->length;
631 }
632
633 static inline
634 void clear_string_field(struct bt_field *field)
635 {
636 struct bt_field_string *string_field = (void *) field;
637
638 BT_ASSERT(field);
639 string_field->length = 0;
640 bt_field_set_single(field, true);
641 }
642
643 enum bt_field_string_set_value_status bt_field_string_set_value(
644 struct bt_field *field, const char *value)
645 {
646 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
647 BT_ASSERT_PRE_DEV_NON_NULL(value, "Value");
648 BT_ASSERT_PRE_DEV_FIELD_HOT(field, "Field");
649 BT_ASSERT_PRE_DEV_FIELD_HAS_CLASS_TYPE(field, BT_FIELD_CLASS_TYPE_STRING,
650 "Field");
651 clear_string_field(field);
652 return (int) bt_field_string_append_with_length(field, value,
653 (uint64_t) strlen(value));
654 }
655
656 enum bt_field_string_append_status bt_field_string_append(
657 struct bt_field *field, const char *value)
658 {
659 return bt_field_string_append_with_length(field,
660 value, (uint64_t) strlen(value));
661 }
662
663 enum bt_field_string_append_status bt_field_string_append_with_length(
664 struct bt_field *field, const char *value, uint64_t length)
665 {
666 struct bt_field_string *string_field = (void *) field;
667 char *data;
668 uint64_t new_length;
669
670 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
671 BT_ASSERT_PRE_DEV_NON_NULL(value, "Value");
672 BT_ASSERT_PRE_DEV_FIELD_HOT(field, "Field");
673 BT_ASSERT_PRE_DEV_FIELD_HAS_CLASS_TYPE(field,
674 BT_FIELD_CLASS_TYPE_STRING, "Field");
675
676 /* Make sure no null bytes are appended */
677 BT_ASSERT_PRE_DEV(memchr(value, '\0', length) == NULL,
678 "String value to append contains a null character: "
679 "partial-value=\"%.32s\", length=%" PRIu64, value, length);
680
681 new_length = length + string_field->length;
682
683 if (G_UNLIKELY(new_length + 1 > string_field->buf->len)) {
684 g_array_set_size(string_field->buf, new_length + 1);
685 }
686
687 data = string_field->buf->data;
688 memcpy(data + string_field->length, value, length);
689 ((char *) string_field->buf->data)[new_length] = '\0';
690 string_field->length = new_length;
691 bt_field_set_single(field, true);
692 return BT_FUNC_STATUS_OK;
693 }
694
695 void bt_field_string_clear(struct bt_field *field)
696 {
697 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
698 BT_ASSERT_PRE_DEV_FIELD_HOT(field, "Field");
699 BT_ASSERT_PRE_DEV_FIELD_HAS_CLASS_TYPE(field,
700 BT_FIELD_CLASS_TYPE_STRING, "Field");
701 clear_string_field(field);
702 }
703
704 uint64_t bt_field_array_get_length(const struct bt_field *field)
705 {
706 const struct bt_field_array *array_field = (const void *) field;
707
708 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
709 BT_ASSERT_PRE_DEV_FIELD_IS_ARRAY(field, "Field");
710 return array_field->length;
711 }
712
713 enum bt_field_dynamic_array_set_length_status bt_field_dynamic_array_set_length(
714 struct bt_field *field, uint64_t length)
715 {
716 int ret = BT_FUNC_STATUS_OK;
717 struct bt_field_array *array_field = (void *) field;
718
719 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
720 BT_ASSERT_PRE_DEV_FIELD_HAS_CLASS_TYPE(field,
721 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY, "Field");
722 BT_ASSERT_PRE_DEV_FIELD_HOT(field, "Field");
723
724 if (G_UNLIKELY(length > array_field->fields->len)) {
725 /* Make more room */
726 struct bt_field_class_array *array_fc;
727 uint64_t cur_len = array_field->fields->len;
728 uint64_t i;
729
730 g_ptr_array_set_size(array_field->fields, length);
731 array_fc = (void *) field->class;
732
733 for (i = cur_len; i < array_field->fields->len; i++) {
734 struct bt_field *elem_field = bt_field_create(
735 array_fc->element_fc);
736
737 if (!elem_field) {
738 BT_LIB_LOGE_APPEND_CAUSE(
739 "Cannot create element field for "
740 "dynamic array field: "
741 "index=%" PRIu64 ", "
742 "%![array-field-]+f", i, field);
743 ret = BT_FUNC_STATUS_MEMORY_ERROR;
744 goto end;
745 }
746
747 BT_ASSERT(!array_field->fields->pdata[i]);
748 array_field->fields->pdata[i] = elem_field;
749 }
750 }
751
752 array_field->length = length;
753
754 end:
755 return ret;
756 }
757
758 static inline
759 struct bt_field *borrow_array_field_element_field_by_index(
760 struct bt_field *field, uint64_t index)
761 {
762 struct bt_field_array *array_field = (void *) field;
763
764 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
765 BT_ASSERT_PRE_DEV_FIELD_IS_ARRAY(field, "Field");
766 BT_ASSERT_PRE_DEV_VALID_INDEX(index, array_field->length);
767 return array_field->fields->pdata[index];
768 }
769
770 struct bt_field *bt_field_array_borrow_element_field_by_index(
771 struct bt_field *field, uint64_t index)
772 {
773 return borrow_array_field_element_field_by_index(field, index);
774 }
775
776 const struct bt_field *
777 bt_field_array_borrow_element_field_by_index_const(
778 const struct bt_field *field, uint64_t index)
779 {
780 return borrow_array_field_element_field_by_index((void *) field, index);
781 }
782
783 static inline
784 struct bt_field *borrow_structure_field_member_field_by_index(
785 struct bt_field *field, uint64_t index)
786 {
787 struct bt_field_structure *struct_field = (void *) field;
788
789 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
790 BT_ASSERT_PRE_DEV_FIELD_HAS_CLASS_TYPE(field,
791 BT_FIELD_CLASS_TYPE_STRUCTURE, "Field");
792 BT_ASSERT_PRE_DEV_VALID_INDEX(index, struct_field->fields->len);
793 return struct_field->fields->pdata[index];
794 }
795
796 struct bt_field *bt_field_structure_borrow_member_field_by_index(
797 struct bt_field *field, uint64_t index)
798 {
799 return borrow_structure_field_member_field_by_index(field,
800 index);
801 }
802
803 const struct bt_field *
804 bt_field_structure_borrow_member_field_by_index_const(
805 const struct bt_field *field, uint64_t index)
806 {
807 return borrow_structure_field_member_field_by_index(
808 (void *) field, index);
809 }
810
811 static inline
812 struct bt_field *borrow_structure_field_member_field_by_name(
813 struct bt_field *field, const char *name)
814 {
815 struct bt_field *ret_field = NULL;
816 struct bt_field_class_structure *struct_fc;
817 struct bt_field_structure *struct_field = (void *) field;
818 gpointer orig_key;
819 gpointer index;
820
821 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
822 BT_ASSERT_PRE_DEV_NON_NULL(name, "Field name");
823 BT_ASSERT_PRE_DEV_FIELD_HAS_CLASS_TYPE(field,
824 BT_FIELD_CLASS_TYPE_STRUCTURE, "Field");
825 struct_fc = (void *) field->class;
826
827 if (!g_hash_table_lookup_extended(struct_fc->common.name_to_index, name,
828 &orig_key, &index)) {
829 goto end;
830 }
831
832 ret_field = struct_field->fields->pdata[GPOINTER_TO_UINT(index)];
833 BT_ASSERT(ret_field);
834
835 end:
836 return ret_field;
837 }
838
839 struct bt_field *bt_field_structure_borrow_member_field_by_name(
840 struct bt_field *field, const char *name)
841 {
842 return borrow_structure_field_member_field_by_name(field, name);
843 }
844
845 const struct bt_field *bt_field_structure_borrow_member_field_by_name_const(
846 const struct bt_field *field, const char *name)
847 {
848 return borrow_structure_field_member_field_by_name(
849 (void *) field, name);
850 }
851
852 static inline
853 struct bt_field *borrow_variant_field_selected_option_field(
854 struct bt_field *field)
855 {
856 struct bt_field_variant *var_field = (void *) field;
857
858 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
859 BT_ASSERT_PRE_DEV_FIELD_IS_VARIANT(field, "Field");
860 BT_ASSERT_PRE_DEV(var_field->selected_field,
861 "Variant field has no selected field: %!+f", field);
862 return var_field->selected_field;
863 }
864
865 struct bt_field *bt_field_variant_borrow_selected_option_field(
866 struct bt_field *field)
867 {
868 return borrow_variant_field_selected_option_field(field);
869 }
870
871 const struct bt_field *bt_field_variant_borrow_selected_option_field_const(
872 const struct bt_field *field)
873 {
874 return borrow_variant_field_selected_option_field((void *) field);
875 }
876
877 static
878 const struct bt_field_class_variant_option *
879 borrow_variant_field_selected_class_option(const struct bt_field *field)
880 {
881 const struct bt_field_class_named_field_class_container *container_fc;
882 const struct bt_field_variant *var_field = (const void *) field;
883
884 BT_ASSERT(field);
885 BT_ASSERT_PRE_DEV(var_field->selected_field,
886 "Variant field has no selected field: %!+f", field);
887 container_fc = (const void *) field->class;
888 return container_fc->named_fcs->pdata[var_field->selected_index];
889 }
890
891 const struct bt_field_class_variant_option *
892 bt_field_variant_borrow_selected_class_option_const(
893 const struct bt_field *field)
894 {
895 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
896 BT_ASSERT_PRE_DEV_FIELD_IS_VARIANT(field, "Field");
897 return borrow_variant_field_selected_class_option(field);
898 }
899
900 const struct bt_field_class_variant_with_unsigned_selector_option *
901 bt_field_variant_with_unsigned_selector_borrow_selected_class_option_const(
902 const struct bt_field *field)
903 {
904 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
905 BT_ASSERT_PRE_DEV_FIELD_HAS_CLASS_TYPE(field,
906 BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR, "Field");
907 return (const void *) borrow_variant_field_selected_class_option(field);
908 }
909
910 const struct bt_field_class_variant_with_signed_selector_option *
911 bt_field_variant_with_signed_selector_borrow_selected_class_option_const(
912 const struct bt_field *field)
913 {
914 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
915 BT_ASSERT_PRE_DEV_FIELD_HAS_CLASS_TYPE(field,
916 BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR, "Field");
917 return (const void *) borrow_variant_field_selected_class_option(field);
918 }
919
920 enum bt_field_variant_select_option_field_by_index_status
921 bt_field_variant_select_option_field_by_index(
922 struct bt_field *field, uint64_t index)
923 {
924 struct bt_field_variant *var_field = (void *) field;
925
926 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
927 BT_ASSERT_PRE_DEV_FIELD_IS_VARIANT(field, "Field");
928 BT_ASSERT_PRE_DEV_FIELD_HOT(field, "Field");
929 BT_ASSERT_PRE_DEV_VALID_INDEX(index, var_field->fields->len);
930 var_field->selected_field = var_field->fields->pdata[index];
931 var_field->selected_index = index;
932 return BT_FUNC_STATUS_OK;
933 }
934
935 uint64_t bt_field_variant_get_selected_option_field_index(
936 const struct bt_field *field)
937 {
938 const struct bt_field_variant *var_field = (const void *) field;
939
940 BT_ASSERT_PRE_DEV_NON_NULL(field, "Field");
941 BT_ASSERT_PRE_DEV_FIELD_IS_VARIANT(field, "Field");
942 BT_ASSERT_PRE_DEV(var_field->selected_field,
943 "Variant field has no selected field: %!+f", field);
944 return var_field->selected_index;
945 }
946
947 static inline
948 void bt_field_finalize(struct bt_field *field)
949 {
950 BT_ASSERT(field);
951 BT_LOGD_STR("Putting field's class.");
952 BT_OBJECT_PUT_REF_AND_RESET(field->class);
953 }
954
955 static
956 void destroy_integer_field(struct bt_field *field)
957 {
958 BT_ASSERT(field);
959 BT_LIB_LOGD("Destroying integer field object: %!+f", field);
960 bt_field_finalize(field);
961 g_free(field);
962 }
963
964 static
965 void destroy_real_field(struct bt_field *field)
966 {
967 BT_ASSERT(field);
968 BT_LIB_LOGD("Destroying real field object: %!+f", field);
969 bt_field_finalize(field);
970 g_free(field);
971 }
972
973 static
974 void destroy_structure_field(struct bt_field *field)
975 {
976 struct bt_field_structure *struct_field = (void *) field;
977
978 BT_ASSERT(field);
979 BT_LIB_LOGD("Destroying structure field object: %!+f", field);
980 bt_field_finalize(field);
981
982 if (struct_field->fields) {
983 g_ptr_array_free(struct_field->fields, TRUE);
984 struct_field->fields = NULL;
985 }
986
987 g_free(field);
988 }
989
990 static
991 void destroy_variant_field(struct bt_field *field)
992 {
993 struct bt_field_variant *var_field = (void *) field;
994
995 BT_ASSERT(field);
996 BT_LIB_LOGD("Destroying variant field object: %!+f", field);
997 bt_field_finalize(field);
998
999 if (var_field->fields) {
1000 g_ptr_array_free(var_field->fields, TRUE);
1001 var_field->fields = NULL;
1002 }
1003
1004 g_free(field);
1005 }
1006
1007 static
1008 void destroy_array_field(struct bt_field *field)
1009 {
1010 struct bt_field_array *array_field = (void *) field;
1011
1012 BT_ASSERT(field);
1013 BT_LIB_LOGD("Destroying array field object: %!+f", field);
1014 bt_field_finalize(field);
1015
1016 if (array_field->fields) {
1017 g_ptr_array_free(array_field->fields, TRUE);
1018 array_field->fields = NULL;
1019 }
1020
1021 g_free(field);
1022 }
1023
1024 static
1025 void destroy_string_field(struct bt_field *field)
1026 {
1027 struct bt_field_string *string_field = (void *) field;
1028
1029 BT_ASSERT(field);
1030 BT_LIB_LOGD("Destroying string field object: %!+f", field);
1031 bt_field_finalize(field);
1032
1033 if (string_field->buf) {
1034 g_array_free(string_field->buf, TRUE);
1035 string_field->buf = NULL;
1036 }
1037
1038 g_free(field);
1039 }
1040
1041 BT_HIDDEN
1042 void bt_field_destroy(struct bt_field *field)
1043 {
1044 BT_ASSERT(field);
1045 field_destroy_funcs[field->class->type](field);
1046 }
1047
1048 static
1049 void reset_single_field(struct bt_field *field)
1050 {
1051 BT_ASSERT(field);
1052 field->is_set = false;
1053 }
1054
1055 static
1056 void reset_structure_field(struct bt_field *field)
1057 {
1058 uint64_t i;
1059 struct bt_field_structure *struct_field = (void *) field;
1060
1061 BT_ASSERT(field);
1062
1063 for (i = 0; i < struct_field->fields->len; i++) {
1064 bt_field_reset(struct_field->fields->pdata[i]);
1065 }
1066 }
1067
1068 static
1069 void reset_variant_field(struct bt_field *field)
1070 {
1071 uint64_t i;
1072 struct bt_field_variant *var_field = (void *) field;
1073
1074 BT_ASSERT(field);
1075
1076 for (i = 0; i < var_field->fields->len; i++) {
1077 bt_field_reset(var_field->fields->pdata[i]);
1078 }
1079 }
1080
1081 static
1082 void reset_array_field(struct bt_field *field)
1083 {
1084 uint64_t i;
1085 struct bt_field_array *array_field = (void *) field;
1086
1087 BT_ASSERT(field);
1088
1089 for (i = 0; i < array_field->fields->len; i++) {
1090 bt_field_reset(array_field->fields->pdata[i]);
1091 }
1092 }
1093
1094 static
1095 void set_single_field_is_frozen(struct bt_field *field, bool is_frozen)
1096 {
1097 field->frozen = is_frozen;
1098 }
1099
1100 static
1101 void set_structure_field_is_frozen(struct bt_field *field, bool is_frozen)
1102 {
1103 uint64_t i;
1104 struct bt_field_structure *struct_field = (void *) field;
1105
1106 BT_LIB_LOGD("Setting structure field's frozen state: "
1107 "%![field-]+f, is-frozen=%d", field, is_frozen);
1108
1109 for (i = 0; i < struct_field->fields->len; i++) {
1110 struct bt_field *member_field = struct_field->fields->pdata[i];
1111
1112 BT_LIB_LOGD("Setting structure field's member field's "
1113 "frozen state: %![field-]+f, index=%" PRIu64,
1114 member_field, i);
1115 bt_field_set_is_frozen(member_field, is_frozen);
1116 }
1117
1118 set_single_field_is_frozen(field, is_frozen);
1119 }
1120
1121 static
1122 void set_variant_field_is_frozen(struct bt_field *field, bool is_frozen)
1123 {
1124 uint64_t i;
1125 struct bt_field_variant *var_field = (void *) field;
1126
1127 BT_LIB_LOGD("Setting variant field's frozen state: "
1128 "%![field-]+f, is-frozen=%d", field, is_frozen);
1129
1130 for (i = 0; i < var_field->fields->len; i++) {
1131 struct bt_field *option_field = var_field->fields->pdata[i];
1132
1133 BT_LIB_LOGD("Setting variant field's option field's "
1134 "frozen state: %![field-]+f, index=%" PRIu64,
1135 option_field, i);
1136 bt_field_set_is_frozen(option_field, is_frozen);
1137 }
1138
1139 set_single_field_is_frozen(field, is_frozen);
1140 }
1141
1142 static
1143 void set_array_field_is_frozen(struct bt_field *field, bool is_frozen)
1144 {
1145 uint64_t i;
1146 struct bt_field_array *array_field = (void *) field;
1147
1148 BT_LIB_LOGD("Setting array field's frozen state: "
1149 "%![field-]+f, is-frozen=%d", field, is_frozen);
1150
1151 for (i = 0; i < array_field->fields->len; i++) {
1152 struct bt_field *elem_field = array_field->fields->pdata[i];
1153
1154 BT_LIB_LOGD("Setting array field's element field's "
1155 "frozen state: %![field-]+f, index=%" PRIu64,
1156 elem_field, i);
1157 bt_field_set_is_frozen(elem_field, is_frozen);
1158 }
1159
1160 set_single_field_is_frozen(field, is_frozen);
1161 }
1162
1163 BT_HIDDEN
1164 void _bt_field_set_is_frozen(const struct bt_field *field,
1165 bool is_frozen)
1166 {
1167 BT_ASSERT(field);
1168 BT_LIB_LOGD("Setting field object's frozen state: %!+f, is-frozen=%d",
1169 field, is_frozen);
1170 BT_ASSERT(field->methods->set_is_frozen);
1171 field->methods->set_is_frozen((void *) field, is_frozen);
1172 }
1173
1174 static
1175 bool single_field_is_set(const struct bt_field *field)
1176 {
1177 BT_ASSERT(field);
1178 return field->is_set;
1179 }
1180
1181 static
1182 bool structure_field_is_set(const struct bt_field *field)
1183 {
1184 bool is_set = true;
1185 uint64_t i;
1186 const struct bt_field_structure *struct_field = (const void *) field;
1187
1188 BT_ASSERT(field);
1189
1190 for (i = 0; i < struct_field->fields->len; i++) {
1191 is_set = bt_field_is_set(struct_field->fields->pdata[i]);
1192 if (!is_set) {
1193 goto end;
1194 }
1195 }
1196
1197 end:
1198 return is_set;
1199 }
1200
1201 static
1202 bool variant_field_is_set(const struct bt_field *field)
1203 {
1204 const struct bt_field_variant *var_field = (const void *) field;
1205 bool is_set = false;
1206
1207 BT_ASSERT(field);
1208
1209 if (var_field->selected_field) {
1210 is_set = bt_field_is_set(var_field->selected_field);
1211 }
1212
1213 return is_set;
1214 }
1215
1216 static
1217 bool array_field_is_set(const struct bt_field *field)
1218 {
1219 bool is_set = true;
1220 uint64_t i;
1221 const struct bt_field_array *array_field = (const void *) field;
1222
1223 BT_ASSERT(field);
1224
1225 for (i = 0; i < array_field->length; i++) {
1226 is_set = bt_field_is_set(array_field->fields->pdata[i]);
1227 if (!is_set) {
1228 goto end;
1229 }
1230 }
1231
1232 end:
1233 return is_set;
1234 }
This page took 0.075822 seconds and 5 git commands to generate.