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