lib: add option field class and field types
[babeltrace.git] / src / lib / trace-ir / resolve-field-path.c
CommitLineData
44c440bc
PP
1/*
2 * Copyright 2018 Philippe Proulx <pproulx@efficios.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
350ad6c1 23#define BT_LOG_TAG "LIB/RESOLVE-FIELD-PATH"
c2d9d9cf 24#include "lib/logging.h"
44c440bc 25
578e048b
MJ
26#include "lib/assert-pre.h"
27#include "common/assert.h"
3fadfbc0 28#include <babeltrace2/trace-ir/field-path-const.h>
44c440bc
PP
29#include <limits.h>
30#include <stdint.h>
31#include <inttypes.h>
32#include <glib.h>
33
578e048b
MJ
34#include "field-class.h"
35#include "field-path.h"
36#include "resolve-field-path.h"
37
44c440bc 38static
5cd6d0e5
PP
39bool find_field_class_recursive(struct bt_field_class *fc,
40 struct bt_field_class *tgt_fc, struct bt_field_path *field_path)
44c440bc
PP
41{
42 bool found = false;
43
5cd6d0e5 44 if (tgt_fc == fc) {
44c440bc
PP
45 found = true;
46 goto end;
47 }
48
864cad70 49 switch (fc->type) {
b38aea74
PP
50 case BT_FIELD_CLASS_TYPE_OPTION:
51 {
52 struct bt_field_class_option *opt_fc = (void *) fc;
53
54 struct bt_field_path_item item = {
55 .type = BT_FIELD_PATH_ITEM_TYPE_CURRENT_OPTION_CONTENT,
56 .index = UINT64_C(-1),
57 };
58
59 bt_field_path_append_item(field_path, &item);
60 found = find_field_class_recursive(opt_fc->content_fc,
61 tgt_fc, field_path);
62 if (found) {
63 goto end;
64 }
65
66 bt_field_path_remove_last_item(field_path);
67 break;
68 }
864cad70 69 case BT_FIELD_CLASS_TYPE_STRUCTURE:
45c51519
PP
70 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR:
71 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR:
72 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR:
44c440bc 73 {
5cd6d0e5
PP
74 struct bt_field_class_named_field_class_container *container_fc =
75 (void *) fc;
44c440bc
PP
76 uint64_t i;
77
5cd6d0e5
PP
78 for (i = 0; i < container_fc->named_fcs->len; i++) {
79 struct bt_named_field_class *named_fc =
45c51519 80 container_fc->named_fcs->pdata[i];
66ddcddf
PP
81 struct bt_field_path_item item = {
82 .type = BT_FIELD_PATH_ITEM_TYPE_INDEX,
83 .index = i,
84 };
44c440bc 85
66ddcddf 86 bt_field_path_append_item(field_path, &item);
5cd6d0e5
PP
87 found = find_field_class_recursive(named_fc->fc,
88 tgt_fc, field_path);
44c440bc
PP
89 if (found) {
90 goto end;
91 }
92
66ddcddf 93 bt_field_path_remove_last_item(field_path);
44c440bc
PP
94 }
95
96 break;
97 }
864cad70
PP
98 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY:
99 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY:
44c440bc 100 {
5cd6d0e5 101 struct bt_field_class_array *array_fc = (void *) fc;
66ddcddf
PP
102 struct bt_field_path_item item = {
103 .type = BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT,
104 .index = UINT64_C(-1),
105 };
44c440bc 106
66ddcddf 107 bt_field_path_append_item(field_path, &item);
5cd6d0e5
PP
108 found = find_field_class_recursive(array_fc->element_fc,
109 tgt_fc, field_path);
66ddcddf
PP
110 if (found) {
111 goto end;
112 }
113
114 bt_field_path_remove_last_item(field_path);
44c440bc
PP
115 break;
116 }
117 default:
118 break;
119 }
120
121end:
122 return found;
123}
124
125static
5cd6d0e5 126int find_field_class(struct bt_field_class *root_fc,
e7ceb9df 127 enum bt_field_path_scope root_scope, struct bt_field_class *tgt_fc,
44c440bc
PP
128 struct bt_field_path **ret_field_path)
129{
130 int ret = 0;
131 struct bt_field_path *field_path = NULL;
132
5cd6d0e5 133 if (!root_fc) {
44c440bc
PP
134 goto end;
135 }
136
137 field_path = bt_field_path_create();
138 if (!field_path) {
139 ret = -1;
140 goto end;
141 }
142
143 field_path->root = root_scope;
5cd6d0e5 144 if (!find_field_class_recursive(root_fc, tgt_fc, field_path)) {
44c440bc 145 /* Not found here */
65300d60 146 BT_OBJECT_PUT_REF_AND_RESET(field_path);
44c440bc
PP
147 }
148
149end:
150 *ret_field_path = field_path;
151 return ret;
152}
153
154static
5cd6d0e5 155struct bt_field_path *find_field_class_in_ctx(struct bt_field_class *fc,
44c440bc
PP
156 struct bt_resolve_field_path_context *ctx)
157{
158 struct bt_field_path *field_path = NULL;
159 int ret;
160
e7ceb9df 161 ret = find_field_class(ctx->packet_context, BT_FIELD_PATH_SCOPE_PACKET_CONTEXT,
5cd6d0e5 162 fc, &field_path);
44c440bc
PP
163 if (ret || field_path) {
164 goto end;
165 }
166
5cd6d0e5 167 ret = find_field_class(ctx->event_common_context,
e7ceb9df 168 BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT, fc, &field_path);
44c440bc
PP
169 if (ret || field_path) {
170 goto end;
171 }
172
5cd6d0e5 173 ret = find_field_class(ctx->event_specific_context,
e7ceb9df 174 BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT, fc, &field_path);
44c440bc
PP
175 if (ret || field_path) {
176 goto end;
177 }
178
e7ceb9df 179 ret = find_field_class(ctx->event_payload, BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD,
5cd6d0e5 180 fc, &field_path);
44c440bc
PP
181 if (ret || field_path) {
182 goto end;
183 }
184
185end:
186 return field_path;
187}
188
bdb288b3 189BT_ASSERT_PRE_DEV_FUNC
44c440bc
PP
190static inline
191bool target_is_before_source(struct bt_field_path *src_field_path,
192 struct bt_field_path *tgt_field_path)
193{
194 bool is_valid = true;
195 uint64_t src_i = 0, tgt_i = 0;
196
197 if (tgt_field_path->root < src_field_path->root) {
198 goto end;
199 }
200
201 if (tgt_field_path->root > src_field_path->root) {
202 is_valid = false;
203 goto end;
204 }
205
206 BT_ASSERT(tgt_field_path->root == src_field_path->root);
207
66ddcddf
PP
208 for (src_i = 0, tgt_i = 0; src_i < src_field_path->items->len &&
209 tgt_i < tgt_field_path->items->len; src_i++, tgt_i++) {
210 struct bt_field_path_item *src_fp_item =
211 bt_field_path_borrow_item_by_index_inline(
212 src_field_path, src_i);
213 struct bt_field_path_item *tgt_fp_item =
214 bt_field_path_borrow_item_by_index_inline(
215 tgt_field_path, tgt_i);
216
217 if (src_fp_item->type == BT_FIELD_PATH_ITEM_TYPE_INDEX &&
218 tgt_fp_item->type == BT_FIELD_PATH_ITEM_TYPE_INDEX) {
219 if (tgt_fp_item->index > src_fp_item->index) {
220 is_valid = false;
221 goto end;
222 }
44c440bc
PP
223 }
224
225 src_i++;
226 tgt_i++;
227 }
228
229end:
230 return is_valid;
231}
232
bdb288b3 233BT_ASSERT_PRE_DEV_FUNC
44c440bc 234static inline
5cd6d0e5 235struct bt_field_class *borrow_root_field_class(
e7ceb9df 236 struct bt_resolve_field_path_context *ctx, enum bt_field_path_scope scope)
44c440bc
PP
237{
238 switch (scope) {
e7ceb9df 239 case BT_FIELD_PATH_SCOPE_PACKET_CONTEXT:
44c440bc 240 return ctx->packet_context;
e7ceb9df 241 case BT_FIELD_PATH_SCOPE_EVENT_COMMON_CONTEXT:
44c440bc 242 return ctx->event_common_context;
e7ceb9df 243 case BT_FIELD_PATH_SCOPE_EVENT_SPECIFIC_CONTEXT:
44c440bc 244 return ctx->event_specific_context;
e7ceb9df 245 case BT_FIELD_PATH_SCOPE_EVENT_PAYLOAD:
44c440bc
PP
246 return ctx->event_payload;
247 default:
248 abort();
249 }
250
251 return NULL;
252}
253
bdb288b3 254BT_ASSERT_PRE_DEV_FUNC
44c440bc 255static inline
66ddcddf
PP
256struct bt_field_class *borrow_child_field_class(
257 struct bt_field_class *parent_fc,
258 struct bt_field_path_item *fp_item)
44c440bc 259{
5cd6d0e5 260 struct bt_field_class *child_fc = NULL;
44c440bc 261
864cad70 262 switch (parent_fc->type) {
b38aea74
PP
263 case BT_FIELD_CLASS_TYPE_OPTION:
264 {
265 struct bt_field_class_option *opt_fc = (void *) parent_fc;
266
267 BT_ASSERT(fp_item->type ==
268 BT_FIELD_PATH_ITEM_TYPE_CURRENT_OPTION_CONTENT);
269 child_fc = opt_fc->content_fc;
270 break;
271 }
864cad70 272 case BT_FIELD_CLASS_TYPE_STRUCTURE:
45c51519
PP
273 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR:
274 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR:
275 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR:
44c440bc 276 {
45c51519
PP
277 struct bt_field_class_named_field_class_container *container_fc =
278 (void *) parent_fc;
66ddcddf 279 struct bt_named_field_class *named_fc;
44c440bc 280
66ddcddf 281 BT_ASSERT(fp_item->type == BT_FIELD_PATH_ITEM_TYPE_INDEX);
45c51519 282 named_fc = container_fc->named_fcs->pdata[fp_item->index];
5cd6d0e5 283 child_fc = named_fc->fc;
44c440bc
PP
284 break;
285 }
864cad70
PP
286 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY:
287 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY:
44c440bc 288 {
5cd6d0e5 289 struct bt_field_class_array *array_fc = (void *) parent_fc;
44c440bc 290
66ddcddf
PP
291 BT_ASSERT(fp_item->type ==
292 BT_FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT);
5cd6d0e5 293 child_fc = array_fc->element_fc;
44c440bc
PP
294 break;
295 }
296 default:
297 break;
298 }
299
5cd6d0e5 300 return child_fc;
44c440bc
PP
301}
302
bdb288b3 303BT_ASSERT_PRE_DEV_FUNC
44c440bc 304static inline
5cd6d0e5 305bool target_field_path_in_different_scope_has_struct_fc_only(
44c440bc
PP
306 struct bt_field_path *src_field_path,
307 struct bt_field_path *tgt_field_path,
308 struct bt_resolve_field_path_context *ctx)
309{
310 bool is_valid = true;
311 uint64_t i = 0;
5cd6d0e5 312 struct bt_field_class *fc;
44c440bc
PP
313
314 if (src_field_path->root == tgt_field_path->root) {
315 goto end;
316 }
317
5cd6d0e5 318 fc = borrow_root_field_class(ctx, tgt_field_path->root);
44c440bc 319
66ddcddf
PP
320 for (i = 0; i < tgt_field_path->items->len; i++) {
321 struct bt_field_path_item *fp_item =
322 bt_field_path_borrow_item_by_index_inline(
323 tgt_field_path, i);
44c440bc 324
864cad70
PP
325 if (fc->type == BT_FIELD_CLASS_TYPE_STATIC_ARRAY ||
326 fc->type == BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY ||
b38aea74 327 fc->type == BT_FIELD_CLASS_TYPE_OPTION ||
45c51519
PP
328 fc->type == BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR ||
329 fc->type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR ||
330 fc->type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR) {
44c440bc
PP
331 is_valid = false;
332 goto end;
333 }
334
66ddcddf
PP
335 BT_ASSERT(fp_item->type == BT_FIELD_PATH_ITEM_TYPE_INDEX);
336 fc = borrow_child_field_class(fc, fp_item);
44c440bc
PP
337 }
338
339end:
340 return is_valid;
341}
342
bdb288b3 343BT_ASSERT_PRE_DEV_FUNC
44c440bc 344static inline
5cd6d0e5 345bool lca_is_structure_field_class(struct bt_field_path *src_field_path,
44c440bc
PP
346 struct bt_field_path *tgt_field_path,
347 struct bt_resolve_field_path_context *ctx)
348{
349 bool is_valid = true;
5cd6d0e5
PP
350 struct bt_field_class *src_fc;
351 struct bt_field_class *tgt_fc;
352 struct bt_field_class *prev_fc = NULL;
44c440bc
PP
353 uint64_t src_i = 0, tgt_i = 0;
354
355 if (src_field_path->root != tgt_field_path->root) {
356 goto end;
357 }
358
5cd6d0e5
PP
359 src_fc = borrow_root_field_class(ctx, src_field_path->root);
360 tgt_fc = borrow_root_field_class(ctx, tgt_field_path->root);
361 BT_ASSERT(src_fc);
362 BT_ASSERT(tgt_fc);
44c440bc 363
66ddcddf
PP
364 for (src_i = 0, tgt_i = 0; src_i < src_field_path->items->len &&
365 tgt_i < tgt_field_path->items->len; src_i++, tgt_i++) {
366 struct bt_field_path_item *src_fp_item =
367 bt_field_path_borrow_item_by_index_inline(
368 src_field_path, src_i);
369 struct bt_field_path_item *tgt_fp_item =
370 bt_field_path_borrow_item_by_index_inline(
371 tgt_field_path, tgt_i);
44c440bc 372
5cd6d0e5
PP
373 if (src_fc != tgt_fc) {
374 if (!prev_fc) {
44c440bc
PP
375 /*
376 * This is correct: the LCA is the root
e6276565
PP
377 * scope field class, which must be a
378 * structure field class.
44c440bc
PP
379 */
380 break;
381 }
382
864cad70 383 if (prev_fc->type != BT_FIELD_CLASS_TYPE_STRUCTURE) {
44c440bc
PP
384 is_valid = false;
385 }
386
387 break;
388 }
389
5cd6d0e5 390 prev_fc = src_fc;
66ddcddf
PP
391 src_fc = borrow_child_field_class(src_fc, src_fp_item);
392 tgt_fc = borrow_child_field_class(tgt_fc, tgt_fp_item);
44c440bc
PP
393 }
394
395end:
396 return is_valid;
397}
398
bdb288b3 399BT_ASSERT_PRE_DEV_FUNC
44c440bc 400static inline
5cd6d0e5 401bool lca_to_target_has_struct_fc_only(struct bt_field_path *src_field_path,
44c440bc
PP
402 struct bt_field_path *tgt_field_path,
403 struct bt_resolve_field_path_context *ctx)
404{
405 bool is_valid = true;
5cd6d0e5
PP
406 struct bt_field_class *src_fc;
407 struct bt_field_class *tgt_fc;
44c440bc
PP
408 uint64_t src_i = 0, tgt_i = 0;
409
410 if (src_field_path->root != tgt_field_path->root) {
411 goto end;
412 }
413
5cd6d0e5
PP
414 src_fc = borrow_root_field_class(ctx, src_field_path->root);
415 tgt_fc = borrow_root_field_class(ctx, tgt_field_path->root);
416 BT_ASSERT(src_fc);
417 BT_ASSERT(tgt_fc);
418 BT_ASSERT(src_fc == tgt_fc);
44c440bc
PP
419
420 /* Find LCA */
66ddcddf
PP
421 for (src_i = 0, tgt_i = 0; src_i < src_field_path->items->len &&
422 tgt_i < tgt_field_path->items->len; src_i++, tgt_i++) {
423 struct bt_field_path_item *src_fp_item =
424 bt_field_path_borrow_item_by_index_inline(
425 src_field_path, src_i);
426 struct bt_field_path_item *tgt_fp_item =
427 bt_field_path_borrow_item_by_index_inline(
428 tgt_field_path, tgt_i);
44c440bc
PP
429
430 if (src_i != tgt_i) {
5cd6d0e5 431 /* Next field class is different: LCA is `tgt_fc` */
44c440bc
PP
432 break;
433 }
434
66ddcddf
PP
435 src_fc = borrow_child_field_class(src_fc, src_fp_item);
436 tgt_fc = borrow_child_field_class(tgt_fc, tgt_fp_item);
44c440bc
PP
437 }
438
5cd6d0e5 439 /* Only structure field classes to the target */
66ddcddf
PP
440 for (; tgt_i < tgt_field_path->items->len; tgt_i++) {
441 struct bt_field_path_item *tgt_fp_item =
442 bt_field_path_borrow_item_by_index_inline(
443 tgt_field_path, tgt_i);
44c440bc 444
864cad70
PP
445 if (tgt_fc->type == BT_FIELD_CLASS_TYPE_STATIC_ARRAY ||
446 tgt_fc->type == BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY ||
b38aea74 447 tgt_fc->type == BT_FIELD_CLASS_TYPE_OPTION ||
45c51519
PP
448 tgt_fc->type == BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR ||
449 tgt_fc->type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR ||
450 tgt_fc->type == BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR) {
44c440bc
PP
451 is_valid = false;
452 goto end;
453 }
454
66ddcddf 455 tgt_fc = borrow_child_field_class(tgt_fc, tgt_fp_item);
44c440bc
PP
456 }
457
458end:
459 return is_valid;
460}
461
bdb288b3 462BT_ASSERT_PRE_DEV_FUNC
44c440bc 463static inline
5cd6d0e5
PP
464bool field_path_is_valid(struct bt_field_class *src_fc,
465 struct bt_field_class *tgt_fc,
44c440bc
PP
466 struct bt_resolve_field_path_context *ctx)
467{
468 bool is_valid = true;
5cd6d0e5
PP
469 struct bt_field_path *src_field_path = find_field_class_in_ctx(
470 src_fc, ctx);
471 struct bt_field_path *tgt_field_path = find_field_class_in_ctx(
472 tgt_fc, ctx);
44c440bc
PP
473
474 if (!src_field_path) {
bdb288b3 475 BT_ASSERT_PRE_DEV_MSG("Cannot find requesting field class in "
5cd6d0e5 476 "resolving context: %!+F", src_fc);
44c440bc
PP
477 is_valid = false;
478 goto end;
479 }
480
481 if (!tgt_field_path) {
bdb288b3 482 BT_ASSERT_PRE_DEV_MSG("Cannot find target field class in "
5cd6d0e5 483 "resolving context: %!+F", tgt_fc);
44c440bc
PP
484 is_valid = false;
485 goto end;
486 }
487
488 /* Target must be before source */
489 if (!target_is_before_source(src_field_path, tgt_field_path)) {
bdb288b3 490 BT_ASSERT_PRE_DEV_MSG("Target field class is located after "
e6276565 491 "requesting field class: %![req-fc-]+F, %![tgt-fc-]+F",
5cd6d0e5 492 src_fc, tgt_fc);
44c440bc
PP
493 is_valid = false;
494 goto end;
495 }
496
497 /*
498 * If target is in a different scope than source, there are no
5cd6d0e5 499 * array or variant field classes on the way to the target.
44c440bc 500 */
5cd6d0e5 501 if (!target_field_path_in_different_scope_has_struct_fc_only(
44c440bc 502 src_field_path, tgt_field_path, ctx)) {
bdb288b3 503 BT_ASSERT_PRE_DEV_MSG("Target field class is located in a "
e6276565
PP
504 "different scope than requesting field class, "
505 "but within an array or a variant field class: "
5cd6d0e5
PP
506 "%![req-fc-]+F, %![tgt-fc-]+F",
507 src_fc, tgt_fc);
44c440bc
PP
508 is_valid = false;
509 goto end;
510 }
511
e6276565 512 /* Same scope: LCA must be a structure field class */
5cd6d0e5 513 if (!lca_is_structure_field_class(src_field_path, tgt_field_path, ctx)) {
bdb288b3 514 BT_ASSERT_PRE_DEV_MSG("Lowest common ancestor of target and "
e6276565 515 "requesting field classes is not a structure field class: "
5cd6d0e5
PP
516 "%![req-fc-]+F, %![tgt-fc-]+F",
517 src_fc, tgt_fc);
44c440bc
PP
518 is_valid = false;
519 goto end;
520 }
521
522 /* Same scope: path from LCA to target has no array/variant FTs */
5cd6d0e5 523 if (!lca_to_target_has_struct_fc_only(src_field_path, tgt_field_path,
44c440bc 524 ctx)) {
bdb288b3 525 BT_ASSERT_PRE_DEV_MSG("Path from lowest common ancestor of target "
e6276565
PP
526 "and requesting field classes to target field class "
527 "contains an array or a variant field class: "
5cd6d0e5 528 "%![req-fc-]+F, %![tgt-fc-]+F", src_fc, tgt_fc);
44c440bc
PP
529 is_valid = false;
530 goto end;
531 }
532
533end:
65300d60
PP
534 bt_object_put_ref(src_field_path);
535 bt_object_put_ref(tgt_field_path);
44c440bc
PP
536 return is_valid;
537}
538
539static
5cd6d0e5
PP
540struct bt_field_path *resolve_field_path(struct bt_field_class *src_fc,
541 struct bt_field_class *tgt_fc,
44c440bc
PP
542 struct bt_resolve_field_path_context *ctx)
543{
bdb288b3 544 BT_ASSERT_PRE_DEV(field_path_is_valid(src_fc, tgt_fc, ctx),
e6276565 545 "Invalid target field class: %![req-fc-]+F, %![tgt-fc-]+F",
5cd6d0e5
PP
546 src_fc, tgt_fc);
547 return find_field_class_in_ctx(tgt_fc, ctx);
44c440bc
PP
548}
549
550BT_HIDDEN
5cd6d0e5 551int bt_resolve_field_paths(struct bt_field_class *fc,
44c440bc
PP
552 struct bt_resolve_field_path_context *ctx)
553{
554 int ret = 0;
555
5cd6d0e5 556 BT_ASSERT(fc);
44c440bc 557
5cd6d0e5 558 /* Resolving part for dynamic array and variant field classes */
864cad70 559 switch (fc->type) {
b38aea74
PP
560 case BT_FIELD_CLASS_TYPE_OPTION:
561 {
562 struct bt_field_class_option *opt_fc = (void *) fc;
563
564 if (opt_fc->selector_fc) {
565 BT_ASSERT(!opt_fc->selector_field_path);
566 opt_fc->selector_field_path = resolve_field_path(
567 fc, opt_fc->selector_fc, ctx);
568 if (!opt_fc->selector_field_path) {
569 ret = -1;
570 goto end;
571 }
572 }
573
574 break;
575 }
864cad70 576 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY:
44c440bc 577 {
9c08c816 578 struct bt_field_class_array_dynamic *dyn_array_fc = (void *) fc;
44c440bc 579
5cd6d0e5
PP
580 if (dyn_array_fc->length_fc) {
581 BT_ASSERT(!dyn_array_fc->length_field_path);
582 dyn_array_fc->length_field_path = resolve_field_path(
583 fc, dyn_array_fc->length_fc, ctx);
584 if (!dyn_array_fc->length_field_path) {
44c440bc
PP
585 ret = -1;
586 goto end;
587 }
588 }
589
590 break;
591 }
45c51519
PP
592 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR:
593 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR:
44c440bc 594 {
45c51519
PP
595 struct bt_field_class_variant_with_selector *var_fc =
596 (void *) fc;
5cd6d0e5
PP
597
598 if (var_fc->selector_fc) {
599 BT_ASSERT(!var_fc->selector_field_path);
600 var_fc->selector_field_path =
601 resolve_field_path(fc,
45c51519 602 (void *) var_fc->selector_fc, ctx);
5cd6d0e5 603 if (!var_fc->selector_field_path) {
44c440bc
PP
604 ret = -1;
605 goto end;
606 }
607 }
608 }
609 default:
610 break;
611 }
612
613 /* Recursive part */
864cad70 614 switch (fc->type) {
b38aea74
PP
615 case BT_FIELD_CLASS_TYPE_OPTION:
616 {
617 struct bt_field_class_option *opt_fc = (void *) fc;
618
619 ret = bt_resolve_field_paths(opt_fc->content_fc, ctx);
620 break;
621 }
864cad70 622 case BT_FIELD_CLASS_TYPE_STRUCTURE:
45c51519
PP
623 case BT_FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR:
624 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR:
625 case BT_FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR:
44c440bc 626 {
5cd6d0e5
PP
627 struct bt_field_class_named_field_class_container *container_fc =
628 (void *) fc;
44c440bc
PP
629 uint64_t i;
630
5cd6d0e5
PP
631 for (i = 0; i < container_fc->named_fcs->len; i++) {
632 struct bt_named_field_class *named_fc =
45c51519 633 container_fc->named_fcs->pdata[i];
44c440bc 634
5cd6d0e5 635 ret = bt_resolve_field_paths(named_fc->fc, ctx);
44c440bc
PP
636 if (ret) {
637 goto end;
638 }
639 }
640
641 break;
642 }
864cad70
PP
643 case BT_FIELD_CLASS_TYPE_STATIC_ARRAY:
644 case BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY:
44c440bc 645 {
5cd6d0e5 646 struct bt_field_class_array *array_fc = (void *) fc;
44c440bc 647
5cd6d0e5 648 ret = bt_resolve_field_paths(array_fc->element_fc, ctx);
44c440bc
PP
649 break;
650 }
651 default:
652 break;
653 }
654
655end:
656 return ret;
657}
This page took 0.06911 seconds and 4 git commands to generate.