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