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