3983f90c94ff63f915b5f39a468e3a182f560c10
[barectf.git] / barectf / config.py
1 # The MIT License (MIT)
2 #
3 # Copyright (c) 2015-2020 Philippe Proulx <pproulx@efficios.com>
4 #
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:
12 #
13 # The above copyright notice and this permission notice shall be
14 # included in all copies or substantial portions of the Software.
15 #
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.
23
24 import barectf.version as barectf_version
25 from typing import Optional, Any, FrozenSet, Mapping, Iterator, Set, Union, Callable
26 import typing
27 from barectf.typing import Count, Alignment, _OptStr, Id
28 import collections.abc
29 import collections
30 import datetime
31 import enum
32 import uuid as uuidp
33
34
35 @enum.unique
36 class ByteOrder(enum.Enum):
37 LITTLE_ENDIAN = 'le'
38 BIG_ENDIAN = 'be'
39
40
41 class _FieldType:
42 @property
43 def alignment(self) -> Alignment:
44 raise NotImplementedError
45
46 @property
47 def size_is_dynamic(self):
48 return False
49
50
51 class _BitArrayFieldType(_FieldType):
52 def __init__(self, size: Count, alignment: Alignment = Alignment(1)):
53 self._size = size
54 self._alignment = alignment
55
56 @property
57 def size(self) -> Count:
58 return self._size
59
60 @property
61 def alignment(self) -> Alignment:
62 return self._alignment
63
64
65 class DisplayBase(enum.Enum):
66 BINARY = 2
67 OCTAL = 8
68 DECIMAL = 10
69 HEXADECIMAL = 16
70
71
72 class _IntegerFieldType(_BitArrayFieldType):
73 def __init__(self, size: Count, alignment: Optional[Alignment] = None,
74 preferred_display_base: DisplayBase = DisplayBase.DECIMAL):
75 if alignment is None:
76 alignment = Alignment(8 if size % 8 == 0 else 1)
77
78 super().__init__(size, alignment)
79 self._preferred_display_base = preferred_display_base
80
81 @property
82 def preferred_display_base(self) -> DisplayBase:
83 return self._preferred_display_base
84
85
86 class UnsignedIntegerFieldType(_IntegerFieldType):
87 def __init__(self, *args, **kwargs):
88 super().__init__(*args, **kwargs)
89 self._mapped_clk_type_name = None
90 self._is_len = False
91
92
93 class SignedIntegerFieldType(_IntegerFieldType):
94 pass
95
96
97 class EnumerationFieldTypeMappingRange:
98 def __init__(self, lower: int, upper: int):
99 self._lower = lower
100 self._upper = upper
101
102 @property
103 def lower(self) -> int:
104 return self._lower
105
106 @property
107 def upper(self) -> int:
108 return self._upper
109
110 def __eq__(self, other: Any) -> bool:
111 if type(other) is not type(self):
112 return False
113
114 return (self._lower, self._upper) == (other._lower, other._upper)
115
116 def __hash__(self) -> int:
117 return hash((self._lower, self._upper))
118
119 def contains(self, value: int) -> bool:
120 return self._lower <= value <= self._upper
121
122
123 class EnumerationFieldTypeMapping:
124 def __init__(self, ranges: Set[EnumerationFieldTypeMappingRange]):
125 self._ranges = frozenset(ranges)
126
127 @property
128 def ranges(self) -> FrozenSet[EnumerationFieldTypeMappingRange]:
129 return self._ranges
130
131 def ranges_contain_value(self, value: int) -> bool:
132 return any([rg.contains(value) for rg in self._ranges])
133
134
135 _EnumFtMappings = Mapping[str, EnumerationFieldTypeMapping]
136
137
138 class EnumerationFieldTypeMappings(collections.abc.Mapping):
139 def __init__(self, mappings: _EnumFtMappings):
140 self._mappings = {label: mapping for label, mapping in mappings.items()}
141
142 def __getitem__(self, key: str) -> EnumerationFieldTypeMapping:
143 return self._mappings[key]
144
145 def __iter__(self) -> Iterator[str]:
146 return iter(self._mappings)
147
148 def __len__(self) -> int:
149 return len(self._mappings)
150
151
152 class _EnumerationFieldType(_IntegerFieldType):
153 def __init__(self, size: Count, alignment: Optional[Alignment] = None,
154 preferred_display_base: DisplayBase = DisplayBase.DECIMAL,
155 mappings: Optional[_EnumFtMappings] = None):
156 super().__init__(size, alignment, preferred_display_base)
157 self._mappings = EnumerationFieldTypeMappings({})
158
159 if mappings is not None:
160 self._mappings = EnumerationFieldTypeMappings(mappings)
161
162 @property
163 def mappings(self) -> EnumerationFieldTypeMappings:
164 return self._mappings
165
166 def labels_for_value(self, value: int) -> Set[str]:
167 labels = set()
168
169 for label, mapping in self._mappings.items():
170 if mapping.ranges_contain_value(value):
171 labels.add(label)
172
173 return labels
174
175
176 class UnsignedEnumerationFieldType(_EnumerationFieldType, UnsignedIntegerFieldType):
177 pass
178
179
180 class SignedEnumerationFieldType(_EnumerationFieldType, SignedIntegerFieldType):
181 pass
182
183
184 class RealFieldType(_BitArrayFieldType):
185 pass
186
187
188 class StringFieldType(_FieldType):
189 @property
190 def alignment(self) -> Alignment:
191 return Alignment(8)
192
193 @property
194 def size_is_dynamic(self):
195 return True
196
197
198 class _ArrayFieldType(_FieldType):
199 def __init__(self, element_field_type: _FieldType):
200 self._element_field_type = element_field_type
201
202 @property
203 def element_field_type(self) -> _FieldType:
204 return self._element_field_type
205
206 @property
207 def alignment(self) -> Alignment:
208 return self._element_field_type.alignment
209
210 @property
211 def size_is_dynamic(self):
212 return self._element_field_type.size_is_dynamic
213
214
215 class StaticArrayFieldType(_ArrayFieldType):
216 def __init__(self, length: Count, element_field_type: _FieldType):
217 super().__init__(element_field_type)
218 self._length = length
219
220 @property
221 def length(self) -> Count:
222 return self._length
223
224
225 class DynamicArrayFieldType(_ArrayFieldType):
226 def __init__(self, length_field_type: UnsignedIntegerFieldType, element_field_type: _FieldType):
227 super().__init__(element_field_type)
228 self._length_field_type = length_field_type
229 self._length_ft_member_name: Optional[str] = None
230
231 @property
232 def length_field_type(self):
233 return self._length_field_type
234
235 @property
236 def size_is_dynamic(self):
237 return True
238
239
240 class StructureFieldTypeMember:
241 def __init__(self, field_type: _FieldType):
242 self._field_type = field_type
243
244 @property
245 def field_type(self) -> _FieldType:
246 return self._field_type
247
248
249 _StructFtMembers = Mapping[str, StructureFieldTypeMember]
250
251
252 class StructureFieldTypeMembers(collections.abc.Mapping):
253 def __init__(self, members: _StructFtMembers):
254 self._members = collections.OrderedDict()
255
256 for name, member in members.items():
257 assert type(member) is StructureFieldTypeMember
258 self._members[name] = member
259
260 def __getitem__(self, key: str) -> StructureFieldTypeMember:
261 return self._members[key]
262
263 def __iter__(self) -> Iterator[str]:
264 return iter(self._members)
265
266 def __len__(self) -> int:
267 return len(self._members)
268
269
270 class StructureFieldType(_FieldType):
271 def __init__(self, minimum_alignment: Alignment = Alignment(1),
272 members: Optional[_StructFtMembers] = None):
273 self._minimum_alignment = minimum_alignment
274 self._members = StructureFieldTypeMembers({})
275
276 if members is not None:
277 self._members = StructureFieldTypeMembers(members)
278
279 self._set_alignment()
280 self._set_dyn_array_ft_length_ft_member_names()
281
282 def _set_alignment(self):
283 self._alignment: Alignment = self._minimum_alignment
284
285 for member in self._members.values():
286 if member.field_type.alignment > self._alignment:
287 self._alignment = member.field_type.alignment
288
289 def _set_dyn_array_ft_length_ft_member_names(self):
290 for member in self._members.values():
291 if type(member.field_type) is DynamicArrayFieldType:
292 # Find length field type member name within the same
293 # structure field type members.
294 for len_name, len_member in self._members.items():
295 if member.field_type.length_field_type is len_member.field_type:
296 member.field_type._length_ft_member_name = len_name
297 len_member.field_type._is_len = True
298 break
299
300 if member.field_type.alignment > self._alignment:
301 self._alignment = member.field_type.alignment
302
303 @property
304 def minimum_alignment(self) -> Alignment:
305 return self._minimum_alignment
306
307 @property
308 def alignment(self) -> Alignment:
309 return self._alignment
310
311 @property
312 def size_is_dynamic(self):
313 return any([member.field_type.size_is_dynamic for member in self.members.values()])
314
315 @property
316 def members(self) -> StructureFieldTypeMembers:
317 return self._members
318
319
320 class _UniqueByName:
321 _name: str
322
323 def __eq__(self, other: Any) -> bool:
324 if type(other) is not type(self):
325 return False
326
327 return self._name == other._name
328
329 def __lt__(self, other: '_UniqueByName'):
330 assert type(self) is type(other)
331 return self._name < other._name
332
333 def __hash__(self) -> int:
334 return hash(self._name)
335
336
337 _OptFt = Optional[_FieldType]
338 _OptStructFt = Optional[StructureFieldType]
339 LogLevel = typing.NewType('LogLevel', int)
340
341
342 class EventRecordType(_UniqueByName):
343 def __init__(self, name: str, log_level: Optional[LogLevel] = None,
344 specific_context_field_type: _OptStructFt = None, payload_field_type: _OptStructFt = None):
345 self._id: Optional[Id] = None
346 self._name = name
347 self._log_level = log_level
348 self._specific_context_field_type = specific_context_field_type
349 self._payload_field_type = payload_field_type
350
351 @property
352 def id(self) -> Optional[Id]:
353 return self._id
354
355 @property
356 def name(self) -> str:
357 return self._name
358
359 @property
360 def log_level(self) -> Optional[LogLevel]:
361 return self._log_level
362
363 @property
364 def specific_context_field_type(self) -> _OptStructFt:
365 return self._specific_context_field_type
366
367 @property
368 def payload_field_type(self) -> _OptStructFt:
369 return self._payload_field_type
370
371
372 class ClockTypeOffset:
373 def __init__(self, seconds: int = 0, cycles: Count = Count(0)):
374 self._seconds = seconds
375 self._cycles = cycles
376
377 @property
378 def seconds(self) -> int:
379 return self._seconds
380
381 @property
382 def cycles(self) -> Count:
383 return self._cycles
384
385
386 _OptUuid = Optional[uuidp.UUID]
387
388
389 class ClockType(_UniqueByName):
390 def __init__(self, name: str, frequency: Count = Count(int(1e9)), uuid: _OptUuid = None,
391 description: _OptStr = None, precision: Count = Count(0),
392 offset: Optional[ClockTypeOffset] = None, origin_is_unix_epoch: bool = False):
393 self._name = name
394 self._frequency = frequency
395 self._uuid = uuid
396 self._description = description
397 self._precision = precision
398 self._offset = ClockTypeOffset()
399
400 if offset is not None:
401 self._offset = offset
402
403 self._origin_is_unix_epoch = origin_is_unix_epoch
404
405 @property
406 def name(self) -> str:
407 return self._name
408
409 @property
410 def frequency(self) -> Count:
411 return self._frequency
412
413 @property
414 def uuid(self) -> _OptUuid:
415 return self._uuid
416
417 @property
418 def description(self) -> _OptStr:
419 return self._description
420
421 @property
422 def precision(self) -> Count:
423 return self._precision
424
425 @property
426 def offset(self) -> ClockTypeOffset:
427 return self._offset
428
429 @property
430 def origin_is_unix_epoch(self) -> bool:
431 return self._origin_is_unix_epoch
432
433
434 DEFAULT_FIELD_TYPE = 'default'
435 _DefaultableUIntFt = Union[str, UnsignedIntegerFieldType]
436 _OptDefaultableUIntFt = Optional[_DefaultableUIntFt]
437 _OptUIntFt = Optional[UnsignedIntegerFieldType]
438
439
440 class DataStreamTypePacketFeatures:
441 def __init__(self, total_size_field_type: _DefaultableUIntFt = DEFAULT_FIELD_TYPE,
442 content_size_field_type: _DefaultableUIntFt = DEFAULT_FIELD_TYPE,
443 beginning_timestamp_field_type: _OptDefaultableUIntFt = None,
444 end_timestamp_field_type: _OptDefaultableUIntFt = None,
445 discarded_event_records_snapshot_counter_field_type: _OptDefaultableUIntFt = DEFAULT_FIELD_TYPE):
446 def get_ft(user_ft: _OptDefaultableUIntFt) -> _OptUIntFt:
447 if user_ft == DEFAULT_FIELD_TYPE:
448 return UnsignedIntegerFieldType(64)
449
450 return typing.cast(_OptUIntFt, user_ft)
451
452 self._total_size_field_type = get_ft(total_size_field_type)
453 self._content_size_field_type = get_ft(content_size_field_type)
454 self._beginning_timestamp_field_type = get_ft(beginning_timestamp_field_type)
455 self._end_timestamp_field_type = get_ft(end_timestamp_field_type)
456 self._discarded_event_records_snapshot_counter_field_type = get_ft(discarded_event_records_snapshot_counter_field_type)
457
458 @property
459 def total_size_field_type(self) -> _OptUIntFt:
460 return self._total_size_field_type
461
462 @property
463 def content_size_field_type(self) -> _OptUIntFt:
464 return self._content_size_field_type
465
466 @property
467 def beginning_timestamp_field_type(self) -> _OptUIntFt:
468 return self._beginning_timestamp_field_type
469
470 @property
471 def end_timestamp_field_type(self) -> _OptUIntFt:
472 return self._end_timestamp_field_type
473
474 @property
475 def discarded_event_records_snapshot_counter_field_type(self) -> _OptUIntFt:
476 return self._discarded_event_records_snapshot_counter_field_type
477
478
479 class DataStreamTypeEventRecordFeatures:
480 def __init__(self, type_id_field_type: _OptDefaultableUIntFt = DEFAULT_FIELD_TYPE,
481 timestamp_field_type: _OptDefaultableUIntFt = None):
482 def get_ft(user_ft: _OptDefaultableUIntFt) -> _OptUIntFt:
483 if user_ft == DEFAULT_FIELD_TYPE:
484 return UnsignedIntegerFieldType(64)
485
486 return typing.cast(_OptUIntFt, user_ft)
487
488 self._type_id_field_type = get_ft(type_id_field_type)
489 self._timestamp_field_type = get_ft(timestamp_field_type)
490
491 @property
492 def type_id_field_type(self) -> _OptUIntFt:
493 return self._type_id_field_type
494
495 @property
496 def timestamp_field_type(self) -> _OptUIntFt:
497 return self._timestamp_field_type
498
499
500 class DataStreamTypeFeatures:
501 def __init__(self, packet_features: Optional[DataStreamTypePacketFeatures] = None,
502 event_record_features: Optional[DataStreamTypeEventRecordFeatures] = None):
503 if packet_features is None:
504 self._packet_features = DataStreamTypePacketFeatures()
505 else:
506 self._packet_features = packet_features
507
508 if event_record_features is None:
509 self._event_record_features = DataStreamTypeEventRecordFeatures()
510 else:
511 self._event_record_features = event_record_features
512
513 @property
514 def packet_features(self) -> DataStreamTypePacketFeatures:
515 return self._packet_features
516
517 @property
518 def event_record_features(self) -> DataStreamTypeEventRecordFeatures:
519 return self._event_record_features
520
521
522 class DataStreamType(_UniqueByName):
523 def __init__(self, name: str, event_record_types: Set[EventRecordType],
524 default_clock_type: Optional[ClockType] = None,
525 features: Optional[DataStreamTypeFeatures] = None,
526 packet_context_field_type_extra_members: Optional[_StructFtMembers] = None,
527 event_record_common_context_field_type: _OptStructFt = None):
528 self._id: Optional[Id] = None
529 self._name = name
530 self._default_clock_type = default_clock_type
531 self._event_record_common_context_field_type = event_record_common_context_field_type
532 self._event_record_types = frozenset(event_record_types)
533
534 # assign unique IDs
535 for index, ert in enumerate(sorted(self._event_record_types, key=lambda evt: evt.name)):
536 assert ert._id is None
537 ert._id = Id(index)
538
539 self._set_features(features)
540 self._packet_context_field_type_extra_members = StructureFieldTypeMembers({})
541
542 if packet_context_field_type_extra_members is not None:
543 self._packet_context_field_type_extra_members = StructureFieldTypeMembers(packet_context_field_type_extra_members)
544
545 self._set_pkt_ctx_ft()
546 self._set_er_header_ft()
547
548 def _set_features(self, features: Optional[DataStreamTypeFeatures]):
549 if features is not None:
550 self._features = features
551 return None
552
553 er_ts_ft = None
554 pkt_beginning_ts_ft = None
555 pkt_end_ts_ft = None
556
557 if self._default_clock_type is not None:
558 # Automatic timestamp field types because the data stream
559 # type has a default clock type.
560 er_ts_ft = DEFAULT_FIELD_TYPE
561 pkt_beginning_ts_ft = DEFAULT_FIELD_TYPE
562 pkt_end_ts_ft = DEFAULT_FIELD_TYPE
563
564 self._features = DataStreamTypeFeatures(DataStreamTypePacketFeatures(beginning_timestamp_field_type=pkt_beginning_ts_ft,
565 end_timestamp_field_type=pkt_end_ts_ft),
566 DataStreamTypeEventRecordFeatures(timestamp_field_type=er_ts_ft))
567
568 def _set_ft_mapped_clk_type_name(self, ft: Optional[UnsignedIntegerFieldType]):
569 if ft is None:
570 return
571
572 if self._default_clock_type is not None:
573 assert isinstance(ft, UnsignedIntegerFieldType)
574 ft._mapped_clk_type_name = self._default_clock_type.name
575
576 def _set_pkt_ctx_ft(self):
577 members = None
578
579 def add_member_if_exists(name: str, ft: _FieldType, set_mapped_clk_type_name: bool = False):
580 nonlocal members
581
582 if ft is not None:
583 if set_mapped_clk_type_name:
584 self._set_ft_mapped_clk_type_name(typing.cast(UnsignedIntegerFieldType, ft))
585
586 members[name] = StructureFieldTypeMember(ft)
587
588 members = collections.OrderedDict([
589 (
590 'packet_size',
591 StructureFieldTypeMember(self._features.packet_features.total_size_field_type)
592 ),
593 (
594 'content_size',
595 StructureFieldTypeMember(self._features.packet_features.content_size_field_type)
596 )
597 ])
598
599 add_member_if_exists('timestamp_begin',
600 self._features.packet_features.beginning_timestamp_field_type, True)
601 add_member_if_exists('timestamp_end', self._features.packet_features.end_timestamp_field_type,
602 True)
603 add_member_if_exists('events_discarded',
604 self._features.packet_features.discarded_event_records_snapshot_counter_field_type)
605
606 if self._packet_context_field_type_extra_members is not None:
607 for name, field_type in self._packet_context_field_type_extra_members.items():
608 assert name not in members
609 members[name] = field_type
610
611 self._pkt_ctx_ft = StructureFieldType(8, members)
612
613 def _set_er_header_ft(self):
614 members = collections.OrderedDict()
615
616 if self._features.event_record_features.type_id_field_type is not None:
617 members['id'] = StructureFieldTypeMember(self._features.event_record_features.type_id_field_type)
618
619 if self._features.event_record_features.timestamp_field_type is not None:
620 ft = self._features.event_record_features.timestamp_field_type
621 self._set_ft_mapped_clk_type_name(ft)
622 members['timestamp'] = StructureFieldTypeMember(ft)
623
624 self._er_header_ft = StructureFieldType(8, members)
625
626 @property
627 def id(self) -> Optional[Id]:
628 return self._id
629
630 @property
631 def name(self) -> str:
632 return self._name
633
634 @property
635 def default_clock_type(self) -> Optional[ClockType]:
636 return self._default_clock_type
637
638 @property
639 def features(self) -> DataStreamTypeFeatures:
640 return self._features
641
642 @property
643 def packet_context_field_type_extra_members(self) -> StructureFieldTypeMembers:
644 return self._packet_context_field_type_extra_members
645
646 @property
647 def event_record_common_context_field_type(self) -> _OptStructFt:
648 return self._event_record_common_context_field_type
649
650 @property
651 def event_record_types(self) -> FrozenSet[EventRecordType]:
652 return self._event_record_types
653
654
655 _OptUuidFt = Optional[Union[str, StaticArrayFieldType]]
656
657
658 class TraceTypeFeatures:
659 def __init__(self, magic_field_type: _OptDefaultableUIntFt = DEFAULT_FIELD_TYPE,
660 uuid_field_type: _OptUuidFt = None,
661 data_stream_type_id_field_type: _OptDefaultableUIntFt = DEFAULT_FIELD_TYPE):
662 def get_field_type(user_ft: Optional[Union[str, _FieldType]],
663 create_default_ft: Callable[[], _FieldType]) -> _OptFt:
664 if user_ft == DEFAULT_FIELD_TYPE:
665 return create_default_ft()
666
667 return typing.cast(_OptFt, user_ft)
668
669 def create_default_magic_ft():
670 return UnsignedIntegerFieldType(32)
671
672 def create_default_uuid_ft():
673 return StaticArrayFieldType(Count(16), UnsignedIntegerFieldType(8))
674
675 def create_default_dst_id_ft():
676 return UnsignedIntegerFieldType(64)
677
678 self._magic_field_type = typing.cast(_OptUIntFt, get_field_type(magic_field_type, create_default_magic_ft))
679 self._uuid_field_type = typing.cast(Optional[StaticArrayFieldType],
680 get_field_type(uuid_field_type, create_default_uuid_ft))
681 self._data_stream_type_id_field_type = typing.cast(_OptUIntFt,
682 get_field_type(data_stream_type_id_field_type,
683 create_default_dst_id_ft))
684
685 @property
686 def magic_field_type(self) -> _OptUIntFt:
687 return self._magic_field_type
688
689 @property
690 def uuid_field_type(self) -> Optional[StaticArrayFieldType]:
691 return self._uuid_field_type
692
693 @property
694 def data_stream_type_id_field_type(self) -> _OptUIntFt:
695 return self._data_stream_type_id_field_type
696
697
698 class TraceType:
699 def __init__(self, native_byte_order: ByteOrder, data_stream_types: Set[DataStreamType],
700 uuid: _OptUuid = None, features: Optional[TraceTypeFeatures] = None):
701 self._native_byte_order = native_byte_order
702 self._data_stream_types = frozenset(data_stream_types)
703
704 # assign unique IDs
705 for index, dst in enumerate(sorted(self._data_stream_types, key=lambda st: st.name)):
706 assert dst._id is None
707 dst._id = Id(index)
708
709 self._uuid = uuid
710 self._set_features(features)
711 self._set_pkt_header_ft()
712
713 def _set_features(self, features: Optional[TraceTypeFeatures]):
714 if features is not None:
715 self._features = features
716 return
717
718 # automatic UUID field type because the trace type has a UUID
719 uuid_ft = None if self._uuid is None else DEFAULT_FIELD_TYPE
720 self._features = TraceTypeFeatures(uuid_field_type=uuid_ft)
721
722 def _set_pkt_header_ft(self):
723 members = collections.OrderedDict()
724
725 def add_member_if_exists(name: str, ft: _OptFt):
726 nonlocal members
727
728 if ft is not None:
729 members[name] = StructureFieldTypeMember(ft)
730
731 add_member_if_exists('magic', self._features.magic_field_type)
732 add_member_if_exists('uuid', self._features.uuid_field_type)
733 add_member_if_exists('stream_id', self._features.data_stream_type_id_field_type)
734 self._pkt_header_ft = StructureFieldType(8, members)
735
736 @property
737 def native_byte_order(self) -> ByteOrder:
738 return self._native_byte_order
739
740 @property
741 def uuid(self) -> _OptUuid:
742 return self._uuid
743
744 @property
745 def data_stream_types(self) -> FrozenSet[DataStreamType]:
746 return self._data_stream_types
747
748 def data_stream_type(self, name: str) -> Optional[DataStreamType]:
749 for cand_dst in self._data_stream_types:
750 if cand_dst.name == name:
751 return cand_dst
752
753 return None
754
755 @property
756 def features(self) -> TraceTypeFeatures:
757 return self._features
758
759 @property
760 def clock_types(self) -> Set[ClockType]:
761 clk_types = set()
762
763 for dst in self._data_stream_types:
764 if dst.default_clock_type is not None:
765 clk_types.add(dst.default_clock_type)
766
767 return clk_types
768
769
770 _EnvEntry = Union[str, int]
771 _EnvEntries = Mapping[str, _EnvEntry]
772
773
774 class TraceEnvironment(collections.abc.Mapping):
775 def __init__(self, environment: _EnvEntries):
776 self._env = {name: value for name, value in environment.items()}
777
778 def __getitem__(self, key: str) -> _EnvEntry:
779 return self._env[key]
780
781 def __iter__(self) -> Iterator[str]:
782 return iter(self._env)
783
784 def __len__(self) -> int:
785 return len(self._env)
786
787
788 class Trace:
789 def __init__(self, type: TraceType, environment: Optional[_EnvEntries] = None):
790 self._type = type
791 self._set_env(environment)
792
793 def _set_env(self, environment: Optional[_EnvEntries]):
794 init_env = collections.OrderedDict([
795 ('domain', 'bare'),
796 ('tracer_name', 'barectf'),
797 ('tracer_major', barectf_version.__major_version__),
798 ('tracer_minor', barectf_version.__minor_version__),
799 ('tracer_patch', barectf_version.__patch_version__),
800 ('barectf_gen_date', str(datetime.datetime.now().isoformat())),
801 ])
802
803 if environment is None:
804 environment = {}
805
806 init_env.update(environment)
807 self._env = TraceEnvironment(typing.cast(_EnvEntries, init_env))
808
809 @property
810 def type(self) -> TraceType:
811 return self._type
812
813 @property
814 def environment(self) -> TraceEnvironment:
815 return self._env
816
817
818 _ClkTypeCTypes = Mapping[ClockType, str]
819
820
821 class ClockTypeCTypes(collections.abc.Mapping):
822 def __init__(self, c_types: _ClkTypeCTypes):
823 self._c_types = {clk_type: c_type for clk_type, c_type in c_types.items()}
824
825 def __getitem__(self, key: ClockType) -> str:
826 return self._c_types[key]
827
828 def __iter__(self) -> Iterator[ClockType]:
829 return iter(self._c_types)
830
831 def __len__(self) -> int:
832 return len(self._c_types)
833
834
835 class ConfigurationCodeGenerationHeaderOptions:
836 def __init__(self, identifier_prefix_definition: bool = False,
837 default_data_stream_type_name_definition: bool = False):
838 self._identifier_prefix_definition = identifier_prefix_definition
839 self._default_data_stream_type_name_definition = default_data_stream_type_name_definition
840
841 @property
842 def identifier_prefix_definition(self) -> bool:
843 return self._identifier_prefix_definition
844
845 @property
846 def default_data_stream_type_name_definition(self) -> bool:
847 return self._default_data_stream_type_name_definition
848
849
850 class ConfigurationCodeGenerationOptions:
851 def __init__(self, identifier_prefix: str = 'barectf_', file_name_prefix: str = 'barectf',
852 default_data_stream_type: Optional[DataStreamType] = None,
853 header_options: Optional[ConfigurationCodeGenerationHeaderOptions] = None,
854 clock_type_c_types: Optional[_ClkTypeCTypes] = None):
855 self._identifier_prefix = identifier_prefix
856 self._file_name_prefix = file_name_prefix
857 self._default_data_stream_type = default_data_stream_type
858
859 self._header_options = ConfigurationCodeGenerationHeaderOptions()
860
861 if header_options is not None:
862 self._header_options = header_options
863
864 self._clock_type_c_types = ClockTypeCTypes({})
865
866 if clock_type_c_types is not None:
867 self._clock_type_c_types = ClockTypeCTypes(clock_type_c_types)
868
869 @property
870 def identifier_prefix(self) -> str:
871 return self._identifier_prefix
872
873 @property
874 def file_name_prefix(self) -> str:
875 return self._file_name_prefix
876
877 @property
878 def default_data_stream_type(self) -> Optional[DataStreamType]:
879 return self._default_data_stream_type
880
881 @property
882 def header_options(self) -> ConfigurationCodeGenerationHeaderOptions:
883 return self._header_options
884
885 @property
886 def clock_type_c_types(self) -> ClockTypeCTypes:
887 return self._clock_type_c_types
888
889
890 class ConfigurationOptions:
891 def __init__(self,
892 code_generation_options: Optional[ConfigurationCodeGenerationOptions] = None):
893 self._code_generation_options = ConfigurationCodeGenerationOptions()
894
895 if code_generation_options is not None:
896 self._code_generation_options = code_generation_options
897
898 @property
899 def code_generation_options(self) -> ConfigurationCodeGenerationOptions:
900 return self._code_generation_options
901
902
903 class Configuration:
904 def __init__(self, trace: Trace, options: Optional[ConfigurationOptions] = None):
905 self._trace = trace
906 self._options = ConfigurationOptions()
907
908 if options is not None:
909 self._options = options
910
911 clk_type_c_types = self._options.code_generation_options.clock_type_c_types
912
913 for dst in trace.type.data_stream_types:
914 def_clk_type = dst.default_clock_type
915
916 if def_clk_type is None:
917 continue
918
919 if def_clk_type not in clk_type_c_types:
920 clk_type_c_types._c_types[def_clk_type] = 'uint32_t'
921
922 @property
923 def trace(self) -> Trace:
924 return self._trace
925
926 @property
927 def options(self) -> ConfigurationOptions:
928 return self._options
This page took 0.050313 seconds and 3 git commands to generate.