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