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