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