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