Python: document FieldDeclaration
[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):
6fd49698
PP
978 """Do not instantiate."""
979
980 def __init__(self):
82839121 981 raise NotImplementedError("EnumerationFieldDeclaration cannot be instantiated")
6fd49698
PP
982
983
984class ArrayFieldDeclaration(FieldDeclaration):
6fd49698
PP
985 """Do not instantiate."""
986
987 def __init__(self):
82839121 988 raise NotImplementedError("ArrayFieldDeclaration cannot be instantiated")
6fd49698
PP
989
990 @property
991 def length(self):
992 """
993 Return the length of an array or a negative
994 value on error.
995 """
82839121 996
6fd49698
PP
997 return nbt._bt_ctf_get_array_len(self._fd)
998
999 @property
1000 def element_declaration(self):
1001 """
1002 Return element declaration.
1003 """
82839121 1004
6fd49698 1005 field_decl_ptr = nbt._bt_python_get_array_element_declaration(self._fd)
82839121 1006
6fd49698
PP
1007 return _create_field_declaration(field_decl_ptr, "", self.scope)
1008
1009
1010class SequenceFieldDeclaration(FieldDeclaration):
6fd49698
PP
1011 """Do not instantiate."""
1012
1013 def __init__(self):
82839121 1014 raise NotImplementedError("SequenceFieldDeclaration cannot be instantiated")
6fd49698
PP
1015
1016 @property
1017 def element_declaration(self):
1018 """
1019 Return element declaration.
1020 """
82839121 1021
6fd49698 1022 field_decl_ptr = nbt._bt_python_get_sequence_element_declaration(self._fd)
82839121 1023
6fd49698
PP
1024 return _create_field_declaration(field_decl_ptr, "", self.scope)
1025
1026
1027class FloatFieldDeclaration(FieldDeclaration):
6fd49698
PP
1028 """Do not instantiate."""
1029
1030 def __init__(self):
82839121 1031 raise NotImplementedError("FloatFieldDeclaration cannot be instantiated")
6fd49698
PP
1032
1033
1034class StructureFieldDeclaration(FieldDeclaration):
6fd49698
PP
1035 """Do not instantiate."""
1036
1037 def __init__(self):
82839121 1038 raise NotImplementedError("StructureFieldDeclaration cannot be instantiated")
6fd49698
PP
1039
1040
1041class StringFieldDeclaration(FieldDeclaration):
6fd49698
PP
1042 """Do not instantiate."""
1043
1044 def __init__(self):
82839121 1045 raise NotImplementedError("StringFieldDeclaration cannot be instantiated")
6fd49698
PP
1046
1047
1048class VariantFieldDeclaration(FieldDeclaration):
6fd49698
PP
1049 """Do not instantiate."""
1050
1051 def __init__(self):
82839121 1052 raise NotImplementedError("VariantFieldDeclaration cannot be instantiated")
6fd49698
PP
1053
1054
1055def field_error():
1056 """
1057 Return the last error code encountered while
1058 accessing a field and reset the error flag.
1059 Return 0 if no error, a negative value otherwise.
1060 """
82839121 1061
6fd49698
PP
1062 return nbt._bt_ctf_field_get_error()
1063
1064
1065def _create_field_declaration(declaration_ptr, name, scope):
1066 """
1067 Private field declaration factory.
1068 """
82839121 1069
6fd49698
PP
1070 if declaration_ptr is None:
1071 raise ValueError("declaration_ptr must be valid")
82839121 1072 if scope not in _scopes:
6fd49698
PP
1073 raise ValueError("Invalid scope provided")
1074
1075 type = nbt._bt_ctf_field_type(declaration_ptr)
1076 declaration = None
82839121 1077
6fd49698
PP
1078 if type == CTFTypeId.INTEGER:
1079 declaration = IntegerFieldDeclaration.__new__(IntegerFieldDeclaration)
1080 elif type == CTFTypeId.ENUM:
82839121 1081 declaration = EnumerationFieldDeclaration.__new__(EnumerationFieldDeclaration)
6fd49698
PP
1082 elif type == CTFTypeId.ARRAY:
1083 declaration = ArrayFieldDeclaration.__new__(ArrayFieldDeclaration)
1084 elif type == CTFTypeId.SEQUENCE:
82839121 1085 declaration = SequenceFieldDeclaration.__new__(SequenceFieldDeclaration)
6fd49698
PP
1086 elif type == CTFTypeId.FLOAT:
1087 declaration = FloatFieldDeclaration.__new__(FloatFieldDeclaration)
1088 elif type == CTFTypeId.STRUCT:
82839121 1089 declaration = StructureFieldDeclaration.__new__(StructureFieldDeclaration)
6fd49698
PP
1090 elif type == CTFTypeId.STRING:
1091 declaration = StringFieldDeclaration.__new__(StringFieldDeclaration)
1092 elif type == CTFTypeId.VARIANT:
1093 declaration = VariantFieldDeclaration.__new__(VariantFieldDeclaration)
1094 else:
1095 return declaration
1096
1097 declaration._fd = declaration_ptr
1098 declaration._s = scope
1099 declaration._name = name
82839121 1100
6fd49698
PP
1101 return declaration
1102
1103
4cde866e 1104class _Definition:
6fd49698
PP
1105 def __init__(self, definition_ptr, scope):
1106 self._d = definition_ptr
1107 self._s = scope
82839121
PP
1108
1109 if scope not in _scopes:
6fd49698
PP
1110 ValueError("Invalid scope provided")
1111
1112 @property
1113 def name(self):
1114 """Return the name of a field or None on error."""
82839121 1115
6fd49698
PP
1116 return nbt._bt_ctf_field_name(self._d)
1117
1118 @property
1119 def type(self):
1120 """Return the type of a field or -1 if unknown."""
82839121 1121
6fd49698
PP
1122 return nbt._bt_ctf_field_type(nbt._bt_ctf_get_decl_from_def(self._d))
1123
1124 @property
1125 def declaration(self):
1126 """Return the associated Definition object."""
82839121 1127
6fd49698
PP
1128 return _create_field_declaration(
1129 nbt._bt_ctf_get_decl_from_def(self._d), self.name, self.scope)
1130
1131 def _get_enum_str(self):
1132 """
1133 Return the string matching the current enumeration.
1134 Return None on error.
1135 """
82839121 1136
6fd49698
PP
1137 return nbt._bt_ctf_get_enum_str(self._d)
1138
1139 def _get_array_element_at(self, index):
1140 """
1141 Return the array's element at position index.
1142 Return None on error
1143 """
82839121 1144
6fd49698 1145 array_ptr = nbt._bt_python_get_array_from_def(self._d)
82839121 1146
6fd49698
PP
1147 if array_ptr is None:
1148 return None
1149
1150 definition_ptr = nbt._bt_array_index(array_ptr, index)
82839121 1151
6fd49698
PP
1152 if definition_ptr is None:
1153 return None
82839121 1154
6fd49698
PP
1155 return _Definition(definition_ptr, self.scope)
1156
1157 def _get_sequence_len(self):
1158 """
1159 Return the len of a sequence or a negative
1160 value on error.
1161 """
82839121 1162
6fd49698 1163 seq = nbt._bt_python_get_sequence_from_def(self._d)
82839121 1164
6fd49698
PP
1165 return nbt._bt_sequence_len(seq)
1166
1167 def _get_sequence_element_at(self, index):
1168 """
1169 Return the sequence's element at position index,
1170 otherwise return None
1171 """
82839121 1172
6fd49698 1173 seq = nbt._bt_python_get_sequence_from_def(self._d)
82839121 1174
6fd49698
PP
1175 if seq is not None:
1176 definition_ptr = nbt._bt_sequence_index(seq, index)
82839121 1177
6fd49698
PP
1178 if definition_ptr is not None:
1179 return _Definition(definition_ptr, self.scope)
82839121 1180
6fd49698
PP
1181 def _get_uint64(self):
1182 """
1183 Return the value associated with the field.
1184 If the field does not exist or is not of the type requested,
1185 the value returned is undefined. To check if an error occured,
1186 use the field_error() function after accessing a field.
1187 """
82839121 1188
6fd49698
PP
1189 return nbt._bt_ctf_get_uint64(self._d)
1190
1191 def _get_int64(self):
1192 """
1193 Return the value associated with the field.
1194 If the field does not exist or is not of the type requested,
1195 the value returned is undefined. To check if an error occured,
1196 use the field_error() function after accessing a field.
1197 """
82839121 1198
6fd49698
PP
1199 return nbt._bt_ctf_get_int64(self._d)
1200
1201 def _get_char_array(self):
1202 """
1203 Return the value associated with the field.
1204 If the field does not exist or is not of the type requested,
1205 the value returned is undefined. To check if an error occurred,
1206 use the field_error() function after accessing a field.
1207 """
82839121 1208
6fd49698
PP
1209 return nbt._bt_ctf_get_char_array(self._d)
1210
1211 def _get_str(self):
1212 """
1213 Return the value associated with the field.
1214 If the field does not exist or is not of the type requested,
1215 the value returned is undefined. To check if an error occurred,
1216 use the field_error() function after accessing a field.
1217 """
82839121 1218
6fd49698
PP
1219 return nbt._bt_ctf_get_string(self._d)
1220
1221 def _get_float(self):
1222 """
1223 Return the value associated with the field.
1224 If the field does not exist or is not of the type requested,
1225 the value returned is undefined. To check if an error occurred,
1226 use the field_error() function after accessing a field.
1227 """
82839121 1228
6fd49698
PP
1229 return nbt._bt_ctf_get_float(self._d)
1230
1231 def _get_variant(self):
1232 """
1233 Return the variant's selected field.
1234 If the field does not exist or is not of the type requested,
1235 the value returned is undefined. To check if an error occurred,
1236 use the field_error() function after accessing a field.
1237 """
82839121 1238
6fd49698
PP
1239 return nbt._bt_ctf_get_variant(self._d)
1240
1241 def _get_struct_field_count(self):
1242 """
1243 Return the number of fields contained in the structure.
1244 If the field does not exist or is not of the type requested,
1245 the value returned is undefined.
1246 """
82839121 1247
6fd49698
PP
1248 return nbt._bt_ctf_get_struct_field_count(self._d)
1249
1250 def _get_struct_field_at(self, i):
1251 """
1252 Return the structure's field at position i.
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_struct_field_index(self._d, i)
1259
1260 @property
1261 def value(self):
1262 """
1263 Return the value associated with the field according to its type.
1264 Return None on error.
1265 """
82839121 1266
6fd49698
PP
1267 id = self.type
1268 value = None
1269
1270 if id == CTFTypeId.STRING:
1271 value = self._get_str()
1272 elif id == CTFTypeId.ARRAY:
1273 element_decl = self.declaration.element_declaration
82839121 1274
6fd49698
PP
1275 if ((element_decl.type == CTFTypeId.INTEGER
1276 and element_decl.length == 8)
1277 and (element_decl.encoding == CTFStringEncoding.ASCII or element_decl.encoding == CTFStringEncoding.UTF8)):
1278 value = nbt._bt_python_get_array_string(self._d)
1279 else:
1280 value = []
82839121 1281
6fd49698
PP
1282 for i in range(self.declaration.length):
1283 element = self._get_array_element_at(i)
1284 value.append(element.value)
1285 elif id == CTFTypeId.INTEGER:
1286 if self.declaration.signedness == 0:
1287 value = self._get_uint64()
1288 else:
1289 value = self._get_int64()
1290 elif id == CTFTypeId.ENUM:
1291 value = self._get_enum_str()
1292 elif id == CTFTypeId.SEQUENCE:
1293 element_decl = self.declaration.element_declaration
82839121 1294
6fd49698
PP
1295 if ((element_decl.type == CTFTypeId.INTEGER
1296 and element_decl.length == 8)
1297 and (element_decl.encoding == CTFStringEncoding.ASCII or element_decl.encoding == CTFStringEncoding.UTF8)):
1298 value = nbt._bt_python_get_sequence_string(self._d)
1299 else:
1300 seq_len = self._get_sequence_len()
1301 value = []
82839121 1302
6fd49698
PP
1303 for i in range(seq_len):
1304 evDef = self._get_sequence_element_at(i)
1305 value.append(evDef.value)
1306 elif id == CTFTypeId.FLOAT:
1307 value = self._get_float()
1308 elif id == CTFTypeId.VARIANT:
1309 variant = _Definition.__new__(_Definition)
1310 variant._d = self._get_variant()
1311 value = variant.value
1312 elif id == CTFTypeId.STRUCT:
1313 value = {}
82839121 1314
6fd49698
PP
1315 for i in range(self._get_struct_field_count()):
1316 member = _Definition(self._get_struct_field_at(i), self.scope)
1317 value[member.name] = member.value
1318
1319 if field_error():
1320 raise FieldError(
1321 "Error occurred while accessing field {} of type {}".format(
1322 self.name,
1323 CTFTypeId.type_name(id)))
82839121 1324
6fd49698
PP
1325 return value
1326
1327 @property
1328 def scope(self):
1329 """Return the scope of a field or None on error."""
82839121 1330
6fd49698
PP
1331 return self._s
1332
1333
1334class CTFWriter:
1335 # Used to compare to -1ULL in error checks
1336 _MAX_UINT64 = 0xFFFFFFFFFFFFFFFF
1337
6fd49698 1338 class EnumerationMapping:
82839121
PP
1339 """
1340 Enumeration mapping class. start and end values are inclusive.
1341 """
6fd49698
PP
1342
1343 def __init__(self, name, start, end):
1344 self.name = name
1345 self.start = start
1346 self.end = end
1347
1348 class Clock:
6fd49698
PP
1349 def __init__(self, name):
1350 self._c = nbt._bt_ctf_clock_create(name)
82839121 1351
6fd49698
PP
1352 if self._c is None:
1353 raise ValueError("Invalid clock name.")
1354
1355 def __del__(self):
1356 nbt._bt_ctf_clock_put(self._c)
1357
6fd49698
PP
1358 @property
1359 def name(self):
82839121
PP
1360 """
1361 Get the clock's name.
1362 """
1363
6fd49698 1364 name = nbt._bt_ctf_clock_get_name(self._c)
82839121 1365
6fd49698
PP
1366 if name is None:
1367 raise ValueError("Invalid clock instance.")
82839121 1368
6fd49698
PP
1369 return name
1370
6fd49698
PP
1371 @property
1372 def description(self):
82839121
PP
1373 """
1374 Get the clock's description. None if unset.
1375 """
1376
6fd49698
PP
1377 return nbt._bt_ctf_clock_get_description(self._c)
1378
6fd49698
PP
1379 @description.setter
1380 def description(self, desc):
82839121
PP
1381 """
1382 Set the clock's description. The description appears in the clock's TSDL
1383 meta-data.
1384 """
1385
6fd49698 1386 ret = nbt._bt_ctf_clock_set_description(self._c, str(desc))
82839121 1387
6fd49698
PP
1388 if ret < 0:
1389 raise ValueError("Invalid clock description.")
1390
6fd49698
PP
1391 @property
1392 def frequency(self):
82839121
PP
1393 """
1394 Get the clock's frequency (Hz).
1395 """
1396
6fd49698 1397 freq = nbt._bt_ctf_clock_get_frequency(self._c)
82839121 1398
6fd49698
PP
1399 if freq == CTFWriter._MAX_UINT64:
1400 raise ValueError("Invalid clock instance")
82839121 1401
6fd49698
PP
1402 return freq
1403
6fd49698
PP
1404 @frequency.setter
1405 def frequency(self, freq):
82839121
PP
1406 """
1407 Set the clock's frequency (Hz).
1408 """
1409
6fd49698 1410 ret = nbt._bt_ctf_clock_set_frequency(self._c, freq)
82839121 1411
6fd49698
PP
1412 if ret < 0:
1413 raise ValueError("Invalid frequency value.")
1414
6fd49698
PP
1415 @property
1416 def precision(self):
82839121
PP
1417 """
1418 Get the clock's precision (in clock ticks).
1419 """
1420
6fd49698 1421 precision = nbt._bt_ctf_clock_get_precision(self._c)
82839121 1422
6fd49698
PP
1423 if precision == CTFWriter._MAX_UINT64:
1424 raise ValueError("Invalid clock instance")
82839121 1425
6fd49698
PP
1426 return precision
1427
6fd49698
PP
1428 @precision.setter
1429 def precision(self, precision):
82839121
PP
1430 """
1431 Set the clock's precision (in clock ticks).
1432 """
1433
6fd49698
PP
1434 ret = nbt._bt_ctf_clock_set_precision(self._c, precision)
1435
6fd49698
PP
1436 @property
1437 def offset_seconds(self):
82839121
PP
1438 """
1439 Get the clock's offset in seconds from POSIX.1 Epoch.
1440 """
1441
6fd49698 1442 offset_s = nbt._bt_ctf_clock_get_offset_s(self._c)
82839121 1443
6fd49698
PP
1444 if offset_s == CTFWriter._MAX_UINT64:
1445 raise ValueError("Invalid clock instance")
82839121 1446
6fd49698
PP
1447 return offset_s
1448
6fd49698
PP
1449 @offset_seconds.setter
1450 def offset_seconds(self, offset_s):
82839121
PP
1451 """
1452 Set the clock's offset in seconds from POSIX.1 Epoch.
1453 """
1454
6fd49698 1455 ret = nbt._bt_ctf_clock_set_offset_s(self._c, offset_s)
82839121 1456
6fd49698
PP
1457 if ret < 0:
1458 raise ValueError("Invalid offset value.")
1459
6fd49698
PP
1460 @property
1461 def offset(self):
82839121
PP
1462 """
1463 Get the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1464 """
1465
6fd49698 1466 offset = nbt._bt_ctf_clock_get_offset(self._c)
82839121 1467
6fd49698
PP
1468 if offset == CTFWriter._MAX_UINT64:
1469 raise ValueError("Invalid clock instance")
82839121 1470
6fd49698
PP
1471 return offset
1472
6fd49698
PP
1473 @offset.setter
1474 def offset(self, offset):
82839121
PP
1475 """
1476 Set the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1477 """
1478
6fd49698 1479 ret = nbt._bt_ctf_clock_set_offset(self._c, offset)
82839121 1480
6fd49698
PP
1481 if ret < 0:
1482 raise ValueError("Invalid offset value.")
1483
6fd49698
PP
1484 @property
1485 def absolute(self):
82839121
PP
1486 """
1487 Get a clock's absolute attribute. A clock is absolute if the clock
1488 is a global reference across the trace's other clocks.
1489 """
1490
6fd49698 1491 is_absolute = nbt._bt_ctf_clock_get_is_absolute(self._c)
82839121 1492
6fd49698
PP
1493 if is_absolute == -1:
1494 raise ValueError("Invalid clock instance")
82839121 1495
6fd49698
PP
1496 return False if is_absolute == 0 else True
1497
6fd49698
PP
1498 @absolute.setter
1499 def absolute(self, is_absolute):
82839121
PP
1500 """
1501 Set a clock's absolute attribute. A clock is absolute if the clock
1502 is a global reference across the trace's other clocks.
1503 """
1504
6fd49698 1505 ret = nbt._bt_ctf_clock_set_is_absolute(self._c, int(is_absolute))
82839121 1506
6fd49698 1507 if ret < 0:
82839121 1508 raise ValueError("Could not set the clock's absolute attribute.")
6fd49698 1509
6fd49698
PP
1510 @property
1511 def uuid(self):
82839121
PP
1512 """
1513 Get a clock's UUID (an object of type UUID).
1514 """
1515
6fd49698 1516 uuid_list = []
82839121 1517
6fd49698
PP
1518 for i in range(16):
1519 ret, value = nbt._bt_python_ctf_clock_get_uuid_index(self._c, i)
82839121 1520
6fd49698
PP
1521 if ret < 0:
1522 raise ValueError("Invalid clock instance")
82839121 1523
6fd49698 1524 uuid_list.append(value)
82839121 1525
6fd49698
PP
1526 return UUID(bytes=bytes(uuid_list))
1527
6fd49698
PP
1528 @uuid.setter
1529 def uuid(self, uuid):
82839121
PP
1530 """
1531 Set a clock's UUID (an object of type UUID).
1532 """
1533
6fd49698 1534 uuid_bytes = uuid.bytes
82839121 1535
6fd49698 1536 if len(uuid_bytes) != 16:
82839121
PP
1537 raise ValueError("Invalid UUID provided. UUID length must be 16 bytes")
1538
6fd49698 1539 for i in range(len(uuid_bytes)):
82839121
PP
1540 ret = nbt._bt_python_ctf_clock_set_uuid_index(self._c, i,
1541 uuid_bytes[i])
1542
6fd49698
PP
1543 if ret < 0:
1544 raise ValueError("Invalid clock instance")
1545
6fd49698
PP
1546 @property
1547 def time(self):
82839121
PP
1548 """
1549 Get the current time in nanoseconds since the clock's origin (offset and
1550 offset_s attributes).
1551 """
1552
6fd49698 1553 time = nbt._bt_ctf_clock_get_time(self._c)
82839121 1554
6fd49698
PP
1555 if time == CTFWriter._MAX_UINT64:
1556 raise ValueError("Invalid clock instance")
82839121 1557
6fd49698
PP
1558 return time
1559
6fd49698
PP
1560 @time.setter
1561 def time(self, time):
82839121
PP
1562 """
1563 Set the current time in nanoseconds since the clock's origin (offset and
1564 offset_s attributes). The clock's value will be sampled as events are
1565 appended to a stream.
1566 """
1567
6fd49698 1568 ret = nbt._bt_ctf_clock_set_time(self._c, time)
82839121 1569
6fd49698
PP
1570 if ret < 0:
1571 raise ValueError("Invalid time value.")
1572
1573 class FieldDeclaration:
6fd49698
PP
1574 """
1575 FieldDeclaration should not be instantiated directly. Instantiate
1576 one of the concrete FieldDeclaration classes.
1577 """
82839121 1578
6fd49698
PP
1579 class IntegerBase:
1580 # These values are based on the bt_ctf_integer_base enum
1581 # declared in event-types.h.
1582 INTEGER_BASE_UNKNOWN = -1
1583 INTEGER_BASE_BINARY = 2
1584 INTEGER_BASE_OCTAL = 8
1585 INTEGER_BASE_DECIMAL = 10
1586 INTEGER_BASE_HEXADECIMAL = 16
1587
1588 def __init__(self):
1589 if self._ft is None:
1590 raise ValueError("FieldDeclaration creation failed.")
1591
1592 def __del__(self):
1593 nbt._bt_ctf_field_type_put(self._ft)
1594
1595 @staticmethod
1596 def _create_field_declaration_from_native_instance(
1597 native_field_declaration):
1598 type_dict = {
1599 CTFTypeId.INTEGER: CTFWriter.IntegerFieldDeclaration,
1600 CTFTypeId.FLOAT: CTFWriter.FloatFieldDeclaration,
1601 CTFTypeId.ENUM: CTFWriter.EnumerationFieldDeclaration,
1602 CTFTypeId.STRING: CTFWriter.StringFieldDeclaration,
1603 CTFTypeId.STRUCT: CTFWriter.StructureFieldDeclaration,
1604 CTFTypeId.VARIANT: CTFWriter.VariantFieldDeclaration,
1605 CTFTypeId.ARRAY: CTFWriter.ArrayFieldDeclaration,
1606 CTFTypeId.SEQUENCE: CTFWriter.SequenceFieldDeclaration
1607 }
1608
82839121
PP
1609 field_type_id = nbt._bt_ctf_field_type_get_type_id(native_field_declaration)
1610
6fd49698
PP
1611 if field_type_id == CTFTypeId.UNKNOWN:
1612 raise TypeError("Invalid field instance")
1613
1614 declaration = CTFWriter.Field.__new__(CTFWriter.Field)
1615 declaration._ft = native_field_declaration
1616 declaration.__class__ = type_dict[field_type_id]
82839121 1617
6fd49698
PP
1618 return declaration
1619
6fd49698
PP
1620 @property
1621 def alignment(self):
82839121
PP
1622 """
1623 Get the field declaration's alignment. Returns -1 on error.
1624 """
1625
6fd49698
PP
1626 return nbt._bt_ctf_field_type_get_alignment(self._ft)
1627
6fd49698
PP
1628 @alignment.setter
1629 def alignment(self, alignment):
82839121
PP
1630 """
1631 Set the field declaration's alignment. Defaults to 1 (bit-aligned). However,
1632 some types, such as structures and string, may impose other alignment
1633 constraints.
1634 """
1635
6fd49698 1636 ret = nbt._bt_ctf_field_type_set_alignment(self._ft, alignment)
82839121 1637
6fd49698
PP
1638 if ret < 0:
1639 raise ValueError("Invalid alignment value.")
1640
6fd49698
PP
1641 @property
1642 def byte_order(self):
82839121
PP
1643 """
1644 Get the field declaration's byte order. One of the ByteOrder's constant.
1645 """
1646
6fd49698
PP
1647 return nbt._bt_ctf_field_type_get_byte_order(self._ft)
1648
6fd49698
PP
1649 @byte_order.setter
1650 def byte_order(self, byte_order):
82839121
PP
1651 """
1652 Set the field declaration's byte order. Use constants defined in the ByteOrder
1653 class.
1654 """
1655
6fd49698 1656 ret = nbt._bt_ctf_field_type_set_byte_order(self._ft, byte_order)
82839121 1657
6fd49698
PP
1658 if ret < 0:
1659 raise ValueError("Could not set byte order value.")
1660
1661 class IntegerFieldDeclaration(FieldDeclaration):
6fd49698 1662 def __init__(self, size):
82839121
PP
1663 """
1664 Create a new integer field declaration of the given size.
1665 """
6fd49698
PP
1666 self._ft = nbt._bt_ctf_field_type_integer_create(size)
1667 super().__init__()
1668
6fd49698
PP
1669 @property
1670 def size(self):
82839121
PP
1671 """
1672 Get an integer's size.
1673 """
1674
6fd49698 1675 ret = nbt._bt_ctf_field_type_integer_get_size(self._ft)
82839121 1676
6fd49698
PP
1677 if ret < 0:
1678 raise ValueError("Could not get Integer's size attribute.")
1679 else:
1680 return ret
1681
6fd49698
PP
1682 @property
1683 def signed(self):
82839121
PP
1684 """
1685 Get an integer's signedness attribute.
1686 """
1687
6fd49698 1688 ret = nbt._bt_ctf_field_type_integer_get_signed(self._ft)
82839121 1689
6fd49698
PP
1690 if ret < 0:
1691 raise ValueError("Could not get Integer's signed attribute.")
1692 elif ret > 0:
1693 return True
1694 else:
1695 return False
1696
6fd49698
PP
1697 @signed.setter
1698 def signed(self, signed):
82839121
PP
1699 """
1700 Set an integer's signedness attribute.
1701 """
1702
6fd49698 1703 ret = nbt._bt_ctf_field_type_integer_set_signed(self._ft, signed)
82839121 1704
6fd49698
PP
1705 if ret < 0:
1706 raise ValueError("Could not set Integer's signed attribute.")
1707
6fd49698
PP
1708 @property
1709 def base(self):
82839121
PP
1710 """
1711 Get the integer's base used to pretty-print the resulting trace.
1712 Returns a constant from the FieldDeclaration.IntegerBase class.
1713 """
1714
6fd49698
PP
1715 return nbt._bt_ctf_field_type_integer_get_base(self._ft)
1716
6fd49698
PP
1717 @base.setter
1718 def base(self, base):
82839121
PP
1719 """
1720 Set the integer's base used to pretty-print the resulting trace.
1721 The base must be a constant of the FieldDeclarationIntegerBase class.
1722 """
1723
6fd49698 1724 ret = nbt._bt_ctf_field_type_integer_set_base(self._ft, base)
82839121 1725
6fd49698
PP
1726 if ret < 0:
1727 raise ValueError("Could not set Integer's base.")
1728
6fd49698
PP
1729 @property
1730 def encoding(self):
82839121
PP
1731 """
1732 Get the integer's encoding (one of the constants of the
1733 CTFStringEncoding class).
1734 Returns a constant from the CTFStringEncoding class.
1735 """
1736
6fd49698
PP
1737 return nbt._bt_ctf_field_type_integer_get_encoding(self._ft)
1738
6fd49698
PP
1739 @encoding.setter
1740 def encoding(self, encoding):
82839121
PP
1741 """
1742 An integer encoding may be set to signal that the integer must be printed
1743 as a text character. Must be a constant from the CTFStringEncoding class.
1744 """
1745
6fd49698 1746 ret = nbt._bt_ctf_field_type_integer_set_encoding(self._ft, encoding)
82839121 1747
6fd49698
PP
1748 if ret < 0:
1749 raise ValueError("Could not set Integer's encoding.")
1750
1751 class EnumerationFieldDeclaration(FieldDeclaration):
6fd49698 1752 def __init__(self, integer_type):
82839121
PP
1753 """
1754 Create a new enumeration field declaration with the given underlying container type.
1755 """
1756 isinst = isinstance(integer_type, CTFWriter.IntegerFieldDeclaration)
1757
1758 if integer_type is None or not isinst:
6fd49698
PP
1759 raise TypeError("Invalid integer container.")
1760
1761 self._ft = nbt._bt_ctf_field_type_enumeration_create(integer_type._ft)
1762 super().__init__()
1763
6fd49698
PP
1764 @property
1765 def container(self):
82839121
PP
1766 """
1767 Get the enumeration's underlying container type.
1768 """
1769
6fd49698 1770 ret = nbt._bt_ctf_field_type_enumeration_get_container_type(self._ft)
82839121 1771
6fd49698
PP
1772 if ret is None:
1773 raise TypeError("Invalid enumeration declaration")
6fd49698 1774
82839121 1775 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(ret)
6fd49698
PP
1776
1777 def add_mapping(self, name, range_start, range_end):
82839121
PP
1778 """
1779 Add a mapping to the enumeration. The range's values are inclusive.
1780 """
1781
6fd49698 1782 if range_start < 0 or range_end < 0:
82839121
PP
1783 ret = nbt._bt_ctf_field_type_enumeration_add_mapping(self._ft,
1784 str(name),
1785 range_start,
1786 range_end)
6fd49698 1787 else:
82839121
PP
1788 ret = nbt._bt_ctf_field_type_enumeration_add_mapping_unsigned(self._ft,
1789 str(name),
1790 range_start,
1791 range_end)
6fd49698
PP
1792
1793 if ret < 0:
82839121 1794 raise ValueError("Could not add mapping to enumeration declaration.")
6fd49698 1795
6fd49698
PP
1796 @property
1797 def mappings(self):
82839121
PP
1798 """
1799 Generator returning instances of EnumerationMapping.
1800 """
1801
6fd49698
PP
1802 signed = self.container.signed
1803
1804 count = nbt._bt_ctf_field_type_enumeration_get_mapping_count(self._ft)
82839121 1805
6fd49698
PP
1806 for i in range(count):
1807 if signed:
82839121 1808 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, i)
6fd49698 1809 else:
82839121 1810 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, i)
6fd49698
PP
1811
1812 if len(ret) != 3:
82839121
PP
1813 msg = "Could not get Enumeration mapping at index {}".format(i)
1814 raise TypeError(msg)
1815
6fd49698
PP
1816 name, range_start, range_end = ret
1817 yield CTFWriter.EnumerationMapping(name, range_start, range_end)
1818
6fd49698 1819 def get_mapping_by_name(self, name):
82839121
PP
1820 """
1821 Get a mapping by name (EnumerationMapping).
1822 """
1823
1824 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_name(self._ft, name)
1825
6fd49698
PP
1826 if index < 0:
1827 return None
1828
1829 if self.container.signed:
82839121 1830 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, index)
6fd49698 1831 else:
82839121 1832 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, index)
6fd49698
PP
1833
1834 if len(ret) != 3:
82839121
PP
1835 msg = "Could not get Enumeration mapping at index {}".format(i)
1836 raise TypeError(msg)
1837
6fd49698 1838 name, range_start, range_end = ret
6fd49698 1839
82839121 1840 return CTFWriter.EnumerationMapping(name, range_start, range_end)
6fd49698
PP
1841
1842 def get_mapping_by_value(self, value):
82839121
PP
1843 """
1844 Get a mapping by value (EnumerationMapping).
1845 """
1846
6fd49698 1847 if value < 0:
82839121 1848 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_value(self._ft, value)
6fd49698 1849 else:
82839121 1850 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value(self._ft, value)
6fd49698
PP
1851
1852 if index < 0:
1853 return None
1854
1855 if self.container.signed:
82839121 1856 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, index)
6fd49698 1857 else:
82839121 1858 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, index)
6fd49698
PP
1859
1860 if len(ret) != 3:
82839121
PP
1861 msg = "Could not get Enumeration mapping at index {}".format(i)
1862 raise TypeError(msg)
1863
6fd49698 1864 name, range_start, range_end = ret
82839121 1865
6fd49698
PP
1866 return CTFWriter.EnumerationMapping(name, range_start, range_end)
1867
1868 class FloatFieldDeclaration(FieldDeclaration):
1869 FLT_EXP_DIG = 8
1870 DBL_EXP_DIG = 11
1871 FLT_MANT_DIG = 24
1872 DBL_MANT_DIG = 53
1873
6fd49698 1874 def __init__(self):
82839121
PP
1875 """
1876 Create a new floating point field declaration.
1877 """
1878
6fd49698
PP
1879 self._ft = nbt._bt_ctf_field_type_floating_point_create()
1880 super().__init__()
1881
6fd49698
PP
1882 @property
1883 def exponent_digits(self):
82839121
PP
1884 """
1885 Get the number of exponent digits used to store the floating point field.
1886 """
1887
1888 ret = nbt._bt_ctf_field_type_floating_point_get_exponent_digits(self._ft)
1889
6fd49698
PP
1890 if ret < 0:
1891 raise TypeError(
1892 "Could not get Floating point exponent digit count")
82839121 1893
6fd49698
PP
1894 return ret
1895
6fd49698
PP
1896 @exponent_digits.setter
1897 def exponent_digits(self, exponent_digits):
82839121
PP
1898 """
1899 Set the number of exponent digits to use to store the floating point field.
1900 The only values currently supported are FLT_EXP_DIG and DBL_EXP_DIG which
1901 are defined as constants of this class.
1902 """
1903
1904 ret = nbt._bt_ctf_field_type_floating_point_set_exponent_digits(self._ft,
1905 exponent_digits)
1906
6fd49698
PP
1907 if ret < 0:
1908 raise ValueError("Could not set exponent digit count.")
1909
6fd49698
PP
1910 @property
1911 def mantissa_digits(self):
82839121
PP
1912 """
1913 Get the number of mantissa digits used to store the floating point field.
1914 """
1915
1916 ret = nbt._bt_ctf_field_type_floating_point_get_mantissa_digits(self._ft)
1917
6fd49698 1918 if ret < 0:
82839121
PP
1919 raise TypeError("Could not get Floating point mantissa digit count")
1920
6fd49698
PP
1921 return ret
1922
6fd49698
PP
1923 @mantissa_digits.setter
1924 def mantissa_digits(self, mantissa_digits):
82839121
PP
1925 """
1926 Set the number of mantissa digits to use to store the floating point field.
1927 The only values currently supported are FLT_MANT_DIG and DBL_MANT_DIG which
1928 are defined as constants of this class.
1929 """
1930
1931 ret = nbt._bt_ctf_field_type_floating_point_set_mantissa_digits(self._ft,
1932 mantissa_digits)
1933
6fd49698
PP
1934 if ret < 0:
1935 raise ValueError("Could not set mantissa digit count.")
1936
da43007d
PP
1937 class FloatingPointFieldDeclaration(FloatFieldDeclaration):
1938 pass
1939
6fd49698 1940 class StructureFieldDeclaration(FieldDeclaration):
6fd49698 1941 def __init__(self):
82839121
PP
1942 """
1943 Create a new structure field declaration.
1944 """
1945
6fd49698
PP
1946 self._ft = nbt._bt_ctf_field_type_structure_create()
1947 super().__init__()
1948
6fd49698 1949 def add_field(self, field_type, field_name):
82839121
PP
1950 """
1951 Add a field of type "field_type" to the structure.
1952 """
1953
1954 ret = nbt._bt_ctf_field_type_structure_add_field(self._ft,
1955 field_type._ft,
1956 str(field_name))
1957
6fd49698
PP
1958 if ret < 0:
1959 raise ValueError("Could not add field to structure.")
1960
6fd49698
PP
1961 @property
1962 def fields(self):
82839121
PP
1963 """
1964 Generator returning the structure's field as tuples of (field name, field declaration).
1965 """
1966
6fd49698 1967 count = nbt._bt_ctf_field_type_structure_get_field_count(self._ft)
82839121 1968
6fd49698
PP
1969 if count < 0:
1970 raise TypeError("Could not get Structure field count")
1971
1972 for i in range(count):
82839121
PP
1973 field_name = nbt._bt_python_ctf_field_type_structure_get_field_name(self._ft, i)
1974
6fd49698 1975 if field_name is None:
82839121
PP
1976 msg = "Could not get Structure field name at index {}".format(i)
1977 raise TypeError(msg)
1978
1979 field_type_native = nbt._bt_python_ctf_field_type_structure_get_field_type(self._ft, i)
6fd49698 1980
6fd49698 1981 if field_type_native is None:
82839121
PP
1982 msg = "Could not get Structure field type at index {}".format(i)
1983 raise TypeError(msg)
6fd49698 1984
82839121 1985 field_type = CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698
PP
1986 yield (field_name, field_type)
1987
6fd49698 1988 def get_field_by_name(self, name):
82839121
PP
1989 """
1990 Get a field declaration by name (FieldDeclaration).
1991 """
6fd49698 1992
82839121 1993 field_type_native = nbt._bt_ctf_field_type_structure_get_field_type_by_name(self._ft, name)
6fd49698 1994
82839121
PP
1995 if field_type_native is None:
1996 msg = "Could not find Structure field with name {}".format(name)
1997 raise TypeError(msg)
6fd49698 1998
82839121 1999 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698 2000
82839121 2001 class VariantFieldDeclaration(FieldDeclaration):
6fd49698 2002 def __init__(self, enum_tag, tag_name):
82839121
PP
2003 """
2004 Create a new variant field declaration.
2005 """
2006
2007 isinst = isinstance(enum_tag, CTFWriter.EnumerationFieldDeclaration)
2008 if enum_tag is None or not isinst:
2009 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
6fd49698 2010
82839121
PP
2011 self._ft = nbt._bt_ctf_field_type_variant_create(enum_tag._ft,
2012 str(tag_name))
6fd49698
PP
2013 super().__init__()
2014
6fd49698
PP
2015 @property
2016 def tag_name(self):
82839121
PP
2017 """
2018 Get the variant's tag name.
2019 """
2020
6fd49698 2021 ret = nbt._bt_ctf_field_type_variant_get_tag_name(self._ft)
82839121 2022
6fd49698
PP
2023 if ret is None:
2024 raise TypeError("Could not get Variant tag name")
82839121 2025
6fd49698
PP
2026 return ret
2027
6fd49698
PP
2028 @property
2029 def tag_type(self):
82839121
PP
2030 """
2031 Get the variant's tag type.
2032 """
2033
6fd49698 2034 ret = nbt._bt_ctf_field_type_variant_get_tag_type(self._ft)
82839121 2035
6fd49698
PP
2036 if ret is None:
2037 raise TypeError("Could not get Variant tag type")
6fd49698 2038
82839121 2039 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(ret)
6fd49698
PP
2040
2041 def add_field(self, field_type, field_name):
82839121
PP
2042 """
2043 Add a field of type "field_type" to the variant.
2044 """
2045
2046 ret = nbt._bt_ctf_field_type_variant_add_field(self._ft,
2047 field_type._ft,
2048 str(field_name))
2049
6fd49698
PP
2050 if ret < 0:
2051 raise ValueError("Could not add field to variant.")
2052
6fd49698
PP
2053 @property
2054 def fields(self):
82839121
PP
2055 """
2056 Generator returning the variant's field as tuples of (field name, field declaration).
2057 """
2058
6fd49698 2059 count = nbt._bt_ctf_field_type_variant_get_field_count(self._ft)
82839121 2060
6fd49698
PP
2061 if count < 0:
2062 raise TypeError("Could not get Variant field count")
2063
2064 for i in range(count):
82839121
PP
2065 field_name = nbt._bt_python_ctf_field_type_variant_get_field_name(self._ft, i)
2066
6fd49698 2067 if field_name is None:
82839121
PP
2068 msg = "Could not get Variant field name at index {}".format(i)
2069 raise TypeError(msg)
2070
2071 field_type_native = nbt._bt_python_ctf_field_type_variant_get_field_type(self._ft, i)
6fd49698 2072
6fd49698 2073 if field_type_native is None:
82839121
PP
2074 msg = "Could not get Variant field type at index {}".format(i)
2075 raise TypeError(msg)
6fd49698 2076
82839121 2077 field_type = CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698
PP
2078 yield (field_name, field_type)
2079
6fd49698 2080 def get_field_by_name(self, name):
82839121
PP
2081 """
2082 Get a field declaration by name (FieldDeclaration).
2083 """
6fd49698 2084
82839121
PP
2085 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_by_name(self._ft,
2086 name)
6fd49698 2087
82839121
PP
2088 if field_type_native is None:
2089 msg = "Could not find Variant field with name {}".format(name)
2090 raise TypeError(msg)
2091
2092 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698
PP
2093
2094 def get_field_from_tag(self, tag):
82839121
PP
2095 """
2096 Get a field declaration from tag (EnumerationField).
2097 """
6fd49698 2098
82839121 2099 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_from_tag(self._ft, tag._f)
6fd49698 2100
82839121
PP
2101 if field_type_native is None:
2102 msg = "Could not find Variant field with tag value {}".format(tag.value)
2103 raise TypeError(msg)
6fd49698 2104
82839121 2105 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698 2106
82839121 2107 class ArrayFieldDeclaration(FieldDeclaration):
6fd49698 2108 def __init__(self, element_type, length):
82839121
PP
2109 """
2110 Create a new array field declaration.
2111 """
2112
2113 self._ft = nbt._bt_ctf_field_type_array_create(element_type._ft,
2114 length)
6fd49698
PP
2115 super().__init__()
2116
6fd49698
PP
2117 @property
2118 def element_type(self):
82839121
PP
2119 """
2120 Get the array's element type.
2121 """
2122
6fd49698 2123 ret = nbt._bt_ctf_field_type_array_get_element_type(self._ft)
82839121 2124
6fd49698
PP
2125 if ret is None:
2126 raise TypeError("Could not get Array element type")
6fd49698 2127
82839121
PP
2128 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(ret)
2129
6fd49698
PP
2130 @property
2131 def length(self):
82839121
PP
2132 """
2133 Get the array's length.
2134 """
2135
6fd49698 2136 ret = nbt._bt_ctf_field_type_array_get_length(self._ft)
82839121 2137
6fd49698
PP
2138 if ret < 0:
2139 raise TypeError("Could not get Array length")
82839121 2140
6fd49698
PP
2141 return ret
2142
2143 class SequenceFieldDeclaration(FieldDeclaration):
6fd49698 2144 def __init__(self, element_type, length_field_name):
82839121
PP
2145 """
2146 Create a new sequence field declaration.
2147 """
2148
2149 self._ft = nbt._bt_ctf_field_type_sequence_create(element_type._ft,
2150 str(length_field_name))
6fd49698
PP
2151 super().__init__()
2152
6fd49698
PP
2153 @property
2154 def element_type(self):
82839121
PP
2155 """
2156 Get the sequence's element type.
2157 """
2158
6fd49698 2159 ret = nbt._bt_ctf_field_type_sequence_get_element_type(self._ft)
82839121 2160
6fd49698
PP
2161 if ret is None:
2162 raise TypeError("Could not get Sequence element type")
6fd49698 2163
82839121
PP
2164 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(ret)
2165
6fd49698
PP
2166 @property
2167 def length_field_name(self):
82839121
PP
2168 """
2169 Get the sequence's length field name.
2170 """
2171
6fd49698 2172 ret = nbt._bt_ctf_field_type_sequence_get_length_field_name(self._ft)
82839121 2173
6fd49698
PP
2174 if ret is None:
2175 raise TypeError("Could not get Sequence length field name")
82839121 2176
6fd49698
PP
2177 return ret
2178
2179 class StringFieldDeclaration(FieldDeclaration):
6fd49698 2180 def __init__(self):
82839121
PP
2181 """
2182 Create a new string field declaration.
2183 """
2184
6fd49698
PP
2185 self._ft = nbt._bt_ctf_field_type_string_create()
2186 super().__init__()
2187
6fd49698
PP
2188 @property
2189 def encoding(self):
82839121
PP
2190 """
2191 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
2192 """
2193
6fd49698
PP
2194 return nbt._bt_ctf_field_type_string_get_encoding(self._ft)
2195
6fd49698
PP
2196 @encoding.setter
2197 def encoding(self, encoding):
82839121
PP
2198 """
2199 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
2200 """
2201
6fd49698
PP
2202 ret = nbt._bt_ctf_field_type_string_set_encoding(self._ft, encoding)
2203 if ret < 0:
2204 raise ValueError("Could not set string encoding.")
2205
6fd49698
PP
2206 @staticmethod
2207 def create_field(field_type):
82839121
PP
2208 """
2209 Create an instance of a field.
2210 """
2211 isinst = isinstance(field_type, CTFWriter.FieldDeclaration)
2212
2213 if field_type is None or not isinst:
2214 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
6fd49698
PP
2215
2216 if isinstance(field_type, CTFWriter.IntegerFieldDeclaration):
2217 return CTFWriter.IntegerField(field_type)
2218 elif isinstance(field_type, CTFWriter.EnumerationFieldDeclaration):
2219 return CTFWriter.EnumerationField(field_type)
2220 elif isinstance(field_type, CTFWriter.FloatFieldDeclaration):
60318a5f 2221 return CTFWriter.FloatingPointField(field_type)
6fd49698
PP
2222 elif isinstance(field_type, CTFWriter.StructureFieldDeclaration):
2223 return CTFWriter.StructureField(field_type)
2224 elif isinstance(field_type, CTFWriter.VariantFieldDeclaration):
2225 return CTFWriter.VariantField(field_type)
2226 elif isinstance(field_type, CTFWriter.ArrayFieldDeclaration):
2227 return CTFWriter.ArrayField(field_type)
2228 elif isinstance(field_type, CTFWriter.SequenceFieldDeclaration):
2229 return CTFWriter.SequenceField(field_type)
2230 elif isinstance(field_type, CTFWriter.StringFieldDeclaration):
2231 return CTFWriter.StringField(field_type)
2232
2233 class Field:
6fd49698
PP
2234 """
2235 Base class, do not instantiate.
2236 """
2237
2238 def __init__(self, field_type):
2239 if not isinstance(field_type, CTFWriter.FieldDeclaration):
2240 raise TypeError("Invalid field_type argument.")
2241
2242 self._f = nbt._bt_ctf_field_create(field_type._ft)
82839121 2243
6fd49698
PP
2244 if self._f is None:
2245 raise ValueError("Field creation failed.")
2246
2247 def __del__(self):
2248 nbt._bt_ctf_field_put(self._f)
2249
2250 @staticmethod
2251 def _create_field_from_native_instance(native_field_instance):
2252 type_dict = {
2253 CTFTypeId.INTEGER: CTFWriter.IntegerField,
60318a5f 2254 CTFTypeId.FLOAT: CTFWriter.FloatingPointField,
6fd49698
PP
2255 CTFTypeId.ENUM: CTFWriter.EnumerationField,
2256 CTFTypeId.STRING: CTFWriter.StringField,
2257 CTFTypeId.STRUCT: CTFWriter.StructureField,
2258 CTFTypeId.VARIANT: CTFWriter.VariantField,
2259 CTFTypeId.ARRAY: CTFWriter.ArrayField,
2260 CTFTypeId.SEQUENCE: CTFWriter.SequenceField
2261 }
2262
2263 field_type = nbt._bt_python_get_field_type(native_field_instance)
82839121 2264
6fd49698
PP
2265 if field_type == CTFTypeId.UNKNOWN:
2266 raise TypeError("Invalid field instance")
2267
2268 field = CTFWriter.Field.__new__(CTFWriter.Field)
2269 field._f = native_field_instance
2270 field.__class__ = type_dict[field_type]
82839121 2271
6fd49698
PP
2272 return field
2273
2274 @property
2275 def declaration(self):
2276 native_field_type = nbt._bt_ctf_field_get_type(self._f)
82839121 2277
6fd49698
PP
2278 if native_field_type is None:
2279 raise TypeError("Invalid field instance")
2280 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(
2281 native_field_type)
2282
2283 class IntegerField(Field):
6fd49698
PP
2284 @property
2285 def value(self):
82839121
PP
2286 """
2287 Get an integer field's value.
2288 """
2289
6fd49698 2290 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
82839121 2291
6fd49698
PP
2292 if signedness < 0:
2293 raise TypeError("Invalid integer instance.")
2294
2295 if signedness == 0:
2296 ret, value = nbt._bt_ctf_field_unsigned_integer_get_value(self._f)
2297 else:
2298 ret, value = nbt._bt_ctf_field_signed_integer_get_value(self._f)
2299
2300 if ret < 0:
2301 raise ValueError("Could not get integer field value.")
82839121 2302
6fd49698
PP
2303 return value
2304
6fd49698
PP
2305 @value.setter
2306 def value(self, value):
82839121
PP
2307 """
2308 Set an integer field's value.
2309 """
2310
6fd49698
PP
2311 if not isinstance(value, int):
2312 raise TypeError("IntegerField's value must be an int")
2313
2314 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
2315 if signedness < 0:
2316 raise TypeError("Invalid integer instance.")
2317
2318 if signedness == 0:
2319 ret = nbt._bt_ctf_field_unsigned_integer_set_value(self._f, value)
2320 else:
2321 ret = nbt._bt_ctf_field_signed_integer_set_value(self._f, value)
2322
2323 if ret < 0:
2324 raise ValueError("Could not set integer field value.")
2325
2326 class EnumerationField(Field):
6fd49698
PP
2327 @property
2328 def container(self):
82839121
PP
2329 """
2330 Return the enumeration's underlying container field (an integer field).
2331 """
2332
6fd49698
PP
2333 container = CTFWriter.IntegerField.__new__(CTFWriter.IntegerField)
2334 container._f = nbt._bt_ctf_field_enumeration_get_container(self._f)
82839121 2335
6fd49698
PP
2336 if container._f is None:
2337 raise TypeError("Invalid enumeration field type.")
82839121 2338
6fd49698
PP
2339 return container
2340
6fd49698
PP
2341 @property
2342 def value(self):
82839121
PP
2343 """
2344 Get the enumeration field's mapping name.
2345 """
2346
6fd49698 2347 value = nbt._bt_ctf_field_enumeration_get_mapping_name(self._f)
82839121 2348
6fd49698
PP
2349 if value is None:
2350 raise ValueError("Could not get enumeration's mapping name.")
82839121 2351
6fd49698
PP
2352 return value
2353
6fd49698
PP
2354 @value.setter
2355 def value(self, value):
82839121
PP
2356 """
2357 Set the enumeration field's value. Must be an integer as mapping names
2358 may be ambiguous.
2359 """
2360
6fd49698
PP
2361 if not isinstance(value, int):
2362 raise TypeError("EnumerationField value must be an int")
82839121 2363
6fd49698
PP
2364 self.container.value = value
2365
60318a5f 2366 class FloatingPointField(Field):
6fd49698
PP
2367 @property
2368 def value(self):
82839121
PP
2369 """
2370 Get a floating point field's value.
2371 """
2372
6fd49698 2373 ret, value = nbt._bt_ctf_field_floating_point_get_value(self._f)
82839121 2374
6fd49698
PP
2375 if ret < 0:
2376 raise ValueError("Could not get floating point field value.")
82839121 2377
6fd49698
PP
2378 return value
2379
6fd49698
PP
2380 @value.setter
2381 def value(self, value):
82839121
PP
2382 """
2383 Set a floating point field's value.
2384 """
2385
6fd49698
PP
2386 if not isinstance(value, int) and not isinstance(value, float):
2387 raise TypeError("Value must be either a float or an int")
2388
2389 ret = nbt._bt_ctf_field_floating_point_set_value(self._f, float(value))
82839121 2390
6fd49698
PP
2391 if ret < 0:
2392 raise ValueError("Could not set floating point field value.")
2393
60318a5f
PP
2394 # oops!! This class is provided to ensure backward-compatibility since
2395 # a stable release publicly exposed this abomination.
2396 class FloatFieldingPoint(FloatingPointField):
2397 pass
2398
6fd49698 2399 class StructureField(Field):
82839121
PP
2400 def field(self, field_name):
2401 """
2402 Get the structure's field corresponding to the provided field name.
2403 """
6fd49698 2404
82839121
PP
2405 native_instance = nbt._bt_ctf_field_structure_get_field(self._f,
2406 str(field_name))
6fd49698 2407
6fd49698
PP
2408 if native_instance is None:
2409 raise ValueError("Invalid field_name provided.")
6fd49698 2410
82839121 2411 return CTFWriter.Field._create_field_from_native_instance(native_instance)
6fd49698 2412
82839121 2413 class VariantField(Field):
6fd49698 2414 def field(self, tag):
82839121
PP
2415 """
2416 Return the variant's selected field. The "tag" field is the selector enum field.
2417 """
2418
6fd49698 2419 native_instance = nbt._bt_ctf_field_variant_get_field(self._f, tag._f)
82839121 2420
6fd49698
PP
2421 if native_instance is None:
2422 raise ValueError("Invalid tag provided.")
6fd49698 2423
82839121 2424 return CTFWriter.Field._create_field_from_native_instance(native_instance)
6fd49698 2425
82839121 2426 class ArrayField(Field):
6fd49698 2427 def field(self, index):
82839121
PP
2428 """
2429 Return the array's field at position "index".
2430 """
2431
6fd49698 2432 native_instance = nbt._bt_ctf_field_array_get_field(self._f, index)
82839121 2433
6fd49698
PP
2434 if native_instance is None:
2435 raise IndexError("Invalid index provided.")
6fd49698 2436
82839121 2437 return CTFWriter.Field._create_field_from_native_instance(native_instance)
6fd49698 2438
82839121 2439 class SequenceField(Field):
6fd49698
PP
2440 @property
2441 def length(self):
82839121
PP
2442 """
2443 Get the sequence's length field (IntegerField).
2444 """
2445
6fd49698 2446 native_instance = nbt._bt_ctf_field_sequence_get_length(self._f)
82839121 2447
6fd49698
PP
2448 if native_instance is None:
2449 length = -1
6fd49698 2450
82839121
PP
2451 return CTFWriter.Field._create_field_from_native_instance(native_instance)
2452
6fd49698
PP
2453 @length.setter
2454 def length(self, length_field):
82839121
PP
2455 """
2456 Set the sequence's length field (IntegerField).
2457 """
2458
6fd49698
PP
2459 if not isinstance(length_field, CTFWriter.IntegerField):
2460 raise TypeError("Invalid length field.")
82839121 2461
6fd49698
PP
2462 if length_field.declaration.signed:
2463 raise TypeError("Sequence field length must be unsigned")
82839121 2464
6fd49698 2465 ret = nbt._bt_ctf_field_sequence_set_length(self._f, length_field._f)
82839121 2466
6fd49698
PP
2467 if ret < 0:
2468 raise ValueError("Could not set sequence length.")
2469
6fd49698 2470 def field(self, index):
82839121
PP
2471 """
2472 Return the sequence's field at position "index".
2473 """
2474
6fd49698 2475 native_instance = nbt._bt_ctf_field_sequence_get_field(self._f, index)
82839121 2476
6fd49698
PP
2477 if native_instance is None:
2478 raise ValueError("Could not get sequence element at index.")
6fd49698 2479
82839121 2480 return CTFWriter.Field._create_field_from_native_instance(native_instance)
6fd49698 2481
82839121 2482 class StringField(Field):
6fd49698
PP
2483 @property
2484 def value(self):
82839121
PP
2485 """
2486 Get a string field's value.
2487 """
2488
6fd49698
PP
2489 return nbt._bt_ctf_field_string_get_value(self._f)
2490
6fd49698
PP
2491 @value.setter
2492 def value(self, value):
82839121
PP
2493 """
2494 Set a string field's value.
2495 """
2496
6fd49698 2497 ret = nbt._bt_ctf_field_string_set_value(self._f, str(value))
82839121 2498
6fd49698
PP
2499 if ret < 0:
2500 raise ValueError("Could not set string field value.")
2501
2502 class EventClass:
6fd49698 2503 def __init__(self, name):
82839121
PP
2504 """
2505 Create a new event class of the given name.
2506 """
2507
6fd49698 2508 self._ec = nbt._bt_ctf_event_class_create(name)
82839121 2509
6fd49698
PP
2510 if self._ec is None:
2511 raise ValueError("Event class creation failed.")
2512
2513 def __del__(self):
2514 nbt._bt_ctf_event_class_put(self._ec)
2515
6fd49698 2516 def add_field(self, field_type, field_name):
82839121
PP
2517 """
2518 Add a field of type "field_type" to the event class.
2519 """
2520
2521 ret = nbt._bt_ctf_event_class_add_field(self._ec, field_type._ft,
2522 str(field_name))
2523
6fd49698
PP
2524 if ret < 0:
2525 raise ValueError("Could not add field to event class.")
2526
6fd49698
PP
2527 @property
2528 def name(self):
82839121
PP
2529 """
2530 Get the event class' name.
2531 """
2532
6fd49698 2533 name = nbt._bt_ctf_event_class_get_name(self._ec)
82839121 2534
6fd49698
PP
2535 if name is None:
2536 raise TypeError("Could not get EventClass name")
82839121 2537
6fd49698
PP
2538 return name
2539
6fd49698
PP
2540 @property
2541 def id(self):
82839121
PP
2542 """
2543 Get the event class' id. Returns a negative value if unset.
2544 """
2545
6fd49698 2546 id = nbt._bt_ctf_event_class_get_id(self._ec)
82839121 2547
6fd49698
PP
2548 if id < 0:
2549 raise TypeError("Could not get EventClass id")
82839121 2550
6fd49698
PP
2551 return id
2552
6fd49698
PP
2553 @id.setter
2554 def id(self, id):
82839121
PP
2555 """
2556 Set the event class' id. Throws a TypeError if the event class
2557 is already registered to a stream class.
2558 """
2559
6fd49698 2560 ret = nbt._bt_ctf_event_class_set_id(self._ec, id)
82839121 2561
6fd49698 2562 if ret < 0:
82839121 2563 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
6fd49698 2564
6fd49698
PP
2565 @property
2566 def stream_class(self):
82839121
PP
2567 """
2568 Get the event class' stream class. Returns None if unset.
2569 """
2570 stream_class_native = nbt._bt_ctf_event_class_get_stream_class(self._ec)
2571
6fd49698
PP
2572 if stream_class_native is None:
2573 return None
82839121 2574
6fd49698
PP
2575 stream_class = CTFWriter.StreamClass.__new__(CTFWriter.StreamClass)
2576 stream_class._sc = stream_class_native
82839121 2577
6fd49698
PP
2578 return stream_class
2579
6fd49698
PP
2580 @property
2581 def fields(self):
82839121
PP
2582 """
2583 Generator returning the event class' fields as tuples of (field name, field declaration).
2584 """
2585
6fd49698 2586 count = nbt._bt_ctf_event_class_get_field_count(self._ec)
82839121 2587
6fd49698
PP
2588 if count < 0:
2589 raise TypeError("Could not get EventClass' field count")
2590
2591 for i in range(count):
82839121
PP
2592 field_name = nbt._bt_python_ctf_event_class_get_field_name(self._ec, i)
2593
6fd49698 2594 if field_name is None:
82839121
PP
2595 msg = "Could not get EventClass' field name at index {}".format(i)
2596 raise TypeError(msg)
2597
2598 field_type_native = nbt._bt_python_ctf_event_class_get_field_type(self._ec, i)
6fd49698 2599
6fd49698 2600 if field_type_native is None:
82839121
PP
2601 msg = "Could not get EventClass' field type at index {}".format(i)
2602 raise TypeError(msg)
6fd49698 2603
82839121 2604 field_type = CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698
PP
2605 yield (field_name, field_type)
2606
6fd49698 2607 def get_field_by_name(self, name):
82839121
PP
2608 """
2609 Get a field declaration by name (FieldDeclaration).
2610 """
6fd49698 2611
82839121 2612 field_type_native = nbt._bt_ctf_event_class_get_field_by_name(self._ec, name)
6fd49698 2613
82839121
PP
2614 if field_type_native is None:
2615 msg = "Could not find EventClass field with name {}".format(name)
2616 raise TypeError(msg)
6fd49698 2617
82839121
PP
2618 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
2619
2620 class Event:
6fd49698 2621 def __init__(self, event_class):
82839121
PP
2622 """
2623 Create a new event of the given event class.
2624 """
2625
6fd49698
PP
2626 if not isinstance(event_class, CTFWriter.EventClass):
2627 raise TypeError("Invalid event_class argument.")
2628
2629 self._e = nbt._bt_ctf_event_create(event_class._ec)
82839121 2630
6fd49698
PP
2631 if self._e is None:
2632 raise ValueError("Event creation failed.")
2633
2634 def __del__(self):
2635 nbt._bt_ctf_event_put(self._e)
2636
6fd49698
PP
2637 @property
2638 def event_class(self):
82839121
PP
2639 """
2640 Get the event's class.
2641 """
2642
6fd49698 2643 event_class_native = nbt._bt_ctf_event_get_class(self._e)
82839121 2644
6fd49698
PP
2645 if event_class_native is None:
2646 return None
82839121 2647
6fd49698
PP
2648 event_class = CTFWriter.EventClass.__new__(CTFWriter.EventClass)
2649 event_class._ec = event_class_native
6fd49698 2650
82839121 2651 return event_class
6fd49698
PP
2652
2653 def clock(self):
82839121
PP
2654 """
2655 Get a clock from event. Returns None if the event's class
2656 is not registered to a stream class.
2657 """
2658
6fd49698 2659 clock_instance = nbt._bt_ctf_event_get_clock(self._e)
82839121 2660
6fd49698
PP
2661 if clock_instance is None:
2662 return None
82839121 2663
6fd49698
PP
2664 clock = CTFWriter.Clock.__new__(CTFWriter.Clock)
2665 clock._c = clock_instance
6fd49698 2666
82839121 2667 return clock
6fd49698
PP
2668
2669 def payload(self, field_name):
82839121
PP
2670 """
2671 Get a field from event.
2672 """
2673
2674 native_instance = nbt._bt_ctf_event_get_payload(self._e,
2675 str(field_name))
2676
6fd49698
PP
2677 if native_instance is None:
2678 raise ValueError("Could not get event payload.")
6fd49698 2679
82839121 2680 return CTFWriter.Field._create_field_from_native_instance(native_instance)
6fd49698
PP
2681
2682 def set_payload(self, field_name, value_field):
82839121
PP
2683 """
2684 Set a manually created field as an event's payload.
2685 """
2686
6fd49698
PP
2687 if not isinstance(value, CTFWriter.Field):
2688 raise TypeError("Invalid value type.")
82839121
PP
2689
2690 ret = nbt._bt_ctf_event_set_payload(self._e, str(field_name),
2691 value_field._f)
2692
6fd49698
PP
2693 if ret < 0:
2694 raise ValueError("Could not set event field payload.")
2695
2696 class StreamClass:
6fd49698 2697 def __init__(self, name):
82839121
PP
2698 """
2699 Create a new stream class of the given name.
2700 """
2701
6fd49698 2702 self._sc = nbt._bt_ctf_stream_class_create(name)
82839121 2703
6fd49698
PP
2704 if self._sc is None:
2705 raise ValueError("Stream class creation failed.")
2706
2707 def __del__(self):
2708 nbt._bt_ctf_stream_class_put(self._sc)
2709
6fd49698
PP
2710 @property
2711 def name(self):
82839121
PP
2712 """
2713 Get a stream class' name.
2714 """
2715
6fd49698 2716 name = nbt._bt_ctf_stream_class_get_name(self._sc)
82839121 2717
6fd49698
PP
2718 if name is None:
2719 raise TypeError("Could not get StreamClass name")
82839121 2720
6fd49698
PP
2721 return name
2722
6fd49698
PP
2723 @property
2724 def clock(self):
82839121
PP
2725 """
2726 Get a stream class' clock.
2727 """
2728
6fd49698 2729 clock_instance = nbt._bt_ctf_stream_class_get_clock(self._sc)
82839121 2730
6fd49698
PP
2731 if clock_instance is None:
2732 return None
82839121 2733
6fd49698
PP
2734 clock = CTFWriter.Clock.__new__(CTFWriter.Clock)
2735 clock._c = clock_instance
82839121 2736
6fd49698
PP
2737 return clock
2738
6fd49698
PP
2739 @clock.setter
2740 def clock(self, clock):
82839121
PP
2741 """
2742 Assign a clock to a stream class.
2743 """
2744
6fd49698
PP
2745 if not isinstance(clock, CTFWriter.Clock):
2746 raise TypeError("Invalid clock type.")
2747
2748 ret = nbt._bt_ctf_stream_class_set_clock(self._sc, clock._c)
82839121 2749
6fd49698
PP
2750 if ret < 0:
2751 raise ValueError("Could not set stream class clock.")
2752
6fd49698
PP
2753 @property
2754 def id(self):
82839121
PP
2755 """
2756 Get a stream class' id.
2757 """
2758
6fd49698 2759 ret = nbt._bt_ctf_stream_class_get_id(self._sc)
82839121 2760
6fd49698
PP
2761 if ret < 0:
2762 raise TypeError("Could not get StreamClass id")
82839121 2763
6fd49698
PP
2764 return ret
2765
6fd49698
PP
2766 @id.setter
2767 def id(self, id):
82839121
PP
2768 """
2769 Assign an id to a stream class.
2770 """
2771
6fd49698 2772 ret = nbt._bt_ctf_stream_class_set_id(self._sc, id)
82839121 2773
6fd49698
PP
2774 if ret < 0:
2775 raise TypeError("Could not set stream class id.")
2776
6fd49698
PP
2777 @property
2778 def event_classes(self):
82839121
PP
2779 """
2780 Generator returning the stream class' event classes.
2781 """
2782
6fd49698 2783 count = nbt._bt_ctf_stream_class_get_event_class_count(self._sc)
82839121 2784
6fd49698
PP
2785 if count < 0:
2786 raise TypeError("Could not get StreamClass' event class count")
2787
2788 for i in range(count):
82839121
PP
2789 event_class_native = nbt._bt_ctf_stream_class_get_event_class(self._sc, i)
2790
6fd49698 2791 if event_class_native is None:
82839121
PP
2792 msg = "Could not get StreamClass' event class at index {}".format(i)
2793 raise TypeError(msg)
6fd49698 2794
82839121 2795 event_class = CTFWriter.EventClass.__new__(CTFWriter.EventClass)
6fd49698
PP
2796 event_class._ec = event_class_native
2797 yield event_class
2798
6fd49698 2799 def add_event_class(self, event_class):
82839121
PP
2800 """
2801 Add an event class to a stream class. New events can be added even after a
2802 stream has been instantiated and events have been appended. However, a stream
2803 will not accept events of a class that has not been added to the stream
2804 class beforehand.
2805 """
2806
6fd49698
PP
2807 if not isinstance(event_class, CTFWriter.EventClass):
2808 raise TypeError("Invalid event_class type.")
2809
82839121
PP
2810 ret = nbt._bt_ctf_stream_class_add_event_class(self._sc,
2811 event_class._ec)
2812
6fd49698
PP
2813 if ret < 0:
2814 raise ValueError("Could not add event class.")
2815
6fd49698
PP
2816 @property
2817 def packet_context_type(self):
82839121
PP
2818 """
2819 Get the StreamClass' packet context type (StructureFieldDeclaration)
2820 """
2821
2822 field_type_native = nbt._bt_ctf_stream_class_get_packet_context_type(self._sc)
2823
6fd49698
PP
2824 if field_type_native is None:
2825 raise ValueError("Invalid StreamClass")
82839121
PP
2826
2827 field_type = CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
2828
6fd49698
PP
2829 return field_type
2830
6fd49698
PP
2831 @packet_context_type.setter
2832 def packet_context_type(self, field_type):
82839121
PP
2833 """
2834 Set a StreamClass' packet context type. Must be of type
2835 StructureFieldDeclaration.
2836 """
2837
6fd49698 2838 if not isinstance(field_type, CTFWriter.StructureFieldDeclaration):
82839121
PP
2839 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
2840
2841 ret = nbt._bt_ctf_stream_class_set_packet_context_type(self._sc,
2842 field_type._ft)
2843
6fd49698
PP
2844 if ret < 0:
2845 raise ValueError("Failed to set packet context type.")
2846
2847 class Stream:
9f8e803f
PP
2848 def __init__(self):
2849 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
6fd49698
PP
2850
2851 def __del__(self):
2852 nbt._bt_ctf_stream_put(self._s)
2853
6fd49698
PP
2854 @property
2855 def discarded_events(self):
82839121
PP
2856 """
2857 Get a stream's discarded event count.
2858 """
2859
6fd49698 2860 ret, count = nbt._bt_ctf_stream_get_discarded_events_count(self._s)
82839121 2861
6fd49698 2862 if ret < 0:
82839121 2863 raise ValueError("Could not get the stream's discarded events count")
6fd49698 2864
82839121 2865 return count
6fd49698
PP
2866
2867 def append_discarded_events(self, event_count):
82839121
PP
2868 """
2869 Increase the current packet's discarded event count.
2870 """
6fd49698 2871
82839121 2872 nbt._bt_ctf_stream_append_discarded_events(self._s, event_count)
6fd49698
PP
2873
2874 def append_event(self, event):
82839121
PP
2875 """
2876 Append "event" to the stream's current packet. The stream's associated clock
2877 will be sampled during this call. The event shall not be modified after
2878 being appended to a stream.
2879 """
2880
6fd49698 2881 ret = nbt._bt_ctf_stream_append_event(self._s, event._e)
82839121 2882
6fd49698
PP
2883 if ret < 0:
2884 raise ValueError("Could not append event to stream.")
2885
6fd49698
PP
2886 @property
2887 def packet_context(self):
82839121
PP
2888 """
2889 Get a Stream's packet context field (a StructureField).
2890 """
2891
6fd49698 2892 native_field = nbt._bt_ctf_stream_get_packet_context(self._s)
82839121 2893
6fd49698
PP
2894 if native_field is None:
2895 raise ValueError("Invalid Stream.")
6fd49698 2896
82839121
PP
2897 return CTFWriter.Field._create_field_from_native_instance(native_field)
2898
6fd49698
PP
2899 @packet_context.setter
2900 def packet_context(self, field):
82839121
PP
2901 """
2902 Set a Stream's packet context field (must be a StructureField).
2903 """
2904
6fd49698 2905 if not isinstance(field, CTFWriter.StructureField):
82839121
PP
2906 raise TypeError("Argument field must be of type StructureField")
2907
6fd49698 2908 ret = nbt._bt_ctf_stream_set_packet_context(self._s, field._f)
82839121 2909
6fd49698
PP
2910 if ret < 0:
2911 raise ValueError("Invalid packet context field.")
2912
6fd49698 2913 def flush(self):
82839121
PP
2914 """
2915 The stream's current packet's events will be flushed to disk. Events
2916 subsequently appended to the stream will be added to a new packet.
2917 """
2918
6fd49698 2919 ret = nbt._bt_ctf_stream_flush(self._s)
82839121 2920
6fd49698
PP
2921 if ret < 0:
2922 raise ValueError("Could not flush stream.")
2923
2924 class Writer:
6fd49698 2925 def __init__(self, path):
82839121
PP
2926 """
2927 Create a new writer that will produce a trace in the given path.
2928 """
2929
6fd49698 2930 self._w = nbt._bt_ctf_writer_create(path)
82839121 2931
6fd49698
PP
2932 if self._w is None:
2933 raise ValueError("Writer creation failed.")
2934
2935 def __del__(self):
2936 nbt._bt_ctf_writer_put(self._w)
2937
6fd49698 2938 def create_stream(self, stream_class):
82839121
PP
2939 """
2940 Create a new stream instance and register it to the writer.
2941 """
2942
6fd49698
PP
2943 if not isinstance(stream_class, CTFWriter.StreamClass):
2944 raise TypeError("Invalid stream_class type.")
2945
2946 stream = CTFWriter.Stream.__new__(CTFWriter.Stream)
2947 stream._s = nbt._bt_ctf_writer_create_stream(self._w, stream_class._sc)
6fd49698 2948
82839121 2949 return stream
6fd49698
PP
2950
2951 def add_environment_field(self, name, value):
82839121
PP
2952 """
2953 Add an environment field to the trace.
2954 """
2955
2956 ret = nbt._bt_ctf_writer_add_environment_field(self._w, str(name),
2957 str(value))
2958
6fd49698
PP
2959 if ret < 0:
2960 raise ValueError("Could not add environment field to trace.")
2961
6fd49698 2962 def add_clock(self, clock):
82839121
PP
2963 """
2964 Add a clock to the trace. Clocks assigned to stream classes must be
2965 registered to the writer.
2966 """
2967
6fd49698 2968 ret = nbt._bt_ctf_writer_add_clock(self._w, clock._c)
82839121 2969
6fd49698
PP
2970 if ret < 0:
2971 raise ValueError("Could not add clock to Writer.")
2972
6fd49698
PP
2973 @property
2974 def metadata(self):
82839121
PP
2975 """
2976 Get the trace's TSDL meta-data.
2977 """
6fd49698 2978
82839121 2979 return nbt._bt_ctf_writer_get_metadata_string(self._w)
6fd49698
PP
2980
2981 def flush_metadata(self):
82839121
PP
2982 """
2983 Flush the trace's metadata to the metadata file.
2984 """
2985
6fd49698
PP
2986 nbt._bt_ctf_writer_flush_metadata(self._w)
2987
6fd49698
PP
2988 @property
2989 def byte_order(self):
82839121
PP
2990 """
2991 Get the trace's byte order. Must be a constant from the ByteOrder
2992 class.
2993 """
2994
6fd49698
PP
2995 raise NotImplementedError("Getter not implemented.")
2996
6fd49698
PP
2997 @byte_order.setter
2998 def byte_order(self, byte_order):
82839121
PP
2999 """
3000 Set the trace's byte order. Must be a constant from the ByteOrder
3001 class. Defaults to the host machine's endianness
3002 """
3003
6fd49698 3004 ret = nbt._bt_ctf_writer_set_byte_order(self._w, byte_order)
82839121 3005
6fd49698
PP
3006 if ret < 0:
3007 raise ValueError("Could not set trace's byte order.")
This page took 0.164571 seconds and 4 git commands to generate.