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