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