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