README.md: add PPA instructions for Ubuntu
[barectf.git] / barectf / metadata.py
1 # The MIT License (MIT)
2 #
3 # Copyright (c) 2015 Philippe Proulx <pproulx@efficios.com>
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
11 #
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 # THE SOFTWARE.
22
23 import enum
24 import collections
25
26
27 @enum.unique
28 class ByteOrder(enum.Enum):
29 LE = 0
30 BE = 1
31
32
33 @enum.unique
34 class Encoding(enum.Enum):
35 NONE = 0
36 UTF8 = 1
37 ASCII = 2
38
39
40 class Type:
41 @property
42 def align(self):
43 return None
44
45 @property
46 def size(self):
47 pass
48
49 @property
50 def is_dynamic(self):
51 raise NotImplementedError()
52
53
54 class PropertyMapping:
55 def __init__(self, object, prop):
56 self._object = object
57 self._prop = prop
58
59 @property
60 def object(self):
61 return self._object
62
63 @object.setter
64 def object(self, value):
65 self._object = value
66
67 @property
68 def prop(self):
69 return self.prop
70
71 @prop.setter
72 def prop(self, value):
73 self.prop = value
74
75
76 class Integer(Type):
77 def __init__(self):
78 self.set_default_size()
79 self.set_default_align()
80 self.set_default_signed()
81 self.set_default_byte_order()
82 self.set_default_base()
83 self.set_default_encoding()
84 self.set_default_property_mappings()
85
86 def set_default_size(self):
87 self._size = None
88
89 def set_default_align(self):
90 self._align = None
91
92 def set_default_signed(self):
93 self._signed = False
94
95 def set_default_byte_order(self):
96 self._byte_order = None
97
98 def set_default_base(self):
99 self._base = 10
100
101 def set_default_encoding(self):
102 self._encoding = Encoding.NONE
103
104 def set_default_property_mappings(self):
105 self._property_mappings = []
106
107 @property
108 def signed(self):
109 return self._signed
110
111 @signed.setter
112 def signed(self, value):
113 self._signed = value
114
115 @property
116 def byte_order(self):
117 return self._byte_order
118
119 @byte_order.setter
120 def byte_order(self, value):
121 self._byte_order = value
122
123 @property
124 def base(self):
125 return self._base
126
127 @base.setter
128 def base(self, value):
129 self._base = value
130
131 @property
132 def encoding(self):
133 return self._encoding
134
135 @encoding.setter
136 def encoding(self, value):
137 self._encoding = value
138
139 @property
140 def align(self):
141 if self._align is None:
142 if self._size is None:
143 return
144 else:
145 if self._size % 8 == 0:
146 return 8
147 else:
148 return 1
149 else:
150 return self._align
151
152 @align.setter
153 def align(self, value):
154 self._align = value
155
156 @property
157 def size(self):
158 return self._size
159
160 @size.setter
161 def size(self, value):
162 self._size = value
163
164 @property
165 def property_mappings(self):
166 return self._property_mappings
167
168 @property
169 def is_dynamic(self):
170 return False
171
172
173 class FloatingPoint(Type):
174 def __init__(self):
175 self.set_default_exp_size()
176 self.set_default_mant_size()
177 self.set_default_align()
178 self.set_default_byte_order()
179
180 def set_default_exp_size(self):
181 self._exp_size = None
182
183 def set_default_mant_size(self):
184 self._mant_size = None
185
186 def set_default_align(self):
187 self._align = 8
188
189 def set_default_byte_order(self):
190 self._byte_order = None
191
192 @property
193 def exp_size(self):
194 return self._exp_size
195
196 @exp_size.setter
197 def exp_size(self, value):
198 self._exp_size = value
199
200 @property
201 def mant_size(self):
202 return self._mant_size
203
204 @mant_size.setter
205 def mant_size(self, value):
206 self._mant_size = value
207
208 @property
209 def size(self):
210 if self._exp_size is None or self._mant_size is None:
211 return
212
213 return self._exp_size + self._mant_size
214
215 @property
216 def byte_order(self):
217 return self._byte_order
218
219 @byte_order.setter
220 def byte_order(self, value):
221 self._byte_order = value
222
223 @property
224 def align(self):
225 return self._align
226
227 @align.setter
228 def align(self, value):
229 self._align = value
230
231 @property
232 def is_dynamic(self):
233 return False
234
235
236 class Enum(Type):
237 def __init__(self):
238 self.set_default_value_type()
239 self.set_default_members()
240
241 def set_default_value_type(self):
242 self._value_type = None
243
244 def set_default_members(self):
245 self._members = collections.OrderedDict()
246
247 @property
248 def align(self):
249 return self._value_type.align
250
251 @property
252 def size(self):
253 return self._value_type.size
254
255 @property
256 def value_type(self):
257 return self._value_type
258
259 @value_type.setter
260 def value_type(self, value):
261 self._value_type = value
262
263 @property
264 def members(self):
265 return self._members
266
267 @property
268 def last_value(self):
269 if not self._members:
270 return
271
272 return list(self._members.values())[-1][1]
273
274 def value_of(self, label):
275 return self._members[label]
276
277 def label_of(self, value):
278 for label, vrange in self._members.items():
279 if value >= vrange[0] and value <= vrange[1]:
280 return label
281
282 def __getitem__(self, key):
283 if type(key) is str:
284 return self.value_of(key)
285 elif type(key) is int:
286 return self.label_of(key)
287
288 raise TypeError('wrong subscript type')
289
290 @property
291 def is_dynamic(self):
292 return False
293
294
295 class String(Type):
296 def __init__(self):
297 self.set_default_encoding()
298
299 def set_default_encoding(self):
300 self._encoding = Encoding.UTF8
301
302 @property
303 def align(self):
304 return 8
305
306 @property
307 def encoding(self):
308 return self._encoding
309
310 @encoding.setter
311 def encoding(self, value):
312 self._encoding = value
313
314 @property
315 def is_dynamic(self):
316 return True
317
318
319 class Array(Type):
320 def __init__(self):
321 self.set_default_element_type()
322 self.set_default_length()
323
324 def set_default_element_type(self):
325 self._default_element_type = None
326
327 def set_default_length(self):
328 self._default_length = None
329
330 @property
331 def align(self):
332 return self._element_type.align
333
334 @property
335 def element_type(self):
336 return self._element_type
337
338 @element_type.setter
339 def element_type(self, value):
340 self._element_type = value
341
342 @property
343 def length(self):
344 return self._length
345
346 @length.setter
347 def length(self, value):
348 self._length = value
349
350 @property
351 def is_variable_length(self):
352 return type(self._length) is not int
353
354 @property
355 def is_dynamic(self):
356 if self.is_variable_length:
357 return True
358
359 return self.element_type.is_dynamic
360
361
362 class Struct(Type):
363 def __init__(self):
364 self.set_default_min_align()
365 self.set_default_fields()
366
367 def set_default_min_align(self):
368 self._min_align = 1
369
370 def set_default_fields(self):
371 self._fields = collections.OrderedDict()
372
373 @property
374 def min_align(self):
375 return self._min_align
376
377 @min_align.setter
378 def min_align(self, value):
379 self._min_align = value
380
381 @property
382 def align(self):
383 align = self.min_align
384
385 for field in self.fields.values():
386 if field.align is None:
387 return
388
389 if field.align > align:
390 align = field.align
391
392 return align
393
394 @property
395 def is_dynamic(self):
396 for field in self.fields.values():
397 if field.is_dynamic:
398 return True
399
400 return False
401
402 @property
403 def fields(self):
404 return self._fields
405
406 def __getitem__(self, key):
407 return self.fields[key]
408
409 def __len__(self):
410 return len(self._fields)
411
412
413 class Variant(Type):
414 def __init__(self):
415 self.set_default_tag()
416 self.set_default_types()
417
418 def set_default_tag(self):
419 self._tag = None
420
421 def set_default_types(self):
422 self._types = collections.OrderedDict()
423
424 @property
425 def align(self):
426 single_type = self.get_single_type()
427
428 if single_type is not None:
429 return single_type.align
430
431 # if all the possible types have the same alignment, then
432 # there's only one possible alignment
433 align = None
434
435 for t in self.types.values():
436 if t.align is None:
437 return
438
439 if align is None:
440 # first
441 align = t.align
442 else:
443 if t.align != align:
444 return
445
446 return align
447
448 @property
449 def size(self):
450 single_type = self.get_single_type()
451
452 if single_type is not None:
453 return single_type.size
454
455 @property
456 def tag(self):
457 return self._tag
458
459 @tag.setter
460 def tag(self, value):
461 self._tag = value
462
463 @property
464 def types(self):
465 return self._types
466
467 def __getitem__(self, key):
468 return self.types[key]
469
470 def get_single_type(self):
471 if len(self.members) == 1:
472 return list(self.members.values())[0]
473
474 @property
475 def is_dynamic(self):
476 single_type = self.get_single_type()
477
478 if single_type is not None:
479 return single_type.is_dynamic
480
481 return True
482
483
484 class Trace:
485 def __init__(self):
486 self._byte_order = None
487 self._packet_header_type = None
488 self._uuid = None
489
490 @property
491 def uuid(self):
492 return self._uuid
493
494 @uuid.setter
495 def uuid(self, value):
496 self._uuid = value
497
498 @property
499 def byte_order(self):
500 return self._byte_order
501
502 @byte_order.setter
503 def byte_order(self, value):
504 self._byte_order = value
505
506 @property
507 def packet_header_type(self):
508 return self._packet_header_type
509
510 @packet_header_type.setter
511 def packet_header_type(self, value):
512 self._packet_header_type = value
513
514
515 class Env(collections.OrderedDict):
516 pass
517
518
519 class Clock:
520 def __init__(self):
521 self.set_default_name()
522 self.set_default_uuid()
523 self.set_default_description()
524 self.set_default_freq()
525 self.set_default_error_cycles()
526 self.set_default_offset_seconds()
527 self.set_default_offset_cycles()
528 self.set_default_absolute()
529 self.set_default_return_ctype()
530
531 def set_default_name(self):
532 self._name = None
533
534 def set_default_uuid(self):
535 self._uuid = None
536
537 def set_default_description(self):
538 self._description = None
539
540 def set_default_freq(self):
541 self._freq = 1000000000
542
543 def set_default_error_cycles(self):
544 self._error_cycles = 0
545
546 def set_default_offset_seconds(self):
547 self._offset_seconds = 0
548
549 def set_default_offset_cycles(self):
550 self._offset_cycles = 0
551
552 def set_default_absolute(self):
553 self._absolute = False
554
555 def set_default_return_ctype(self):
556 self._return_ctype = 'uint32_t'
557
558 @property
559 def name(self):
560 return self._name
561
562 @name.setter
563 def name(self, value):
564 self._name = value
565
566 @property
567 def uuid(self):
568 return self._uuid
569
570 @uuid.setter
571 def uuid(self, value):
572 self._uuid = value
573
574 @property
575 def description(self):
576 return self._description
577
578 @description.setter
579 def description(self, value):
580 self._description = value
581
582 @property
583 def error_cycles(self):
584 return self._error_cycles
585
586 @error_cycles.setter
587 def error_cycles(self, value):
588 self._error_cycles = value
589
590 @property
591 def freq(self):
592 return self._freq
593
594 @freq.setter
595 def freq(self, value):
596 self._freq = value
597
598 @property
599 def offset_seconds(self):
600 return self._offset_seconds
601
602 @offset_seconds.setter
603 def offset_seconds(self, value):
604 self._offset_seconds = value
605
606 @property
607 def offset_cycles(self):
608 return self._offset_cycles
609
610 @offset_cycles.setter
611 def offset_cycles(self, value):
612 self._offset_cycles = value
613
614 @property
615 def absolute(self):
616 return self._absolute
617
618 @absolute.setter
619 def absolute(self, value):
620 self._absolute = value
621
622 @property
623 def return_ctype(self):
624 return self._return_ctype
625
626 @return_ctype.setter
627 def return_ctype(self, value):
628 self._return_ctype = value
629
630
631 LogLevel = collections.namedtuple('LogLevel', ['name', 'value'])
632
633
634 class Event:
635 def __init__(self):
636 self._id = None
637 self._name = None
638 self._log_level = None
639 self._context_type = None
640 self._payload_type = None
641
642 @property
643 def id(self):
644 return self._id
645
646 @id.setter
647 def id(self, value):
648 self._id = value
649
650 @property
651 def name(self):
652 return self._name
653
654 @name.setter
655 def name(self, value):
656 self._name = value
657
658 @property
659 def log_level(self):
660 return self._log_level
661
662 @log_level.setter
663 def log_level(self, value):
664 self._log_level = value
665
666 @property
667 def context_type(self):
668 return self._context_type
669
670 @context_type.setter
671 def context_type(self, value):
672 self._context_type = value
673
674 @property
675 def payload_type(self):
676 return self._payload_type
677
678 @payload_type.setter
679 def payload_type(self, value):
680 self._payload_type = value
681
682 def __getitem__(self, key):
683 if type(self.payload_type) in [Struct, Variant]:
684 return self.payload_type[key]
685
686 raise TypeError('{} is not subscriptable')
687
688
689 class Stream:
690 def __init__(self):
691 self._id = 0
692 self._name = None
693 self._packet_context_type = None
694 self._event_header_type = None
695 self._event_context_type = None
696 self._events = collections.OrderedDict()
697
698 @property
699 def name(self):
700 return self._name
701
702 @name.setter
703 def name(self, value):
704 self._name = value
705
706 @property
707 def id(self):
708 return self._id
709
710 @id.setter
711 def id(self, value):
712 self._id = value
713
714 @property
715 def packet_context_type(self):
716 return self._packet_context_type
717
718 @packet_context_type.setter
719 def packet_context_type(self, value):
720 self._packet_context_type = value
721
722 @property
723 def event_header_type(self):
724 return self._event_header_type
725
726 @event_header_type.setter
727 def event_header_type(self, value):
728 self._event_header_type = value
729
730 @property
731 def event_context_type(self):
732 return self._event_context_type
733
734 @event_context_type.setter
735 def event_context_type(self, value):
736 self._event_context_type = value
737
738 @property
739 def events(self):
740 return self._events
741
742 def is_event_empty(self, event):
743 total_fields = 0
744
745 if self.event_header_type:
746 total_fields += len(self.event_header_type)
747
748 if self.event_context_type:
749 total_fields += len(self.event_context_type)
750
751 if event.context_type:
752 total_fields += len(event.context_type)
753
754 if event.payload_type:
755 total_fields += len(event.payload_type)
756
757 return total_fields == 0
758
759
760 class Metadata:
761 def __init__(self):
762 self._trace = None
763 self._env = collections.OrderedDict()
764 self._clocks = collections.OrderedDict()
765 self._streams = collections.OrderedDict()
766
767 @property
768 def trace(self):
769 return self._trace
770
771 @trace.setter
772 def trace(self, value):
773 self._trace = value
774
775 @property
776 def env(self):
777 return self._env
778
779 @env.setter
780 def env(self, value):
781 self._env = value
782
783 @property
784 def clocks(self):
785 return self._clocks
786
787 @clocks.setter
788 def clocks(self, value):
789 self._clocks = value
790
791 @property
792 def streams(self):
793 return self._streams
794
795 @streams.setter
796 def streams(self, value):
797 self._streams = value
This page took 0.043964 seconds and 4 git commands to generate.