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