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