Make configuration and metadata objects immutable
[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 import barectf
26 import datetime
27
28
29 @enum.unique
30 class ByteOrder(enum.Enum):
31 LE = 0
32 BE = 1
33
34
35 @enum.unique
36 class Encoding(enum.Enum):
37 NONE = 0
38 UTF8 = 1
39 ASCII = 2
40
41
42 class Type:
43 @property
44 def align(self):
45 return None
46
47 @property
48 def size(self):
49 pass
50
51 @property
52 def is_dynamic(self):
53 return False
54
55
56 class PropertyMapping:
57 def __init__(self, object, prop):
58 self._object = object
59 self._prop = prop
60
61 @property
62 def object(self):
63 return self._object
64
65 @property
66 def prop(self):
67 return self.prop
68
69
70 class Integer(Type):
71 def __init__(self, size, byte_order, align=None, signed=False,
72 base=10, encoding=Encoding.NONE, property_mappings=None):
73 self._size = size
74 self._byte_order = byte_order
75
76 if align is None:
77 if size % 8 == 0:
78 self._align = 8
79 else:
80 self._align = 1
81 else:
82 self._align = align
83
84 self._signed = signed
85 self._base = base
86 self._encoding = encoding
87
88 if property_mappings is None:
89 self._property_mappings = []
90 else:
91 self._property_mappings = property_mappings
92
93 @property
94 def signed(self):
95 return self._signed
96
97 @property
98 def byte_order(self):
99 return self._byte_order
100
101 @property
102 def base(self):
103 return self._base
104
105 @property
106 def encoding(self):
107 return self._encoding
108
109 @property
110 def align(self):
111 return self._align
112
113 @property
114 def size(self):
115 return self._size
116
117 @property
118 def property_mappings(self):
119 return self._property_mappings
120
121
122 class FloatingPoint(Type):
123 def __init__(self, exp_size, mant_size, byte_order, align=8):
124 self._exp_size = exp_size
125 self._mant_size = mant_size
126 self._byte_order = byte_order
127 self._align = align
128
129 @property
130 def exp_size(self):
131 return self._exp_size
132
133 @property
134 def mant_size(self):
135 return self._mant_size
136
137 @property
138 def size(self):
139 return self._exp_size + self._mant_size
140
141 @property
142 def byte_order(self):
143 return self._byte_order
144
145 @property
146 def align(self):
147 return self._align
148
149
150 class Enum(Type):
151 def __init__(self, value_type, members=None):
152 self._value_type = value_type
153
154 if members is None:
155 self._members = collections.OrderedDict()
156 else:
157 self._members = members
158
159 @property
160 def align(self):
161 return self._value_type.align
162
163 @property
164 def size(self):
165 return self._value_type.size
166
167 @property
168 def value_type(self):
169 return self._value_type
170
171 @property
172 def members(self):
173 return self._members
174
175 @property
176 def last_value(self):
177 if len(self._members) == 0:
178 return
179
180 return list(self._members.values())[-1][1]
181
182 def value_of(self, label):
183 return self._members[label]
184
185 def label_of(self, value):
186 for label, vrange in self._members.items():
187 if value >= vrange[0] and value <= vrange[1]:
188 return label
189
190 def __getitem__(self, key):
191 if type(key) is str:
192 return self.value_of(key)
193 elif type(key) is int:
194 return self.label_of(key)
195
196 raise TypeError('Wrong subscript type')
197
198
199 class String(Type):
200 def __init__(self, encoding=Encoding.UTF8):
201 self._encoding = encoding.UTF8
202
203 @property
204 def align(self):
205 return 8
206
207 @property
208 def encoding(self):
209 return self._encoding
210
211 @property
212 def is_dynamic(self):
213 return True
214
215
216 class Array(Type):
217 def __init__(self, element_type, length):
218 self._element_type = element_type
219 self._length = length
220
221 @property
222 def align(self):
223 return self._element_type.align
224
225 @property
226 def element_type(self):
227 return self._element_type
228
229 @property
230 def length(self):
231 return self._length
232
233
234 class Struct(Type):
235 def __init__(self, min_align=1, fields=None):
236 self._min_align = min_align
237
238 if fields is None:
239 self._fields = collections.OrderedDict()
240 else:
241 self._fields = fields
242
243 self._align = self.min_align
244
245 for field in self.fields.values():
246 if field.align is None:
247 continue
248
249 if field.align > self._align:
250 self._align = field.align
251
252 @property
253 def min_align(self):
254 return self._min_align
255
256 @property
257 def align(self):
258 return self._align
259
260 @property
261 def fields(self):
262 return self._fields
263
264 def __getitem__(self, key):
265 return self.fields[key]
266
267 def __len__(self):
268 return len(self._fields)
269
270
271 class Trace:
272 def __init__(self, byte_order, uuid=None, packet_header_type=None):
273 self._byte_order = byte_order
274 self._uuid = uuid
275 self._packet_header_type = packet_header_type
276
277 @property
278 def uuid(self):
279 return self._uuid
280
281 @property
282 def byte_order(self):
283 return self._byte_order
284
285 @property
286 def packet_header_type(self):
287 return self._packet_header_type
288
289
290 class Clock:
291 def __init__(self, name, uuid=None, description=None, freq=int(1e9),
292 error_cycles=0, offset_seconds=0, offset_cycles=0,
293 absolute=False, return_ctype='uint32_t'):
294 self._name = name
295 self._uuid = uuid
296 self._description = description
297 self._freq = freq
298 self._error_cycles = error_cycles
299 self._offset_seconds = offset_seconds
300 self._offset_cycles = offset_cycles
301 self._absolute = absolute
302 self._return_ctype = return_ctype
303
304 @property
305 def name(self):
306 return self._name
307
308 @property
309 def uuid(self):
310 return self._uuid
311
312 @property
313 def description(self):
314 return self._description
315
316 @property
317 def error_cycles(self):
318 return self._error_cycles
319
320 @property
321 def freq(self):
322 return self._freq
323
324 @property
325 def offset_seconds(self):
326 return self._offset_seconds
327
328 @property
329 def offset_cycles(self):
330 return self._offset_cycles
331
332 @property
333 def absolute(self):
334 return self._absolute
335
336 @property
337 def return_ctype(self):
338 return self._return_ctype
339
340
341 LogLevel = collections.namedtuple('LogLevel', ['name', 'value'])
342
343
344 class Event:
345 def __init__(self, id, name, log_level=None, payload_type=None,
346 context_type=None):
347 self._id = id
348 self._name = name
349 self._payload_type = payload_type
350 self._log_level = log_level
351 self._context_type = context_type
352
353 @property
354 def id(self):
355 return self._id
356
357 @property
358 def name(self):
359 return self._name
360
361 @property
362 def log_level(self):
363 return self._log_level
364
365 @property
366 def context_type(self):
367 return self._context_type
368
369 @property
370 def payload_type(self):
371 return self._payload_type
372
373 def __getitem__(self, key):
374 if self.payload_type is None:
375 raise KeyError(key)
376
377 return self.payload_type[key]
378
379
380 class Stream:
381 def __init__(self, id, name=None, packet_context_type=None,
382 event_header_type=None, event_context_type=None,
383 events=None):
384 self._id = id
385 self._name = name
386 self._packet_context_type = packet_context_type
387 self._event_header_type = event_header_type
388 self._event_context_type = event_context_type
389
390 if events is None:
391 self._events = collections.OrderedDict()
392 else:
393 self._events = events
394
395 @property
396 def name(self):
397 return self._name
398
399 @property
400 def id(self):
401 return self._id
402
403 @property
404 def packet_context_type(self):
405 return self._packet_context_type
406
407 @property
408 def event_header_type(self):
409 return self._event_header_type
410
411 @property
412 def event_context_type(self):
413 return self._event_context_type
414
415 @property
416 def events(self):
417 return self._events
418
419
420 class Metadata:
421 def __init__(self, trace, env=None, clocks=None, streams=None,
422 default_stream_name=None):
423 self._trace = trace
424 version_tuple = barectf.get_version_tuple()
425 self._env = collections.OrderedDict([
426 ('domain', 'bare'),
427 ('tracer_name', 'barectf'),
428 ('tracer_major', version_tuple[0]),
429 ('tracer_minor', version_tuple[1]),
430 ('tracer_patch', version_tuple[2]),
431 ('barectf_gen_date', str(datetime.datetime.now().isoformat())),
432 ])
433
434 if env is not None:
435 self._env.update(env)
436
437 if clocks is None:
438 self._clocks = collections.OrderedDict()
439 else:
440 self._clocks = clocks
441
442 if streams is None:
443 self._streams = collections.OrderedDict()
444 else:
445 self._streams = streams
446
447 self._default_stream_name = default_stream_name
448
449 @property
450 def trace(self):
451 return self._trace
452
453 @property
454 def env(self):
455 return self._env
456
457 @property
458 def clocks(self):
459 return self._clocks
460
461 @property
462 def streams(self):
463 return self._streams
464
465 @property
466 def default_stream_name(self):
467 return self._default_stream_name
468
469 @property
470 def default_stream(self):
471 if self._default_stream_name in self._streams:
472 return self._streams[self._default_stream_name]
This page took 0.038615 seconds and 5 git commands to generate.