`_FieldType`: add `size_is_dynamic` property
[deliverable/barectf.git] / barectf / config.py
CommitLineData
e5aa0be3
PP
1# The MIT License (MIT)
2#
4a90140d 3# Copyright (c) 2015-2020 Philippe Proulx <pproulx@efficios.com>
e5aa0be3 4#
1378f213
PP
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:
e5aa0be3 12#
1378f213
PP
13# The above copyright notice and this permission notice shall be
14# included in all copies or substantial portions of the Software.
e5aa0be3 15#
1378f213
PP
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.
e5aa0be3 23
4810b707 24import barectf.version as barectf_version
2d55dc7d
PP
25from typing import Optional, Any, FrozenSet, Mapping, Iterator, Set, Union
26import typing
27from barectf.typing import Count, Alignment, _OptStr, Id
4810b707
PP
28import collections.abc
29import collections
30import datetime
31import enum
2d55dc7d 32import uuid as uuidp
e5aa0be3
PP
33
34
4810b707
PP
35@enum.unique
36class ByteOrder(enum.Enum):
37 LITTLE_ENDIAN = 'le'
38 BIG_ENDIAN = 'be'
e5aa0be3
PP
39
40
4810b707
PP
41class _FieldType:
42 @property
2d55dc7d 43 def alignment(self) -> Alignment:
4810b707 44 raise NotImplementedError
a1a610d4 45
1960170e
PP
46 @property
47 def size_is_dynamic(self):
48 return False
49
e5aa0be3 50
4810b707 51class _BitArrayFieldType(_FieldType):
2d55dc7d
PP
52 def __init__(self, size: Count, byte_order: Optional[ByteOrder] = None,
53 alignment: Alignment = Alignment(1)):
4810b707
PP
54 self._size = size
55 self._byte_order = byte_order
56 self._alignment = alignment
e5aa0be3
PP
57
58 @property
2d55dc7d 59 def size(self) -> Count:
4810b707 60 return self._size
e5aa0be3 61
e5aa0be3 62 @property
2d55dc7d 63 def byte_order(self) -> Optional[ByteOrder]:
4810b707 64 return self._byte_order
e5aa0be3 65
893854db 66 @property
2d55dc7d 67 def alignment(self) -> Alignment:
4810b707
PP
68 return self._alignment
69
70
71class DisplayBase(enum.Enum):
72 BINARY = 2
73 OCTAL = 8
74 DECIMAL = 10
75 HEXADECIMAL = 16
76
77
78class _IntegerFieldType(_BitArrayFieldType):
2d55dc7d
PP
79 def __init__(self, size: Count, byte_order: Optional[ByteOrder] = None,
80 alignment: Optional[Alignment] = None,
81 preferred_display_base: DisplayBase = DisplayBase.DECIMAL):
5833e4da
PP
82 if alignment is None:
83 alignment = Alignment(8 if size % 8 == 0 else 1)
4810b707 84
5833e4da 85 super().__init__(size, byte_order, alignment)
4810b707
PP
86 self._preferred_display_base = preferred_display_base
87
88 @property
2d55dc7d 89 def preferred_display_base(self) -> DisplayBase:
4810b707
PP
90 return self._preferred_display_base
91
92
93class UnsignedIntegerFieldType(_IntegerFieldType):
94 def __init__(self, *args):
95 super().__init__(*args)
96 self._mapped_clk_type_name = None
97
98
99class SignedIntegerFieldType(_IntegerFieldType):
100 pass
101
102
103class EnumerationFieldTypeMappingRange:
2d55dc7d 104 def __init__(self, lower: int, upper: int):
4810b707
PP
105 self._lower = lower
106 self._upper = upper
107
108 @property
2d55dc7d 109 def lower(self) -> int:
4810b707
PP
110 return self._lower
111
112 @property
2d55dc7d 113 def upper(self) -> int:
4810b707
PP
114 return self._upper
115
2d55dc7d 116 def __eq__(self, other: Any) -> bool:
4810b707
PP
117 if type(other) is not type(self):
118 return False
119
120 return (self._lower, self._upper) == (other._lower, other._upper)
121
2d55dc7d 122 def __hash__(self) -> int:
4810b707
PP
123 return hash((self._lower, self._upper))
124
2d55dc7d 125 def contains(self, value: int) -> bool:
4810b707
PP
126 return self._lower <= value <= self._upper
127
128
129class EnumerationFieldTypeMapping:
2d55dc7d 130 def __init__(self, ranges: Set[EnumerationFieldTypeMappingRange]):
4810b707
PP
131 self._ranges = frozenset(ranges)
132
133 @property
2d55dc7d 134 def ranges(self) -> FrozenSet[EnumerationFieldTypeMappingRange]:
4810b707
PP
135 return self._ranges
136
2d55dc7d 137 def ranges_contain_value(self, value: int) -> bool:
4810b707
PP
138 return any([rg.contains(value) for rg in self._ranges])
139
140
2d55dc7d
PP
141_EnumFtMappings = Mapping[str, EnumerationFieldTypeMapping]
142
143
4810b707 144class EnumerationFieldTypeMappings(collections.abc.Mapping):
2d55dc7d 145 def __init__(self, mappings: _EnumFtMappings):
4810b707
PP
146 self._mappings = {label: mapping for label, mapping in mappings.items()}
147
2d55dc7d 148 def __getitem__(self, key: str) -> EnumerationFieldTypeMapping:
4810b707
PP
149 return self._mappings[key]
150
2d55dc7d 151 def __iter__(self) -> Iterator[str]:
4810b707
PP
152 return iter(self._mappings)
153
2d55dc7d 154 def __len__(self) -> int:
4810b707 155 return len(self._mappings)
893854db 156
893854db 157
4810b707 158class _EnumerationFieldType(_IntegerFieldType):
2d55dc7d
PP
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):
4810b707
PP
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
2d55dc7d 170 def mappings(self) -> EnumerationFieldTypeMappings:
4810b707
PP
171 return self._mappings
172
2d55dc7d 173 def labels_for_value(self, value: int) -> Set[str]:
4810b707
PP
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
183class UnsignedEnumerationFieldType(_EnumerationFieldType, UnsignedIntegerFieldType):
184 pass
185
186
187class SignedEnumerationFieldType(_EnumerationFieldType, SignedIntegerFieldType):
188 pass
189
190
191class RealFieldType(_BitArrayFieldType):
192 pass
193
194
195class StringFieldType(_FieldType):
196 @property
2d55dc7d
PP
197 def alignment(self) -> Alignment:
198 return Alignment(8)
4810b707 199
1960170e
PP
200 @property
201 def size_is_dynamic(self):
202 return True
203
4810b707
PP
204
205class _ArrayFieldType(_FieldType):
2d55dc7d 206 def __init__(self, element_field_type: _FieldType):
4810b707
PP
207 self._element_field_type = element_field_type
208
209 @property
2d55dc7d 210 def element_field_type(self) -> _FieldType:
4810b707 211 return self._element_field_type
893854db
PP
212
213 @property
2d55dc7d 214 def alignment(self) -> Alignment:
4810b707
PP
215 return self._element_field_type.alignment
216
217
218class StaticArrayFieldType(_ArrayFieldType):
2d55dc7d 219 def __init__(self, length: Count, element_field_type: _FieldType):
4810b707
PP
220 super().__init__(element_field_type)
221 self._length = length
893854db 222
893854db 223 @property
2d55dc7d 224 def length(self) -> Count:
4810b707
PP
225 return self._length
226
227
228class StructureFieldTypeMember:
2d55dc7d 229 def __init__(self, field_type: _FieldType):
4810b707
PP
230 self._field_type = field_type
231
232 @property
2d55dc7d 233 def field_type(self) -> _FieldType:
4810b707
PP
234 return self._field_type
235
236
2d55dc7d
PP
237_StructFtMembers = Mapping[str, StructureFieldTypeMember]
238
239
4810b707 240class StructureFieldTypeMembers(collections.abc.Mapping):
2d55dc7d 241 def __init__(self, members: _StructFtMembers):
4810b707
PP
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
2d55dc7d 248 def __getitem__(self, key: str) -> StructureFieldTypeMember:
4810b707
PP
249 return self._members[key]
250
2d55dc7d 251 def __iter__(self) -> Iterator[str]:
4810b707
PP
252 return iter(self._members)
253
2d55dc7d 254 def __len__(self) -> int:
4810b707
PP
255 return len(self._members)
256
257
258class StructureFieldType(_FieldType):
2d55dc7d
PP
259 def __init__(self, minimum_alignment: Alignment = Alignment(1),
260 members: Optional[_StructFtMembers] = None):
4810b707
PP
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):
2d55dc7d 270 self._alignment: Alignment = self._minimum_alignment
4810b707
PP
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
2d55dc7d 277 def minimum_alignment(self) -> Alignment:
4810b707
PP
278 return self._minimum_alignment
279
280 @property
2d55dc7d 281 def alignment(self) -> Alignment:
4810b707
PP
282 return self._alignment
283
1960170e
PP
284 @property
285 def size_is_dynamic(self):
286 return any([member.field_type.size_is_dynamic for member in self.members.values()])
287
4810b707 288 @property
2d55dc7d 289 def members(self) -> StructureFieldTypeMembers:
4810b707
PP
290 return self._members
291
292
293class _UniqueByName:
2d55dc7d
PP
294 _name: str
295
296 def __eq__(self, other: Any) -> bool:
4810b707
PP
297 if type(other) is not type(self):
298 return False
299
300 return self._name == other._name
301
2d55dc7d 302 def __lt__(self, other: '_UniqueByName'):
4810b707
PP
303 assert type(self) is type(other)
304 return self._name < other._name
305
2d55dc7d 306 def __hash__(self) -> int:
4810b707
PP
307 return hash(self._name)
308
309
2d55dc7d
PP
310_OptFt = Optional[_FieldType]
311_OptStructFt = Optional[StructureFieldType]
312LogLevel = typing.NewType('LogLevel', int)
313
314
4810b707 315class EventType(_UniqueByName):
2d55dc7d
PP
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
4810b707
PP
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
2d55dc7d 325 def id(self) -> Optional[Id]:
4810b707
PP
326 return self._id
327
328 @property
2d55dc7d 329 def name(self) -> str:
4810b707
PP
330 return self._name
331
332 @property
2d55dc7d 333 def log_level(self) -> Optional[LogLevel]:
4810b707
PP
334 return self._log_level
335
336 @property
2d55dc7d 337 def specific_context_field_type(self) -> _OptStructFt:
4810b707
PP
338 return self._specific_context_field_type
339
340 @property
2d55dc7d 341 def payload_field_type(self) -> _OptStructFt:
4810b707
PP
342 return self._payload_field_type
343
344
345class ClockTypeOffset:
2d55dc7d 346 def __init__(self, seconds: int = 0, cycles: Count = Count(0)):
4810b707
PP
347 self._seconds = seconds
348 self._cycles = cycles
349
350 @property
2d55dc7d 351 def seconds(self) -> int:
4810b707
PP
352 return self._seconds
353
354 @property
2d55dc7d 355 def cycles(self) -> Count:
4810b707
PP
356 return self._cycles
357
358
2d55dc7d
PP
359_OptUuid = Optional[uuidp.UUID]
360
361
4810b707 362class ClockType(_UniqueByName):
2d55dc7d
PP
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):
4810b707
PP
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
2d55dc7d 379 def name(self) -> str:
4810b707
PP
380 return self._name
381
382 @property
2d55dc7d 383 def frequency(self) -> Count:
4810b707
PP
384 return self._frequency
385
386 @property
2d55dc7d 387 def uuid(self) -> _OptUuid:
4810b707
PP
388 return self._uuid
389
390 @property
2d55dc7d 391 def description(self) -> _OptStr:
4810b707
PP
392 return self._description
393
394 @property
2d55dc7d 395 def precision(self) -> Count:
4810b707
PP
396 return self._precision
397
398 @property
2d55dc7d 399 def offset(self) -> ClockTypeOffset:
4810b707
PP
400 return self._offset
401
402 @property
2d55dc7d 403 def origin_is_unix_epoch(self) -> bool:
4810b707
PP
404 return self._origin_is_unix_epoch
405
406
407DEFAULT_FIELD_TYPE = 'default'
2d55dc7d
PP
408_DefaultableUIntFt = Union[str, UnsignedIntegerFieldType]
409_OptDefaultableUIntFt = Optional[_DefaultableUIntFt]
410_OptUIntFt = Optional[UnsignedIntegerFieldType]
4810b707
PP
411
412
413class StreamTypePacketFeatures:
2d55dc7d
PP
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:
4810b707
PP
420 if user_ft == DEFAULT_FIELD_TYPE:
421 return UnsignedIntegerFieldType(64)
422
2d55dc7d 423 return typing.cast(_OptUIntFt, user_ft)
4810b707
PP
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
2d55dc7d 432 def total_size_field_type(self) -> _OptUIntFt:
4810b707
PP
433 return self._total_size_field_type
434
435 @property
2d55dc7d 436 def content_size_field_type(self) -> _OptUIntFt:
4810b707
PP
437 return self._content_size_field_type
438
439 @property
2d55dc7d 440 def beginning_time_field_type(self) -> _OptUIntFt:
4810b707
PP
441 return self._beginning_time_field_type
442
443 @property
2d55dc7d 444 def end_time_field_type(self) -> _OptUIntFt:
4810b707
PP
445 return self._end_time_field_type
446
447 @property
2d55dc7d 448 def discarded_events_counter_field_type(self) -> _OptUIntFt:
4810b707
PP
449 return self._discarded_events_counter_field_type
450
451
452class StreamTypeEventFeatures:
2d55dc7d
PP
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:
4810b707
PP
457 return UnsignedIntegerFieldType(64)
458
2d55dc7d 459 return typing.cast(_OptUIntFt, user_ft)
4810b707
PP
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
2d55dc7d 465 def type_id_field_type(self) -> _OptUIntFt:
4810b707
PP
466 return self._type_id_field_type
467
468 @property
2d55dc7d 469 def time_field_type(self) -> _OptUIntFt:
4810b707
PP
470 return self._time_field_type
471
472
473class StreamTypeFeatures:
2d55dc7d
PP
474 def __init__(self, packet_features: Optional[StreamTypePacketFeatures] = None,
475 event_features: Optional[StreamTypeEventFeatures] = None):
4810b707
PP
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
2d55dc7d 487 def packet_features(self) -> StreamTypePacketFeatures:
4810b707
PP
488 return self._packet_features
489
490 @property
2d55dc7d 491 def event_features(self) -> StreamTypeEventFeatures:
4810b707
PP
492 return self._event_features
493
494
495class StreamType(_UniqueByName):
2d55dc7d
PP
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
4810b707
PP
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
2d55dc7d 510 ev_type._id = Id(index)
4810b707
PP
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
2d55dc7d 521 def _set_features(self, features: Optional[StreamTypeFeatures]):
4810b707
PP
522 if features is not None:
523 self._features = features
2d55dc7d 524 return None
4810b707
PP
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
2d55dc7d 541 def _set_ft_mapped_clk_type_name(self, ft: Optional[UnsignedIntegerFieldType]):
4810b707
PP
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):
2d55dc7d
PP
550 members = None
551
552 def add_member_if_exists(name: str, ft: _FieldType, set_mapped_clk_type_name: bool = False):
4810b707
PP
553 nonlocal members
554
555 if ft is not None:
556 if set_mapped_clk_type_name:
2d55dc7d 557 self._set_ft_mapped_clk_type_name(typing.cast(UnsignedIntegerFieldType, ft))
4810b707
PP
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
2d55dc7d 600 def id(self) -> Optional[Id]:
4810b707
PP
601 return self._id
602
603 @property
2d55dc7d 604 def name(self) -> str:
4810b707
PP
605 return self._name
606
607 @property
2d55dc7d 608 def default_clock_type(self) -> Optional[ClockType]:
4810b707
PP
609 return self._default_clock_type
610
611 @property
2d55dc7d 612 def features(self) -> StreamTypeFeatures:
4810b707
PP
613 return self._features
614
615 @property
2d55dc7d 616 def packet_context_field_type_extra_members(self) -> StructureFieldTypeMembers:
4810b707
PP
617 return self._packet_context_field_type_extra_members
618
619 @property
2d55dc7d 620 def event_common_context_field_type(self) -> _OptStructFt:
4810b707
PP
621 return self._event_common_context_field_type
622
623 @property
2d55dc7d 624 def event_types(self) -> FrozenSet[EventType]:
4810b707
PP
625 return self._event_types
626
627
2d55dc7d
PP
628_OptUuidFt = Optional[Union[str, StaticArrayFieldType]]
629
630
4810b707 631class TraceTypeFeatures:
2d55dc7d
PP
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
4810b707 638
2d55dc7d 639 return typing.cast(_OptFt, user_ft)
4810b707 640
2d55dc7d
PP
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)))
4810b707
PP
648
649 @property
2d55dc7d 650 def magic_field_type(self) -> _OptUIntFt:
4810b707
PP
651 return self._magic_field_type
652
653 @property
2d55dc7d 654 def uuid_field_type(self) -> Optional[StaticArrayFieldType]:
4810b707
PP
655 return self._uuid_field_type
656
657 @property
2d55dc7d 658 def stream_type_id_field_type(self) -> _OptUIntFt:
4810b707
PP
659 return self._stream_type_id_field_type
660
661
662class TraceType:
2d55dc7d
PP
663 def __init__(self, stream_types: Set[StreamType], default_byte_order: ByteOrder,
664 uuid: _OptUuid = None, features: Optional[TraceTypeFeatures] = None):
4810b707
PP
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
2d55dc7d 671 stream_type._id = Id(index)
4810b707
PP
672
673 self._uuid = uuid
674 self._set_features(features)
675 self._set_pkt_header_ft()
676 self._set_fts_effective_byte_order()
677
2d55dc7d 678 def _set_features(self, features: Optional[TraceTypeFeatures]):
4810b707
PP
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):
2d55dc7d
PP
688 members = collections.OrderedDict()
689
690 def add_member_if_exists(name: str, ft: _OptFt):
4810b707
PP
691 nonlocal members
692
2d55dc7d
PP
693 if ft is not None:
694 members[name] = StructureFieldTypeMember(ft)
4810b707 695
4810b707
PP
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):
2d55dc7d 702 def set_ft_effective_byte_order(ft: _OptFt):
4810b707
PP
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
2d55dc7d 731 def default_byte_order(self) -> ByteOrder:
4810b707
PP
732 return self._default_byte_order
733
734 @property
2d55dc7d 735 def uuid(self) -> _OptUuid:
4810b707
PP
736 return self._uuid
737
738 @property
2d55dc7d 739 def stream_types(self) -> FrozenSet[StreamType]:
4810b707
PP
740 return self._stream_types
741
2d55dc7d 742 def stream_type(self, name: str) -> Optional[StreamType]:
4810b707
PP
743 for cand_stream_type in self._stream_types:
744 if cand_stream_type.name == name:
745 return cand_stream_type
746
2d55dc7d
PP
747 return None
748
4810b707 749 @property
2d55dc7d 750 def features(self) -> TraceTypeFeatures:
4810b707
PP
751 return self._features
752
de49021e
PP
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
4810b707 763
2d55dc7d
PP
764_EnvEntry = Union[str, int]
765_EnvEntries = Mapping[str, _EnvEntry]
766
767
4810b707 768class TraceEnvironment(collections.abc.Mapping):
2d55dc7d 769 def __init__(self, environment: _EnvEntries):
4810b707
PP
770 self._env = {name: value for name, value in environment.items()}
771
2d55dc7d 772 def __getitem__(self, key: str) -> _EnvEntry:
4810b707
PP
773 return self._env[key]
774
2d55dc7d 775 def __iter__(self) -> Iterator[str]:
4810b707
PP
776 return iter(self._env)
777
2d55dc7d 778 def __len__(self) -> int:
4810b707
PP
779 return len(self._env)
780
781
782class Trace:
2d55dc7d 783 def __init__(self, type: TraceType, environment: Optional[_EnvEntries] = None):
4810b707
PP
784 self._type = type
785 self._set_env(environment)
786
2d55dc7d 787 def _set_env(self, environment: Optional[_EnvEntries]):
4810b707
PP
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)
2d55dc7d 801 self._env = TraceEnvironment(typing.cast(_EnvEntries, init_env))
4810b707
PP
802
803 @property
2d55dc7d 804 def type(self) -> TraceType:
4810b707
PP
805 return self._type
806
807 @property
2d55dc7d 808 def environment(self) -> TraceEnvironment:
4810b707
PP
809 return self._env
810
811
2d55dc7d
PP
812_ClkTypeCTypes = Mapping[ClockType, str]
813
814
4810b707 815class ClockTypeCTypes(collections.abc.Mapping):
2d55dc7d 816 def __init__(self, c_types: _ClkTypeCTypes):
4810b707
PP
817 self._c_types = {clk_type: c_type for clk_type, c_type in c_types.items()}
818
2d55dc7d 819 def __getitem__(self, key: ClockType) -> str:
4810b707
PP
820 return self._c_types[key]
821
2d55dc7d 822 def __iter__(self) -> Iterator[ClockType]:
4810b707
PP
823 return iter(self._c_types)
824
2d55dc7d 825 def __len__(self) -> int:
4810b707
PP
826 return len(self._c_types)
827
828
829class ConfigurationCodeGenerationHeaderOptions:
2d55dc7d
PP
830 def __init__(self, identifier_prefix_definition: bool = False,
831 default_stream_type_name_definition: bool = False):
4810b707
PP
832 self._identifier_prefix_definition = identifier_prefix_definition
833 self._default_stream_type_name_definition = default_stream_type_name_definition
834
835 @property
2d55dc7d 836 def identifier_prefix_definition(self) -> bool:
4810b707
PP
837 return self._identifier_prefix_definition
838
839 @property
2d55dc7d 840 def default_stream_type_name_definition(self) -> bool:
4810b707
PP
841 return self._default_stream_type_name_definition
842
843
844class ConfigurationCodeGenerationOptions:
2d55dc7d
PP
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):
4810b707
PP
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
2d55dc7d 864 def identifier_prefix(self) -> str:
4810b707
PP
865 return self._identifier_prefix
866
867 @property
2d55dc7d 868 def file_name_prefix(self) -> str:
4810b707
PP
869 return self._file_name_prefix
870
871 @property
2d55dc7d 872 def default_stream_type(self) -> Optional[StreamType]:
4810b707
PP
873 return self._default_stream_type
874
875 @property
2d55dc7d 876 def header_options(self) -> ConfigurationCodeGenerationHeaderOptions:
4810b707
PP
877 return self._header_options
878
879 @property
2d55dc7d 880 def clock_type_c_types(self) -> ClockTypeCTypes:
4810b707
PP
881 return self._clock_type_c_types
882
883
884class ConfigurationOptions:
2d55dc7d
PP
885 def __init__(self,
886 code_generation_options: Optional[ConfigurationCodeGenerationOptions] = None):
4810b707
PP
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
2d55dc7d 893 def code_generation_options(self) -> ConfigurationCodeGenerationOptions:
4810b707
PP
894 return self._code_generation_options
895
896
897class Configuration:
2d55dc7d 898 def __init__(self, trace: Trace, options: Optional[ConfigurationOptions] = None):
4810b707
PP
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
2d55dc7d 917 def trace(self) -> Trace:
4810b707
PP
918 return self._trace
919
920 @property
2d55dc7d 921 def options(self) -> ConfigurationOptions:
4810b707 922 return self._options
This page took 0.077492 seconds and 4 git commands to generate.