Modify bt_ctf_field_enumeration_get_single_mapping to return iterator
[babeltrace.git] / formats / ctf / ir / validation.c
CommitLineData
09840de5
PP
1/*
2 * validation.c
3 *
4 * Babeltrace - CTF IR: Validation of trace, stream class, and event class
5 *
6 * Copyright 2016 Philippe Proulx <pproulx@efficios.com>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26
27#include <babeltrace/ctf-ir/validation-internal.h>
28#include <babeltrace/ctf-ir/resolve-internal.h>
29#include <babeltrace/ctf-ir/trace-internal.h>
30#include <babeltrace/ctf-ir/stream-class-internal.h>
2e33ac5a 31#include <babeltrace/ctf-ir/field-types-internal.h>
272df73e 32#include <babeltrace/ctf-ir/event-class-internal.h>
09840de5
PP
33#include <babeltrace/values.h>
34#include <babeltrace/babeltrace-internal.h>
35#include <babeltrace/ref.h>
36
37#define _printf_error(fmt, args...) \
38 printf_verbose("[validation] " fmt, ## args)
39
40/*
41 * This function resolves and validates the field types of an event
42 * class. Only `event_context_type` and `event_payload_type` are
43 * resolved and validated; the other field types are used as eventual
44 * resolving targets.
45 *
46 * All parameters are owned by the caller.
47 */
48static
49int validate_event_class_types(struct bt_value *environment,
50 struct bt_ctf_field_type *packet_header_type,
51 struct bt_ctf_field_type *packet_context_type,
52 struct bt_ctf_field_type *event_header_type,
53 struct bt_ctf_field_type *stream_event_ctx_type,
54 struct bt_ctf_field_type *event_context_type,
55 struct bt_ctf_field_type *event_payload_type)
56{
57 int ret = 0;
58
59 /* Resolve sequence type lengths and variant type tags first */
60 ret = bt_ctf_resolve_types(environment, packet_header_type,
61 packet_context_type, event_header_type, stream_event_ctx_type,
62 event_context_type, event_payload_type,
63 BT_CTF_RESOLVE_FLAG_EVENT_CONTEXT |
64 BT_CTF_RESOLVE_FLAG_EVENT_PAYLOAD);
65 if (ret) {
66 _printf_error("Cannot resolve event class types\n");
67 goto end;
68 }
69
70 /* Validate field types individually */
71 if (event_context_type) {
72 ret = bt_ctf_field_type_validate(event_context_type);
73 if (ret) {
74 _printf_error("Invalid event context type\n");
75 goto end;
76 }
77 }
78
79 if (event_payload_type) {
80 ret = bt_ctf_field_type_validate(event_payload_type);
81 if (ret) {
82 _printf_error("Invalid event payload type\n");
83 goto end;
84 }
85 }
86
87end:
88 return ret;
89}
90
91/*
92 * This function resolves and validates the field types of a stream
93 * class. Only `packet_context_type`, `event_header_type`, and
94 * `stream_event_ctx_type` are resolved and validated; the other field
95 * type is used as an eventual resolving target.
96 *
97 * All parameters are owned by the caller.
98 */
99static
100int validate_stream_class_types(struct bt_value *environment,
101 struct bt_ctf_field_type *packet_header_type,
102 struct bt_ctf_field_type *packet_context_type,
103 struct bt_ctf_field_type *event_header_type,
104 struct bt_ctf_field_type *stream_event_ctx_type)
105{
106 int ret = 0;
107
108 /* Resolve sequence type lengths and variant type tags first */
109 ret = bt_ctf_resolve_types(environment, packet_header_type,
110 packet_context_type, event_header_type, stream_event_ctx_type,
111 NULL, NULL,
112 BT_CTF_RESOLVE_FLAG_PACKET_CONTEXT |
113 BT_CTF_RESOLVE_FLAG_EVENT_HEADER |
114 BT_CTF_RESOLVE_FLAG_STREAM_EVENT_CTX);
115 if (ret) {
116 _printf_error("Cannot resolve stream class types\n");
117 goto end;
118 }
119
120 /* Validate field types individually */
121 if (packet_context_type) {
122 ret = bt_ctf_field_type_validate(packet_context_type);
123 if (ret) {
124 _printf_error("Invalid stream packet context type\n");
125 goto end;
126 }
127 }
128
129 if (event_header_type) {
130 ret = bt_ctf_field_type_validate(event_header_type);
131 if (ret) {
132 _printf_error("Invalid stream event header type\n");
133 goto end;
134 }
135 }
136
137 if (stream_event_ctx_type) {
138 ret = bt_ctf_field_type_validate(
139 stream_event_ctx_type);
140 if (ret) {
141 _printf_error("Invalid stream event context type\n");
142 goto end;
143 }
144 }
145
146end:
147 return ret;
148}
149
150/*
151 * This function resolves and validates the field types of a trace.
152 *
153 * All parameters are owned by the caller.
154 */
155static
156int validate_trace_types(struct bt_value *environment,
157 struct bt_ctf_field_type *packet_header_type)
158{
159 int ret = 0;
160
161 /* Resolve sequence type lengths and variant type tags first */
162 ret = bt_ctf_resolve_types(environment, packet_header_type,
163 NULL, NULL, NULL, NULL, NULL,
164 BT_CTF_RESOLVE_FLAG_PACKET_HEADER);
165 if (ret) {
166 _printf_error("Cannot resolve trace types\n");
167 goto end;
168 }
169
170 /* Validate field types individually */
171 if (packet_header_type) {
172 ret = bt_ctf_field_type_validate(packet_header_type);
173 if (ret) {
174 _printf_error("Invalid trace packet header type\n");
175 goto end;
176 }
177 }
178
179end:
180 return ret;
181}
182
183/*
184 * Checks whether or not `field_type` contains a variant or a sequence
185 * field type, recursively. Returns 1 if it's the case.
186 *
187 * `field_type` is owned by the caller.
188 */
189static
190int field_type_contains_sequence_or_variant_ft(struct bt_ctf_field_type *type)
191{
192 int ret = 0;
9a19a512 193 enum bt_ctf_type_id type_id = bt_ctf_field_type_get_type_id(type);
09840de5
PP
194
195 switch (type_id) {
9a19a512
PP
196 case BT_CTF_TYPE_ID_SEQUENCE:
197 case BT_CTF_TYPE_ID_VARIANT:
09840de5
PP
198 ret = 1;
199 goto end;
9a19a512
PP
200 case BT_CTF_TYPE_ID_ARRAY:
201 case BT_CTF_TYPE_ID_STRUCT:
09840de5
PP
202 {
203 int i;
204 int field_count = bt_ctf_field_type_get_field_count(type);
205
206 if (field_count < 0) {
207 ret = -1;
208 goto end;
209 }
210
211 for (i = 0; i < field_count; ++i) {
212 struct bt_ctf_field_type *child_type =
213 bt_ctf_field_type_get_field_at_index(type, i);
214
215 ret = field_type_contains_sequence_or_variant_ft(
216 child_type);
217 BT_PUT(child_type);
218 if (ret != 0) {
219 goto end;
220 }
221 }
222 break;
223 }
224 default:
225 break;
226 }
227
228end:
229 return ret;
230}
231
232BT_HIDDEN
233int bt_ctf_validate_class_types(struct bt_value *environment,
234 struct bt_ctf_field_type *packet_header_type,
235 struct bt_ctf_field_type *packet_context_type,
236 struct bt_ctf_field_type *event_header_type,
237 struct bt_ctf_field_type *stream_event_ctx_type,
238 struct bt_ctf_field_type *event_context_type,
239 struct bt_ctf_field_type *event_payload_type,
240 int trace_valid, int stream_class_valid, int event_class_valid,
241 struct bt_ctf_validation_output *output,
242 enum bt_ctf_validation_flag validate_flags)
243{
244 int ret = 0;
245 int contains_seq_var;
246 int valid_ret;
247
248 /* Clean output values */
249 memset(output, 0, sizeof(*output));
250
251 /* Set initial valid flags according to valid parameters */
252 if (trace_valid) {
253 output->valid_flags |= BT_CTF_VALIDATION_FLAG_TRACE;
254 }
255
256 if (stream_class_valid) {
257 output->valid_flags |= BT_CTF_VALIDATION_FLAG_STREAM;
258 }
259
260 if (event_class_valid) {
261 output->valid_flags |= BT_CTF_VALIDATION_FLAG_EVENT;
262 }
263
264 /* Own the type parameters */
265 bt_get(packet_header_type);
266 bt_get(packet_context_type);
267 bt_get(event_header_type);
268 bt_get(stream_event_ctx_type);
269 bt_get(event_context_type);
270 bt_get(event_payload_type);
271
272 /* Validate trace */
273 if ((validate_flags & BT_CTF_VALIDATION_FLAG_TRACE) && !trace_valid) {
274 struct bt_ctf_field_type *packet_header_type_copy = NULL;
275
276 /* Create field type copies */
277 if (packet_header_type) {
278 contains_seq_var =
279 field_type_contains_sequence_or_variant_ft(
280 packet_header_type);
281 if (contains_seq_var < 0) {
282 ret = contains_seq_var;
283 goto error;
284 } else if (!contains_seq_var) {
285 /* No copy is needed */
286 packet_header_type_copy = packet_header_type;
287 bt_get(packet_header_type_copy);
288 goto skip_packet_header_type_copy;
289 }
290
291 packet_header_type_copy =
292 bt_ctf_field_type_copy(packet_header_type);
293 if (!packet_header_type_copy) {
294 ret = -1;
295 _printf_error("Cannot copy packet header type\n");
296 goto error;
297 }
298
299 /*
300 * Freeze this copy: if it's returned to the
301 * caller, it cannot be modified any way since
302 * it will be resolved.
303 */
304 bt_ctf_field_type_freeze(packet_header_type_copy);
305 }
306
307skip_packet_header_type_copy:
308 /* Put original reference and move copy */
309 BT_MOVE(packet_header_type, packet_header_type_copy);
310
311 /* Validate trace field types */
312 valid_ret = validate_trace_types(environment,
313 packet_header_type);
314 if (!valid_ret) {
315 /* Trace is valid */
316 output->valid_flags |= BT_CTF_VALIDATION_FLAG_TRACE;
317 }
318 }
319
320 /* Validate stream class */
321 if ((validate_flags & BT_CTF_VALIDATION_FLAG_STREAM) &&
322 !stream_class_valid) {
323 struct bt_ctf_field_type *packet_context_type_copy = NULL;
324 struct bt_ctf_field_type *event_header_type_copy = NULL;
325 struct bt_ctf_field_type *stream_event_ctx_type_copy = NULL;
326
327 if (packet_context_type) {
328 contains_seq_var =
329 field_type_contains_sequence_or_variant_ft(
330 packet_context_type);
331 if (contains_seq_var < 0) {
332 ret = contains_seq_var;
333 goto error;
334 } else if (!contains_seq_var) {
335 /* No copy is needed */
336 packet_context_type_copy = packet_context_type;
337 bt_get(packet_context_type_copy);
338 goto skip_packet_context_type_copy;
339 }
340
341 packet_context_type_copy =
342 bt_ctf_field_type_copy(packet_context_type);
343 if (!packet_context_type_copy) {
344 _printf_error("Cannot copy packet context type\n");
345 goto sc_validation_error;
346 }
347
348 /*
349 * Freeze this copy: if it's returned to the
350 * caller, it cannot be modified any way since
351 * it will be resolved.
352 */
353 bt_ctf_field_type_freeze(packet_context_type_copy);
354 }
355
356skip_packet_context_type_copy:
357 if (event_header_type) {
358 contains_seq_var =
359 field_type_contains_sequence_or_variant_ft(
360 event_header_type);
361 if (contains_seq_var < 0) {
362 ret = contains_seq_var;
363 goto error;
364 } else if (!contains_seq_var) {
365 /* No copy is needed */
366 event_header_type_copy = event_header_type;
367 bt_get(event_header_type_copy);
368 goto skip_event_header_type_copy;
369 }
370
371 event_header_type_copy =
372 bt_ctf_field_type_copy(event_header_type);
373 if (!event_header_type_copy) {
374 _printf_error("Cannot copy event header type\n");
375 goto sc_validation_error;
376 }
377
378 /*
379 * Freeze this copy: if it's returned to the
380 * caller, it cannot be modified any way since
381 * it will be resolved.
382 */
383 bt_ctf_field_type_freeze(event_header_type_copy);
384 }
385
386skip_event_header_type_copy:
387 if (stream_event_ctx_type) {
388 contains_seq_var =
389 field_type_contains_sequence_or_variant_ft(
390 stream_event_ctx_type);
391 if (contains_seq_var < 0) {
392 ret = contains_seq_var;
393 goto error;
394 } else if (!contains_seq_var) {
395 /* No copy is needed */
396 stream_event_ctx_type_copy =
397 stream_event_ctx_type;
398 bt_get(stream_event_ctx_type_copy);
399 goto skip_stream_event_ctx_type_copy;
400 }
401
402 stream_event_ctx_type_copy =
403 bt_ctf_field_type_copy(stream_event_ctx_type);
404 if (!stream_event_ctx_type_copy) {
405 _printf_error("Cannot copy stream event context type\n");
406 goto sc_validation_error;
407 }
408
409 /*
410 * Freeze this copy: if it's returned to the
411 * caller, it cannot be modified any way since
412 * it will be resolved.
413 */
414 bt_ctf_field_type_freeze(stream_event_ctx_type_copy);
415 }
416
417skip_stream_event_ctx_type_copy:
418 /* Put original references and move copies */
419 BT_MOVE(packet_context_type, packet_context_type_copy);
420 BT_MOVE(event_header_type, event_header_type_copy);
421 BT_MOVE(stream_event_ctx_type, stream_event_ctx_type_copy);
422
423 /* Validate stream class field types */
424 valid_ret = validate_stream_class_types(environment,
425 packet_header_type, packet_context_type,
426 event_header_type, stream_event_ctx_type);
427 if (!valid_ret) {
428 /* Stream class is valid */
429 output->valid_flags |= BT_CTF_VALIDATION_FLAG_STREAM;
430 }
431
432 goto sc_validation_done;
433
434sc_validation_error:
435 BT_PUT(packet_context_type_copy);
436 BT_PUT(event_header_type_copy);
437 BT_PUT(stream_event_ctx_type_copy);
438 ret = -1;
439 goto error;
440 }
441
442sc_validation_done:
443 /* Validate event class */
444 if ((validate_flags & BT_CTF_VALIDATION_FLAG_EVENT) &&
445 !event_class_valid) {
446 struct bt_ctf_field_type *event_context_type_copy = NULL;
447 struct bt_ctf_field_type *event_payload_type_copy = NULL;
448
449 if (event_context_type) {
450 contains_seq_var =
451 field_type_contains_sequence_or_variant_ft(
452 event_context_type);
453 if (contains_seq_var < 0) {
454 ret = contains_seq_var;
455 goto error;
456 } else if (!contains_seq_var) {
457 /* No copy is needed */
458 event_context_type_copy = event_context_type;
459 bt_get(event_context_type_copy);
460 goto skip_event_context_type_copy;
461 }
462
463 event_context_type_copy =
464 bt_ctf_field_type_copy(event_context_type);
465 if (!event_context_type_copy) {
466 _printf_error("Cannot copy event context type\n");
467 goto ec_validation_error;
468 }
469
470 /*
471 * Freeze this copy: if it's returned to the
472 * caller, it cannot be modified any way since
473 * it will be resolved.
474 */
475 bt_ctf_field_type_freeze(event_context_type_copy);
476 }
477
478skip_event_context_type_copy:
479 if (event_payload_type) {
480 contains_seq_var =
481 field_type_contains_sequence_or_variant_ft(
482 event_payload_type);
483 if (contains_seq_var < 0) {
484 ret = contains_seq_var;
485 goto error;
486 } else if (!contains_seq_var) {
487 /* No copy is needed */
488 event_payload_type_copy = event_payload_type;
489 bt_get(event_payload_type_copy);
490 goto skip_event_payload_type_copy;
491 }
492
493 event_payload_type_copy =
494 bt_ctf_field_type_copy(event_payload_type);
495 if (!event_payload_type_copy) {
496 _printf_error("Cannot copy event payload type\n");
497 goto ec_validation_error;
498 }
499
500 /*
501 * Freeze this copy: if it's returned to the
502 * caller, it cannot be modified any way since
503 * it will be resolved.
504 */
505 bt_ctf_field_type_freeze(event_payload_type_copy);
506 }
507
508skip_event_payload_type_copy:
509 /* Put original references and move copies */
510 BT_MOVE(event_context_type, event_context_type_copy);
511 BT_MOVE(event_payload_type, event_payload_type_copy);
512
513 /* Validate event class field types */
514 valid_ret = validate_event_class_types(environment,
515 packet_header_type, packet_context_type,
516 event_header_type, stream_event_ctx_type,
517 event_context_type, event_payload_type);
518 if (!valid_ret) {
519 /* Event class is valid */
520 output->valid_flags |= BT_CTF_VALIDATION_FLAG_EVENT;
521 }
522
523 goto ec_validation_done;
524
525ec_validation_error:
526 BT_PUT(event_context_type_copy);
527 BT_PUT(event_payload_type_copy);
528 ret = -1;
529 goto error;
530 }
531
532ec_validation_done:
533 /*
534 * Validation is complete. Move the field types that were used
535 * to validate (and that were possibly altered by the validation
536 * process) to the output values.
537 */
538 BT_MOVE(output->packet_header_type, packet_header_type);
539 BT_MOVE(output->packet_context_type, packet_context_type);
540 BT_MOVE(output->event_header_type, event_header_type);
541 BT_MOVE(output->stream_event_ctx_type, stream_event_ctx_type);
542 BT_MOVE(output->event_context_type, event_context_type);
543 BT_MOVE(output->event_payload_type, event_payload_type);
544
545 return ret;
546
547error:
548 BT_PUT(packet_header_type);
549 BT_PUT(packet_context_type);
550 BT_PUT(event_header_type);
551 BT_PUT(stream_event_ctx_type);
552 BT_PUT(event_context_type);
553 BT_PUT(event_payload_type);
554
555 return ret;
556}
557
558BT_HIDDEN
559void bt_ctf_validation_replace_types(struct bt_ctf_trace *trace,
560 struct bt_ctf_stream_class *stream_class,
561 struct bt_ctf_event_class *event_class,
562 struct bt_ctf_validation_output *output,
563 enum bt_ctf_validation_flag replace_flags)
564{
565 if ((replace_flags & BT_CTF_VALIDATION_FLAG_TRACE) && trace) {
b46969a9 566 bt_ctf_field_type_freeze(trace->packet_header_type);
09840de5
PP
567 BT_MOVE(trace->packet_header_type, output->packet_header_type);
568 }
569
570 if ((replace_flags & BT_CTF_VALIDATION_FLAG_STREAM) && stream_class) {
b46969a9
PP
571 bt_ctf_field_type_freeze(stream_class->packet_context_type);
572 bt_ctf_field_type_freeze(stream_class->event_header_type);
573 bt_ctf_field_type_freeze(stream_class->event_context_type);
09840de5
PP
574 BT_MOVE(stream_class->packet_context_type,
575 output->packet_context_type);
576 BT_MOVE(stream_class->event_header_type,
577 output->event_header_type);
578 BT_MOVE(stream_class->event_context_type,
579 output->stream_event_ctx_type);
580 }
581
582 if ((replace_flags & BT_CTF_VALIDATION_FLAG_EVENT) && event_class) {
b46969a9
PP
583 bt_ctf_field_type_freeze(event_class->context);
584 bt_ctf_field_type_freeze(event_class->fields);
09840de5
PP
585 BT_MOVE(event_class->context, output->event_context_type);
586 BT_MOVE(event_class->fields, output->event_payload_type);
587 }
588}
589
590BT_HIDDEN
591void bt_ctf_validation_output_put_types(
592 struct bt_ctf_validation_output *output)
593{
594 BT_PUT(output->packet_header_type);
595 BT_PUT(output->packet_context_type);
596 BT_PUT(output->event_header_type);
597 BT_PUT(output->stream_event_ctx_type);
598 BT_PUT(output->event_context_type);
599 BT_PUT(output->event_payload_type);
600}
This page took 0.049006 seconds and 4 git commands to generate.