1 # The MIT License (MIT)
3 # Copyright (c) 2015-2020 Philippe Proulx <pproulx@efficios.com>
5 # Permission is hereby granted, free of charge, to any person obtaining
6 # a copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish,
9 # distribute, sublicense, and/or sell copies of the Software, and to
10 # permit persons to whom the Software is furnished to do so, subject to
11 # the following conditions:
13 # The above copyright notice and this permission notice shall be
14 # included in all copies or substantial portions of the Software.
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 import barectf
.config_parse_common
as barectf_config_parse_common
25 from barectf
.config_parse_common
import _ConfigurationParseError
26 from barectf
.config_parse_common
import _append_error_ctx
27 from barectf
.config_parse_common
import _MapNode
28 import barectf
.config
as barectf_config
29 from barectf
.config
import _OptFt
, _OptStructFt
32 from barectf
.typing
import Count
, Alignment
, VersionNumber
33 from typing
import Optional
, List
, Dict
, Any
, TextIO
, Set
, Iterable
, Callable
, Tuple
, Type
37 # A barectf 3 YAML configuration parser.
39 # When you build such a parser, it parses the configuration node `node`
40 # (already loaded from the file having the path `path`) and creates a
41 # corresponding `barectf.Configuration` object which you can get with
42 # the `config` property.
44 # See the comments of _parse() for more implementation details about the
45 # parsing stages and general strategy.
46 class _Parser(barectf_config_parse_common
._Parser
):
47 # Builds a barectf 3 YAML configuration parser and parses the root
48 # configuration node `node` (already loaded from the file-like
49 # object `root_file`).
50 def __init__(self
, root_file
: TextIO
, node
: barectf_config_parse_common
._ConfigNodeV
3,
51 with_pkg_include_dir
: bool, inclusion_dirs
: Optional
[List
[str]],
52 ignore_include_not_found
: bool):
53 super().__init
__(root_file
, node
, with_pkg_include_dir
, inclusion_dirs
,
54 ignore_include_not_found
, VersionNumber(3))
55 self
._ft
_cls
_name
_to
_create
_method
: Dict
[str, Callable
[[_MapNode
], barectf_config
._FieldType
]] = {
56 'unsigned-integer': self
._create
_int
_ft
,
57 'signed-integer': self
._create
_int
_ft
,
58 'unsigned-enumeration': self
._create
_enum
_ft
,
59 'signed-enumeration': self
._create
_enum
_ft
,
60 'real': self
._create
_real
_ft
,
61 'string': self
._create
_string
_ft
,
62 'static-array': self
._create
_static
_array
_ft
,
63 'structure': self
._create
_struct
_ft
,
67 # Validates the alignment `alignment`, raising a
68 # `_ConfigurationParseError` exception using `ctx_obj_name` if it's
71 def _validate_alignment(alignment
: Alignment
, ctx_obj_name
: str):
74 # check for power of two
75 if (alignment
& (alignment
- 1)) != 0:
76 raise _ConfigurationParseError(ctx_obj_name
,
77 f
'Invalid alignment (not a power of two): {alignment}')
79 # Validates the TSDL identifier `iden`, raising a
80 # `_ConfigurationParseError` exception using `ctx_obj_name` and
81 # `prop` to format the message if it's invalid.
83 def _validate_iden(iden
: str, ctx_obj_name
: str, prop
: str):
84 assert type(iden
) is str
103 if iden
in ctf_keywords
:
104 msg
= f
'Invalid {prop} (not a valid identifier): `{iden}`'
105 raise _ConfigurationParseError(ctx_obj_name
, msg
)
108 def _alignment_prop(ft_node
: _MapNode
, prop_name
: str) -> Alignment
:
109 alignment
= ft_node
.get(prop_name
)
111 if alignment
is not None:
112 _Parser
._validate
_alignment
(alignment
, '`prop_name` property')
114 return Alignment(alignment
)
117 def _trace_type_node(self
) -> _MapNode
:
118 return self
.config_node
['trace']['type']
121 def _byte_order_from_node(node
: str) -> barectf_config
.ByteOrder
:
123 'big-endian': barectf_config
.ByteOrder
.BIG_ENDIAN
,
124 'little-endian': barectf_config
.ByteOrder
.LITTLE_ENDIAN
,
127 # Creates a bit array field type having the type `ft_type` from the
128 # bit array field type node `ft_node`, passing the additional
129 # `*args` to ft_type.__init__().
130 def _create_common_bit_array_ft(self
, ft_node
: _MapNode
,
131 ft_type
: Type
[barectf_config
._BitArrayFieldType
],
132 default_alignment
: Optional
[Alignment
],
133 *args
) -> barectf_config
._BitArrayFieldType
:
134 alignment
= self
._alignment
_prop
(ft_node
, 'alignment')
136 if alignment
is None:
137 alignment
= default_alignment
139 return ft_type(ft_node
['size'], alignment
, *args
)
141 # Creates an integer field type having the type `ft_type` from the
142 # integer field type node `ft_node`, passing the additional `*args`
143 # to ft_type.__init__().
144 def _create_common_int_ft(self
, ft_node
: _MapNode
,
145 ft_type
: Type
[barectf_config
._IntegerFieldType
], *args
) -> barectf_config
._IntegerFieldType
:
146 preferred_display_base
= {
147 'binary': barectf_config
.DisplayBase
.BINARY
,
148 'octal': barectf_config
.DisplayBase
.OCTAL
,
149 'decimal': barectf_config
.DisplayBase
.DECIMAL
,
150 'hexadecimal': barectf_config
.DisplayBase
.HEXADECIMAL
,
151 }[ft_node
.get('preferred-display-base', 'decimal')]
152 return typing
.cast(barectf_config
._IntegerFieldType
,
153 self
._create
_common
_bit
_array
_ft
(ft_node
, ft_type
, None,
154 preferred_display_base
, *args
))
156 # Creates an integer field type from the unsigned/signed integer
157 # field type node `ft_node`.
158 def _create_int_ft(self
, ft_node
: _MapNode
) -> barectf_config
._IntegerFieldType
:
160 'unsigned-integer': barectf_config
.UnsignedIntegerFieldType
,
161 'signed-integer': barectf_config
.SignedIntegerFieldType
,
163 return self
._create
_common
_int
_ft
(ft_node
, ft_type
)
165 # Creates an enumeration field type from the unsigned/signed
166 # enumeration field type node `ft_node`.
167 def _create_enum_ft(self
, ft_node
: _MapNode
) -> barectf_config
._EnumerationFieldType
:
169 'unsigned-enumeration': barectf_config
.UnsignedEnumerationFieldType
,
170 'signed-enumeration': barectf_config
.SignedEnumerationFieldType
,
172 mappings
= collections
.OrderedDict()
174 for label
, mapping_node
in ft_node
.get('mappings', {}).items():
177 for range_node
in mapping_node
:
178 if type(range_node
) is list:
179 ranges
.add(barectf_config
.EnumerationFieldTypeMappingRange(range_node
[0],
182 assert type(range_node
) is int
183 ranges
.add(barectf_config
.EnumerationFieldTypeMappingRange(range_node
,
186 mappings
[label
] = barectf_config
.EnumerationFieldTypeMapping(ranges
)
188 return typing
.cast(barectf_config
._EnumerationFieldType
,
189 self
._create
_common
_int
_ft
(ft_node
, ft_type
,
190 barectf_config
.EnumerationFieldTypeMappings(mappings
)))
192 # Creates a real field type from the real field type node `ft_node`.
193 def _create_real_ft(self
, ft_node
: _MapNode
) -> barectf_config
.RealFieldType
:
194 return typing
.cast(barectf_config
.RealFieldType
,
195 self
._create
_common
_bit
_array
_ft
(ft_node
, barectf_config
.RealFieldType
,
198 # Creates a string field type from the string field type node
200 def _create_string_ft(self
, ft_node
: _MapNode
) -> barectf_config
.StringFieldType
:
201 return barectf_config
.StringFieldType()
203 # Creates a static array field type from the static array field type
205 def _create_static_array_ft(self
, ft_node
: _MapNode
) -> barectf_config
.StaticArrayFieldType
:
206 prop_name
= 'element-field-type'
209 element_ft
= self
._create
_ft
(ft_node
[prop_name
])
210 except _ConfigurationParseError
as exc
:
211 _append_error_ctx(exc
, f
'`{prop_name}` property')
213 return barectf_config
.StaticArrayFieldType(ft_node
['length'], element_ft
)
215 # Creates structure field type members from the structure field type
216 # members node `members_node`.
218 # `prop_name` is the name of the property of which `members_node` is
220 def _create_struct_ft_members(self
, members_node
: List
[_MapNode
], prop_name
: str):
221 members
= collections
.OrderedDict()
222 member_names
: Set
[str] = set()
224 for member_node
in members_node
:
225 member_name
, member_node
= list(member_node
.items())[0]
227 if member_name
in member_names
:
228 raise _ConfigurationParseError(f
'`{prop_name}` property',
229 f
'Duplicate member `{member_name}`')
231 self
._validate
_iden
(member_name
, f
'`{prop_name}` property',
232 'structure field type member name')
233 member_names
.add(member_name
)
234 ft_prop_name
= 'field-type'
235 ft_node
= member_node
[ft_prop_name
]
238 if ft_node
['class'] in ['structure']:
239 raise _ConfigurationParseError(f
'`{ft_prop_name}` property',
240 'Nested structure field types are not supported')
243 member_ft
= self
._create
_ft
(ft_node
)
244 except _ConfigurationParseError
as exc
:
245 exc
._append
_ctx
(f
'`{ft_prop_name}` property')
246 except _ConfigurationParseError
as exc
:
247 _append_error_ctx(exc
, f
'Structure field type member `{member_name}`')
249 members
[member_name
] = barectf_config
.StructureFieldTypeMember(member_ft
)
251 return barectf_config
.StructureFieldTypeMembers(members
)
253 # Creates a structure field type from the structure field type node
255 def _create_struct_ft(self
, ft_node
: _MapNode
) -> barectf_config
.StructureFieldType
:
256 minimum_alignment
= self
._alignment
_prop
(ft_node
, 'minimum-alignment')
258 if minimum_alignment
is None:
259 minimum_alignment
= 1
262 prop_name
= 'members'
263 members_node
= ft_node
.get(prop_name
)
265 if members_node
is not None:
266 members
= self
._create
_struct
_ft
_members
(members_node
, prop_name
)
268 return barectf_config
.StructureFieldType(minimum_alignment
, members
)
270 # Creates a field type from the field type node `ft_node`.
271 def _create_ft(self
, ft_node
: _MapNode
) -> barectf_config
._FieldType
:
272 return self
._ft
_cls
_name
_to
_create
_method
[ft_node
['class']](ft_node
)
274 # Creates a field type from the field type node `parent_node[key]`
276 def _try_create_ft(self
, parent_node
: _MapNode
, key
: str) -> _OptFt
:
277 if key
not in parent_node
:
281 return self
._create
_ft
(parent_node
[key
])
282 except _ConfigurationParseError
as exc
:
283 _append_error_ctx(exc
, f
'`{key}` property')
285 # satisfy static type checker (never reached)
288 # Like _try_create_ft(), but casts the result's type to
289 # `barectf_config.StructureFieldType` to satisfy static type
291 def _try_create_struct_ft(self
, parent_node
: _MapNode
, key
: str) -> _OptStructFt
:
292 return typing
.cast(barectf_config
.StructureFieldType
,
293 self
._try
_create
_ft
(parent_node
, key
))
295 # Returns the total number of members in the structure field type
296 # node `ft_node` if it exists, otherwise 0.
298 def _total_struct_ft_node_members(ft_node
: Optional
[_MapNode
]) -> Count
:
302 members_node
= ft_node
.get('members')
304 if members_node
is None:
307 return Count(len(members_node
))
309 # Creates an event type from the event type node `ev_type_node`
312 # `ev_member_count` is the total number of structure field type
313 # members within the event type so far (from the common part in its
314 # stream type). For example, if the stream type has a event header
315 # field type with `id` and `timestamp` members, then
316 # `ev_member_count` is 2.
317 def _create_ev_type(self
, name
: str, ev_type_node
: _MapNode
, ev_member_count
: Count
) -> barectf_config
.EventType
:
319 self
._validate
_iden
(name
, '`name` property', 'event type name')
321 # make sure the event type is not empty
322 spec_ctx_ft_prop_name
= 'specific-context-field-type'
323 payload_ft_prop_name
= 'payload-field-type'
324 ev_member_count
= Count(ev_member_count
+ self
._total
_struct
_ft
_node
_members
(ev_type_node
.get(spec_ctx_ft_prop_name
)))
325 ev_member_count
= Count(ev_member_count
+ self
._total
_struct
_ft
_node
_members
(ev_type_node
.get(payload_ft_prop_name
)))
327 if ev_member_count
== 0:
328 raise _ConfigurationParseError('Event type', 'Event type is empty (no members).')
331 return barectf_config
.EventType(name
, ev_type_node
.get('log-level'),
332 self
._try
_create
_struct
_ft
(ev_type_node
,
333 spec_ctx_ft_prop_name
),
334 self
._try
_create
_struct
_ft
(ev_type_node
,
335 payload_ft_prop_name
))
336 except _ConfigurationParseError
as exc
:
337 _append_error_ctx(exc
, f
'Event type `{name}`')
339 # satisfy static type checker (never reached)
342 # Returns the effective feature field type for the field type
343 # node `parent_node[key]`, if any.
347 # If `parent_node[key]` is `False`:
350 # If `parent_node[key]` is `True`:
351 # `barectf_config.DEFAULT_FIELD_TYPE`.
353 # If `parent_node[key]` doesn't exist:
354 # `none` (parameter).
357 # A created field type.
358 def _feature_ft(self
, parent_node
: _MapNode
, key
: str, none
: Any
= None) -> Any
:
359 if key
not in parent_node
:
360 # missing: default feature field type
363 ft_node
= parent_node
[key
]
364 assert ft_node
is not None
367 # default feature field type
368 return barectf_config
.DEFAULT_FIELD_TYPE
374 assert type(ft_node
) is collections
.OrderedDict
375 return self
._create
_ft
(ft_node
)
377 def _create_stream_type(self
, name
: str, stream_type_node
: _MapNode
) -> barectf_config
.StreamType
:
379 # validate stream type's name
380 self
._validate
_iden
(name
, '`name` property', 'stream type name')
382 # get default clock type, if any
384 prop_name
= '$default-clock-type-name'
385 def_clk_type_name
= stream_type_node
.get(prop_name
)
387 if def_clk_type_name
is not None:
389 def_clk_type
= self
._clk
_type
(def_clk_type_name
, prop_name
)
390 except _ConfigurationParseError
as exc
:
391 _append_error_ctx(exc
, f
'`{prop_name}` property')
393 # create feature field types
394 pkt_total_size_ft
= barectf_config
.DEFAULT_FIELD_TYPE
395 pkt_content_size_ft
= barectf_config
.DEFAULT_FIELD_TYPE
396 pkt_beginning_time_ft
= None
397 pkt_end_time_ft
= None
398 pkt_discarded_events_counter_ft
= None
399 ev_type_id_ft
= barectf_config
.DEFAULT_FIELD_TYPE
402 if def_clk_type
is not None:
403 # The stream type has a default clock type. Initialize
404 # the packet beginning time, packet end time, and event
405 # time field types to default field types.
407 # This means your stream type node only needs a default
408 # clock type name to enable those features
409 # automatically. Those features do not add any parameter
410 # to the tracing event functions.
411 pkt_beginning_time_ft
= barectf_config
.DEFAULT_FIELD_TYPE
412 pkt_end_time_ft
= barectf_config
.DEFAULT_FIELD_TYPE
413 ev_time_ft
= barectf_config
.DEFAULT_FIELD_TYPE
415 features_node
= stream_type_node
.get('$features')
417 if features_node
is not None:
418 # create packet feature field types
419 pkt_node
= features_node
.get('packet')
421 if pkt_node
is not None:
422 pkt_total_size_ft
= self
._feature
_ft
(pkt_node
, 'total-size-field-type',
424 pkt_content_size_ft
= self
._feature
_ft
(pkt_node
, 'content-size-field-type',
426 pkt_beginning_time_ft
= self
._feature
_ft
(pkt_node
, 'beginning-time-field-type',
427 pkt_beginning_time_ft
)
428 pkt_end_time_ft
= self
._feature
_ft
(pkt_node
, 'end-time-field-type',
430 pkt_discarded_events_counter_ft
= self
._feature
_ft
(pkt_node
,
431 'discarded-events-counter-field-type',
432 pkt_discarded_events_counter_ft
)
434 # create event feature field types
435 ev_node
= features_node
.get('event')
436 type_id_ft_prop_name
= 'type-id-field-type'
438 if ev_node
is not None:
439 ev_type_id_ft
= self
._feature
_ft
(ev_node
, type_id_ft_prop_name
, ev_type_id_ft
)
440 ev_time_ft
= self
._feature
_ft
(ev_node
, 'time-field-type', ev_time_ft
)
442 ev_types_prop_name
= 'event-types'
443 ev_type_count
= len(stream_type_node
[ev_types_prop_name
])
446 if ev_type_id_ft
is None and ev_type_count
> 1:
447 raise _ConfigurationParseError(f
'`{type_id_ft_prop_name}` property',
448 'Event type ID field type feature is required because stream type has more than one event type')
450 if isinstance(ev_type_id_ft
, barectf_config
._IntegerFieldType
):
451 ev_type_id_int_ft
= typing
.cast(barectf_config
._IntegerFieldType
, ev_type_id_ft
)
453 if ev_type_count
> (1 << ev_type_id_int_ft
.size
):
454 raise _ConfigurationParseError(f
'`{type_id_ft_prop_name}` property',
455 f
'Field type\'s size ({ev_type_id_int_ft.size} bits) is too small to accomodate {ev_type_count} event types')
456 except _ConfigurationParseError
as exc
:
457 exc
._append
_ctx
('`event` property')
458 _append_error_ctx(exc
, '`$features` property')
460 pkt_features
= barectf_config
.StreamTypePacketFeatures(pkt_total_size_ft
,
462 pkt_beginning_time_ft
,
464 pkt_discarded_events_counter_ft
)
465 ev_features
= barectf_config
.StreamTypeEventFeatures(ev_type_id_ft
, ev_time_ft
)
466 features
= barectf_config
.StreamTypeFeatures(pkt_features
, ev_features
)
468 # create packet context (structure) field type extra members
469 pkt_ctx_ft_extra_members
= None
470 prop_name
= 'packet-context-field-type-extra-members'
471 pkt_ctx_ft_extra_members_node
= stream_type_node
.get(prop_name
)
473 if pkt_ctx_ft_extra_members_node
is not None:
474 pkt_ctx_ft_extra_members
= self
._create
_struct
_ft
_members
(pkt_ctx_ft_extra_members_node
,
477 # check for illegal packet context field type member names
478 reserved_member_names
= {
487 for member_name
in pkt_ctx_ft_extra_members
:
488 if member_name
in reserved_member_names
:
489 raise _ConfigurationParseError(f
'`{prop_name}` property',
490 f
'Packet context field type member name `{member_name}` is reserved.')
493 ev_header_common_ctx_member_count
= Count(0)
495 if ev_features
.type_id_field_type
is not None:
496 ev_header_common_ctx_member_count
= Count(ev_header_common_ctx_member_count
+ 1)
498 if ev_features
.time_field_type
is not None:
499 ev_header_common_ctx_member_count
= Count(ev_header_common_ctx_member_count
+ 1)
501 ev_common_ctx_ft_prop_name
= 'event-common-context-field-type'
502 ev_common_ctx_ft_node
= stream_type_node
.get(ev_common_ctx_ft_prop_name
)
503 ev_header_common_ctx_member_count
= Count(ev_header_common_ctx_member_count
+ self
._total
_struct
_ft
_node
_members
(ev_common_ctx_ft_node
))
506 for ev_name
, ev_type_node
in stream_type_node
[ev_types_prop_name
].items():
507 ev_types
.add(self
._create
_ev
_type
(ev_name
, ev_type_node
, ev_header_common_ctx_member_count
))
510 return barectf_config
.StreamType(name
, ev_types
, def_clk_type
, features
,
511 pkt_ctx_ft_extra_members
,
512 self
._try
_create
_struct
_ft
(stream_type_node
,
513 ev_common_ctx_ft_prop_name
))
514 except _ConfigurationParseError
as exc
:
515 _append_error_ctx(exc
, f
'Stream type `{name}`')
517 # satisfy static type checker (never reached)
520 def _clk_type(self
, name
: str, prop_name
: str) -> barectf_config
.ClockType
:
521 clk_type
= self
._clk
_types
.get(name
)
524 raise _ConfigurationParseError(f
'`{prop_name}` property',
525 f
'Clock type `{name}` does not exist')
529 def _create_clk_type(self
, name
: str, clk_type_node
: _MapNode
) -> barectf_config
.ClockType
:
530 self
._validate
_iden
(name
, '`name` property', 'clock type name')
532 uuid_node
= clk_type_node
.get('uuid')
534 if uuid_node
is not None:
535 clk_type_uuid
= uuid
.UUID(uuid_node
)
538 offset_cycles
= Count(0)
539 offset_node
= clk_type_node
.get('offset')
541 if offset_node
is not None:
542 offset_seconds
= offset_node
.get('seconds', 0)
543 offset_cycles
= offset_node
.get('cycles', Count(0))
545 return barectf_config
.ClockType(name
, clk_type_node
.get('frequency', int(1e9
)),
546 clk_type_uuid
, clk_type_node
.get('description'),
547 clk_type_node
.get('precision', 0),
548 barectf_config
.ClockTypeOffset(offset_seconds
, offset_cycles
),
549 clk_type_node
.get('origin-is-unix-epoch', False))
551 def _create_clk_types(self
):
554 for clk_type_name
, clk_type_node
in self
._trace
_type
_node
.get('clock-types', {}).items():
555 self
._clk
_types
[clk_type_name
] = self
._create
_clk
_type
(clk_type_name
, clk_type_node
)
557 def _create_trace_type(self
):
559 # create clock types (_create_stream_type() needs them)
560 self
._create
_clk
_types
()
563 trace_type_uuid
= None
564 uuid_node
= self
._trace
_type
_node
.get('uuid')
566 if uuid_node
is not None:
567 if uuid_node
== 'auto':
568 trace_type_uuid
= uuid
.uuid1()
570 trace_type_uuid
= uuid
.UUID(uuid_node
)
572 # create feature field types
573 magic_ft
= barectf_config
.DEFAULT_FIELD_TYPE
575 stream_type_id_ft
= barectf_config
.DEFAULT_FIELD_TYPE
577 if trace_type_uuid
is not None:
578 # Trace type has a UUID: initialize UUID field type to
579 # a default field type.
580 uuid_ft
= barectf_config
.DEFAULT_FIELD_TYPE
582 features_node
= self
._trace
_type
_node
.get('$features')
583 stream_type_id_ft_prop_name
= 'stream-type-id-field-type'
585 if features_node
is not None:
586 magic_ft
= self
._feature
_ft
(features_node
, 'magic-field-type',
588 uuid_ft
= self
._feature
_ft
(features_node
, 'uuid-field-type', uuid_ft
)
589 stream_type_id_ft
= self
._feature
_ft
(features_node
, stream_type_id_ft_prop_name
,
592 stream_types_prop_name
= 'stream-types'
593 stream_type_count
= len(self
._trace
_type
_node
[stream_types_prop_name
])
596 if stream_type_id_ft
is None and stream_type_count
> 1:
597 raise _ConfigurationParseError(f
'`{stream_type_id_ft_prop_name}` property',
598 'Stream type ID field type feature is required because trace type has more than one stream type')
600 if isinstance(stream_type_id_ft
, barectf_config
._FieldType
) and stream_type_count
> (1 << stream_type_id_ft
.size
):
601 raise _ConfigurationParseError(f
'`{stream_type_id_ft_prop_name}` property',
602 f
'Field type\'s size ({stream_type_id_ft.size} bits) is too small to accomodate {stream_type_count} stream types')
603 except _ConfigurationParseError
as exc
:
604 _append_error_ctx(exc
, '`$features` property')
606 features
= barectf_config
.TraceTypeFeatures(magic_ft
, uuid_ft
, stream_type_id_ft
)
608 # create stream types
611 for stream_name
, stream_type_node
in self
._trace
_type
_node
[stream_types_prop_name
].items():
612 stream_types
.add(self
._create
_stream
_type
(stream_name
, stream_type_node
))
615 return barectf_config
.TraceType(stream_types
, trace_type_uuid
, features
)
616 except _ConfigurationParseError
as exc
:
617 _append_error_ctx(exc
, 'Trace type')
619 def _create_trace(self
):
621 trace_type
= self
._create
_trace
_type
()
622 trace_node
= self
.config_node
['trace']
624 env_node
= trace_node
.get('environment')
626 if env_node
is not None:
627 # validate each environment variable name
628 for name
in env_node
:
629 self
._validate
_iden
(name
, '`environment` property',
630 'environment variable name')
632 # the node already has the expected structure
633 env
= barectf_config
.TraceEnvironment(env_node
)
635 return barectf_config
.Trace(trace_type
, env
)
637 except _ConfigurationParseError
as exc
:
638 _append_error_ctx(exc
, 'Trace')
640 def _create_config(self
):
642 trace
= self
._create
_trace
()
644 # find default stream type, if any
645 def_stream_type
= None
647 for stream_type_name
, stream_type_node
in self
._trace
_type
_node
['stream-types'].items():
648 prop_name
= '$is-default'
649 is_default
= stream_type_node
.get(prop_name
)
651 if is_default
is True:
652 if def_stream_type
is not None:
653 exc
= _ConfigurationParseError(f
'`{prop_name}` property',
654 f
'Duplicate default stream type (`{def_stream_type.name}`)')
655 exc
._append
_ctx
(f
'Stream type `{stream_type_name}`')
656 _append_error_ctx(exc
, 'Trace type')
658 def_stream_type
= trace
.type.stream_type(stream_type_name
)
660 # create clock type C type mapping
661 clk_types_node
= self
._trace
_type
_node
.get('clock-types')
662 clk_type_c_types
= None
664 if clk_types_node
is not None:
665 clk_type_c_types
= collections
.OrderedDict()
667 for stream_type
in trace
.type.stream_types
:
668 if stream_type
.default_clock_type
is None:
671 clk_type_node
= clk_types_node
[stream_type
.default_clock_type
.name
]
672 c_type
= clk_type_node
.get('$c-type')
674 if c_type
is not None:
675 clk_type_c_types
[stream_type
.default_clock_type
] = c_type
678 iden_prefix_def
= False
679 def_stream_type_name_def
= False
680 opts_node
= self
.config_node
.get('options')
681 iden_prefix
= 'barectf_'
682 file_name_prefix
= 'barectf'
684 if opts_node
is not None:
685 code_gen_opts_node
= opts_node
.get('code-generation')
687 if code_gen_opts_node
is not None:
688 prefix_node
= code_gen_opts_node
.get('prefix', 'barectf')
690 if type(prefix_node
) is str:
692 iden_prefix
= f
'{prefix_node}_'
693 file_name_prefix
= prefix_node
695 iden_prefix
= prefix_node
['identifier']
696 file_name_prefix
= prefix_node
['file-name']
698 header_opts
= code_gen_opts_node
.get('header')
700 if header_opts
is not None:
701 iden_prefix_def
= header_opts
.get('identifier-prefix-definition', False)
702 def_stream_type_name_def
= header_opts
.get('default-stream-type-name-definition',
705 header_opts
= barectf_config
.ConfigurationCodeGenerationHeaderOptions(iden_prefix_def
,
706 def_stream_type_name_def
)
707 cg_opts
= barectf_config
.ConfigurationCodeGenerationOptions(iden_prefix
, file_name_prefix
,
708 def_stream_type
, header_opts
,
710 opts
= barectf_config
.ConfigurationOptions(cg_opts
)
712 # create configuration
713 self
._config
= barectf_config
.Configuration(trace
, self
._target
_byte
_order
, opts
)
715 # Expands the field type aliases found in the trace type node.
717 # This method modifies the trace type node.
719 # When this method returns:
721 # * Any field type alias is replaced with its full field type
724 # * The `$field-type-aliases` property of the trace type node is
726 def _expand_ft_aliases(self
):
727 def resolve_ft_alias_from(parent_node
: _MapNode
, key
: str):
728 if key
not in parent_node
:
731 if type(parent_node
[key
]) not in [collections
.OrderedDict
, str]:
734 self
._resolve
_ft
_alias
_from
(ft_aliases_node
, parent_node
, key
)
736 ft_aliases_node
= self
._trace
_type
_node
['$field-type-aliases']
738 # Expand field type aliases within trace, stream, and event type
740 features_prop_name
= '$features'
743 features_node
= self
._trace
_type
_node
.get(features_prop_name
)
745 if features_node
is not None:
747 resolve_ft_alias_from(features_node
, 'magic-field-type')
748 resolve_ft_alias_from(features_node
, 'uuid-field-type')
749 resolve_ft_alias_from(features_node
, 'stream-type-id-field-type')
750 except _ConfigurationParseError
as exc
:
751 _append_error_ctx(exc
, f
'`{features_prop_name}` property')
752 except _ConfigurationParseError
as exc
:
753 _append_error_ctx(exc
, 'Trace type')
755 for stream_type_name
, stream_type_node
in self
._trace
_type
_node
['stream-types'].items():
757 features_node
= stream_type_node
.get(features_prop_name
)
759 if features_node
is not None:
761 pkt_prop_name
= 'packet'
762 pkt_node
= features_node
.get(pkt_prop_name
)
764 if pkt_node
is not None:
766 resolve_ft_alias_from(pkt_node
, 'total-size-field-type')
767 resolve_ft_alias_from(pkt_node
, 'content-size-field-type')
768 resolve_ft_alias_from(pkt_node
, 'beginning-time-field-type')
769 resolve_ft_alias_from(pkt_node
, 'end-time-field-type')
770 resolve_ft_alias_from(pkt_node
,
771 'discarded-events-counter-field-type')
772 except _ConfigurationParseError
as exc
:
773 _append_error_ctx(exc
, f
'`{pkt_prop_name}` property')
775 ev_prop_name
= 'event'
776 ev_node
= features_node
.get(ev_prop_name
)
778 if ev_node
is not None:
780 resolve_ft_alias_from(ev_node
, 'type-id-field-type')
781 resolve_ft_alias_from(ev_node
, 'time-field-type')
782 except _ConfigurationParseError
as exc
:
783 _append_error_ctx(exc
, f
'`{ev_prop_name}` property')
784 except _ConfigurationParseError
as exc
:
785 _append_error_ctx(exc
, f
'`{features_prop_name}` property')
787 pkt_ctx_ft_extra_members_prop_name
= 'packet-context-field-type-extra-members'
788 pkt_ctx_ft_extra_members_node
= stream_type_node
.get(pkt_ctx_ft_extra_members_prop_name
)
790 if pkt_ctx_ft_extra_members_node
is not None:
792 for member_node
in pkt_ctx_ft_extra_members_node
:
793 member_node
= list(member_node
.values())[0]
794 resolve_ft_alias_from(member_node
, 'field-type')
795 except _ConfigurationParseError
as exc
:
796 _append_error_ctx(exc
, f
'`{pkt_ctx_ft_extra_members_prop_name}` property')
798 resolve_ft_alias_from(stream_type_node
, 'event-common-context-field-type')
800 for ev_type_name
, ev_type_node
in stream_type_node
['event-types'].items():
802 resolve_ft_alias_from(ev_type_node
, 'specific-context-field-type')
803 resolve_ft_alias_from(ev_type_node
, 'payload-field-type')
804 except _ConfigurationParseError
as exc
:
805 _append_error_ctx(exc
, f
'Event type `{ev_type_name}`')
806 except _ConfigurationParseError
as exc
:
807 _append_error_ctx(exc
, f
'Stream type `{stream_type_name}`')
809 # remove the (now unneeded) `$field-type-aliases` property
810 del self
._trace
_type
_node
['$field-type-aliases']
812 # Applies field type inheritance to all field type nodes found in
813 # the trace type node.
815 # This method modifies the trace type node.
817 # When this method returns, no field type node has an `$inherit`
819 def _apply_fts_inheritance(self
):
820 def apply_ft_inheritance(parent_node
: _MapNode
, key
: str):
821 if key
not in parent_node
:
824 if type(parent_node
[key
]) is not collections
.OrderedDict
:
827 self
._apply
_ft
_inheritance
(parent_node
, key
)
829 features_prop_name
= '$features'
830 features_node
= self
._trace
_type
_node
.get(features_prop_name
)
832 if features_node
is not None:
833 apply_ft_inheritance(features_node
, 'magic-field-type')
834 apply_ft_inheritance(features_node
, 'uuid-field-type')
835 apply_ft_inheritance(features_node
, 'stream-type-id-field-type')
837 for stream_type_node
in self
._trace
_type
_node
['stream-types'].values():
838 features_node
= stream_type_node
.get(features_prop_name
)
840 if features_node
is not None:
841 pkt_node
= features_node
.get('packet')
843 if pkt_node
is not None:
844 apply_ft_inheritance(pkt_node
, 'total-size-field-type')
845 apply_ft_inheritance(pkt_node
, 'content-size-field-type')
846 apply_ft_inheritance(pkt_node
, 'beginning-time-field-type')
847 apply_ft_inheritance(pkt_node
, 'end-time-field-type')
848 apply_ft_inheritance(pkt_node
, 'discarded-events-counter-field-type')
850 ev_node
= features_node
.get('event')
852 if ev_node
is not None:
853 apply_ft_inheritance(ev_node
, 'type-id-field-type')
854 apply_ft_inheritance(ev_node
, 'time-field-type')
856 pkt_ctx_ft_extra_members_node
= stream_type_node
.get('packet-context-field-type-extra-members')
858 if pkt_ctx_ft_extra_members_node
is not None:
859 for member_node
in pkt_ctx_ft_extra_members_node
:
860 member_node
= list(member_node
.values())[0]
861 apply_ft_inheritance(member_node
, 'field-type')
863 apply_ft_inheritance(stream_type_node
, 'event-common-context-field-type')
865 for ev_type_node
in stream_type_node
['event-types'].values():
866 apply_ft_inheritance(ev_type_node
, 'specific-context-field-type')
867 apply_ft_inheritance(ev_type_node
, 'payload-field-type')
869 # Normalizes structure field type member nodes.
871 # A structure field type member node can look like this:
873 # - msg: custom-string
875 # which is the equivalent of this:
878 # field-type: custom-string
880 # This method normalizes form 1 to use form 2.
881 def _normalize_struct_ft_member_nodes(self
):
882 def normalize_members_node(members_node
: List
[_MapNode
]):
883 ft_prop_name
= 'field-type'
885 for member_node
in members_node
:
886 member_name
, val_node
= list(member_node
.items())[0]
888 if type(val_node
) is str:
889 member_node
[member_name
] = collections
.OrderedDict({
890 ft_prop_name
: val_node
893 normalize_struct_ft_member_nodes(member_node
[member_name
], ft_prop_name
)
895 def normalize_struct_ft_member_nodes(parent_node
: _MapNode
, key
: str):
896 if type(parent_node
) is not collections
.OrderedDict
:
899 ft_node
= parent_node
.get(key
)
901 if type(ft_node
) is not collections
.OrderedDict
:
904 ft_node
= typing
.cast(collections
.OrderedDict
, ft_node
)
905 members_nodes
= ft_node
.get('members')
907 if members_nodes
is not None:
908 normalize_members_node(members_nodes
)
910 prop_name
= '$field-type-aliases'
911 ft_aliases_node
= self
._trace
_type
_node
.get(prop_name
)
913 if ft_aliases_node
is not None:
914 for alias
in ft_aliases_node
:
915 normalize_struct_ft_member_nodes(ft_aliases_node
, alias
)
917 features_prop_name
= '$features'
918 features_node
= self
._trace
_type
_node
.get(features_prop_name
)
920 if features_node
is not None:
921 normalize_struct_ft_member_nodes(features_node
, 'magic-field-type')
922 normalize_struct_ft_member_nodes(features_node
, 'uuid-field-type')
923 normalize_struct_ft_member_nodes(features_node
, 'stream-type-id-field-type')
925 for stream_type_node
in self
._trace
_type
_node
['stream-types'].values():
926 features_node
= stream_type_node
.get(features_prop_name
)
928 if features_node
is not None:
929 pkt_node
= features_node
.get('packet')
931 if pkt_node
is not None:
932 normalize_struct_ft_member_nodes(pkt_node
, 'total-size-field-type')
933 normalize_struct_ft_member_nodes(pkt_node
, 'content-size-field-type')
934 normalize_struct_ft_member_nodes(pkt_node
, 'beginning-time-field-type')
935 normalize_struct_ft_member_nodes(pkt_node
, 'end-time-field-type')
936 normalize_struct_ft_member_nodes(pkt_node
,
937 'discarded-events-counter-field-type')
939 ev_node
= features_node
.get('event')
941 if ev_node
is not None:
942 normalize_struct_ft_member_nodes(ev_node
, 'type-id-field-type')
943 normalize_struct_ft_member_nodes(ev_node
, 'time-field-type')
945 pkt_ctx_ft_extra_members_node
= stream_type_node
.get('packet-context-field-type-extra-members')
947 if pkt_ctx_ft_extra_members_node
is not None:
948 normalize_members_node(pkt_ctx_ft_extra_members_node
)
950 normalize_struct_ft_member_nodes(stream_type_node
, 'event-common-context-field-type')
952 for ev_type_node
in stream_type_node
['event-types'].values():
953 normalize_struct_ft_member_nodes(ev_type_node
, 'specific-context-field-type')
954 normalize_struct_ft_member_nodes(ev_type_node
, 'payload-field-type')
956 # Calls _expand_ft_aliases() and _apply_fts_inheritance() if the
957 # trace type node has a `$field-type-aliases` property.
958 def _expand_fts(self
):
959 # Make sure that the current configuration node is valid
960 # considering field types are not expanded yet.
961 self
._schema
_validator
.validate(self
.config_node
,
962 'config/3/config-pre-field-type-expansion')
964 prop_name
= '$field-type-aliases'
965 ft_aliases_node
= self
._trace
_type
_node
.get(prop_name
)
967 if ft_aliases_node
is None:
968 # If there's no `'$field-type-aliases'` node, then there's
969 # no field type aliases and therefore no possible
971 if prop_name
in self
._trace
_type
_node
:
972 del self
._trace
_type
_node
[prop_name
]
976 # normalize structure field type member nodes
977 self
._normalize
_struct
_ft
_member
_nodes
()
979 # first, expand field type aliases
980 self
._expand
_ft
_aliases
()
982 # next, apply inheritance to create effective field type nodes
983 self
._apply
_fts
_inheritance
()
985 # Substitute the event type node log level aliases with their
986 # numeric equivalents.
988 # Removes the `$log-level-aliases` property of the trace type node.
989 def _sub_log_level_aliases(self
):
990 # Make sure that the current configuration node is valid
991 # considering log level aliases are not substituted yet.
992 self
._schema
_validator
.validate(self
.config_node
,
993 'config/3/config-pre-log-level-alias-sub')
995 log_level_aliases_prop_name
= '$log-level-aliases'
996 log_level_aliases_node
= self
._trace
_type
_node
.get(log_level_aliases_prop_name
)
998 if log_level_aliases_prop_name
in self
._trace
_type
_node
:
999 del self
._trace
_type
_node
[log_level_aliases_prop_name
]
1001 if log_level_aliases_node
is None:
1002 # no log level aliases
1005 # substitute log level aliases
1006 for stream_type_name
, stream_type_node
in self
._trace
_type
_node
['stream-types'].items():
1008 for ev_type_name
, ev_type_node
in stream_type_node
['event-types'].items():
1010 prop_name
= 'log-level'
1011 ll_node
= ev_type_node
.get(prop_name
)
1016 if type(ll_node
) is str:
1017 if ll_node
not in log_level_aliases_node
:
1018 raise _ConfigurationParseError(f
'`{prop_name}` property',
1019 f
'Log level alias `{ll_node}` does not exist')
1021 ev_type_node
[prop_name
] = log_level_aliases_node
[ll_node
]
1022 except _ConfigurationParseError
as exc
:
1023 _append_error_ctx(exc
, f
'Event type `{ev_type_name}`')
1024 except _ConfigurationParseError
as exc
:
1025 _append_error_ctx(exc
, f
'Stream type `{stream_type_name}`')
1027 # Generator of parent node and key pairs for all the nodes,
1028 # recursively, of `node`.
1030 # It is safe to delete a yielded node during the iteration.
1032 def _props(node
: Any
) -> Iterable
[Tuple
[Any
, str]]:
1033 if type(node
) is collections
.OrderedDict
:
1034 for key
in list(node
):
1035 yield from _Parser
._props
(node
[key
])
1037 elif type(node
) is list:
1038 for item_node
in node
:
1039 yield from _Parser
._props
(item_node
)
1041 def _trace_type_props(self
) -> Iterable
[Tuple
[Any
, str]]:
1042 yield from _Parser
._props
(self
.config_node
['trace']['type'])
1044 # Normalize the properties of the configuration node.
1046 # This method, for each property of the trace type node:
1048 # 1. Removes it if it's `None` (means default).
1050 # 2. Chooses a specific `class` property value.
1052 # 3. Chooses a specific `byte-order`/`target-byte-order` property
1055 # 4. Chooses a specific `preferred-display-base` property value.
1057 # This method also applies 1. to the trace node's `environment`
1059 def _normalize_props(self
):
1060 def normalize_byte_order_prop(parent_node
: _MapNode
, key
: str):
1061 node
= parent_node
[key
]
1063 if node
in ['be', 'big']:
1064 parent_node
[key
] = 'big-endian'
1065 elif node
in ['le', 'little']:
1066 parent_node
[key
] = 'little-endian'
1068 trace_node
= self
.config_node
['trace']
1069 normalize_byte_order_prop(self
.config_node
, 'target-byte-order')
1071 for parent_node
, key
in self
._trace
_type
_props
():
1072 node
= parent_node
[key
]
1075 # a `None` property is equivalent to not having it
1076 del parent_node
[key
]
1079 if key
== 'class' and type(node
) is str:
1080 # field type class aliases
1081 if node
in ['uint', 'unsigned-int']:
1082 parent_node
[key
] = 'unsigned-integer'
1083 elif node
in ['sint', 'signed-int']:
1084 parent_node
[key
] = 'signed-integer'
1085 elif node
in ['uenum', 'unsigned-enum']:
1086 parent_node
[key
] = 'unsigned-enumeration'
1087 elif node
in ['senum', 'signed-enum']:
1088 parent_node
[key
] = 'signed-enumeration'
1090 parent_node
[key
] = 'string'
1091 elif node
== 'struct':
1092 parent_node
[key
] = 'structure'
1093 elif key
== 'preferred-display-base' and type(node
) is str:
1094 # display base aliases
1096 parent_node
[key
] = 'binary'
1098 parent_node
[key
] = 'octal'
1100 parent_node
[key
] = 'decimal'
1102 parent_node
[key
] = 'hexadecimal'
1104 prop_name
= 'environment'
1106 if prop_name
in trace_node
:
1107 node
= trace_node
[prop_name
]
1110 del trace_node
[prop_name
]
1112 # Sets the parser's target byte order.
1113 def _set_target_byte_order(self
):
1114 self
._target
_byte
_order
_node
= self
.config_node
['target-byte-order']
1115 self
._target
_byte
_order
= self
._byte
_order
_from
_node
(self
._target
_byte
_order
_node
)
1117 # Processes the inclusions of the event type node `ev_type_node`,
1118 # returning the effective node.
1119 def _process_ev_type_node_include(self
, ev_type_node
: _MapNode
) -> _MapNode
:
1120 # Make sure the event type node is valid for the inclusion
1122 self
._schema
_validator
.validate(ev_type_node
, 'config/3/event-type-pre-include')
1124 # process inclusions
1125 return self
._process
_node
_include
(ev_type_node
, self
._process
_ev
_type
_node
_include
)
1127 # Processes the inclusions of the stream type node
1128 # `stream_type_node`, returning the effective node.
1129 def _process_stream_type_node_include(self
, stream_type_node
: _MapNode
) -> _MapNode
:
1130 def process_children_include(stream_type_node
: _MapNode
):
1131 prop_name
= 'event-types'
1133 if prop_name
in stream_type_node
:
1134 ev_types_node
= stream_type_node
[prop_name
]
1136 for key
in list(ev_types_node
):
1137 ev_types_node
[key
] = self
._process
_ev
_type
_node
_include
(ev_types_node
[key
])
1139 # Make sure the stream type node is valid for the inclusion
1141 self
._schema
_validator
.validate(stream_type_node
, 'config/3/stream-type-pre-include')
1143 # process inclusions
1144 return self
._process
_node
_include
(stream_type_node
, self
._process
_stream
_type
_node
_include
,
1145 process_children_include
)
1147 # Processes the inclusions of the clock type node `clk_type_node`,
1148 # returning the effective node.
1149 def _process_clk_type_node_include(self
, clk_type_node
: _MapNode
) -> _MapNode
:
1150 # Make sure the clock type node is valid for the inclusion
1152 self
._schema
_validator
.validate(clk_type_node
, 'config/3/clock-type-pre-include')
1154 # process inclusions
1155 return self
._process
_node
_include
(clk_type_node
, self
._process
_clk
_type
_node
_include
)
1157 # Processes the inclusions of the trace type node `trace_type_node`,
1158 # returning the effective node.
1159 def _process_trace_type_node_include(self
, trace_type_node
: _MapNode
) -> _MapNode
:
1160 def process_children_include(trace_type_node
: _MapNode
):
1161 prop_name
= 'clock-types'
1163 if prop_name
in trace_type_node
:
1164 clk_types_node
= trace_type_node
[prop_name
]
1166 for key
in list(clk_types_node
):
1167 clk_types_node
[key
] = self
._process
_clk
_type
_node
_include
(clk_types_node
[key
])
1169 prop_name
= 'stream-types'
1171 if prop_name
in trace_type_node
:
1172 stream_types_node
= trace_type_node
[prop_name
]
1174 for key
in list(stream_types_node
):
1175 stream_types_node
[key
] = self
._process
_stream
_type
_node
_include
(stream_types_node
[key
])
1177 # Make sure the trace type node is valid for the inclusion
1179 self
._schema
_validator
.validate(trace_type_node
, 'config/3/trace-type-pre-include')
1181 # process inclusions
1182 return self
._process
_node
_include
(trace_type_node
, self
._process
_trace
_type
_node
_include
,
1183 process_children_include
)
1185 # Processes the inclusions of the trace node `trace_node`, returning
1186 # the effective node.
1187 def _process_trace_node_include(self
, trace_node
: _MapNode
) -> _MapNode
:
1188 def process_children_include(trace_node
: _MapNode
):
1190 trace_node
[prop_name
] = self
._process
_trace
_type
_node
_include
(trace_node
[prop_name
])
1192 # Make sure the trace node is valid for the inclusion processing
1194 self
._schema
_validator
.validate(trace_node
, 'config/3/trace-pre-include')
1196 # process inclusions
1197 return self
._process
_node
_include
(trace_node
, self
._process
_trace
_node
_include
,
1198 process_children_include
)
1200 # Processes the inclusions of the configuration node, modifying it
1201 # during the process.
1202 def _process_config_includes(self
):
1203 # Process inclusions in this order:
1205 # 1. Clock type node and event type nodes (the order between
1206 # those is not important).
1208 # 2. Stream type nodes.
1210 # 3. Trace type node.
1216 # * A trace node can include a trace type node, clock type
1217 # nodes, stream type nodes, and event type nodes.
1219 # * A trace type node can include clock type nodes, stream type
1220 # nodes, and event type nodes.
1222 # * A stream type node can include event type nodes.
1224 # First, make sure the configuration node itself is valid for
1225 # the inclusion processing stage.
1226 self
._schema
_validator
.validate(self
.config_node
, 'config/3/config-pre-include')
1228 # Process trace node inclusions.
1230 # self._process_trace_node_include() returns a new (or the same)
1231 # trace node without any `$include` property in it, recursively.
1232 self
.config_node
['trace'] = self
._process
_trace
_node
_include
(self
.config_node
['trace'])
1235 # process configuration node inclusions
1236 self
._process
_config
_includes
()
1238 # Expand field type nodes.
1242 # 1. Replaces field type aliases with "effective" field type
1243 # nodes, recursively.
1245 # After this step, the `$field-type-aliases` property of the
1246 # trace type node is gone.
1248 # 2. Applies inheritance, following the `$inherit` properties.
1250 # After this step, field type nodes do not contain `$inherit`
1253 # This is done blindly, in that the process _doesn't_ validate
1254 # field type nodes at this point.
1257 # Substitute log level aliases.
1261 # 1. Replaces log level aliases in event type nodes with their
1262 # numeric equivalents as found in the `$log-level-aliases`
1263 # property of the trace type node.
1265 # 2. Removes the `$log-level-aliases` property from the trace
1267 self
._sub
_log
_level
_aliases
()
1269 # At this point, the configuration node must be valid as an
1270 # effective configuration node.
1271 self
._schema
_validator
.validate(self
.config_node
, 'config/3/config')
1273 # Normalize properties.
1275 # This process removes `None` properties and chooses specific
1276 # enumerators when aliases exist (for example, `big-endian`
1279 # The goal of this is that, if the user then gets this parser's
1280 # `config_node` property, it has a normal and very readable
1283 # It also makes _create_config() easier to implement because it
1284 # doesn't need to check for `None` nodes or enumerator aliases.
1285 self
._normalize
_props
()
1287 # Set the target byte order.
1288 self
._set
_target
_byte
_order
()
1290 # Create a barectf configuration object from the configuration
1292 self
._create
_config
()
1295 def config(self
) -> barectf_config
.Configuration
:
1299 def config_node(self
) -> _MapNode
:
1300 return typing
.cast(barectf_config_parse_common
._ConfigNodeV
3, self
._root
_node
).config_node