Python: document VariantFieldDeclaration
[babeltrace.git] / bindings / python / bt.py
CommitLineData
6fd49698
PP
1# nativebt.i.in
2#
3# Babeltrace native interface Python module
4#
5# Copyright 2012-2015 EfficiOS Inc.
6#
7# Author: Danny Serres <danny.serres@efficios.com>
8# Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9#
10# Permission is hereby granted, free of charge, to any person obtaining a copy
11# of this software and associated documentation files (the "Software"), to deal
12# in the Software without restriction, including without limitation the rights
13# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14# copies of the Software, and to permit persons to whom the Software is
15# furnished to do so, subject to the following conditions:
16#
17# The above copyright notice and this permission notice shall be included in
18# all copies or substantial portions of the Software.
19#
20# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26# SOFTWARE.
27
28import babeltrace.nativebt as nbt
29import collections
30import os
31from datetime import datetime
32from uuid import UUID
33
34
35class TraceCollection:
6fd49698 36 """
e6d1a1c5
PP
37 A :class:`TraceCollection` is a collection of opened traces.
38
39 In general, once a trace collection is created, you add one to many
40 independent traces to it using :meth:`add_trace` or
41 :meth:`add_traces_recursive`, and then iterate the ordered events
42 of all traces merged together using :attr:`events`.
43
44 You may use :meth:`remove_trace` to close and remove a specific
45 trace from a trace collection, although all the traces of a given
46 trace collection will be automatically removed when it is garbage
47 collected.
6fd49698
PP
48 """
49
50 def __init__(self):
e6d1a1c5
PP
51 """
52 Creates an empty trace collection.
53 """
54
6fd49698
PP
55 self._tc = nbt._bt_context_create()
56
57 def __del__(self):
58 nbt._bt_context_put(self._tc)
59
60 def add_trace(self, path, format_str):
61 """
e6d1a1c5 62 Adds a trace to the trace collection.
6fd49698 63
e6d1a1c5
PP
64 The trace is located at the file system path *path*. This
65 function **does not** recurse directories to find the trace:
66 *path* must point to the exact trace location (see
67 :meth:`add_traces_recursive` for a recursive version of this
68 function).
6fd49698 69
e6d1a1c5
PP
70 *format_str* is a string indicating the Babeltrace type of the
71 trace to add. ``ctf`` is the only currently supported trace
72 format.
6fd49698 73
e6d1a1c5 74 Once added, the trace is opened.
6fd49698 75
e6d1a1c5
PP
76 Returns the corresponding :class:`TraceHandle` instance for
77 this opened trace on success, or ``None`` on error.
6fd49698 78 """
82839121
PP
79
80 ret = nbt._bt_context_add_trace(self._tc, path, format_str,
81 None, None, None)
82
6fd49698
PP
83 if ret < 0:
84 return None
85
86 th = TraceHandle.__new__(TraceHandle)
87 th._id = ret
88 th._trace_collection = self
82839121 89
6fd49698
PP
90 return th
91
92 def add_traces_recursive(self, path, format_str):
93 """
e6d1a1c5
PP
94 Adds traces to this trace collection by recursively searching
95 in the *path* directory.
96
97 *format_str* is a string indicating the Babeltrace type of the
98 traces to find and add. ``ctf`` is the only currently supported
99 trace format.
6fd49698 100
e6d1a1c5 101 See also :meth:`add_trace`.
6fd49698 102
e6d1a1c5
PP
103 Returns a :class:`dict` object mapping full paths to trace
104 handles for each trace found, or ``None`` on error.
6fd49698
PP
105 """
106
107 trace_handles = {}
6fd49698
PP
108 noTrace = True
109 error = False
110
111 for fullpath, dirs, files in os.walk(path):
112 if "metadata" in files:
113 trace_handle = self.add_trace(fullpath, format_str)
82839121 114
6fd49698
PP
115 if trace_handle is None:
116 error = True
117 continue
118
119 trace_handles[fullpath] = trace_handle
120 noTrace = False
121
122 if noTrace and error:
123 return None
82839121 124
6fd49698
PP
125 return trace_handles
126
127 def remove_trace(self, trace_handle):
128 """
e6d1a1c5
PP
129 Removes a trace from the trace collection using its trace
130 handle *trace_handle*.
131
132 :class:`TraceHandle` objects are returned by :meth:`add_trace`
133 and :meth:`add_traces_recursive`.
134
135 The trace is closed before being removed.
6fd49698 136 """
82839121 137
6fd49698
PP
138 try:
139 nbt._bt_context_remove_trace(self._tc, trace_handle._id)
140 except AttributeError:
82839121 141 raise TypeError("in remove_trace, argument 2 must be a TraceHandle instance")
6fd49698
PP
142
143 @property
144 def events(self):
145 """
e6d1a1c5
PP
146 Generates the ordered :class:`Event` objects of all the opened
147 traces contained in this trace collection. Iterate this function
148 to iterate actual events.
6fd49698
PP
149
150 Due to limitations of the native Babeltrace API, only one event
e6d1a1c5
PP
151 may be "alive" at a given time, i.e. a user **should never**
152 store a copy of the events returned by this function for
153 ulterior use. Users shall make sure to copy the information
154 they need *from* an event before accessing the next one.
155
156 Furthermore, :class:`Event` objects become invalid when the
157 generator goes out of scope as the underlying iterator will be
158 reclaimed. Using an event after the the generator has gone out
159 of scope may result in a crash or data corruption.
6fd49698 160 """
82839121 161
6fd49698
PP
162 begin_pos_ptr = nbt._bt_iter_pos()
163 end_pos_ptr = nbt._bt_iter_pos()
164 begin_pos_ptr.type = nbt.SEEK_BEGIN
165 end_pos_ptr.type = nbt.SEEK_LAST
166
167 for event in self._events(begin_pos_ptr, end_pos_ptr):
168 yield event
169
170 def events_timestamps(self, timestamp_begin, timestamp_end):
171 """
e6d1a1c5
PP
172 Generates the ordered :class:`Event` objects of all the opened
173 traces contained in this trace collection from *timestamp_begin*
174 to *timestamp_end*.
175
176 See :attr:`events` for notes and limitations.
6fd49698 177 """
82839121 178
6fd49698
PP
179 begin_pos_ptr = nbt._bt_iter_pos()
180 end_pos_ptr = nbt._bt_iter_pos()
181 begin_pos_ptr.type = end_pos_ptr.type = nbt.SEEK_TIME
182 begin_pos_ptr.u.seek_time = timestamp_begin
183 end_pos_ptr.u.seek_time = timestamp_end
184
185 for event in self._events(begin_pos_ptr, end_pos_ptr):
186 yield event
187
188 @property
189 def timestamp_begin(self):
e6d1a1c5
PP
190 """
191 Trace collection's begin timestamp.
192 """
193
6fd49698
PP
194 pos_ptr = nbt._bt_iter_pos()
195 pos_ptr.type = nbt.SEEK_BEGIN
82839121 196
6fd49698
PP
197 return self._timestamp_at_pos(pos_ptr)
198
199 @property
200 def timestamp_end(self):
e6d1a1c5
PP
201 """
202 Trace collection's end timestamp.
203 """
204
6fd49698
PP
205 pos_ptr = nbt._bt_iter_pos()
206 pos_ptr.type = nbt.SEEK_LAST
82839121 207
6fd49698
PP
208 return self._timestamp_at_pos(pos_ptr)
209
210 def _timestamp_at_pos(self, pos_ptr):
211 ctf_it_ptr = nbt._bt_ctf_iter_create(self._tc, pos_ptr, pos_ptr)
82839121 212
6fd49698 213 if ctf_it_ptr is None:
82839121
PP
214 raise NotImplementedError("Creation of multiple iterators is unsupported.")
215
6fd49698
PP
216 ev_ptr = nbt._bt_ctf_iter_read_event(ctf_it_ptr)
217 nbt._bt_ctf_iter_destroy(ctf_it_ptr)
82839121 218
6fd49698
PP
219 def _events(self, begin_pos_ptr, end_pos_ptr):
220 ctf_it_ptr = nbt._bt_ctf_iter_create(self._tc, begin_pos_ptr, end_pos_ptr)
82839121 221
6fd49698 222 if ctf_it_ptr is None:
82839121 223 raise NotImplementedError("Creation of multiple iterators is unsupported.")
6fd49698
PP
224
225 while True:
226 ev_ptr = nbt._bt_ctf_iter_read_event(ctf_it_ptr)
82839121 227
6fd49698
PP
228 if ev_ptr is None:
229 break
230
231 ev = Event.__new__(Event)
232 ev._e = ev_ptr
82839121 233
6fd49698
PP
234 try:
235 yield ev
236 except GeneratorExit:
237 break
238
239 ret = nbt._bt_iter_next(nbt._bt_ctf_get_iter(ctf_it_ptr))
82839121 240
6fd49698
PP
241 if ret != 0:
242 break
243
244 nbt._bt_ctf_iter_destroy(ctf_it_ptr)
245
246
6fd49698 247# Based on enum bt_clock_type in clock-type.h
8f52f384 248class _ClockType:
6fd49698
PP
249 CLOCK_CYCLES = 0
250 CLOCK_REAL = 1
251
252
4cde866e 253class TraceHandle:
6fd49698 254 """
d5e16d9b
PP
255 A :class:`TraceHandle` is a handle allowing the user to manipulate
256 a specific trace directly. It is a unique identifier representing a
257 trace, and is not meant to be instantiated by the user.
6fd49698
PP
258 """
259
260 def __init__(self):
261 raise NotImplementedError("TraceHandle cannot be instantiated")
262
263 def __repr__(self):
264 return "Babeltrace TraceHandle: trace_id('{0}')".format(self._id)
265
266 @property
267 def id(self):
d5e16d9b
PP
268 """
269 Trace handle's numeric ID.
270 """
82839121 271
6fd49698
PP
272 return self._id
273
274 @property
275 def path(self):
d5e16d9b
PP
276 """
277 Path of the underlying trace.
278 """
82839121
PP
279
280 return nbt._bt_trace_handle_get_path(self._trace_collection._tc,
281 self._id)
6fd49698
PP
282
283 @property
284 def timestamp_begin(self):
d5e16d9b
PP
285 """
286 Buffers creation timestamp (nanoseconds since Epoch) of the
287 underlying trace.
288 """
82839121
PP
289
290 return nbt._bt_trace_handle_get_timestamp_begin(self._trace_collection._tc,
291 self._id,
8f52f384 292 _ClockType.CLOCK_REAL)
6fd49698
PP
293
294 @property
295 def timestamp_end(self):
d5e16d9b
PP
296 """
297 Buffers destruction timestamp (nanoseconds since Epoch) of the
298 underlying trace.
299 """
82839121
PP
300
301 return nbt._bt_trace_handle_get_timestamp_end(self._trace_collection._tc,
302 self._id,
8f52f384 303 _ClockType.CLOCK_REAL)
6fd49698
PP
304
305 @property
306 def events(self):
307 """
d5e16d9b
PP
308 Generates all the :class:`EventDeclaration` objects of the
309 underlying trace.
310
311 Note that this doesn't generate actual trace *events*, but
312 rather their declarations, i.e. their layouts and metadata.
6fd49698 313 """
82839121
PP
314
315 ret = nbt._bt_python_event_decl_listcaller(self.id,
316 self._trace_collection._tc)
6fd49698
PP
317
318 if not isinstance(ret, list):
319 return
320
321 ptr_list, count = ret
82839121 322
6fd49698
PP
323 for i in range(count):
324 tmp = EventDeclaration.__new__(EventDeclaration)
325 tmp._ed = nbt._bt_python_decl_one_from_list(ptr_list, i)
326 yield tmp
327
328
329class CTFStringEncoding:
31576864
PP
330 """
331 CTF string encodings.
332 """
333
334 #: None
6fd49698 335 NONE = 0
31576864
PP
336
337 #: UTF-8
6fd49698 338 UTF8 = 1
31576864
PP
339
340 #: ASCII
6fd49698 341 ASCII = 2
31576864
PP
342
343 #: Unknown
6fd49698
PP
344 UNKNOWN = 3
345
346
347# Based on the enum in ctf-writer/writer.h
348class ByteOrder:
41475115
PP
349 """
350 Byte orders.
351 """
352
353 #: Native byte order
6fd49698 354 BYTE_ORDER_NATIVE = 0
41475115
PP
355
356 #: Little-endian
6fd49698 357 BYTE_ORDER_LITTLE_ENDIAN = 1
41475115
PP
358
359 #: Big-endian
6fd49698 360 BYTE_ORDER_BIG_ENDIAN = 2
41475115
PP
361
362 #: Network byte order (big-endian)
6fd49698 363 BYTE_ORDER_NETWORK = 3
41475115
PP
364
365 #: Unknown byte order
6fd49698
PP
366 BYTE_ORDER_UNKNOWN = 4 # Python-specific entry
367
368
369# enum equivalent, accessible constants
370# These are taken directly from ctf/events.h
371# All changes to enums must also be made here
372class CTFTypeId:
69f0ef36
PP
373 """
374 CTF numeric type identifiers.
375 """
376
377 #: Unknown type
6fd49698 378 UNKNOWN = 0
69f0ef36
PP
379
380 #: Integer
6fd49698 381 INTEGER = 1
69f0ef36
PP
382
383 #: Floating point number
6fd49698 384 FLOAT = 2
69f0ef36
PP
385
386 #: Enumeration
6fd49698 387 ENUM = 3
69f0ef36
PP
388
389 #: String
6fd49698 390 STRING = 4
69f0ef36
PP
391
392 #: Structure
6fd49698 393 STRUCT = 5
69f0ef36
PP
394
395 #: Untagged variant
6fd49698 396 UNTAGGED_VARIANT = 6
69f0ef36
PP
397
398 #: Variant
6fd49698 399 VARIANT = 7
69f0ef36
PP
400
401 #: Array
6fd49698 402 ARRAY = 8
69f0ef36
PP
403
404 #: Sequence
6fd49698 405 SEQUENCE = 9
69f0ef36 406
6fd49698
PP
407 NR_CTF_TYPES = 10
408
409 def type_name(id):
69f0ef36
PP
410 """
411 Returns the name of the CTF numeric type identifier *id*.
412 """
413
6fd49698
PP
414 name = "UNKNOWN_TYPE"
415 constants = [
416 attr for attr in dir(CTFTypeId) if not callable(
417 getattr(
418 CTFTypeId,
419 attr)) and not attr.startswith("__")]
82839121 420
6fd49698
PP
421 for attr in constants:
422 if getattr(CTFTypeId, attr) == id:
423 name = attr
424 break
82839121 425
6fd49698
PP
426 return name
427
428
429class CTFScope:
6331aac6
PP
430 """
431 CTF scopes.
432 """
433
434 #: Packet header
6fd49698 435 TRACE_PACKET_HEADER = 0
6331aac6
PP
436
437 #: Packet context
6fd49698 438 STREAM_PACKET_CONTEXT = 1
6331aac6
PP
439
440 #: Event header
6fd49698 441 STREAM_EVENT_HEADER = 2
6331aac6
PP
442
443 #: Stream event context
6fd49698 444 STREAM_EVENT_CONTEXT = 3
6331aac6
PP
445
446 #: Event context
6fd49698 447 EVENT_CONTEXT = 4
6331aac6
PP
448
449 #: Event fields
6fd49698
PP
450 EVENT_FIELDS = 5
451
452 def scope_name(scope):
6331aac6
PP
453 """
454 Returns the name of the CTF scope *scope*.
455 """
456
6fd49698
PP
457 name = "UNKNOWN_SCOPE"
458 constants = [
459 attr for attr in dir(CTFScope) if not callable(
460 getattr(
461 CTFScope,
462 attr)) and not attr.startswith("__")]
82839121 463
6fd49698
PP
464 for attr in constants:
465 if getattr(CTFScope, attr) == scope:
466 name = attr
467 break
82839121 468
6fd49698
PP
469 return name
470
471
472# Priority of the scopes when searching for event fields
82839121
PP
473_scopes = [
474 CTFScope.EVENT_FIELDS,
475 CTFScope.EVENT_CONTEXT,
476 CTFScope.STREAM_EVENT_CONTEXT,
477 CTFScope.STREAM_EVENT_HEADER,
478 CTFScope.STREAM_PACKET_CONTEXT,
479 CTFScope.TRACE_PACKET_HEADER
480]
6fd49698
PP
481
482
483class Event(collections.Mapping):
6fd49698 484 """
edcd731c
PP
485 An :class:`Event` object represents a trace event. :class:`Event`
486 objects are returned by :attr:`TraceCollection.events` and are
487 not meant to be instantiated by the user.
488
489 :class:`Event` has a :class:`dict`-like interface for accessing
490 an event's field value by field name:
491
492 .. code-block:: python
493
494 event['my_field']
495
496 If a field name exists in multiple scopes, the value of the first
497 field found is returned. The scopes are searched in the following
498 order:
499
500 1. Event fields (:attr:`CTFScope.EVENT_FIELDS`)
501 2. Event context (:attr:`CTFScope.EVENT_CONTEXT`)
502 3. Stream event context (:attr:`CTFScope.STREAM_EVENT_CONTEXT`)
503 4. Event header (:attr:`CTFScope.STREAM_EVENT_HEADER`)
504 5. Packet context (:attr:`CTFScope.STREAM_PACKET_CONTEXT`)
505 6. Packet header (:attr:`CTFScope.TRACE_PACKET_HEADER`)
506
507 It is still possible to obtain a field's value from a specific
508 scope using :meth:`field_with_scope`.
509
510 Field values are returned as native Python types, that is:
511
512 +-----------------------+----------------------------------+
513 | Field type | Python type |
514 +=======================+==================================+
515 | Integer | :class:`int` |
516 +-----------------------+----------------------------------+
517 | Floating point number | :class:`float` |
518 +-----------------------+----------------------------------+
519 | Enumeration | :class:`str` (enumeration label) |
520 +-----------------------+----------------------------------+
521 | String | :class:`str` |
522 +-----------------------+----------------------------------+
523 | Array | :class:`list` of native Python |
524 | | objects |
525 +-----------------------+----------------------------------+
526 | Sequence | :class:`list` of native Python |
527 | | objects |
528 +-----------------------+----------------------------------+
529 | Structure | :class:`dict` mapping field |
530 | | names to native Python objects |
531 +-----------------------+----------------------------------+
532
533 For example, printing the third element of a sequence named ``seq``
534 in a structure named ``my_struct`` of the ``event``'s field named
535 ``my_field`` is done this way:
536
537 .. code-block:: python
538
539 print(event['my_field']['my_struct']['seq'][2])
6fd49698
PP
540 """
541
542 def __init__(self):
543 raise NotImplementedError("Event cannot be instantiated")
544
545 @property
546 def name(self):
edcd731c
PP
547 """
548 Event's name or ``None`` on error.
549 """
82839121 550
6fd49698
PP
551 return nbt._bt_ctf_event_name(self._e)
552
553 @property
554 def cycles(self):
555 """
edcd731c 556 Event's timestamp in cycles or -1 on error.
6fd49698 557 """
82839121 558
6fd49698
PP
559 return nbt._bt_ctf_get_cycles(self._e)
560
561 @property
562 def timestamp(self):
563 """
edcd731c 564 Event's timestamp (nanoseconds since Epoch) or -1 on error.
6fd49698 565 """
82839121 566
6fd49698
PP
567 return nbt._bt_ctf_get_timestamp(self._e)
568
569 @property
570 def datetime(self):
571 """
edcd731c
PP
572 Event's timestamp as a standard :class:`datetime.datetime`
573 object.
574
575 Note that the :class:`datetime.datetime` class' precision
576 is limited to microseconds, whereas :attr:`timestamp` provides
577 the event's timestamp with a nanosecond resolution.
6fd49698 578 """
82839121 579
6fd49698
PP
580 return datetime.fromtimestamp(self.timestamp / 1E9)
581
582 def field_with_scope(self, field_name, scope):
583 """
edcd731c
PP
584 Returns the value of a field named *field_name* within the
585 scope *scope*, or ``None`` if the field cannot be found.
586
587 *scope* must be one of :class:`CTFScope` constants.
6fd49698 588 """
82839121
PP
589
590 if scope not in _scopes:
6fd49698 591 raise ValueError("Invalid scope provided")
82839121 592
6fd49698 593 field = self._field_with_scope(field_name, scope)
82839121 594
6fd49698
PP
595 if field is not None:
596 return field.value
82839121 597
6fd49698 598 def field_list_with_scope(self, scope):
edcd731c
PP
599 """
600 Returns a list of field names in the scope *scope*.
601 """
82839121
PP
602
603 if scope not in _scopes:
6fd49698 604 raise ValueError("Invalid scope provided")
82839121 605
6fd49698 606 field_names = []
82839121 607
6fd49698
PP
608 for field in self._field_list_with_scope(scope):
609 field_names.append(field.name)
82839121 610
6fd49698
PP
611 return field_names
612
613 @property
614 def handle(self):
615 """
edcd731c
PP
616 :class:`TraceHandle` object containing this event, or ``None``
617 on error.
6fd49698 618 """
82839121 619
6fd49698 620 ret = nbt._bt_ctf_event_get_handle_id(self._e)
82839121 621
6fd49698
PP
622 if ret < 0:
623 return None
624
625 th = TraceHandle.__new__(TraceHandle)
626 th._id = ret
627 th._trace_collection = self.get_trace_collection()
82839121 628
6fd49698
PP
629 return th
630
631 @property
632 def trace_collection(self):
633 """
edcd731c
PP
634 :class:`TraceCollection` object containing this event, or
635 ``None`` on error.
6fd49698 636 """
82839121 637
6fd49698
PP
638 trace_collection = TraceCollection()
639 trace_collection._tc = nbt._bt_ctf_event_get_context(self._e)
82839121 640
decd548b 641 if trace_collection._tc is not None:
6fd49698
PP
642 return trace_collection
643
644 def __getitem__(self, field_name):
6fd49698 645 field = self._field(field_name)
82839121 646
6fd49698
PP
647 if field is not None:
648 return field.value
82839121 649
6fd49698
PP
650 raise KeyError(field_name)
651
652 def __iter__(self):
653 for key in self.keys():
654 yield key
655
656 def __len__(self):
657 count = 0
82839121 658
6fd49698
PP
659 for scope in _scopes:
660 scope_ptr = nbt._bt_ctf_get_top_level_scope(self._e, scope)
661 ret = nbt._bt_python_field_listcaller(self._e, scope_ptr)
82839121 662
6fd49698
PP
663 if isinstance(ret, list):
664 count += ret[1]
82839121 665
6fd49698
PP
666 return count
667
668 def __contains__(self, field_name):
669 return self._field(field_name) is not None
670
671 def keys(self):
edcd731c
PP
672 """
673 Returns the list of field names.
674
675 Note: field names are unique within the returned list, although
676 a field name could exist in multiple scopes. Use
677 :meth:`field_list_with_scope` to obtain the list of field names
678 of a given scope.
679 """
82839121 680
6fd49698 681 field_names = set()
82839121 682
6fd49698
PP
683 for scope in _scopes:
684 for name in self.field_list_with_scope(scope):
685 field_names.add(name)
82839121 686
6fd49698
PP
687 return list(field_names)
688
689 def get(self, field_name, default=None):
edcd731c
PP
690 """
691 Returns the value of the field named *field_name*, or *default*
692 when not found.
693
694 See :class:`Event` note about how fields are retrieved by
695 name when multiple fields share the same name in different
696 scopes.
697 """
698
6fd49698 699 field = self._field(field_name)
82839121 700
6fd49698
PP
701 if field is None:
702 return default
82839121 703
6fd49698
PP
704 return field.value
705
706 def items(self):
edcd731c
PP
707 """
708 Generates pairs of (field name, field value).
709
710 This method iterates :meth:`keys` to find field names, which
711 means some fields could be unavailable if other fields share
712 their names in scopes with higher priorities.
713 """
714
6fd49698
PP
715 for field in self.keys():
716 yield (field, self[field])
717
718 def _field_with_scope(self, field_name, scope):
719 scope_ptr = nbt._bt_ctf_get_top_level_scope(self._e, scope)
82839121 720
6fd49698
PP
721 if scope_ptr is None:
722 return None
723
724 definition_ptr = nbt._bt_ctf_get_field(self._e, scope_ptr, field_name)
82839121 725
6fd49698
PP
726 if definition_ptr is None:
727 return None
728
729 field = _Definition(definition_ptr, scope)
82839121 730
6fd49698
PP
731 return field
732
733 def _field(self, field_name):
734 field = None
82839121 735
6fd49698
PP
736 for scope in _scopes:
737 field = self._field_with_scope(field_name, scope)
82839121 738
6fd49698
PP
739 if field is not None:
740 break
82839121 741
6fd49698
PP
742 return field
743
744 def _field_list_with_scope(self, scope):
745 fields = []
746 scope_ptr = nbt._bt_ctf_get_top_level_scope(self._e, scope)
747
748 # Returns a list [list_ptr, count]. If list_ptr is NULL, SWIG will only
749 # provide the "count" return value
750 count = 0
751 list_ptr = None
752 ret = nbt._bt_python_field_listcaller(self._e, scope_ptr)
82839121 753
6fd49698
PP
754 if isinstance(ret, list):
755 list_ptr, count = ret
756
757 for i in range(count):
758 definition_ptr = nbt._bt_python_field_one_from_list(list_ptr, i)
82839121 759
6fd49698
PP
760 if definition_ptr is not None:
761 definition = _Definition(definition_ptr, scope)
762 fields.append(definition)
82839121 763
6fd49698
PP
764 return fields
765
766
767class FieldError(Exception):
a1cfe2c2
PP
768 """
769 Field error, raised when a field's value cannot be accessed.
770 """
771
6fd49698
PP
772 def __init__(self, value):
773 self.value = value
774
775 def __str__(self):
776 return repr(self.value)
777
778
4cde866e 779class EventDeclaration:
e4b7a146
PP
780 """
781 An event declaration contains the properties of a class of events,
782 that is, the common properties and fields layout of all the actual
783 recorded events associated with this declaration.
784
785 This class is not meant to be instantiated by the user. It is
786 returned by :attr:`TraceHandle.events`.
787 """
82839121 788
6fd49698
PP
789 MAX_UINT64 = 0xFFFFFFFFFFFFFFFF
790
791 def __init__(self):
792 raise NotImplementedError("EventDeclaration cannot be instantiated")
793
794 @property
795 def name(self):
e4b7a146
PP
796 """
797 Event's name, or ``None`` on error.
798 """
82839121 799
6fd49698
PP
800 return nbt._bt_ctf_get_decl_event_name(self._ed)
801
802 @property
803 def id(self):
e4b7a146
PP
804 """
805 Event's numeric ID, or -1 on error.
806 """
82839121 807
6fd49698 808 id = nbt._bt_ctf_get_decl_event_id(self._ed)
82839121 809
6fd49698
PP
810 if id == self.MAX_UINT64:
811 id = -1
82839121 812
6fd49698
PP
813 return id
814
815 @property
816 def fields(self):
817 """
e4b7a146 818 Generates all the event's field declarations, going through
6fd49698 819 each scope in the following order:
e4b7a146
PP
820
821 1. Event fields (:attr:`CTFScope.EVENT_FIELDS`)
822 2. Event context (:attr:`CTFScope.EVENT_CONTEXT`)
823 3. Stream event context (:attr:`CTFScope.STREAM_EVENT_CONTEXT`)
824 4. Event header (:attr:`CTFScope.STREAM_EVENT_HEADER`)
825 5. Packet context (:attr:`CTFScope.STREAM_PACKET_CONTEXT`)
826 6. Packet header (:attr:`CTFScope.TRACE_PACKET_HEADER`)
827
828 All the generated field declarations inherit
829 :class:`FieldDeclaration`, and are among:
830
831 * :class:`IntegerFieldDeclaration`
832 * :class:`FloatFieldDeclaration`
833 * :class:`EnumerationFieldDeclaration`
834 * :class:`StringFieldDeclaration`
835 * :class:`ArrayFieldDeclaration`
836 * :class:`SequenceFieldDeclaration`
837 * :class:`StructureFieldDeclaration`
838 * :class:`VariantFieldDeclaration`
6fd49698 839 """
82839121 840
6fd49698
PP
841 for scope in _scopes:
842 for declaration in self.fields_scope(scope):
843 yield declaration
844
845 def fields_scope(self, scope):
846 """
e4b7a146
PP
847 Generates all the field declarations of the event's scope
848 *scope*.
849
850 *scope* must be one of :class:`CTFScope` constants.
851
852 All the generated field declarations inherit
853 :class:`FieldDeclaration`, and are among:
854
855 * :class:`IntegerFieldDeclaration`
856 * :class:`FloatFieldDeclaration`
857 * :class:`EnumerationFieldDeclaration`
858 * :class:`StringFieldDeclaration`
859 * :class:`ArrayFieldDeclaration`
860 * :class:`SequenceFieldDeclaration`
861 * :class:`StructureFieldDeclaration`
862 * :class:`VariantFieldDeclaration`
6fd49698
PP
863 """
864 ret = nbt._by_python_field_decl_listcaller(self._ed, scope)
865
866 if not isinstance(ret, list):
867 return
868
869 list_ptr, count = ret
82839121 870
6fd49698 871 for i in range(count):
82839121
PP
872 field_decl_ptr = nbt._bt_python_field_decl_one_from_list(list_ptr, i)
873
874 if field_decl_ptr is not None:
875 decl_ptr = nbt._bt_ctf_get_decl_from_field_decl(field_decl_ptr)
876 name = nbt._bt_ctf_get_decl_field_name(field_decl_ptr)
877 field_declaration = _create_field_declaration(decl_ptr, name,
878 scope)
6fd49698
PP
879 yield field_declaration
880
881
4cde866e 882class FieldDeclaration:
a44d5a34
PP
883 """
884 Base class for concrete field declarations.
885
886 This class is not meant to be instantiated by the user.
887 """
6fd49698
PP
888
889 def __init__(self):
890 raise NotImplementedError("FieldDeclaration cannot be instantiated")
891
892 def __repr__(self):
82839121
PP
893 return "({0}) {1} {2}".format(CTFScope.scope_name(self.scope),
894 CTFTypeId.type_name(self.type),
895 self.name)
6fd49698
PP
896
897 @property
898 def name(self):
a44d5a34
PP
899 """
900 Field's name, or ``None`` on error.
901 """
82839121 902
6fd49698
PP
903 return self._name
904
905 @property
906 def type(self):
907 """
a44d5a34 908 Field's type (one of :class:`CTFTypeId` constants).
6fd49698 909 """
82839121 910
6fd49698
PP
911 return nbt._bt_ctf_field_type(self._fd)
912
913 @property
914 def scope(self):
915 """
a44d5a34 916 Field's scope (one of :class:`CTFScope` constants).
6fd49698 917 """
82839121 918
6fd49698
PP
919 return self._s
920
921
922class IntegerFieldDeclaration(FieldDeclaration):
6fd49698
PP
923 """Do not instantiate."""
924
925 def __init__(self):
82839121 926 raise NotImplementedError("IntegerFieldDeclaration cannot be instantiated")
6fd49698
PP
927
928 @property
929 def signedness(self):
930 """
931 Return the signedness of an integer:
932 0 if unsigned; 1 if signed; -1 on error.
933 """
82839121 934
6fd49698
PP
935 return nbt._bt_ctf_get_int_signedness(self._fd)
936
937 @property
938 def base(self):
939 """Return the base of an int or a negative value on error."""
82839121 940
6fd49698
PP
941 return nbt._bt_ctf_get_int_base(self._fd)
942
943 @property
944 def byte_order(self):
945 """
946 Return the byte order. One of class ByteOrder's entries.
947 """
82839121 948
6fd49698 949 ret = nbt._bt_ctf_get_int_byte_order(self._fd)
82839121 950
6fd49698
PP
951 if ret == 1234:
952 return ByteOrder.BYTE_ORDER_LITTLE_ENDIAN
953 elif ret == 4321:
954 return ByteOrder.BYTE_ORDER_BIG_ENDIAN
955 else:
956 return ByteOrder.BYTE_ORDER_UNKNOWN
957
958 @property
959 def length(self):
960 """
961 Return the size, in bits, of an int or a negative
962 value on error.
963 """
82839121 964
6fd49698
PP
965 return nbt._bt_ctf_get_int_len(self._fd)
966
967 @property
968 def encoding(self):
969 """
970 Return the encoding. One of class CTFStringEncoding's entries.
971 Return a negative value on error.
972 """
82839121 973
6fd49698
PP
974 return nbt._bt_ctf_get_encoding(self._fd)
975
976
977class EnumerationFieldDeclaration(FieldDeclaration):
13e9bbf5
PP
978 """
979 Enumeration field declaration.
980
981 .. note::
982
983 As of this version, this class is missing some properties.
984 """
6fd49698
PP
985
986 def __init__(self):
82839121 987 raise NotImplementedError("EnumerationFieldDeclaration cannot be instantiated")
6fd49698
PP
988
989
990class ArrayFieldDeclaration(FieldDeclaration):
c0a2c1b7
PP
991 """
992 Static array field declaration.
993 """
6fd49698
PP
994
995 def __init__(self):
82839121 996 raise NotImplementedError("ArrayFieldDeclaration cannot be instantiated")
6fd49698
PP
997
998 @property
999 def length(self):
1000 """
c0a2c1b7
PP
1001 Static array's fixed length (number of contained elements), or
1002 a negative value on error.
6fd49698 1003 """
82839121 1004
6fd49698
PP
1005 return nbt._bt_ctf_get_array_len(self._fd)
1006
1007 @property
1008 def element_declaration(self):
1009 """
c0a2c1b7 1010 Underlying element's field declaration.
6fd49698 1011 """
82839121 1012
6fd49698 1013 field_decl_ptr = nbt._bt_python_get_array_element_declaration(self._fd)
82839121 1014
6fd49698
PP
1015 return _create_field_declaration(field_decl_ptr, "", self.scope)
1016
1017
1018class SequenceFieldDeclaration(FieldDeclaration):
8eee0eb9
PP
1019 """
1020 Sequence (dynamic array) field declaration.
1021
1022 .. note::
1023
1024 As of this version, this class is missing some properties.
1025 """
6fd49698
PP
1026
1027 def __init__(self):
82839121 1028 raise NotImplementedError("SequenceFieldDeclaration cannot be instantiated")
6fd49698
PP
1029
1030 @property
1031 def element_declaration(self):
1032 """
8eee0eb9 1033 Underlying element's field declaration.
6fd49698 1034 """
82839121 1035
6fd49698 1036 field_decl_ptr = nbt._bt_python_get_sequence_element_declaration(self._fd)
82839121 1037
6fd49698
PP
1038 return _create_field_declaration(field_decl_ptr, "", self.scope)
1039
1040
1041class FloatFieldDeclaration(FieldDeclaration):
2847a298
PP
1042 """
1043 Floating point number field declaration.
1044
1045 .. note::
1046
1047 As of this version, this class is missing some properties.
1048 """
6fd49698
PP
1049
1050 def __init__(self):
82839121 1051 raise NotImplementedError("FloatFieldDeclaration cannot be instantiated")
6fd49698
PP
1052
1053
1054class StructureFieldDeclaration(FieldDeclaration):
e5d0468a
PP
1055 """
1056 Structure (ordered map of field names to field declarations) field
1057 declaration.
1058
1059 .. note::
1060
1061 As of this version, this class is missing some properties.
1062 """
6fd49698
PP
1063
1064 def __init__(self):
82839121 1065 raise NotImplementedError("StructureFieldDeclaration cannot be instantiated")
6fd49698
PP
1066
1067
1068class StringFieldDeclaration(FieldDeclaration):
ed1ff4cf
PP
1069 """
1070 String (NULL-terminated array of bytes) field declaration.
1071
1072 .. note::
1073
1074 As of this version, this class is missing some properties.
1075 """
6fd49698
PP
1076
1077 def __init__(self):
82839121 1078 raise NotImplementedError("StringFieldDeclaration cannot be instantiated")
6fd49698
PP
1079
1080
1081class VariantFieldDeclaration(FieldDeclaration):
e7e90300
PP
1082 """
1083 Variant (dynamic selection between different types) field declaration.
1084
1085 .. note::
1086
1087 As of this version, this class is missing some properties.
1088 """
6fd49698
PP
1089
1090 def __init__(self):
82839121 1091 raise NotImplementedError("VariantFieldDeclaration cannot be instantiated")
6fd49698
PP
1092
1093
1094def field_error():
1095 """
1096 Return the last error code encountered while
1097 accessing a field and reset the error flag.
1098 Return 0 if no error, a negative value otherwise.
1099 """
82839121 1100
6fd49698
PP
1101 return nbt._bt_ctf_field_get_error()
1102
1103
1104def _create_field_declaration(declaration_ptr, name, scope):
1105 """
1106 Private field declaration factory.
1107 """
82839121 1108
6fd49698
PP
1109 if declaration_ptr is None:
1110 raise ValueError("declaration_ptr must be valid")
82839121 1111 if scope not in _scopes:
6fd49698
PP
1112 raise ValueError("Invalid scope provided")
1113
1114 type = nbt._bt_ctf_field_type(declaration_ptr)
1115 declaration = None
82839121 1116
6fd49698
PP
1117 if type == CTFTypeId.INTEGER:
1118 declaration = IntegerFieldDeclaration.__new__(IntegerFieldDeclaration)
1119 elif type == CTFTypeId.ENUM:
82839121 1120 declaration = EnumerationFieldDeclaration.__new__(EnumerationFieldDeclaration)
6fd49698
PP
1121 elif type == CTFTypeId.ARRAY:
1122 declaration = ArrayFieldDeclaration.__new__(ArrayFieldDeclaration)
1123 elif type == CTFTypeId.SEQUENCE:
82839121 1124 declaration = SequenceFieldDeclaration.__new__(SequenceFieldDeclaration)
6fd49698
PP
1125 elif type == CTFTypeId.FLOAT:
1126 declaration = FloatFieldDeclaration.__new__(FloatFieldDeclaration)
1127 elif type == CTFTypeId.STRUCT:
82839121 1128 declaration = StructureFieldDeclaration.__new__(StructureFieldDeclaration)
6fd49698
PP
1129 elif type == CTFTypeId.STRING:
1130 declaration = StringFieldDeclaration.__new__(StringFieldDeclaration)
1131 elif type == CTFTypeId.VARIANT:
1132 declaration = VariantFieldDeclaration.__new__(VariantFieldDeclaration)
1133 else:
1134 return declaration
1135
1136 declaration._fd = declaration_ptr
1137 declaration._s = scope
1138 declaration._name = name
82839121 1139
6fd49698
PP
1140 return declaration
1141
1142
4cde866e 1143class _Definition:
6fd49698
PP
1144 def __init__(self, definition_ptr, scope):
1145 self._d = definition_ptr
1146 self._s = scope
82839121
PP
1147
1148 if scope not in _scopes:
6fd49698
PP
1149 ValueError("Invalid scope provided")
1150
1151 @property
1152 def name(self):
1153 """Return the name of a field or None on error."""
82839121 1154
6fd49698
PP
1155 return nbt._bt_ctf_field_name(self._d)
1156
1157 @property
1158 def type(self):
1159 """Return the type of a field or -1 if unknown."""
82839121 1160
6fd49698
PP
1161 return nbt._bt_ctf_field_type(nbt._bt_ctf_get_decl_from_def(self._d))
1162
1163 @property
1164 def declaration(self):
1165 """Return the associated Definition object."""
82839121 1166
6fd49698
PP
1167 return _create_field_declaration(
1168 nbt._bt_ctf_get_decl_from_def(self._d), self.name, self.scope)
1169
1170 def _get_enum_str(self):
1171 """
1172 Return the string matching the current enumeration.
1173 Return None on error.
1174 """
82839121 1175
6fd49698
PP
1176 return nbt._bt_ctf_get_enum_str(self._d)
1177
1178 def _get_array_element_at(self, index):
1179 """
1180 Return the array's element at position index.
1181 Return None on error
1182 """
82839121 1183
6fd49698 1184 array_ptr = nbt._bt_python_get_array_from_def(self._d)
82839121 1185
6fd49698
PP
1186 if array_ptr is None:
1187 return None
1188
1189 definition_ptr = nbt._bt_array_index(array_ptr, index)
82839121 1190
6fd49698
PP
1191 if definition_ptr is None:
1192 return None
82839121 1193
6fd49698
PP
1194 return _Definition(definition_ptr, self.scope)
1195
1196 def _get_sequence_len(self):
1197 """
1198 Return the len of a sequence or a negative
1199 value on error.
1200 """
82839121 1201
6fd49698 1202 seq = nbt._bt_python_get_sequence_from_def(self._d)
82839121 1203
6fd49698
PP
1204 return nbt._bt_sequence_len(seq)
1205
1206 def _get_sequence_element_at(self, index):
1207 """
1208 Return the sequence's element at position index,
1209 otherwise return None
1210 """
82839121 1211
6fd49698 1212 seq = nbt._bt_python_get_sequence_from_def(self._d)
82839121 1213
6fd49698
PP
1214 if seq is not None:
1215 definition_ptr = nbt._bt_sequence_index(seq, index)
82839121 1216
6fd49698
PP
1217 if definition_ptr is not None:
1218 return _Definition(definition_ptr, self.scope)
82839121 1219
6fd49698
PP
1220 def _get_uint64(self):
1221 """
1222 Return the value associated with the field.
1223 If the field does not exist or is not of the type requested,
1224 the value returned is undefined. To check if an error occured,
1225 use the field_error() function after accessing a field.
1226 """
82839121 1227
6fd49698
PP
1228 return nbt._bt_ctf_get_uint64(self._d)
1229
1230 def _get_int64(self):
1231 """
1232 Return the value associated with the field.
1233 If the field does not exist or is not of the type requested,
1234 the value returned is undefined. To check if an error occured,
1235 use the field_error() function after accessing a field.
1236 """
82839121 1237
6fd49698
PP
1238 return nbt._bt_ctf_get_int64(self._d)
1239
1240 def _get_char_array(self):
1241 """
1242 Return the value associated with the field.
1243 If the field does not exist or is not of the type requested,
1244 the value returned is undefined. To check if an error occurred,
1245 use the field_error() function after accessing a field.
1246 """
82839121 1247
6fd49698
PP
1248 return nbt._bt_ctf_get_char_array(self._d)
1249
1250 def _get_str(self):
1251 """
1252 Return the value associated with the field.
1253 If the field does not exist or is not of the type requested,
1254 the value returned is undefined. To check if an error occurred,
1255 use the field_error() function after accessing a field.
1256 """
82839121 1257
6fd49698
PP
1258 return nbt._bt_ctf_get_string(self._d)
1259
1260 def _get_float(self):
1261 """
1262 Return the value associated with the field.
1263 If the field does not exist or is not of the type requested,
1264 the value returned is undefined. To check if an error occurred,
1265 use the field_error() function after accessing a field.
1266 """
82839121 1267
6fd49698
PP
1268 return nbt._bt_ctf_get_float(self._d)
1269
1270 def _get_variant(self):
1271 """
1272 Return the variant's selected field.
1273 If the field does not exist or is not of the type requested,
1274 the value returned is undefined. To check if an error occurred,
1275 use the field_error() function after accessing a field.
1276 """
82839121 1277
6fd49698
PP
1278 return nbt._bt_ctf_get_variant(self._d)
1279
1280 def _get_struct_field_count(self):
1281 """
1282 Return the number of fields contained in the structure.
1283 If the field does not exist or is not of the type requested,
1284 the value returned is undefined.
1285 """
82839121 1286
6fd49698
PP
1287 return nbt._bt_ctf_get_struct_field_count(self._d)
1288
1289 def _get_struct_field_at(self, i):
1290 """
1291 Return the structure's field at position i.
1292 If the field does not exist or is not of the type requested,
1293 the value returned is undefined. To check if an error occurred,
1294 use the field_error() function after accessing a field.
1295 """
82839121 1296
6fd49698
PP
1297 return nbt._bt_ctf_get_struct_field_index(self._d, i)
1298
1299 @property
1300 def value(self):
1301 """
1302 Return the value associated with the field according to its type.
1303 Return None on error.
1304 """
82839121 1305
6fd49698
PP
1306 id = self.type
1307 value = None
1308
1309 if id == CTFTypeId.STRING:
1310 value = self._get_str()
1311 elif id == CTFTypeId.ARRAY:
1312 element_decl = self.declaration.element_declaration
82839121 1313
6fd49698
PP
1314 if ((element_decl.type == CTFTypeId.INTEGER
1315 and element_decl.length == 8)
1316 and (element_decl.encoding == CTFStringEncoding.ASCII or element_decl.encoding == CTFStringEncoding.UTF8)):
1317 value = nbt._bt_python_get_array_string(self._d)
1318 else:
1319 value = []
82839121 1320
6fd49698
PP
1321 for i in range(self.declaration.length):
1322 element = self._get_array_element_at(i)
1323 value.append(element.value)
1324 elif id == CTFTypeId.INTEGER:
1325 if self.declaration.signedness == 0:
1326 value = self._get_uint64()
1327 else:
1328 value = self._get_int64()
1329 elif id == CTFTypeId.ENUM:
1330 value = self._get_enum_str()
1331 elif id == CTFTypeId.SEQUENCE:
1332 element_decl = self.declaration.element_declaration
82839121 1333
6fd49698
PP
1334 if ((element_decl.type == CTFTypeId.INTEGER
1335 and element_decl.length == 8)
1336 and (element_decl.encoding == CTFStringEncoding.ASCII or element_decl.encoding == CTFStringEncoding.UTF8)):
1337 value = nbt._bt_python_get_sequence_string(self._d)
1338 else:
1339 seq_len = self._get_sequence_len()
1340 value = []
82839121 1341
6fd49698
PP
1342 for i in range(seq_len):
1343 evDef = self._get_sequence_element_at(i)
1344 value.append(evDef.value)
1345 elif id == CTFTypeId.FLOAT:
1346 value = self._get_float()
1347 elif id == CTFTypeId.VARIANT:
1348 variant = _Definition.__new__(_Definition)
1349 variant._d = self._get_variant()
1350 value = variant.value
1351 elif id == CTFTypeId.STRUCT:
1352 value = {}
82839121 1353
6fd49698
PP
1354 for i in range(self._get_struct_field_count()):
1355 member = _Definition(self._get_struct_field_at(i), self.scope)
1356 value[member.name] = member.value
1357
1358 if field_error():
1359 raise FieldError(
1360 "Error occurred while accessing field {} of type {}".format(
1361 self.name,
1362 CTFTypeId.type_name(id)))
82839121 1363
6fd49698
PP
1364 return value
1365
1366 @property
1367 def scope(self):
1368 """Return the scope of a field or None on error."""
82839121 1369
6fd49698
PP
1370 return self._s
1371
1372
1373class CTFWriter:
1374 # Used to compare to -1ULL in error checks
1375 _MAX_UINT64 = 0xFFFFFFFFFFFFFFFF
1376
6fd49698 1377 class EnumerationMapping:
82839121
PP
1378 """
1379 Enumeration mapping class. start and end values are inclusive.
1380 """
6fd49698
PP
1381
1382 def __init__(self, name, start, end):
1383 self.name = name
1384 self.start = start
1385 self.end = end
1386
1387 class Clock:
6fd49698
PP
1388 def __init__(self, name):
1389 self._c = nbt._bt_ctf_clock_create(name)
82839121 1390
6fd49698
PP
1391 if self._c is None:
1392 raise ValueError("Invalid clock name.")
1393
1394 def __del__(self):
1395 nbt._bt_ctf_clock_put(self._c)
1396
6fd49698
PP
1397 @property
1398 def name(self):
82839121
PP
1399 """
1400 Get the clock's name.
1401 """
1402
6fd49698 1403 name = nbt._bt_ctf_clock_get_name(self._c)
82839121 1404
6fd49698
PP
1405 if name is None:
1406 raise ValueError("Invalid clock instance.")
82839121 1407
6fd49698
PP
1408 return name
1409
6fd49698
PP
1410 @property
1411 def description(self):
82839121
PP
1412 """
1413 Get the clock's description. None if unset.
1414 """
1415
6fd49698
PP
1416 return nbt._bt_ctf_clock_get_description(self._c)
1417
6fd49698
PP
1418 @description.setter
1419 def description(self, desc):
82839121
PP
1420 """
1421 Set the clock's description. The description appears in the clock's TSDL
1422 meta-data.
1423 """
1424
6fd49698 1425 ret = nbt._bt_ctf_clock_set_description(self._c, str(desc))
82839121 1426
6fd49698
PP
1427 if ret < 0:
1428 raise ValueError("Invalid clock description.")
1429
6fd49698
PP
1430 @property
1431 def frequency(self):
82839121
PP
1432 """
1433 Get the clock's frequency (Hz).
1434 """
1435
6fd49698 1436 freq = nbt._bt_ctf_clock_get_frequency(self._c)
82839121 1437
6fd49698
PP
1438 if freq == CTFWriter._MAX_UINT64:
1439 raise ValueError("Invalid clock instance")
82839121 1440
6fd49698
PP
1441 return freq
1442
6fd49698
PP
1443 @frequency.setter
1444 def frequency(self, freq):
82839121
PP
1445 """
1446 Set the clock's frequency (Hz).
1447 """
1448
6fd49698 1449 ret = nbt._bt_ctf_clock_set_frequency(self._c, freq)
82839121 1450
6fd49698
PP
1451 if ret < 0:
1452 raise ValueError("Invalid frequency value.")
1453
6fd49698
PP
1454 @property
1455 def precision(self):
82839121
PP
1456 """
1457 Get the clock's precision (in clock ticks).
1458 """
1459
6fd49698 1460 precision = nbt._bt_ctf_clock_get_precision(self._c)
82839121 1461
6fd49698
PP
1462 if precision == CTFWriter._MAX_UINT64:
1463 raise ValueError("Invalid clock instance")
82839121 1464
6fd49698
PP
1465 return precision
1466
6fd49698
PP
1467 @precision.setter
1468 def precision(self, precision):
82839121
PP
1469 """
1470 Set the clock's precision (in clock ticks).
1471 """
1472
6fd49698
PP
1473 ret = nbt._bt_ctf_clock_set_precision(self._c, precision)
1474
6fd49698
PP
1475 @property
1476 def offset_seconds(self):
82839121
PP
1477 """
1478 Get the clock's offset in seconds from POSIX.1 Epoch.
1479 """
1480
6fd49698 1481 offset_s = nbt._bt_ctf_clock_get_offset_s(self._c)
82839121 1482
6fd49698
PP
1483 if offset_s == CTFWriter._MAX_UINT64:
1484 raise ValueError("Invalid clock instance")
82839121 1485
6fd49698
PP
1486 return offset_s
1487
6fd49698
PP
1488 @offset_seconds.setter
1489 def offset_seconds(self, offset_s):
82839121
PP
1490 """
1491 Set the clock's offset in seconds from POSIX.1 Epoch.
1492 """
1493
6fd49698 1494 ret = nbt._bt_ctf_clock_set_offset_s(self._c, offset_s)
82839121 1495
6fd49698
PP
1496 if ret < 0:
1497 raise ValueError("Invalid offset value.")
1498
6fd49698
PP
1499 @property
1500 def offset(self):
82839121
PP
1501 """
1502 Get the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1503 """
1504
6fd49698 1505 offset = nbt._bt_ctf_clock_get_offset(self._c)
82839121 1506
6fd49698
PP
1507 if offset == CTFWriter._MAX_UINT64:
1508 raise ValueError("Invalid clock instance")
82839121 1509
6fd49698
PP
1510 return offset
1511
6fd49698
PP
1512 @offset.setter
1513 def offset(self, offset):
82839121
PP
1514 """
1515 Set the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1516 """
1517
6fd49698 1518 ret = nbt._bt_ctf_clock_set_offset(self._c, offset)
82839121 1519
6fd49698
PP
1520 if ret < 0:
1521 raise ValueError("Invalid offset value.")
1522
6fd49698
PP
1523 @property
1524 def absolute(self):
82839121
PP
1525 """
1526 Get a clock's absolute attribute. A clock is absolute if the clock
1527 is a global reference across the trace's other clocks.
1528 """
1529
6fd49698 1530 is_absolute = nbt._bt_ctf_clock_get_is_absolute(self._c)
82839121 1531
6fd49698
PP
1532 if is_absolute == -1:
1533 raise ValueError("Invalid clock instance")
82839121 1534
6fd49698
PP
1535 return False if is_absolute == 0 else True
1536
6fd49698
PP
1537 @absolute.setter
1538 def absolute(self, is_absolute):
82839121
PP
1539 """
1540 Set a clock's absolute attribute. A clock is absolute if the clock
1541 is a global reference across the trace's other clocks.
1542 """
1543
6fd49698 1544 ret = nbt._bt_ctf_clock_set_is_absolute(self._c, int(is_absolute))
82839121 1545
6fd49698 1546 if ret < 0:
82839121 1547 raise ValueError("Could not set the clock's absolute attribute.")
6fd49698 1548
6fd49698
PP
1549 @property
1550 def uuid(self):
82839121
PP
1551 """
1552 Get a clock's UUID (an object of type UUID).
1553 """
1554
6fd49698 1555 uuid_list = []
82839121 1556
6fd49698
PP
1557 for i in range(16):
1558 ret, value = nbt._bt_python_ctf_clock_get_uuid_index(self._c, i)
82839121 1559
6fd49698
PP
1560 if ret < 0:
1561 raise ValueError("Invalid clock instance")
82839121 1562
6fd49698 1563 uuid_list.append(value)
82839121 1564
6fd49698
PP
1565 return UUID(bytes=bytes(uuid_list))
1566
6fd49698
PP
1567 @uuid.setter
1568 def uuid(self, uuid):
82839121
PP
1569 """
1570 Set a clock's UUID (an object of type UUID).
1571 """
1572
6fd49698 1573 uuid_bytes = uuid.bytes
82839121 1574
6fd49698 1575 if len(uuid_bytes) != 16:
82839121
PP
1576 raise ValueError("Invalid UUID provided. UUID length must be 16 bytes")
1577
6fd49698 1578 for i in range(len(uuid_bytes)):
82839121
PP
1579 ret = nbt._bt_python_ctf_clock_set_uuid_index(self._c, i,
1580 uuid_bytes[i])
1581
6fd49698
PP
1582 if ret < 0:
1583 raise ValueError("Invalid clock instance")
1584
6fd49698
PP
1585 @property
1586 def time(self):
82839121
PP
1587 """
1588 Get the current time in nanoseconds since the clock's origin (offset and
1589 offset_s attributes).
1590 """
1591
6fd49698 1592 time = nbt._bt_ctf_clock_get_time(self._c)
82839121 1593
6fd49698
PP
1594 if time == CTFWriter._MAX_UINT64:
1595 raise ValueError("Invalid clock instance")
82839121 1596
6fd49698
PP
1597 return time
1598
6fd49698
PP
1599 @time.setter
1600 def time(self, time):
82839121
PP
1601 """
1602 Set the current time in nanoseconds since the clock's origin (offset and
1603 offset_s attributes). The clock's value will be sampled as events are
1604 appended to a stream.
1605 """
1606
6fd49698 1607 ret = nbt._bt_ctf_clock_set_time(self._c, time)
82839121 1608
6fd49698
PP
1609 if ret < 0:
1610 raise ValueError("Invalid time value.")
1611
1612 class FieldDeclaration:
6fd49698
PP
1613 """
1614 FieldDeclaration should not be instantiated directly. Instantiate
1615 one of the concrete FieldDeclaration classes.
1616 """
82839121 1617
6fd49698
PP
1618 class IntegerBase:
1619 # These values are based on the bt_ctf_integer_base enum
1620 # declared in event-types.h.
1621 INTEGER_BASE_UNKNOWN = -1
1622 INTEGER_BASE_BINARY = 2
1623 INTEGER_BASE_OCTAL = 8
1624 INTEGER_BASE_DECIMAL = 10
1625 INTEGER_BASE_HEXADECIMAL = 16
1626
1627 def __init__(self):
1628 if self._ft is None:
1629 raise ValueError("FieldDeclaration creation failed.")
1630
1631 def __del__(self):
1632 nbt._bt_ctf_field_type_put(self._ft)
1633
1634 @staticmethod
1635 def _create_field_declaration_from_native_instance(
1636 native_field_declaration):
1637 type_dict = {
1638 CTFTypeId.INTEGER: CTFWriter.IntegerFieldDeclaration,
1639 CTFTypeId.FLOAT: CTFWriter.FloatFieldDeclaration,
1640 CTFTypeId.ENUM: CTFWriter.EnumerationFieldDeclaration,
1641 CTFTypeId.STRING: CTFWriter.StringFieldDeclaration,
1642 CTFTypeId.STRUCT: CTFWriter.StructureFieldDeclaration,
1643 CTFTypeId.VARIANT: CTFWriter.VariantFieldDeclaration,
1644 CTFTypeId.ARRAY: CTFWriter.ArrayFieldDeclaration,
1645 CTFTypeId.SEQUENCE: CTFWriter.SequenceFieldDeclaration
1646 }
1647
82839121
PP
1648 field_type_id = nbt._bt_ctf_field_type_get_type_id(native_field_declaration)
1649
6fd49698
PP
1650 if field_type_id == CTFTypeId.UNKNOWN:
1651 raise TypeError("Invalid field instance")
1652
1653 declaration = CTFWriter.Field.__new__(CTFWriter.Field)
1654 declaration._ft = native_field_declaration
1655 declaration.__class__ = type_dict[field_type_id]
82839121 1656
6fd49698
PP
1657 return declaration
1658
6fd49698
PP
1659 @property
1660 def alignment(self):
82839121
PP
1661 """
1662 Get the field declaration's alignment. Returns -1 on error.
1663 """
1664
6fd49698
PP
1665 return nbt._bt_ctf_field_type_get_alignment(self._ft)
1666
6fd49698
PP
1667 @alignment.setter
1668 def alignment(self, alignment):
82839121
PP
1669 """
1670 Set the field declaration's alignment. Defaults to 1 (bit-aligned). However,
1671 some types, such as structures and string, may impose other alignment
1672 constraints.
1673 """
1674
6fd49698 1675 ret = nbt._bt_ctf_field_type_set_alignment(self._ft, alignment)
82839121 1676
6fd49698
PP
1677 if ret < 0:
1678 raise ValueError("Invalid alignment value.")
1679
6fd49698
PP
1680 @property
1681 def byte_order(self):
82839121
PP
1682 """
1683 Get the field declaration's byte order. One of the ByteOrder's constant.
1684 """
1685
6fd49698
PP
1686 return nbt._bt_ctf_field_type_get_byte_order(self._ft)
1687
6fd49698
PP
1688 @byte_order.setter
1689 def byte_order(self, byte_order):
82839121
PP
1690 """
1691 Set the field declaration's byte order. Use constants defined in the ByteOrder
1692 class.
1693 """
1694
6fd49698 1695 ret = nbt._bt_ctf_field_type_set_byte_order(self._ft, byte_order)
82839121 1696
6fd49698
PP
1697 if ret < 0:
1698 raise ValueError("Could not set byte order value.")
1699
1700 class IntegerFieldDeclaration(FieldDeclaration):
6fd49698 1701 def __init__(self, size):
82839121
PP
1702 """
1703 Create a new integer field declaration of the given size.
1704 """
6fd49698
PP
1705 self._ft = nbt._bt_ctf_field_type_integer_create(size)
1706 super().__init__()
1707
6fd49698
PP
1708 @property
1709 def size(self):
82839121
PP
1710 """
1711 Get an integer's size.
1712 """
1713
6fd49698 1714 ret = nbt._bt_ctf_field_type_integer_get_size(self._ft)
82839121 1715
6fd49698
PP
1716 if ret < 0:
1717 raise ValueError("Could not get Integer's size attribute.")
1718 else:
1719 return ret
1720
6fd49698
PP
1721 @property
1722 def signed(self):
82839121
PP
1723 """
1724 Get an integer's signedness attribute.
1725 """
1726
6fd49698 1727 ret = nbt._bt_ctf_field_type_integer_get_signed(self._ft)
82839121 1728
6fd49698
PP
1729 if ret < 0:
1730 raise ValueError("Could not get Integer's signed attribute.")
1731 elif ret > 0:
1732 return True
1733 else:
1734 return False
1735
6fd49698
PP
1736 @signed.setter
1737 def signed(self, signed):
82839121
PP
1738 """
1739 Set an integer's signedness attribute.
1740 """
1741
6fd49698 1742 ret = nbt._bt_ctf_field_type_integer_set_signed(self._ft, signed)
82839121 1743
6fd49698
PP
1744 if ret < 0:
1745 raise ValueError("Could not set Integer's signed attribute.")
1746
6fd49698
PP
1747 @property
1748 def base(self):
82839121
PP
1749 """
1750 Get the integer's base used to pretty-print the resulting trace.
1751 Returns a constant from the FieldDeclaration.IntegerBase class.
1752 """
1753
6fd49698
PP
1754 return nbt._bt_ctf_field_type_integer_get_base(self._ft)
1755
6fd49698
PP
1756 @base.setter
1757 def base(self, base):
82839121
PP
1758 """
1759 Set the integer's base used to pretty-print the resulting trace.
1760 The base must be a constant of the FieldDeclarationIntegerBase class.
1761 """
1762
6fd49698 1763 ret = nbt._bt_ctf_field_type_integer_set_base(self._ft, base)
82839121 1764
6fd49698
PP
1765 if ret < 0:
1766 raise ValueError("Could not set Integer's base.")
1767
6fd49698
PP
1768 @property
1769 def encoding(self):
82839121
PP
1770 """
1771 Get the integer's encoding (one of the constants of the
1772 CTFStringEncoding class).
1773 Returns a constant from the CTFStringEncoding class.
1774 """
1775
6fd49698
PP
1776 return nbt._bt_ctf_field_type_integer_get_encoding(self._ft)
1777
6fd49698
PP
1778 @encoding.setter
1779 def encoding(self, encoding):
82839121
PP
1780 """
1781 An integer encoding may be set to signal that the integer must be printed
1782 as a text character. Must be a constant from the CTFStringEncoding class.
1783 """
1784
6fd49698 1785 ret = nbt._bt_ctf_field_type_integer_set_encoding(self._ft, encoding)
82839121 1786
6fd49698
PP
1787 if ret < 0:
1788 raise ValueError("Could not set Integer's encoding.")
1789
1790 class EnumerationFieldDeclaration(FieldDeclaration):
6fd49698 1791 def __init__(self, integer_type):
82839121
PP
1792 """
1793 Create a new enumeration field declaration with the given underlying container type.
1794 """
1795 isinst = isinstance(integer_type, CTFWriter.IntegerFieldDeclaration)
1796
1797 if integer_type is None or not isinst:
6fd49698
PP
1798 raise TypeError("Invalid integer container.")
1799
1800 self._ft = nbt._bt_ctf_field_type_enumeration_create(integer_type._ft)
1801 super().__init__()
1802
6fd49698
PP
1803 @property
1804 def container(self):
82839121
PP
1805 """
1806 Get the enumeration's underlying container type.
1807 """
1808
6fd49698 1809 ret = nbt._bt_ctf_field_type_enumeration_get_container_type(self._ft)
82839121 1810
6fd49698
PP
1811 if ret is None:
1812 raise TypeError("Invalid enumeration declaration")
6fd49698 1813
82839121 1814 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(ret)
6fd49698
PP
1815
1816 def add_mapping(self, name, range_start, range_end):
82839121
PP
1817 """
1818 Add a mapping to the enumeration. The range's values are inclusive.
1819 """
1820
6fd49698 1821 if range_start < 0 or range_end < 0:
82839121
PP
1822 ret = nbt._bt_ctf_field_type_enumeration_add_mapping(self._ft,
1823 str(name),
1824 range_start,
1825 range_end)
6fd49698 1826 else:
82839121
PP
1827 ret = nbt._bt_ctf_field_type_enumeration_add_mapping_unsigned(self._ft,
1828 str(name),
1829 range_start,
1830 range_end)
6fd49698
PP
1831
1832 if ret < 0:
82839121 1833 raise ValueError("Could not add mapping to enumeration declaration.")
6fd49698 1834
6fd49698
PP
1835 @property
1836 def mappings(self):
82839121
PP
1837 """
1838 Generator returning instances of EnumerationMapping.
1839 """
1840
6fd49698
PP
1841 signed = self.container.signed
1842
1843 count = nbt._bt_ctf_field_type_enumeration_get_mapping_count(self._ft)
82839121 1844
6fd49698
PP
1845 for i in range(count):
1846 if signed:
82839121 1847 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, i)
6fd49698 1848 else:
82839121 1849 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, i)
6fd49698
PP
1850
1851 if len(ret) != 3:
82839121
PP
1852 msg = "Could not get Enumeration mapping at index {}".format(i)
1853 raise TypeError(msg)
1854
6fd49698
PP
1855 name, range_start, range_end = ret
1856 yield CTFWriter.EnumerationMapping(name, range_start, range_end)
1857
6fd49698 1858 def get_mapping_by_name(self, name):
82839121
PP
1859 """
1860 Get a mapping by name (EnumerationMapping).
1861 """
1862
1863 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_name(self._ft, name)
1864
6fd49698
PP
1865 if index < 0:
1866 return None
1867
1868 if self.container.signed:
82839121 1869 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, index)
6fd49698 1870 else:
82839121 1871 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, index)
6fd49698
PP
1872
1873 if len(ret) != 3:
82839121
PP
1874 msg = "Could not get Enumeration mapping at index {}".format(i)
1875 raise TypeError(msg)
1876
6fd49698 1877 name, range_start, range_end = ret
6fd49698 1878
82839121 1879 return CTFWriter.EnumerationMapping(name, range_start, range_end)
6fd49698
PP
1880
1881 def get_mapping_by_value(self, value):
82839121
PP
1882 """
1883 Get a mapping by value (EnumerationMapping).
1884 """
1885
6fd49698 1886 if value < 0:
82839121 1887 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_value(self._ft, value)
6fd49698 1888 else:
82839121 1889 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value(self._ft, value)
6fd49698
PP
1890
1891 if index < 0:
1892 return None
1893
1894 if self.container.signed:
82839121 1895 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, index)
6fd49698 1896 else:
82839121 1897 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, index)
6fd49698
PP
1898
1899 if len(ret) != 3:
82839121
PP
1900 msg = "Could not get Enumeration mapping at index {}".format(i)
1901 raise TypeError(msg)
1902
6fd49698 1903 name, range_start, range_end = ret
82839121 1904
6fd49698
PP
1905 return CTFWriter.EnumerationMapping(name, range_start, range_end)
1906
1907 class FloatFieldDeclaration(FieldDeclaration):
1908 FLT_EXP_DIG = 8
1909 DBL_EXP_DIG = 11
1910 FLT_MANT_DIG = 24
1911 DBL_MANT_DIG = 53
1912
6fd49698 1913 def __init__(self):
82839121
PP
1914 """
1915 Create a new floating point field declaration.
1916 """
1917
6fd49698
PP
1918 self._ft = nbt._bt_ctf_field_type_floating_point_create()
1919 super().__init__()
1920
6fd49698
PP
1921 @property
1922 def exponent_digits(self):
82839121
PP
1923 """
1924 Get the number of exponent digits used to store the floating point field.
1925 """
1926
1927 ret = nbt._bt_ctf_field_type_floating_point_get_exponent_digits(self._ft)
1928
6fd49698
PP
1929 if ret < 0:
1930 raise TypeError(
1931 "Could not get Floating point exponent digit count")
82839121 1932
6fd49698
PP
1933 return ret
1934
6fd49698
PP
1935 @exponent_digits.setter
1936 def exponent_digits(self, exponent_digits):
82839121
PP
1937 """
1938 Set the number of exponent digits to use to store the floating point field.
1939 The only values currently supported are FLT_EXP_DIG and DBL_EXP_DIG which
1940 are defined as constants of this class.
1941 """
1942
1943 ret = nbt._bt_ctf_field_type_floating_point_set_exponent_digits(self._ft,
1944 exponent_digits)
1945
6fd49698
PP
1946 if ret < 0:
1947 raise ValueError("Could not set exponent digit count.")
1948
6fd49698
PP
1949 @property
1950 def mantissa_digits(self):
82839121
PP
1951 """
1952 Get the number of mantissa digits used to store the floating point field.
1953 """
1954
1955 ret = nbt._bt_ctf_field_type_floating_point_get_mantissa_digits(self._ft)
1956
6fd49698 1957 if ret < 0:
82839121
PP
1958 raise TypeError("Could not get Floating point mantissa digit count")
1959
6fd49698
PP
1960 return ret
1961
6fd49698
PP
1962 @mantissa_digits.setter
1963 def mantissa_digits(self, mantissa_digits):
82839121
PP
1964 """
1965 Set the number of mantissa digits to use to store the floating point field.
1966 The only values currently supported are FLT_MANT_DIG and DBL_MANT_DIG which
1967 are defined as constants of this class.
1968 """
1969
1970 ret = nbt._bt_ctf_field_type_floating_point_set_mantissa_digits(self._ft,
1971 mantissa_digits)
1972
6fd49698
PP
1973 if ret < 0:
1974 raise ValueError("Could not set mantissa digit count.")
1975
da43007d
PP
1976 class FloatingPointFieldDeclaration(FloatFieldDeclaration):
1977 pass
1978
6fd49698 1979 class StructureFieldDeclaration(FieldDeclaration):
6fd49698 1980 def __init__(self):
82839121
PP
1981 """
1982 Create a new structure field declaration.
1983 """
1984
6fd49698
PP
1985 self._ft = nbt._bt_ctf_field_type_structure_create()
1986 super().__init__()
1987
6fd49698 1988 def add_field(self, field_type, field_name):
82839121
PP
1989 """
1990 Add a field of type "field_type" to the structure.
1991 """
1992
1993 ret = nbt._bt_ctf_field_type_structure_add_field(self._ft,
1994 field_type._ft,
1995 str(field_name))
1996
6fd49698
PP
1997 if ret < 0:
1998 raise ValueError("Could not add field to structure.")
1999
6fd49698
PP
2000 @property
2001 def fields(self):
82839121
PP
2002 """
2003 Generator returning the structure's field as tuples of (field name, field declaration).
2004 """
2005
6fd49698 2006 count = nbt._bt_ctf_field_type_structure_get_field_count(self._ft)
82839121 2007
6fd49698
PP
2008 if count < 0:
2009 raise TypeError("Could not get Structure field count")
2010
2011 for i in range(count):
82839121
PP
2012 field_name = nbt._bt_python_ctf_field_type_structure_get_field_name(self._ft, i)
2013
6fd49698 2014 if field_name is None:
82839121
PP
2015 msg = "Could not get Structure field name at index {}".format(i)
2016 raise TypeError(msg)
2017
2018 field_type_native = nbt._bt_python_ctf_field_type_structure_get_field_type(self._ft, i)
6fd49698 2019
6fd49698 2020 if field_type_native is None:
82839121
PP
2021 msg = "Could not get Structure field type at index {}".format(i)
2022 raise TypeError(msg)
6fd49698 2023
82839121 2024 field_type = CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698
PP
2025 yield (field_name, field_type)
2026
6fd49698 2027 def get_field_by_name(self, name):
82839121
PP
2028 """
2029 Get a field declaration by name (FieldDeclaration).
2030 """
6fd49698 2031
82839121 2032 field_type_native = nbt._bt_ctf_field_type_structure_get_field_type_by_name(self._ft, name)
6fd49698 2033
82839121
PP
2034 if field_type_native is None:
2035 msg = "Could not find Structure field with name {}".format(name)
2036 raise TypeError(msg)
6fd49698 2037
82839121 2038 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698 2039
82839121 2040 class VariantFieldDeclaration(FieldDeclaration):
6fd49698 2041 def __init__(self, enum_tag, tag_name):
82839121
PP
2042 """
2043 Create a new variant field declaration.
2044 """
2045
2046 isinst = isinstance(enum_tag, CTFWriter.EnumerationFieldDeclaration)
2047 if enum_tag is None or not isinst:
2048 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
6fd49698 2049
82839121
PP
2050 self._ft = nbt._bt_ctf_field_type_variant_create(enum_tag._ft,
2051 str(tag_name))
6fd49698
PP
2052 super().__init__()
2053
6fd49698
PP
2054 @property
2055 def tag_name(self):
82839121
PP
2056 """
2057 Get the variant's tag name.
2058 """
2059
6fd49698 2060 ret = nbt._bt_ctf_field_type_variant_get_tag_name(self._ft)
82839121 2061
6fd49698
PP
2062 if ret is None:
2063 raise TypeError("Could not get Variant tag name")
82839121 2064
6fd49698
PP
2065 return ret
2066
6fd49698
PP
2067 @property
2068 def tag_type(self):
82839121
PP
2069 """
2070 Get the variant's tag type.
2071 """
2072
6fd49698 2073 ret = nbt._bt_ctf_field_type_variant_get_tag_type(self._ft)
82839121 2074
6fd49698
PP
2075 if ret is None:
2076 raise TypeError("Could not get Variant tag type")
6fd49698 2077
82839121 2078 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(ret)
6fd49698
PP
2079
2080 def add_field(self, field_type, field_name):
82839121
PP
2081 """
2082 Add a field of type "field_type" to the variant.
2083 """
2084
2085 ret = nbt._bt_ctf_field_type_variant_add_field(self._ft,
2086 field_type._ft,
2087 str(field_name))
2088
6fd49698
PP
2089 if ret < 0:
2090 raise ValueError("Could not add field to variant.")
2091
6fd49698
PP
2092 @property
2093 def fields(self):
82839121
PP
2094 """
2095 Generator returning the variant's field as tuples of (field name, field declaration).
2096 """
2097
6fd49698 2098 count = nbt._bt_ctf_field_type_variant_get_field_count(self._ft)
82839121 2099
6fd49698
PP
2100 if count < 0:
2101 raise TypeError("Could not get Variant field count")
2102
2103 for i in range(count):
82839121
PP
2104 field_name = nbt._bt_python_ctf_field_type_variant_get_field_name(self._ft, i)
2105
6fd49698 2106 if field_name is None:
82839121
PP
2107 msg = "Could not get Variant field name at index {}".format(i)
2108 raise TypeError(msg)
2109
2110 field_type_native = nbt._bt_python_ctf_field_type_variant_get_field_type(self._ft, i)
6fd49698 2111
6fd49698 2112 if field_type_native is None:
82839121
PP
2113 msg = "Could not get Variant field type at index {}".format(i)
2114 raise TypeError(msg)
6fd49698 2115
82839121 2116 field_type = CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698
PP
2117 yield (field_name, field_type)
2118
6fd49698 2119 def get_field_by_name(self, name):
82839121
PP
2120 """
2121 Get a field declaration by name (FieldDeclaration).
2122 """
6fd49698 2123
82839121
PP
2124 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_by_name(self._ft,
2125 name)
6fd49698 2126
82839121
PP
2127 if field_type_native is None:
2128 msg = "Could not find Variant field with name {}".format(name)
2129 raise TypeError(msg)
2130
2131 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698
PP
2132
2133 def get_field_from_tag(self, tag):
82839121
PP
2134 """
2135 Get a field declaration from tag (EnumerationField).
2136 """
6fd49698 2137
82839121 2138 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_from_tag(self._ft, tag._f)
6fd49698 2139
82839121
PP
2140 if field_type_native is None:
2141 msg = "Could not find Variant field with tag value {}".format(tag.value)
2142 raise TypeError(msg)
6fd49698 2143
82839121 2144 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698 2145
82839121 2146 class ArrayFieldDeclaration(FieldDeclaration):
6fd49698 2147 def __init__(self, element_type, length):
82839121
PP
2148 """
2149 Create a new array field declaration.
2150 """
2151
2152 self._ft = nbt._bt_ctf_field_type_array_create(element_type._ft,
2153 length)
6fd49698
PP
2154 super().__init__()
2155
6fd49698
PP
2156 @property
2157 def element_type(self):
82839121
PP
2158 """
2159 Get the array's element type.
2160 """
2161
6fd49698 2162 ret = nbt._bt_ctf_field_type_array_get_element_type(self._ft)
82839121 2163
6fd49698
PP
2164 if ret is None:
2165 raise TypeError("Could not get Array element type")
6fd49698 2166
82839121
PP
2167 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(ret)
2168
6fd49698
PP
2169 @property
2170 def length(self):
82839121
PP
2171 """
2172 Get the array's length.
2173 """
2174
6fd49698 2175 ret = nbt._bt_ctf_field_type_array_get_length(self._ft)
82839121 2176
6fd49698
PP
2177 if ret < 0:
2178 raise TypeError("Could not get Array length")
82839121 2179
6fd49698
PP
2180 return ret
2181
2182 class SequenceFieldDeclaration(FieldDeclaration):
6fd49698 2183 def __init__(self, element_type, length_field_name):
82839121
PP
2184 """
2185 Create a new sequence field declaration.
2186 """
2187
2188 self._ft = nbt._bt_ctf_field_type_sequence_create(element_type._ft,
2189 str(length_field_name))
6fd49698
PP
2190 super().__init__()
2191
6fd49698
PP
2192 @property
2193 def element_type(self):
82839121
PP
2194 """
2195 Get the sequence's element type.
2196 """
2197
6fd49698 2198 ret = nbt._bt_ctf_field_type_sequence_get_element_type(self._ft)
82839121 2199
6fd49698
PP
2200 if ret is None:
2201 raise TypeError("Could not get Sequence element type")
6fd49698 2202
82839121
PP
2203 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(ret)
2204
6fd49698
PP
2205 @property
2206 def length_field_name(self):
82839121
PP
2207 """
2208 Get the sequence's length field name.
2209 """
2210
6fd49698 2211 ret = nbt._bt_ctf_field_type_sequence_get_length_field_name(self._ft)
82839121 2212
6fd49698
PP
2213 if ret is None:
2214 raise TypeError("Could not get Sequence length field name")
82839121 2215
6fd49698
PP
2216 return ret
2217
2218 class StringFieldDeclaration(FieldDeclaration):
6fd49698 2219 def __init__(self):
82839121
PP
2220 """
2221 Create a new string field declaration.
2222 """
2223
6fd49698
PP
2224 self._ft = nbt._bt_ctf_field_type_string_create()
2225 super().__init__()
2226
6fd49698
PP
2227 @property
2228 def encoding(self):
82839121
PP
2229 """
2230 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
2231 """
2232
6fd49698
PP
2233 return nbt._bt_ctf_field_type_string_get_encoding(self._ft)
2234
6fd49698
PP
2235 @encoding.setter
2236 def encoding(self, encoding):
82839121
PP
2237 """
2238 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
2239 """
2240
6fd49698
PP
2241 ret = nbt._bt_ctf_field_type_string_set_encoding(self._ft, encoding)
2242 if ret < 0:
2243 raise ValueError("Could not set string encoding.")
2244
6fd49698
PP
2245 @staticmethod
2246 def create_field(field_type):
82839121
PP
2247 """
2248 Create an instance of a field.
2249 """
2250 isinst = isinstance(field_type, CTFWriter.FieldDeclaration)
2251
2252 if field_type is None or not isinst:
2253 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
6fd49698
PP
2254
2255 if isinstance(field_type, CTFWriter.IntegerFieldDeclaration):
2256 return CTFWriter.IntegerField(field_type)
2257 elif isinstance(field_type, CTFWriter.EnumerationFieldDeclaration):
2258 return CTFWriter.EnumerationField(field_type)
2259 elif isinstance(field_type, CTFWriter.FloatFieldDeclaration):
60318a5f 2260 return CTFWriter.FloatingPointField(field_type)
6fd49698
PP
2261 elif isinstance(field_type, CTFWriter.StructureFieldDeclaration):
2262 return CTFWriter.StructureField(field_type)
2263 elif isinstance(field_type, CTFWriter.VariantFieldDeclaration):
2264 return CTFWriter.VariantField(field_type)
2265 elif isinstance(field_type, CTFWriter.ArrayFieldDeclaration):
2266 return CTFWriter.ArrayField(field_type)
2267 elif isinstance(field_type, CTFWriter.SequenceFieldDeclaration):
2268 return CTFWriter.SequenceField(field_type)
2269 elif isinstance(field_type, CTFWriter.StringFieldDeclaration):
2270 return CTFWriter.StringField(field_type)
2271
2272 class Field:
6fd49698
PP
2273 """
2274 Base class, do not instantiate.
2275 """
2276
2277 def __init__(self, field_type):
2278 if not isinstance(field_type, CTFWriter.FieldDeclaration):
2279 raise TypeError("Invalid field_type argument.")
2280
2281 self._f = nbt._bt_ctf_field_create(field_type._ft)
82839121 2282
6fd49698
PP
2283 if self._f is None:
2284 raise ValueError("Field creation failed.")
2285
2286 def __del__(self):
2287 nbt._bt_ctf_field_put(self._f)
2288
2289 @staticmethod
2290 def _create_field_from_native_instance(native_field_instance):
2291 type_dict = {
2292 CTFTypeId.INTEGER: CTFWriter.IntegerField,
60318a5f 2293 CTFTypeId.FLOAT: CTFWriter.FloatingPointField,
6fd49698
PP
2294 CTFTypeId.ENUM: CTFWriter.EnumerationField,
2295 CTFTypeId.STRING: CTFWriter.StringField,
2296 CTFTypeId.STRUCT: CTFWriter.StructureField,
2297 CTFTypeId.VARIANT: CTFWriter.VariantField,
2298 CTFTypeId.ARRAY: CTFWriter.ArrayField,
2299 CTFTypeId.SEQUENCE: CTFWriter.SequenceField
2300 }
2301
2302 field_type = nbt._bt_python_get_field_type(native_field_instance)
82839121 2303
6fd49698
PP
2304 if field_type == CTFTypeId.UNKNOWN:
2305 raise TypeError("Invalid field instance")
2306
2307 field = CTFWriter.Field.__new__(CTFWriter.Field)
2308 field._f = native_field_instance
2309 field.__class__ = type_dict[field_type]
82839121 2310
6fd49698
PP
2311 return field
2312
2313 @property
2314 def declaration(self):
2315 native_field_type = nbt._bt_ctf_field_get_type(self._f)
82839121 2316
6fd49698
PP
2317 if native_field_type is None:
2318 raise TypeError("Invalid field instance")
2319 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(
2320 native_field_type)
2321
2322 class IntegerField(Field):
6fd49698
PP
2323 @property
2324 def value(self):
82839121
PP
2325 """
2326 Get an integer field's value.
2327 """
2328
6fd49698 2329 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
82839121 2330
6fd49698
PP
2331 if signedness < 0:
2332 raise TypeError("Invalid integer instance.")
2333
2334 if signedness == 0:
2335 ret, value = nbt._bt_ctf_field_unsigned_integer_get_value(self._f)
2336 else:
2337 ret, value = nbt._bt_ctf_field_signed_integer_get_value(self._f)
2338
2339 if ret < 0:
2340 raise ValueError("Could not get integer field value.")
82839121 2341
6fd49698
PP
2342 return value
2343
6fd49698
PP
2344 @value.setter
2345 def value(self, value):
82839121
PP
2346 """
2347 Set an integer field's value.
2348 """
2349
6fd49698
PP
2350 if not isinstance(value, int):
2351 raise TypeError("IntegerField's value must be an int")
2352
2353 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
2354 if signedness < 0:
2355 raise TypeError("Invalid integer instance.")
2356
2357 if signedness == 0:
2358 ret = nbt._bt_ctf_field_unsigned_integer_set_value(self._f, value)
2359 else:
2360 ret = nbt._bt_ctf_field_signed_integer_set_value(self._f, value)
2361
2362 if ret < 0:
2363 raise ValueError("Could not set integer field value.")
2364
2365 class EnumerationField(Field):
6fd49698
PP
2366 @property
2367 def container(self):
82839121
PP
2368 """
2369 Return the enumeration's underlying container field (an integer field).
2370 """
2371
6fd49698
PP
2372 container = CTFWriter.IntegerField.__new__(CTFWriter.IntegerField)
2373 container._f = nbt._bt_ctf_field_enumeration_get_container(self._f)
82839121 2374
6fd49698
PP
2375 if container._f is None:
2376 raise TypeError("Invalid enumeration field type.")
82839121 2377
6fd49698
PP
2378 return container
2379
6fd49698
PP
2380 @property
2381 def value(self):
82839121
PP
2382 """
2383 Get the enumeration field's mapping name.
2384 """
2385
6fd49698 2386 value = nbt._bt_ctf_field_enumeration_get_mapping_name(self._f)
82839121 2387
6fd49698
PP
2388 if value is None:
2389 raise ValueError("Could not get enumeration's mapping name.")
82839121 2390
6fd49698
PP
2391 return value
2392
6fd49698
PP
2393 @value.setter
2394 def value(self, value):
82839121
PP
2395 """
2396 Set the enumeration field's value. Must be an integer as mapping names
2397 may be ambiguous.
2398 """
2399
6fd49698
PP
2400 if not isinstance(value, int):
2401 raise TypeError("EnumerationField value must be an int")
82839121 2402
6fd49698
PP
2403 self.container.value = value
2404
60318a5f 2405 class FloatingPointField(Field):
6fd49698
PP
2406 @property
2407 def value(self):
82839121
PP
2408 """
2409 Get a floating point field's value.
2410 """
2411
6fd49698 2412 ret, value = nbt._bt_ctf_field_floating_point_get_value(self._f)
82839121 2413
6fd49698
PP
2414 if ret < 0:
2415 raise ValueError("Could not get floating point field value.")
82839121 2416
6fd49698
PP
2417 return value
2418
6fd49698
PP
2419 @value.setter
2420 def value(self, value):
82839121
PP
2421 """
2422 Set a floating point field's value.
2423 """
2424
6fd49698
PP
2425 if not isinstance(value, int) and not isinstance(value, float):
2426 raise TypeError("Value must be either a float or an int")
2427
2428 ret = nbt._bt_ctf_field_floating_point_set_value(self._f, float(value))
82839121 2429
6fd49698
PP
2430 if ret < 0:
2431 raise ValueError("Could not set floating point field value.")
2432
60318a5f
PP
2433 # oops!! This class is provided to ensure backward-compatibility since
2434 # a stable release publicly exposed this abomination.
2435 class FloatFieldingPoint(FloatingPointField):
2436 pass
2437
6fd49698 2438 class StructureField(Field):
82839121
PP
2439 def field(self, field_name):
2440 """
2441 Get the structure's field corresponding to the provided field name.
2442 """
6fd49698 2443
82839121
PP
2444 native_instance = nbt._bt_ctf_field_structure_get_field(self._f,
2445 str(field_name))
6fd49698 2446
6fd49698
PP
2447 if native_instance is None:
2448 raise ValueError("Invalid field_name provided.")
6fd49698 2449
82839121 2450 return CTFWriter.Field._create_field_from_native_instance(native_instance)
6fd49698 2451
82839121 2452 class VariantField(Field):
6fd49698 2453 def field(self, tag):
82839121
PP
2454 """
2455 Return the variant's selected field. The "tag" field is the selector enum field.
2456 """
2457
6fd49698 2458 native_instance = nbt._bt_ctf_field_variant_get_field(self._f, tag._f)
82839121 2459
6fd49698
PP
2460 if native_instance is None:
2461 raise ValueError("Invalid tag provided.")
6fd49698 2462
82839121 2463 return CTFWriter.Field._create_field_from_native_instance(native_instance)
6fd49698 2464
82839121 2465 class ArrayField(Field):
6fd49698 2466 def field(self, index):
82839121
PP
2467 """
2468 Return the array's field at position "index".
2469 """
2470
6fd49698 2471 native_instance = nbt._bt_ctf_field_array_get_field(self._f, index)
82839121 2472
6fd49698
PP
2473 if native_instance is None:
2474 raise IndexError("Invalid index provided.")
6fd49698 2475
82839121 2476 return CTFWriter.Field._create_field_from_native_instance(native_instance)
6fd49698 2477
82839121 2478 class SequenceField(Field):
6fd49698
PP
2479 @property
2480 def length(self):
82839121
PP
2481 """
2482 Get the sequence's length field (IntegerField).
2483 """
2484
6fd49698 2485 native_instance = nbt._bt_ctf_field_sequence_get_length(self._f)
82839121 2486
6fd49698
PP
2487 if native_instance is None:
2488 length = -1
6fd49698 2489
82839121
PP
2490 return CTFWriter.Field._create_field_from_native_instance(native_instance)
2491
6fd49698
PP
2492 @length.setter
2493 def length(self, length_field):
82839121
PP
2494 """
2495 Set the sequence's length field (IntegerField).
2496 """
2497
6fd49698
PP
2498 if not isinstance(length_field, CTFWriter.IntegerField):
2499 raise TypeError("Invalid length field.")
82839121 2500
6fd49698
PP
2501 if length_field.declaration.signed:
2502 raise TypeError("Sequence field length must be unsigned")
82839121 2503
6fd49698 2504 ret = nbt._bt_ctf_field_sequence_set_length(self._f, length_field._f)
82839121 2505
6fd49698
PP
2506 if ret < 0:
2507 raise ValueError("Could not set sequence length.")
2508
6fd49698 2509 def field(self, index):
82839121
PP
2510 """
2511 Return the sequence's field at position "index".
2512 """
2513
6fd49698 2514 native_instance = nbt._bt_ctf_field_sequence_get_field(self._f, index)
82839121 2515
6fd49698
PP
2516 if native_instance is None:
2517 raise ValueError("Could not get sequence element at index.")
6fd49698 2518
82839121 2519 return CTFWriter.Field._create_field_from_native_instance(native_instance)
6fd49698 2520
82839121 2521 class StringField(Field):
6fd49698
PP
2522 @property
2523 def value(self):
82839121
PP
2524 """
2525 Get a string field's value.
2526 """
2527
6fd49698
PP
2528 return nbt._bt_ctf_field_string_get_value(self._f)
2529
6fd49698
PP
2530 @value.setter
2531 def value(self, value):
82839121
PP
2532 """
2533 Set a string field's value.
2534 """
2535
6fd49698 2536 ret = nbt._bt_ctf_field_string_set_value(self._f, str(value))
82839121 2537
6fd49698
PP
2538 if ret < 0:
2539 raise ValueError("Could not set string field value.")
2540
2541 class EventClass:
6fd49698 2542 def __init__(self, name):
82839121
PP
2543 """
2544 Create a new event class of the given name.
2545 """
2546
6fd49698 2547 self._ec = nbt._bt_ctf_event_class_create(name)
82839121 2548
6fd49698
PP
2549 if self._ec is None:
2550 raise ValueError("Event class creation failed.")
2551
2552 def __del__(self):
2553 nbt._bt_ctf_event_class_put(self._ec)
2554
6fd49698 2555 def add_field(self, field_type, field_name):
82839121
PP
2556 """
2557 Add a field of type "field_type" to the event class.
2558 """
2559
2560 ret = nbt._bt_ctf_event_class_add_field(self._ec, field_type._ft,
2561 str(field_name))
2562
6fd49698
PP
2563 if ret < 0:
2564 raise ValueError("Could not add field to event class.")
2565
6fd49698
PP
2566 @property
2567 def name(self):
82839121
PP
2568 """
2569 Get the event class' name.
2570 """
2571
6fd49698 2572 name = nbt._bt_ctf_event_class_get_name(self._ec)
82839121 2573
6fd49698
PP
2574 if name is None:
2575 raise TypeError("Could not get EventClass name")
82839121 2576
6fd49698
PP
2577 return name
2578
6fd49698
PP
2579 @property
2580 def id(self):
82839121
PP
2581 """
2582 Get the event class' id. Returns a negative value if unset.
2583 """
2584
6fd49698 2585 id = nbt._bt_ctf_event_class_get_id(self._ec)
82839121 2586
6fd49698
PP
2587 if id < 0:
2588 raise TypeError("Could not get EventClass id")
82839121 2589
6fd49698
PP
2590 return id
2591
6fd49698
PP
2592 @id.setter
2593 def id(self, id):
82839121
PP
2594 """
2595 Set the event class' id. Throws a TypeError if the event class
2596 is already registered to a stream class.
2597 """
2598
6fd49698 2599 ret = nbt._bt_ctf_event_class_set_id(self._ec, id)
82839121 2600
6fd49698 2601 if ret < 0:
82839121 2602 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
6fd49698 2603
6fd49698
PP
2604 @property
2605 def stream_class(self):
82839121
PP
2606 """
2607 Get the event class' stream class. Returns None if unset.
2608 """
2609 stream_class_native = nbt._bt_ctf_event_class_get_stream_class(self._ec)
2610
6fd49698
PP
2611 if stream_class_native is None:
2612 return None
82839121 2613
6fd49698
PP
2614 stream_class = CTFWriter.StreamClass.__new__(CTFWriter.StreamClass)
2615 stream_class._sc = stream_class_native
82839121 2616
6fd49698
PP
2617 return stream_class
2618
6fd49698
PP
2619 @property
2620 def fields(self):
82839121
PP
2621 """
2622 Generator returning the event class' fields as tuples of (field name, field declaration).
2623 """
2624
6fd49698 2625 count = nbt._bt_ctf_event_class_get_field_count(self._ec)
82839121 2626
6fd49698
PP
2627 if count < 0:
2628 raise TypeError("Could not get EventClass' field count")
2629
2630 for i in range(count):
82839121
PP
2631 field_name = nbt._bt_python_ctf_event_class_get_field_name(self._ec, i)
2632
6fd49698 2633 if field_name is None:
82839121
PP
2634 msg = "Could not get EventClass' field name at index {}".format(i)
2635 raise TypeError(msg)
2636
2637 field_type_native = nbt._bt_python_ctf_event_class_get_field_type(self._ec, i)
6fd49698 2638
6fd49698 2639 if field_type_native is None:
82839121
PP
2640 msg = "Could not get EventClass' field type at index {}".format(i)
2641 raise TypeError(msg)
6fd49698 2642
82839121 2643 field_type = CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698
PP
2644 yield (field_name, field_type)
2645
6fd49698 2646 def get_field_by_name(self, name):
82839121
PP
2647 """
2648 Get a field declaration by name (FieldDeclaration).
2649 """
6fd49698 2650
82839121 2651 field_type_native = nbt._bt_ctf_event_class_get_field_by_name(self._ec, name)
6fd49698 2652
82839121
PP
2653 if field_type_native is None:
2654 msg = "Could not find EventClass field with name {}".format(name)
2655 raise TypeError(msg)
6fd49698 2656
82839121
PP
2657 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
2658
2659 class Event:
6fd49698 2660 def __init__(self, event_class):
82839121
PP
2661 """
2662 Create a new event of the given event class.
2663 """
2664
6fd49698
PP
2665 if not isinstance(event_class, CTFWriter.EventClass):
2666 raise TypeError("Invalid event_class argument.")
2667
2668 self._e = nbt._bt_ctf_event_create(event_class._ec)
82839121 2669
6fd49698
PP
2670 if self._e is None:
2671 raise ValueError("Event creation failed.")
2672
2673 def __del__(self):
2674 nbt._bt_ctf_event_put(self._e)
2675
6fd49698
PP
2676 @property
2677 def event_class(self):
82839121
PP
2678 """
2679 Get the event's class.
2680 """
2681
6fd49698 2682 event_class_native = nbt._bt_ctf_event_get_class(self._e)
82839121 2683
6fd49698
PP
2684 if event_class_native is None:
2685 return None
82839121 2686
6fd49698
PP
2687 event_class = CTFWriter.EventClass.__new__(CTFWriter.EventClass)
2688 event_class._ec = event_class_native
6fd49698 2689
82839121 2690 return event_class
6fd49698
PP
2691
2692 def clock(self):
82839121
PP
2693 """
2694 Get a clock from event. Returns None if the event's class
2695 is not registered to a stream class.
2696 """
2697
6fd49698 2698 clock_instance = nbt._bt_ctf_event_get_clock(self._e)
82839121 2699
6fd49698
PP
2700 if clock_instance is None:
2701 return None
82839121 2702
6fd49698
PP
2703 clock = CTFWriter.Clock.__new__(CTFWriter.Clock)
2704 clock._c = clock_instance
6fd49698 2705
82839121 2706 return clock
6fd49698
PP
2707
2708 def payload(self, field_name):
82839121
PP
2709 """
2710 Get a field from event.
2711 """
2712
2713 native_instance = nbt._bt_ctf_event_get_payload(self._e,
2714 str(field_name))
2715
6fd49698
PP
2716 if native_instance is None:
2717 raise ValueError("Could not get event payload.")
6fd49698 2718
82839121 2719 return CTFWriter.Field._create_field_from_native_instance(native_instance)
6fd49698
PP
2720
2721 def set_payload(self, field_name, value_field):
82839121
PP
2722 """
2723 Set a manually created field as an event's payload.
2724 """
2725
6fd49698
PP
2726 if not isinstance(value, CTFWriter.Field):
2727 raise TypeError("Invalid value type.")
82839121
PP
2728
2729 ret = nbt._bt_ctf_event_set_payload(self._e, str(field_name),
2730 value_field._f)
2731
6fd49698
PP
2732 if ret < 0:
2733 raise ValueError("Could not set event field payload.")
2734
2735 class StreamClass:
6fd49698 2736 def __init__(self, name):
82839121
PP
2737 """
2738 Create a new stream class of the given name.
2739 """
2740
6fd49698 2741 self._sc = nbt._bt_ctf_stream_class_create(name)
82839121 2742
6fd49698
PP
2743 if self._sc is None:
2744 raise ValueError("Stream class creation failed.")
2745
2746 def __del__(self):
2747 nbt._bt_ctf_stream_class_put(self._sc)
2748
6fd49698
PP
2749 @property
2750 def name(self):
82839121
PP
2751 """
2752 Get a stream class' name.
2753 """
2754
6fd49698 2755 name = nbt._bt_ctf_stream_class_get_name(self._sc)
82839121 2756
6fd49698
PP
2757 if name is None:
2758 raise TypeError("Could not get StreamClass name")
82839121 2759
6fd49698
PP
2760 return name
2761
6fd49698
PP
2762 @property
2763 def clock(self):
82839121
PP
2764 """
2765 Get a stream class' clock.
2766 """
2767
6fd49698 2768 clock_instance = nbt._bt_ctf_stream_class_get_clock(self._sc)
82839121 2769
6fd49698
PP
2770 if clock_instance is None:
2771 return None
82839121 2772
6fd49698
PP
2773 clock = CTFWriter.Clock.__new__(CTFWriter.Clock)
2774 clock._c = clock_instance
82839121 2775
6fd49698
PP
2776 return clock
2777
6fd49698
PP
2778 @clock.setter
2779 def clock(self, clock):
82839121
PP
2780 """
2781 Assign a clock to a stream class.
2782 """
2783
6fd49698
PP
2784 if not isinstance(clock, CTFWriter.Clock):
2785 raise TypeError("Invalid clock type.")
2786
2787 ret = nbt._bt_ctf_stream_class_set_clock(self._sc, clock._c)
82839121 2788
6fd49698
PP
2789 if ret < 0:
2790 raise ValueError("Could not set stream class clock.")
2791
6fd49698
PP
2792 @property
2793 def id(self):
82839121
PP
2794 """
2795 Get a stream class' id.
2796 """
2797
6fd49698 2798 ret = nbt._bt_ctf_stream_class_get_id(self._sc)
82839121 2799
6fd49698
PP
2800 if ret < 0:
2801 raise TypeError("Could not get StreamClass id")
82839121 2802
6fd49698
PP
2803 return ret
2804
6fd49698
PP
2805 @id.setter
2806 def id(self, id):
82839121
PP
2807 """
2808 Assign an id to a stream class.
2809 """
2810
6fd49698 2811 ret = nbt._bt_ctf_stream_class_set_id(self._sc, id)
82839121 2812
6fd49698
PP
2813 if ret < 0:
2814 raise TypeError("Could not set stream class id.")
2815
6fd49698
PP
2816 @property
2817 def event_classes(self):
82839121
PP
2818 """
2819 Generator returning the stream class' event classes.
2820 """
2821
6fd49698 2822 count = nbt._bt_ctf_stream_class_get_event_class_count(self._sc)
82839121 2823
6fd49698
PP
2824 if count < 0:
2825 raise TypeError("Could not get StreamClass' event class count")
2826
2827 for i in range(count):
82839121
PP
2828 event_class_native = nbt._bt_ctf_stream_class_get_event_class(self._sc, i)
2829
6fd49698 2830 if event_class_native is None:
82839121
PP
2831 msg = "Could not get StreamClass' event class at index {}".format(i)
2832 raise TypeError(msg)
6fd49698 2833
82839121 2834 event_class = CTFWriter.EventClass.__new__(CTFWriter.EventClass)
6fd49698
PP
2835 event_class._ec = event_class_native
2836 yield event_class
2837
6fd49698 2838 def add_event_class(self, event_class):
82839121
PP
2839 """
2840 Add an event class to a stream class. New events can be added even after a
2841 stream has been instantiated and events have been appended. However, a stream
2842 will not accept events of a class that has not been added to the stream
2843 class beforehand.
2844 """
2845
6fd49698
PP
2846 if not isinstance(event_class, CTFWriter.EventClass):
2847 raise TypeError("Invalid event_class type.")
2848
82839121
PP
2849 ret = nbt._bt_ctf_stream_class_add_event_class(self._sc,
2850 event_class._ec)
2851
6fd49698
PP
2852 if ret < 0:
2853 raise ValueError("Could not add event class.")
2854
6fd49698
PP
2855 @property
2856 def packet_context_type(self):
82839121
PP
2857 """
2858 Get the StreamClass' packet context type (StructureFieldDeclaration)
2859 """
2860
2861 field_type_native = nbt._bt_ctf_stream_class_get_packet_context_type(self._sc)
2862
6fd49698
PP
2863 if field_type_native is None:
2864 raise ValueError("Invalid StreamClass")
82839121
PP
2865
2866 field_type = CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
2867
6fd49698
PP
2868 return field_type
2869
6fd49698
PP
2870 @packet_context_type.setter
2871 def packet_context_type(self, field_type):
82839121
PP
2872 """
2873 Set a StreamClass' packet context type. Must be of type
2874 StructureFieldDeclaration.
2875 """
2876
6fd49698 2877 if not isinstance(field_type, CTFWriter.StructureFieldDeclaration):
82839121
PP
2878 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
2879
2880 ret = nbt._bt_ctf_stream_class_set_packet_context_type(self._sc,
2881 field_type._ft)
2882
6fd49698
PP
2883 if ret < 0:
2884 raise ValueError("Failed to set packet context type.")
2885
2886 class Stream:
9f8e803f
PP
2887 def __init__(self):
2888 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
6fd49698
PP
2889
2890 def __del__(self):
2891 nbt._bt_ctf_stream_put(self._s)
2892
6fd49698
PP
2893 @property
2894 def discarded_events(self):
82839121
PP
2895 """
2896 Get a stream's discarded event count.
2897 """
2898
6fd49698 2899 ret, count = nbt._bt_ctf_stream_get_discarded_events_count(self._s)
82839121 2900
6fd49698 2901 if ret < 0:
82839121 2902 raise ValueError("Could not get the stream's discarded events count")
6fd49698 2903
82839121 2904 return count
6fd49698
PP
2905
2906 def append_discarded_events(self, event_count):
82839121
PP
2907 """
2908 Increase the current packet's discarded event count.
2909 """
6fd49698 2910
82839121 2911 nbt._bt_ctf_stream_append_discarded_events(self._s, event_count)
6fd49698
PP
2912
2913 def append_event(self, event):
82839121
PP
2914 """
2915 Append "event" to the stream's current packet. The stream's associated clock
2916 will be sampled during this call. The event shall not be modified after
2917 being appended to a stream.
2918 """
2919
6fd49698 2920 ret = nbt._bt_ctf_stream_append_event(self._s, event._e)
82839121 2921
6fd49698
PP
2922 if ret < 0:
2923 raise ValueError("Could not append event to stream.")
2924
6fd49698
PP
2925 @property
2926 def packet_context(self):
82839121
PP
2927 """
2928 Get a Stream's packet context field (a StructureField).
2929 """
2930
6fd49698 2931 native_field = nbt._bt_ctf_stream_get_packet_context(self._s)
82839121 2932
6fd49698
PP
2933 if native_field is None:
2934 raise ValueError("Invalid Stream.")
6fd49698 2935
82839121
PP
2936 return CTFWriter.Field._create_field_from_native_instance(native_field)
2937
6fd49698
PP
2938 @packet_context.setter
2939 def packet_context(self, field):
82839121
PP
2940 """
2941 Set a Stream's packet context field (must be a StructureField).
2942 """
2943
6fd49698 2944 if not isinstance(field, CTFWriter.StructureField):
82839121
PP
2945 raise TypeError("Argument field must be of type StructureField")
2946
6fd49698 2947 ret = nbt._bt_ctf_stream_set_packet_context(self._s, field._f)
82839121 2948
6fd49698
PP
2949 if ret < 0:
2950 raise ValueError("Invalid packet context field.")
2951
6fd49698 2952 def flush(self):
82839121
PP
2953 """
2954 The stream's current packet's events will be flushed to disk. Events
2955 subsequently appended to the stream will be added to a new packet.
2956 """
2957
6fd49698 2958 ret = nbt._bt_ctf_stream_flush(self._s)
82839121 2959
6fd49698
PP
2960 if ret < 0:
2961 raise ValueError("Could not flush stream.")
2962
2963 class Writer:
6fd49698 2964 def __init__(self, path):
82839121
PP
2965 """
2966 Create a new writer that will produce a trace in the given path.
2967 """
2968
6fd49698 2969 self._w = nbt._bt_ctf_writer_create(path)
82839121 2970
6fd49698
PP
2971 if self._w is None:
2972 raise ValueError("Writer creation failed.")
2973
2974 def __del__(self):
2975 nbt._bt_ctf_writer_put(self._w)
2976
6fd49698 2977 def create_stream(self, stream_class):
82839121
PP
2978 """
2979 Create a new stream instance and register it to the writer.
2980 """
2981
6fd49698
PP
2982 if not isinstance(stream_class, CTFWriter.StreamClass):
2983 raise TypeError("Invalid stream_class type.")
2984
2985 stream = CTFWriter.Stream.__new__(CTFWriter.Stream)
2986 stream._s = nbt._bt_ctf_writer_create_stream(self._w, stream_class._sc)
6fd49698 2987
82839121 2988 return stream
6fd49698
PP
2989
2990 def add_environment_field(self, name, value):
82839121
PP
2991 """
2992 Add an environment field to the trace.
2993 """
2994
2995 ret = nbt._bt_ctf_writer_add_environment_field(self._w, str(name),
2996 str(value))
2997
6fd49698
PP
2998 if ret < 0:
2999 raise ValueError("Could not add environment field to trace.")
3000
6fd49698 3001 def add_clock(self, clock):
82839121
PP
3002 """
3003 Add a clock to the trace. Clocks assigned to stream classes must be
3004 registered to the writer.
3005 """
3006
6fd49698 3007 ret = nbt._bt_ctf_writer_add_clock(self._w, clock._c)
82839121 3008
6fd49698
PP
3009 if ret < 0:
3010 raise ValueError("Could not add clock to Writer.")
3011
6fd49698
PP
3012 @property
3013 def metadata(self):
82839121
PP
3014 """
3015 Get the trace's TSDL meta-data.
3016 """
6fd49698 3017
82839121 3018 return nbt._bt_ctf_writer_get_metadata_string(self._w)
6fd49698
PP
3019
3020 def flush_metadata(self):
82839121
PP
3021 """
3022 Flush the trace's metadata to the metadata file.
3023 """
3024
6fd49698
PP
3025 nbt._bt_ctf_writer_flush_metadata(self._w)
3026
6fd49698
PP
3027 @property
3028 def byte_order(self):
82839121
PP
3029 """
3030 Get the trace's byte order. Must be a constant from the ByteOrder
3031 class.
3032 """
3033
6fd49698
PP
3034 raise NotImplementedError("Getter not implemented.")
3035
6fd49698
PP
3036 @byte_order.setter
3037 def byte_order(self, byte_order):
82839121
PP
3038 """
3039 Set the trace's byte order. Must be a constant from the ByteOrder
3040 class. Defaults to the host machine's endianness
3041 """
3042
6fd49698 3043 ret = nbt._bt_ctf_writer_set_byte_order(self._w, byte_order)
82839121 3044
6fd49698
PP
3045 if ret < 0:
3046 raise ValueError("Could not set trace's byte order.")
This page took 0.158575 seconds and 4 git commands to generate.