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