Python: document CTFStringEncoding
[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:
349 BYTE_ORDER_NATIVE = 0
350 BYTE_ORDER_LITTLE_ENDIAN = 1
351 BYTE_ORDER_BIG_ENDIAN = 2
352 BYTE_ORDER_NETWORK = 3
353 BYTE_ORDER_UNKNOWN = 4 # Python-specific entry
354
355
356# enum equivalent, accessible constants
357# These are taken directly from ctf/events.h
358# All changes to enums must also be made here
359class CTFTypeId:
360 UNKNOWN = 0
361 INTEGER = 1
362 FLOAT = 2
363 ENUM = 3
364 STRING = 4
365 STRUCT = 5
366 UNTAGGED_VARIANT = 6
367 VARIANT = 7
368 ARRAY = 8
369 SEQUENCE = 9
370 NR_CTF_TYPES = 10
371
372 def type_name(id):
373 name = "UNKNOWN_TYPE"
374 constants = [
375 attr for attr in dir(CTFTypeId) if not callable(
376 getattr(
377 CTFTypeId,
378 attr)) and not attr.startswith("__")]
82839121 379
6fd49698
PP
380 for attr in constants:
381 if getattr(CTFTypeId, attr) == id:
382 name = attr
383 break
82839121 384
6fd49698
PP
385 return name
386
387
388class CTFScope:
389 TRACE_PACKET_HEADER = 0
390 STREAM_PACKET_CONTEXT = 1
391 STREAM_EVENT_HEADER = 2
392 STREAM_EVENT_CONTEXT = 3
393 EVENT_CONTEXT = 4
394 EVENT_FIELDS = 5
395
396 def scope_name(scope):
397 name = "UNKNOWN_SCOPE"
398 constants = [
399 attr for attr in dir(CTFScope) if not callable(
400 getattr(
401 CTFScope,
402 attr)) and not attr.startswith("__")]
82839121 403
6fd49698
PP
404 for attr in constants:
405 if getattr(CTFScope, attr) == scope:
406 name = attr
407 break
82839121 408
6fd49698
PP
409 return name
410
411
412# Priority of the scopes when searching for event fields
82839121
PP
413_scopes = [
414 CTFScope.EVENT_FIELDS,
415 CTFScope.EVENT_CONTEXT,
416 CTFScope.STREAM_EVENT_CONTEXT,
417 CTFScope.STREAM_EVENT_HEADER,
418 CTFScope.STREAM_PACKET_CONTEXT,
419 CTFScope.TRACE_PACKET_HEADER
420]
6fd49698
PP
421
422
423class Event(collections.Mapping):
6fd49698
PP
424 """
425 This class represents an event from the trace.
426 It is obtained using the TraceCollection generator functions.
427 Do not instantiate.
428 """
429
430 def __init__(self):
431 raise NotImplementedError("Event cannot be instantiated")
432
433 @property
434 def name(self):
435 """Return the name of the event or None on error."""
82839121 436
6fd49698
PP
437 return nbt._bt_ctf_event_name(self._e)
438
439 @property
440 def cycles(self):
441 """
442 Return the timestamp of the event as written in
443 the packet (in cycles) or -1ULL on error.
444 """
82839121 445
6fd49698
PP
446 return nbt._bt_ctf_get_cycles(self._e)
447
448 @property
449 def timestamp(self):
450 """
451 Return the timestamp of the event offset with the
452 system clock source or -1ULL on error.
453 """
82839121 454
6fd49698
PP
455 return nbt._bt_ctf_get_timestamp(self._e)
456
457 @property
458 def datetime(self):
459 """
460 Return a datetime object based on the event's
461 timestamp. Note that the datetime class' precision
462 is limited to microseconds.
463 """
82839121 464
6fd49698
PP
465 return datetime.fromtimestamp(self.timestamp / 1E9)
466
467 def field_with_scope(self, field_name, scope):
468 """
469 Get field_name's value in scope.
470 None is returned if no field matches field_name.
471 """
82839121
PP
472
473 if scope not in _scopes:
6fd49698 474 raise ValueError("Invalid scope provided")
82839121 475
6fd49698 476 field = self._field_with_scope(field_name, scope)
82839121 477
6fd49698
PP
478 if field is not None:
479 return field.value
82839121 480
6fd49698
PP
481 def field_list_with_scope(self, scope):
482 """Return a list of field names in scope."""
82839121
PP
483
484 if scope not in _scopes:
6fd49698 485 raise ValueError("Invalid scope provided")
82839121 486
6fd49698 487 field_names = []
82839121 488
6fd49698
PP
489 for field in self._field_list_with_scope(scope):
490 field_names.append(field.name)
82839121 491
6fd49698
PP
492 return field_names
493
494 @property
495 def handle(self):
496 """
497 Get the TraceHandle associated with this event
498 Return None on error
499 """
82839121 500
6fd49698 501 ret = nbt._bt_ctf_event_get_handle_id(self._e)
82839121 502
6fd49698
PP
503 if ret < 0:
504 return None
505
506 th = TraceHandle.__new__(TraceHandle)
507 th._id = ret
508 th._trace_collection = self.get_trace_collection()
82839121 509
6fd49698
PP
510 return th
511
512 @property
513 def trace_collection(self):
514 """
515 Get the TraceCollection associated with this event.
516 Return None on error.
517 """
82839121 518
6fd49698
PP
519 trace_collection = TraceCollection()
520 trace_collection._tc = nbt._bt_ctf_event_get_context(self._e)
82839121 521
decd548b 522 if trace_collection._tc is not None:
6fd49698
PP
523 return trace_collection
524
525 def __getitem__(self, field_name):
526 """
527 Get field_name's value. If the field_name exists in multiple
528 scopes, the first field found is returned. The scopes are searched
529 in the following order:
530 1) EVENT_FIELDS
531 2) EVENT_CONTEXT
532 3) STREAM_EVENT_CONTEXT
533 4) STREAM_EVENT_HEADER
534 5) STREAM_PACKET_CONTEXT
535 6) TRACE_PACKET_HEADER
536 None is returned if no field matches field_name.
537
538 Use field_with_scope() to explicitly access fields in a given
539 scope.
540 """
82839121 541
6fd49698 542 field = self._field(field_name)
82839121 543
6fd49698
PP
544 if field is not None:
545 return field.value
82839121 546
6fd49698
PP
547 raise KeyError(field_name)
548
549 def __iter__(self):
550 for key in self.keys():
551 yield key
552
553 def __len__(self):
554 count = 0
82839121 555
6fd49698
PP
556 for scope in _scopes:
557 scope_ptr = nbt._bt_ctf_get_top_level_scope(self._e, scope)
558 ret = nbt._bt_python_field_listcaller(self._e, scope_ptr)
82839121 559
6fd49698
PP
560 if isinstance(ret, list):
561 count += ret[1]
82839121 562
6fd49698
PP
563 return count
564
565 def __contains__(self, field_name):
566 return self._field(field_name) is not None
567
568 def keys(self):
569 """Return a list of field names."""
82839121 570
6fd49698 571 field_names = set()
82839121 572
6fd49698
PP
573 for scope in _scopes:
574 for name in self.field_list_with_scope(scope):
575 field_names.add(name)
82839121 576
6fd49698
PP
577 return list(field_names)
578
579 def get(self, field_name, default=None):
580 field = self._field(field_name)
82839121 581
6fd49698
PP
582 if field is None:
583 return default
82839121 584
6fd49698
PP
585 return field.value
586
587 def items(self):
588 for field in self.keys():
589 yield (field, self[field])
590
591 def _field_with_scope(self, field_name, scope):
592 scope_ptr = nbt._bt_ctf_get_top_level_scope(self._e, scope)
82839121 593
6fd49698
PP
594 if scope_ptr is None:
595 return None
596
597 definition_ptr = nbt._bt_ctf_get_field(self._e, scope_ptr, field_name)
82839121 598
6fd49698
PP
599 if definition_ptr is None:
600 return None
601
602 field = _Definition(definition_ptr, scope)
82839121 603
6fd49698
PP
604 return field
605
606 def _field(self, field_name):
607 field = None
82839121 608
6fd49698
PP
609 for scope in _scopes:
610 field = self._field_with_scope(field_name, scope)
82839121 611
6fd49698
PP
612 if field is not None:
613 break
82839121 614
6fd49698
PP
615 return field
616
617 def _field_list_with_scope(self, scope):
618 fields = []
619 scope_ptr = nbt._bt_ctf_get_top_level_scope(self._e, scope)
620
621 # Returns a list [list_ptr, count]. If list_ptr is NULL, SWIG will only
622 # provide the "count" return value
623 count = 0
624 list_ptr = None
625 ret = nbt._bt_python_field_listcaller(self._e, scope_ptr)
82839121 626
6fd49698
PP
627 if isinstance(ret, list):
628 list_ptr, count = ret
629
630 for i in range(count):
631 definition_ptr = nbt._bt_python_field_one_from_list(list_ptr, i)
82839121 632
6fd49698
PP
633 if definition_ptr is not None:
634 definition = _Definition(definition_ptr, scope)
635 fields.append(definition)
82839121 636
6fd49698
PP
637 return fields
638
639
640class FieldError(Exception):
6fd49698
PP
641 def __init__(self, value):
642 self.value = value
643
644 def __str__(self):
645 return repr(self.value)
646
647
4cde866e 648class EventDeclaration:
6fd49698 649 """Event declaration class. Do not instantiate."""
82839121 650
6fd49698
PP
651 MAX_UINT64 = 0xFFFFFFFFFFFFFFFF
652
653 def __init__(self):
654 raise NotImplementedError("EventDeclaration cannot be instantiated")
655
656 @property
657 def name(self):
658 """Return the name of the event or None on error"""
82839121 659
6fd49698
PP
660 return nbt._bt_ctf_get_decl_event_name(self._ed)
661
662 @property
663 def id(self):
664 """Return the event-ID of the event or -1 on error"""
82839121 665
6fd49698 666 id = nbt._bt_ctf_get_decl_event_id(self._ed)
82839121 667
6fd49698
PP
668 if id == self.MAX_UINT64:
669 id = -1
82839121 670
6fd49698
PP
671 return id
672
673 @property
674 def fields(self):
675 """
676 Generator returning all FieldDeclarations of an event, going through
677 each scope in the following order:
678 1) EVENT_FIELDS
679 2) EVENT_CONTEXT
680 3) STREAM_EVENT_CONTEXT
681 4) STREAM_EVENT_HEADER
682 5) STREAM_PACKET_CONTEXT
683 6) TRACE_PACKET_HEADER
684 """
82839121 685
6fd49698
PP
686 for scope in _scopes:
687 for declaration in self.fields_scope(scope):
688 yield declaration
689
690 def fields_scope(self, scope):
691 """
692 Generator returning FieldDeclarations of the current event in scope.
693 """
694 ret = nbt._by_python_field_decl_listcaller(self._ed, scope)
695
696 if not isinstance(ret, list):
697 return
698
699 list_ptr, count = ret
82839121 700
6fd49698 701 for i in range(count):
82839121
PP
702 field_decl_ptr = nbt._bt_python_field_decl_one_from_list(list_ptr, i)
703
704 if field_decl_ptr is not None:
705 decl_ptr = nbt._bt_ctf_get_decl_from_field_decl(field_decl_ptr)
706 name = nbt._bt_ctf_get_decl_field_name(field_decl_ptr)
707 field_declaration = _create_field_declaration(decl_ptr, name,
708 scope)
6fd49698
PP
709 yield field_declaration
710
711
4cde866e 712class FieldDeclaration:
6fd49698
PP
713 """Field declaration class. Do not instantiate."""
714
715 def __init__(self):
716 raise NotImplementedError("FieldDeclaration cannot be instantiated")
717
718 def __repr__(self):
82839121
PP
719 return "({0}) {1} {2}".format(CTFScope.scope_name(self.scope),
720 CTFTypeId.type_name(self.type),
721 self.name)
6fd49698
PP
722
723 @property
724 def name(self):
725 """Return the name of a FieldDeclaration or None on error."""
82839121 726
6fd49698
PP
727 return self._name
728
729 @property
730 def type(self):
731 """
732 Return the FieldDeclaration's type. One of the entries in class
733 CTFTypeId.
734 """
82839121 735
6fd49698
PP
736 return nbt._bt_ctf_field_type(self._fd)
737
738 @property
739 def scope(self):
740 """
741 Return the FieldDeclaration's scope.
742 """
82839121 743
6fd49698
PP
744 return self._s
745
746
747class IntegerFieldDeclaration(FieldDeclaration):
6fd49698
PP
748 """Do not instantiate."""
749
750 def __init__(self):
82839121 751 raise NotImplementedError("IntegerFieldDeclaration cannot be instantiated")
6fd49698
PP
752
753 @property
754 def signedness(self):
755 """
756 Return the signedness of an integer:
757 0 if unsigned; 1 if signed; -1 on error.
758 """
82839121 759
6fd49698
PP
760 return nbt._bt_ctf_get_int_signedness(self._fd)
761
762 @property
763 def base(self):
764 """Return the base of an int or a negative value on error."""
82839121 765
6fd49698
PP
766 return nbt._bt_ctf_get_int_base(self._fd)
767
768 @property
769 def byte_order(self):
770 """
771 Return the byte order. One of class ByteOrder's entries.
772 """
82839121 773
6fd49698 774 ret = nbt._bt_ctf_get_int_byte_order(self._fd)
82839121 775
6fd49698
PP
776 if ret == 1234:
777 return ByteOrder.BYTE_ORDER_LITTLE_ENDIAN
778 elif ret == 4321:
779 return ByteOrder.BYTE_ORDER_BIG_ENDIAN
780 else:
781 return ByteOrder.BYTE_ORDER_UNKNOWN
782
783 @property
784 def length(self):
785 """
786 Return the size, in bits, of an int or a negative
787 value on error.
788 """
82839121 789
6fd49698
PP
790 return nbt._bt_ctf_get_int_len(self._fd)
791
792 @property
793 def encoding(self):
794 """
795 Return the encoding. One of class CTFStringEncoding's entries.
796 Return a negative value on error.
797 """
82839121 798
6fd49698
PP
799 return nbt._bt_ctf_get_encoding(self._fd)
800
801
802class EnumerationFieldDeclaration(FieldDeclaration):
6fd49698
PP
803 """Do not instantiate."""
804
805 def __init__(self):
82839121 806 raise NotImplementedError("EnumerationFieldDeclaration cannot be instantiated")
6fd49698
PP
807
808
809class ArrayFieldDeclaration(FieldDeclaration):
6fd49698
PP
810 """Do not instantiate."""
811
812 def __init__(self):
82839121 813 raise NotImplementedError("ArrayFieldDeclaration cannot be instantiated")
6fd49698
PP
814
815 @property
816 def length(self):
817 """
818 Return the length of an array or a negative
819 value on error.
820 """
82839121 821
6fd49698
PP
822 return nbt._bt_ctf_get_array_len(self._fd)
823
824 @property
825 def element_declaration(self):
826 """
827 Return element declaration.
828 """
82839121 829
6fd49698 830 field_decl_ptr = nbt._bt_python_get_array_element_declaration(self._fd)
82839121 831
6fd49698
PP
832 return _create_field_declaration(field_decl_ptr, "", self.scope)
833
834
835class SequenceFieldDeclaration(FieldDeclaration):
6fd49698
PP
836 """Do not instantiate."""
837
838 def __init__(self):
82839121 839 raise NotImplementedError("SequenceFieldDeclaration cannot be instantiated")
6fd49698
PP
840
841 @property
842 def element_declaration(self):
843 """
844 Return element declaration.
845 """
82839121 846
6fd49698 847 field_decl_ptr = nbt._bt_python_get_sequence_element_declaration(self._fd)
82839121 848
6fd49698
PP
849 return _create_field_declaration(field_decl_ptr, "", self.scope)
850
851
852class FloatFieldDeclaration(FieldDeclaration):
6fd49698
PP
853 """Do not instantiate."""
854
855 def __init__(self):
82839121 856 raise NotImplementedError("FloatFieldDeclaration cannot be instantiated")
6fd49698
PP
857
858
859class StructureFieldDeclaration(FieldDeclaration):
6fd49698
PP
860 """Do not instantiate."""
861
862 def __init__(self):
82839121 863 raise NotImplementedError("StructureFieldDeclaration cannot be instantiated")
6fd49698
PP
864
865
866class StringFieldDeclaration(FieldDeclaration):
6fd49698
PP
867 """Do not instantiate."""
868
869 def __init__(self):
82839121 870 raise NotImplementedError("StringFieldDeclaration cannot be instantiated")
6fd49698
PP
871
872
873class VariantFieldDeclaration(FieldDeclaration):
6fd49698
PP
874 """Do not instantiate."""
875
876 def __init__(self):
82839121 877 raise NotImplementedError("VariantFieldDeclaration cannot be instantiated")
6fd49698
PP
878
879
880def field_error():
881 """
882 Return the last error code encountered while
883 accessing a field and reset the error flag.
884 Return 0 if no error, a negative value otherwise.
885 """
82839121 886
6fd49698
PP
887 return nbt._bt_ctf_field_get_error()
888
889
890def _create_field_declaration(declaration_ptr, name, scope):
891 """
892 Private field declaration factory.
893 """
82839121 894
6fd49698
PP
895 if declaration_ptr is None:
896 raise ValueError("declaration_ptr must be valid")
82839121 897 if scope not in _scopes:
6fd49698
PP
898 raise ValueError("Invalid scope provided")
899
900 type = nbt._bt_ctf_field_type(declaration_ptr)
901 declaration = None
82839121 902
6fd49698
PP
903 if type == CTFTypeId.INTEGER:
904 declaration = IntegerFieldDeclaration.__new__(IntegerFieldDeclaration)
905 elif type == CTFTypeId.ENUM:
82839121 906 declaration = EnumerationFieldDeclaration.__new__(EnumerationFieldDeclaration)
6fd49698
PP
907 elif type == CTFTypeId.ARRAY:
908 declaration = ArrayFieldDeclaration.__new__(ArrayFieldDeclaration)
909 elif type == CTFTypeId.SEQUENCE:
82839121 910 declaration = SequenceFieldDeclaration.__new__(SequenceFieldDeclaration)
6fd49698
PP
911 elif type == CTFTypeId.FLOAT:
912 declaration = FloatFieldDeclaration.__new__(FloatFieldDeclaration)
913 elif type == CTFTypeId.STRUCT:
82839121 914 declaration = StructureFieldDeclaration.__new__(StructureFieldDeclaration)
6fd49698
PP
915 elif type == CTFTypeId.STRING:
916 declaration = StringFieldDeclaration.__new__(StringFieldDeclaration)
917 elif type == CTFTypeId.VARIANT:
918 declaration = VariantFieldDeclaration.__new__(VariantFieldDeclaration)
919 else:
920 return declaration
921
922 declaration._fd = declaration_ptr
923 declaration._s = scope
924 declaration._name = name
82839121 925
6fd49698
PP
926 return declaration
927
928
4cde866e 929class _Definition:
6fd49698
PP
930 def __init__(self, definition_ptr, scope):
931 self._d = definition_ptr
932 self._s = scope
82839121
PP
933
934 if scope not in _scopes:
6fd49698
PP
935 ValueError("Invalid scope provided")
936
937 @property
938 def name(self):
939 """Return the name of a field or None on error."""
82839121 940
6fd49698
PP
941 return nbt._bt_ctf_field_name(self._d)
942
943 @property
944 def type(self):
945 """Return the type of a field or -1 if unknown."""
82839121 946
6fd49698
PP
947 return nbt._bt_ctf_field_type(nbt._bt_ctf_get_decl_from_def(self._d))
948
949 @property
950 def declaration(self):
951 """Return the associated Definition object."""
82839121 952
6fd49698
PP
953 return _create_field_declaration(
954 nbt._bt_ctf_get_decl_from_def(self._d), self.name, self.scope)
955
956 def _get_enum_str(self):
957 """
958 Return the string matching the current enumeration.
959 Return None on error.
960 """
82839121 961
6fd49698
PP
962 return nbt._bt_ctf_get_enum_str(self._d)
963
964 def _get_array_element_at(self, index):
965 """
966 Return the array's element at position index.
967 Return None on error
968 """
82839121 969
6fd49698 970 array_ptr = nbt._bt_python_get_array_from_def(self._d)
82839121 971
6fd49698
PP
972 if array_ptr is None:
973 return None
974
975 definition_ptr = nbt._bt_array_index(array_ptr, index)
82839121 976
6fd49698
PP
977 if definition_ptr is None:
978 return None
82839121 979
6fd49698
PP
980 return _Definition(definition_ptr, self.scope)
981
982 def _get_sequence_len(self):
983 """
984 Return the len of a sequence or a negative
985 value on error.
986 """
82839121 987
6fd49698 988 seq = nbt._bt_python_get_sequence_from_def(self._d)
82839121 989
6fd49698
PP
990 return nbt._bt_sequence_len(seq)
991
992 def _get_sequence_element_at(self, index):
993 """
994 Return the sequence's element at position index,
995 otherwise return None
996 """
82839121 997
6fd49698 998 seq = nbt._bt_python_get_sequence_from_def(self._d)
82839121 999
6fd49698
PP
1000 if seq is not None:
1001 definition_ptr = nbt._bt_sequence_index(seq, index)
82839121 1002
6fd49698
PP
1003 if definition_ptr is not None:
1004 return _Definition(definition_ptr, self.scope)
82839121 1005
6fd49698
PP
1006 def _get_uint64(self):
1007 """
1008 Return the value associated with the field.
1009 If the field does not exist or is not of the type requested,
1010 the value returned is undefined. To check if an error occured,
1011 use the field_error() function after accessing a field.
1012 """
82839121 1013
6fd49698
PP
1014 return nbt._bt_ctf_get_uint64(self._d)
1015
1016 def _get_int64(self):
1017 """
1018 Return the value associated with the field.
1019 If the field does not exist or is not of the type requested,
1020 the value returned is undefined. To check if an error occured,
1021 use the field_error() function after accessing a field.
1022 """
82839121 1023
6fd49698
PP
1024 return nbt._bt_ctf_get_int64(self._d)
1025
1026 def _get_char_array(self):
1027 """
1028 Return the value associated with the field.
1029 If the field does not exist or is not of the type requested,
1030 the value returned is undefined. To check if an error occurred,
1031 use the field_error() function after accessing a field.
1032 """
82839121 1033
6fd49698
PP
1034 return nbt._bt_ctf_get_char_array(self._d)
1035
1036 def _get_str(self):
1037 """
1038 Return the value associated with the field.
1039 If the field does not exist or is not of the type requested,
1040 the value returned is undefined. To check if an error occurred,
1041 use the field_error() function after accessing a field.
1042 """
82839121 1043
6fd49698
PP
1044 return nbt._bt_ctf_get_string(self._d)
1045
1046 def _get_float(self):
1047 """
1048 Return the value associated with the field.
1049 If the field does not exist or is not of the type requested,
1050 the value returned is undefined. To check if an error occurred,
1051 use the field_error() function after accessing a field.
1052 """
82839121 1053
6fd49698
PP
1054 return nbt._bt_ctf_get_float(self._d)
1055
1056 def _get_variant(self):
1057 """
1058 Return the variant's selected field.
1059 If the field does not exist or is not of the type requested,
1060 the value returned is undefined. To check if an error occurred,
1061 use the field_error() function after accessing a field.
1062 """
82839121 1063
6fd49698
PP
1064 return nbt._bt_ctf_get_variant(self._d)
1065
1066 def _get_struct_field_count(self):
1067 """
1068 Return the number of fields contained in the structure.
1069 If the field does not exist or is not of the type requested,
1070 the value returned is undefined.
1071 """
82839121 1072
6fd49698
PP
1073 return nbt._bt_ctf_get_struct_field_count(self._d)
1074
1075 def _get_struct_field_at(self, i):
1076 """
1077 Return the structure's field at position i.
1078 If the field does not exist or is not of the type requested,
1079 the value returned is undefined. To check if an error occurred,
1080 use the field_error() function after accessing a field.
1081 """
82839121 1082
6fd49698
PP
1083 return nbt._bt_ctf_get_struct_field_index(self._d, i)
1084
1085 @property
1086 def value(self):
1087 """
1088 Return the value associated with the field according to its type.
1089 Return None on error.
1090 """
82839121 1091
6fd49698
PP
1092 id = self.type
1093 value = None
1094
1095 if id == CTFTypeId.STRING:
1096 value = self._get_str()
1097 elif id == CTFTypeId.ARRAY:
1098 element_decl = self.declaration.element_declaration
82839121 1099
6fd49698
PP
1100 if ((element_decl.type == CTFTypeId.INTEGER
1101 and element_decl.length == 8)
1102 and (element_decl.encoding == CTFStringEncoding.ASCII or element_decl.encoding == CTFStringEncoding.UTF8)):
1103 value = nbt._bt_python_get_array_string(self._d)
1104 else:
1105 value = []
82839121 1106
6fd49698
PP
1107 for i in range(self.declaration.length):
1108 element = self._get_array_element_at(i)
1109 value.append(element.value)
1110 elif id == CTFTypeId.INTEGER:
1111 if self.declaration.signedness == 0:
1112 value = self._get_uint64()
1113 else:
1114 value = self._get_int64()
1115 elif id == CTFTypeId.ENUM:
1116 value = self._get_enum_str()
1117 elif id == CTFTypeId.SEQUENCE:
1118 element_decl = self.declaration.element_declaration
82839121 1119
6fd49698
PP
1120 if ((element_decl.type == CTFTypeId.INTEGER
1121 and element_decl.length == 8)
1122 and (element_decl.encoding == CTFStringEncoding.ASCII or element_decl.encoding == CTFStringEncoding.UTF8)):
1123 value = nbt._bt_python_get_sequence_string(self._d)
1124 else:
1125 seq_len = self._get_sequence_len()
1126 value = []
82839121 1127
6fd49698
PP
1128 for i in range(seq_len):
1129 evDef = self._get_sequence_element_at(i)
1130 value.append(evDef.value)
1131 elif id == CTFTypeId.FLOAT:
1132 value = self._get_float()
1133 elif id == CTFTypeId.VARIANT:
1134 variant = _Definition.__new__(_Definition)
1135 variant._d = self._get_variant()
1136 value = variant.value
1137 elif id == CTFTypeId.STRUCT:
1138 value = {}
82839121 1139
6fd49698
PP
1140 for i in range(self._get_struct_field_count()):
1141 member = _Definition(self._get_struct_field_at(i), self.scope)
1142 value[member.name] = member.value
1143
1144 if field_error():
1145 raise FieldError(
1146 "Error occurred while accessing field {} of type {}".format(
1147 self.name,
1148 CTFTypeId.type_name(id)))
82839121 1149
6fd49698
PP
1150 return value
1151
1152 @property
1153 def scope(self):
1154 """Return the scope of a field or None on error."""
82839121 1155
6fd49698
PP
1156 return self._s
1157
1158
1159class CTFWriter:
1160 # Used to compare to -1ULL in error checks
1161 _MAX_UINT64 = 0xFFFFFFFFFFFFFFFF
1162
6fd49698 1163 class EnumerationMapping:
82839121
PP
1164 """
1165 Enumeration mapping class. start and end values are inclusive.
1166 """
6fd49698
PP
1167
1168 def __init__(self, name, start, end):
1169 self.name = name
1170 self.start = start
1171 self.end = end
1172
1173 class Clock:
6fd49698
PP
1174 def __init__(self, name):
1175 self._c = nbt._bt_ctf_clock_create(name)
82839121 1176
6fd49698
PP
1177 if self._c is None:
1178 raise ValueError("Invalid clock name.")
1179
1180 def __del__(self):
1181 nbt._bt_ctf_clock_put(self._c)
1182
6fd49698
PP
1183 @property
1184 def name(self):
82839121
PP
1185 """
1186 Get the clock's name.
1187 """
1188
6fd49698 1189 name = nbt._bt_ctf_clock_get_name(self._c)
82839121 1190
6fd49698
PP
1191 if name is None:
1192 raise ValueError("Invalid clock instance.")
82839121 1193
6fd49698
PP
1194 return name
1195
6fd49698
PP
1196 @property
1197 def description(self):
82839121
PP
1198 """
1199 Get the clock's description. None if unset.
1200 """
1201
6fd49698
PP
1202 return nbt._bt_ctf_clock_get_description(self._c)
1203
6fd49698
PP
1204 @description.setter
1205 def description(self, desc):
82839121
PP
1206 """
1207 Set the clock's description. The description appears in the clock's TSDL
1208 meta-data.
1209 """
1210
6fd49698 1211 ret = nbt._bt_ctf_clock_set_description(self._c, str(desc))
82839121 1212
6fd49698
PP
1213 if ret < 0:
1214 raise ValueError("Invalid clock description.")
1215
6fd49698
PP
1216 @property
1217 def frequency(self):
82839121
PP
1218 """
1219 Get the clock's frequency (Hz).
1220 """
1221
6fd49698 1222 freq = nbt._bt_ctf_clock_get_frequency(self._c)
82839121 1223
6fd49698
PP
1224 if freq == CTFWriter._MAX_UINT64:
1225 raise ValueError("Invalid clock instance")
82839121 1226
6fd49698
PP
1227 return freq
1228
6fd49698
PP
1229 @frequency.setter
1230 def frequency(self, freq):
82839121
PP
1231 """
1232 Set the clock's frequency (Hz).
1233 """
1234
6fd49698 1235 ret = nbt._bt_ctf_clock_set_frequency(self._c, freq)
82839121 1236
6fd49698
PP
1237 if ret < 0:
1238 raise ValueError("Invalid frequency value.")
1239
6fd49698
PP
1240 @property
1241 def precision(self):
82839121
PP
1242 """
1243 Get the clock's precision (in clock ticks).
1244 """
1245
6fd49698 1246 precision = nbt._bt_ctf_clock_get_precision(self._c)
82839121 1247
6fd49698
PP
1248 if precision == CTFWriter._MAX_UINT64:
1249 raise ValueError("Invalid clock instance")
82839121 1250
6fd49698
PP
1251 return precision
1252
6fd49698
PP
1253 @precision.setter
1254 def precision(self, precision):
82839121
PP
1255 """
1256 Set the clock's precision (in clock ticks).
1257 """
1258
6fd49698
PP
1259 ret = nbt._bt_ctf_clock_set_precision(self._c, precision)
1260
6fd49698
PP
1261 @property
1262 def offset_seconds(self):
82839121
PP
1263 """
1264 Get the clock's offset in seconds from POSIX.1 Epoch.
1265 """
1266
6fd49698 1267 offset_s = nbt._bt_ctf_clock_get_offset_s(self._c)
82839121 1268
6fd49698
PP
1269 if offset_s == CTFWriter._MAX_UINT64:
1270 raise ValueError("Invalid clock instance")
82839121 1271
6fd49698
PP
1272 return offset_s
1273
6fd49698
PP
1274 @offset_seconds.setter
1275 def offset_seconds(self, offset_s):
82839121
PP
1276 """
1277 Set the clock's offset in seconds from POSIX.1 Epoch.
1278 """
1279
6fd49698 1280 ret = nbt._bt_ctf_clock_set_offset_s(self._c, offset_s)
82839121 1281
6fd49698
PP
1282 if ret < 0:
1283 raise ValueError("Invalid offset value.")
1284
6fd49698
PP
1285 @property
1286 def offset(self):
82839121
PP
1287 """
1288 Get the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1289 """
1290
6fd49698 1291 offset = nbt._bt_ctf_clock_get_offset(self._c)
82839121 1292
6fd49698
PP
1293 if offset == CTFWriter._MAX_UINT64:
1294 raise ValueError("Invalid clock instance")
82839121 1295
6fd49698
PP
1296 return offset
1297
6fd49698
PP
1298 @offset.setter
1299 def offset(self, offset):
82839121
PP
1300 """
1301 Set the clock's offset in ticks from POSIX.1 Epoch + offset in seconds.
1302 """
1303
6fd49698 1304 ret = nbt._bt_ctf_clock_set_offset(self._c, offset)
82839121 1305
6fd49698
PP
1306 if ret < 0:
1307 raise ValueError("Invalid offset value.")
1308
6fd49698
PP
1309 @property
1310 def absolute(self):
82839121
PP
1311 """
1312 Get a clock's absolute attribute. A clock is absolute if the clock
1313 is a global reference across the trace's other clocks.
1314 """
1315
6fd49698 1316 is_absolute = nbt._bt_ctf_clock_get_is_absolute(self._c)
82839121 1317
6fd49698
PP
1318 if is_absolute == -1:
1319 raise ValueError("Invalid clock instance")
82839121 1320
6fd49698
PP
1321 return False if is_absolute == 0 else True
1322
6fd49698
PP
1323 @absolute.setter
1324 def absolute(self, is_absolute):
82839121
PP
1325 """
1326 Set a clock's absolute attribute. A clock is absolute if the clock
1327 is a global reference across the trace's other clocks.
1328 """
1329
6fd49698 1330 ret = nbt._bt_ctf_clock_set_is_absolute(self._c, int(is_absolute))
82839121 1331
6fd49698 1332 if ret < 0:
82839121 1333 raise ValueError("Could not set the clock's absolute attribute.")
6fd49698 1334
6fd49698
PP
1335 @property
1336 def uuid(self):
82839121
PP
1337 """
1338 Get a clock's UUID (an object of type UUID).
1339 """
1340
6fd49698 1341 uuid_list = []
82839121 1342
6fd49698
PP
1343 for i in range(16):
1344 ret, value = nbt._bt_python_ctf_clock_get_uuid_index(self._c, i)
82839121 1345
6fd49698
PP
1346 if ret < 0:
1347 raise ValueError("Invalid clock instance")
82839121 1348
6fd49698 1349 uuid_list.append(value)
82839121 1350
6fd49698
PP
1351 return UUID(bytes=bytes(uuid_list))
1352
6fd49698
PP
1353 @uuid.setter
1354 def uuid(self, uuid):
82839121
PP
1355 """
1356 Set a clock's UUID (an object of type UUID).
1357 """
1358
6fd49698 1359 uuid_bytes = uuid.bytes
82839121 1360
6fd49698 1361 if len(uuid_bytes) != 16:
82839121
PP
1362 raise ValueError("Invalid UUID provided. UUID length must be 16 bytes")
1363
6fd49698 1364 for i in range(len(uuid_bytes)):
82839121
PP
1365 ret = nbt._bt_python_ctf_clock_set_uuid_index(self._c, i,
1366 uuid_bytes[i])
1367
6fd49698
PP
1368 if ret < 0:
1369 raise ValueError("Invalid clock instance")
1370
6fd49698
PP
1371 @property
1372 def time(self):
82839121
PP
1373 """
1374 Get the current time in nanoseconds since the clock's origin (offset and
1375 offset_s attributes).
1376 """
1377
6fd49698 1378 time = nbt._bt_ctf_clock_get_time(self._c)
82839121 1379
6fd49698
PP
1380 if time == CTFWriter._MAX_UINT64:
1381 raise ValueError("Invalid clock instance")
82839121 1382
6fd49698
PP
1383 return time
1384
6fd49698
PP
1385 @time.setter
1386 def time(self, time):
82839121
PP
1387 """
1388 Set the current time in nanoseconds since the clock's origin (offset and
1389 offset_s attributes). The clock's value will be sampled as events are
1390 appended to a stream.
1391 """
1392
6fd49698 1393 ret = nbt._bt_ctf_clock_set_time(self._c, time)
82839121 1394
6fd49698
PP
1395 if ret < 0:
1396 raise ValueError("Invalid time value.")
1397
1398 class FieldDeclaration:
6fd49698
PP
1399 """
1400 FieldDeclaration should not be instantiated directly. Instantiate
1401 one of the concrete FieldDeclaration classes.
1402 """
82839121 1403
6fd49698
PP
1404 class IntegerBase:
1405 # These values are based on the bt_ctf_integer_base enum
1406 # declared in event-types.h.
1407 INTEGER_BASE_UNKNOWN = -1
1408 INTEGER_BASE_BINARY = 2
1409 INTEGER_BASE_OCTAL = 8
1410 INTEGER_BASE_DECIMAL = 10
1411 INTEGER_BASE_HEXADECIMAL = 16
1412
1413 def __init__(self):
1414 if self._ft is None:
1415 raise ValueError("FieldDeclaration creation failed.")
1416
1417 def __del__(self):
1418 nbt._bt_ctf_field_type_put(self._ft)
1419
1420 @staticmethod
1421 def _create_field_declaration_from_native_instance(
1422 native_field_declaration):
1423 type_dict = {
1424 CTFTypeId.INTEGER: CTFWriter.IntegerFieldDeclaration,
1425 CTFTypeId.FLOAT: CTFWriter.FloatFieldDeclaration,
1426 CTFTypeId.ENUM: CTFWriter.EnumerationFieldDeclaration,
1427 CTFTypeId.STRING: CTFWriter.StringFieldDeclaration,
1428 CTFTypeId.STRUCT: CTFWriter.StructureFieldDeclaration,
1429 CTFTypeId.VARIANT: CTFWriter.VariantFieldDeclaration,
1430 CTFTypeId.ARRAY: CTFWriter.ArrayFieldDeclaration,
1431 CTFTypeId.SEQUENCE: CTFWriter.SequenceFieldDeclaration
1432 }
1433
82839121
PP
1434 field_type_id = nbt._bt_ctf_field_type_get_type_id(native_field_declaration)
1435
6fd49698
PP
1436 if field_type_id == CTFTypeId.UNKNOWN:
1437 raise TypeError("Invalid field instance")
1438
1439 declaration = CTFWriter.Field.__new__(CTFWriter.Field)
1440 declaration._ft = native_field_declaration
1441 declaration.__class__ = type_dict[field_type_id]
82839121 1442
6fd49698
PP
1443 return declaration
1444
6fd49698
PP
1445 @property
1446 def alignment(self):
82839121
PP
1447 """
1448 Get the field declaration's alignment. Returns -1 on error.
1449 """
1450
6fd49698
PP
1451 return nbt._bt_ctf_field_type_get_alignment(self._ft)
1452
6fd49698
PP
1453 @alignment.setter
1454 def alignment(self, alignment):
82839121
PP
1455 """
1456 Set the field declaration's alignment. Defaults to 1 (bit-aligned). However,
1457 some types, such as structures and string, may impose other alignment
1458 constraints.
1459 """
1460
6fd49698 1461 ret = nbt._bt_ctf_field_type_set_alignment(self._ft, alignment)
82839121 1462
6fd49698
PP
1463 if ret < 0:
1464 raise ValueError("Invalid alignment value.")
1465
6fd49698
PP
1466 @property
1467 def byte_order(self):
82839121
PP
1468 """
1469 Get the field declaration's byte order. One of the ByteOrder's constant.
1470 """
1471
6fd49698
PP
1472 return nbt._bt_ctf_field_type_get_byte_order(self._ft)
1473
6fd49698
PP
1474 @byte_order.setter
1475 def byte_order(self, byte_order):
82839121
PP
1476 """
1477 Set the field declaration's byte order. Use constants defined in the ByteOrder
1478 class.
1479 """
1480
6fd49698 1481 ret = nbt._bt_ctf_field_type_set_byte_order(self._ft, byte_order)
82839121 1482
6fd49698
PP
1483 if ret < 0:
1484 raise ValueError("Could not set byte order value.")
1485
1486 class IntegerFieldDeclaration(FieldDeclaration):
6fd49698 1487 def __init__(self, size):
82839121
PP
1488 """
1489 Create a new integer field declaration of the given size.
1490 """
6fd49698
PP
1491 self._ft = nbt._bt_ctf_field_type_integer_create(size)
1492 super().__init__()
1493
6fd49698
PP
1494 @property
1495 def size(self):
82839121
PP
1496 """
1497 Get an integer's size.
1498 """
1499
6fd49698 1500 ret = nbt._bt_ctf_field_type_integer_get_size(self._ft)
82839121 1501
6fd49698
PP
1502 if ret < 0:
1503 raise ValueError("Could not get Integer's size attribute.")
1504 else:
1505 return ret
1506
6fd49698
PP
1507 @property
1508 def signed(self):
82839121
PP
1509 """
1510 Get an integer's signedness attribute.
1511 """
1512
6fd49698 1513 ret = nbt._bt_ctf_field_type_integer_get_signed(self._ft)
82839121 1514
6fd49698
PP
1515 if ret < 0:
1516 raise ValueError("Could not get Integer's signed attribute.")
1517 elif ret > 0:
1518 return True
1519 else:
1520 return False
1521
6fd49698
PP
1522 @signed.setter
1523 def signed(self, signed):
82839121
PP
1524 """
1525 Set an integer's signedness attribute.
1526 """
1527
6fd49698 1528 ret = nbt._bt_ctf_field_type_integer_set_signed(self._ft, signed)
82839121 1529
6fd49698
PP
1530 if ret < 0:
1531 raise ValueError("Could not set Integer's signed attribute.")
1532
6fd49698
PP
1533 @property
1534 def base(self):
82839121
PP
1535 """
1536 Get the integer's base used to pretty-print the resulting trace.
1537 Returns a constant from the FieldDeclaration.IntegerBase class.
1538 """
1539
6fd49698
PP
1540 return nbt._bt_ctf_field_type_integer_get_base(self._ft)
1541
6fd49698
PP
1542 @base.setter
1543 def base(self, base):
82839121
PP
1544 """
1545 Set the integer's base used to pretty-print the resulting trace.
1546 The base must be a constant of the FieldDeclarationIntegerBase class.
1547 """
1548
6fd49698 1549 ret = nbt._bt_ctf_field_type_integer_set_base(self._ft, base)
82839121 1550
6fd49698
PP
1551 if ret < 0:
1552 raise ValueError("Could not set Integer's base.")
1553
6fd49698
PP
1554 @property
1555 def encoding(self):
82839121
PP
1556 """
1557 Get the integer's encoding (one of the constants of the
1558 CTFStringEncoding class).
1559 Returns a constant from the CTFStringEncoding class.
1560 """
1561
6fd49698
PP
1562 return nbt._bt_ctf_field_type_integer_get_encoding(self._ft)
1563
6fd49698
PP
1564 @encoding.setter
1565 def encoding(self, encoding):
82839121
PP
1566 """
1567 An integer encoding may be set to signal that the integer must be printed
1568 as a text character. Must be a constant from the CTFStringEncoding class.
1569 """
1570
6fd49698 1571 ret = nbt._bt_ctf_field_type_integer_set_encoding(self._ft, encoding)
82839121 1572
6fd49698
PP
1573 if ret < 0:
1574 raise ValueError("Could not set Integer's encoding.")
1575
1576 class EnumerationFieldDeclaration(FieldDeclaration):
6fd49698 1577 def __init__(self, integer_type):
82839121
PP
1578 """
1579 Create a new enumeration field declaration with the given underlying container type.
1580 """
1581 isinst = isinstance(integer_type, CTFWriter.IntegerFieldDeclaration)
1582
1583 if integer_type is None or not isinst:
6fd49698
PP
1584 raise TypeError("Invalid integer container.")
1585
1586 self._ft = nbt._bt_ctf_field_type_enumeration_create(integer_type._ft)
1587 super().__init__()
1588
6fd49698
PP
1589 @property
1590 def container(self):
82839121
PP
1591 """
1592 Get the enumeration's underlying container type.
1593 """
1594
6fd49698 1595 ret = nbt._bt_ctf_field_type_enumeration_get_container_type(self._ft)
82839121 1596
6fd49698
PP
1597 if ret is None:
1598 raise TypeError("Invalid enumeration declaration")
6fd49698 1599
82839121 1600 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(ret)
6fd49698
PP
1601
1602 def add_mapping(self, name, range_start, range_end):
82839121
PP
1603 """
1604 Add a mapping to the enumeration. The range's values are inclusive.
1605 """
1606
6fd49698 1607 if range_start < 0 or range_end < 0:
82839121
PP
1608 ret = nbt._bt_ctf_field_type_enumeration_add_mapping(self._ft,
1609 str(name),
1610 range_start,
1611 range_end)
6fd49698 1612 else:
82839121
PP
1613 ret = nbt._bt_ctf_field_type_enumeration_add_mapping_unsigned(self._ft,
1614 str(name),
1615 range_start,
1616 range_end)
6fd49698
PP
1617
1618 if ret < 0:
82839121 1619 raise ValueError("Could not add mapping to enumeration declaration.")
6fd49698 1620
6fd49698
PP
1621 @property
1622 def mappings(self):
82839121
PP
1623 """
1624 Generator returning instances of EnumerationMapping.
1625 """
1626
6fd49698
PP
1627 signed = self.container.signed
1628
1629 count = nbt._bt_ctf_field_type_enumeration_get_mapping_count(self._ft)
82839121 1630
6fd49698
PP
1631 for i in range(count):
1632 if signed:
82839121 1633 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, i)
6fd49698 1634 else:
82839121 1635 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, i)
6fd49698
PP
1636
1637 if len(ret) != 3:
82839121
PP
1638 msg = "Could not get Enumeration mapping at index {}".format(i)
1639 raise TypeError(msg)
1640
6fd49698
PP
1641 name, range_start, range_end = ret
1642 yield CTFWriter.EnumerationMapping(name, range_start, range_end)
1643
6fd49698 1644 def get_mapping_by_name(self, name):
82839121
PP
1645 """
1646 Get a mapping by name (EnumerationMapping).
1647 """
1648
1649 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_name(self._ft, name)
1650
6fd49698
PP
1651 if index < 0:
1652 return None
1653
1654 if self.container.signed:
82839121 1655 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, index)
6fd49698 1656 else:
82839121 1657 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, index)
6fd49698
PP
1658
1659 if len(ret) != 3:
82839121
PP
1660 msg = "Could not get Enumeration mapping at index {}".format(i)
1661 raise TypeError(msg)
1662
6fd49698 1663 name, range_start, range_end = ret
6fd49698 1664
82839121 1665 return CTFWriter.EnumerationMapping(name, range_start, range_end)
6fd49698
PP
1666
1667 def get_mapping_by_value(self, value):
82839121
PP
1668 """
1669 Get a mapping by value (EnumerationMapping).
1670 """
1671
6fd49698 1672 if value < 0:
82839121 1673 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_value(self._ft, value)
6fd49698 1674 else:
82839121 1675 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value(self._ft, value)
6fd49698
PP
1676
1677 if index < 0:
1678 return None
1679
1680 if self.container.signed:
82839121 1681 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, index)
6fd49698 1682 else:
82839121 1683 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, index)
6fd49698
PP
1684
1685 if len(ret) != 3:
82839121
PP
1686 msg = "Could not get Enumeration mapping at index {}".format(i)
1687 raise TypeError(msg)
1688
6fd49698 1689 name, range_start, range_end = ret
82839121 1690
6fd49698
PP
1691 return CTFWriter.EnumerationMapping(name, range_start, range_end)
1692
1693 class FloatFieldDeclaration(FieldDeclaration):
1694 FLT_EXP_DIG = 8
1695 DBL_EXP_DIG = 11
1696 FLT_MANT_DIG = 24
1697 DBL_MANT_DIG = 53
1698
6fd49698 1699 def __init__(self):
82839121
PP
1700 """
1701 Create a new floating point field declaration.
1702 """
1703
6fd49698
PP
1704 self._ft = nbt._bt_ctf_field_type_floating_point_create()
1705 super().__init__()
1706
6fd49698
PP
1707 @property
1708 def exponent_digits(self):
82839121
PP
1709 """
1710 Get the number of exponent digits used to store the floating point field.
1711 """
1712
1713 ret = nbt._bt_ctf_field_type_floating_point_get_exponent_digits(self._ft)
1714
6fd49698
PP
1715 if ret < 0:
1716 raise TypeError(
1717 "Could not get Floating point exponent digit count")
82839121 1718
6fd49698
PP
1719 return ret
1720
6fd49698
PP
1721 @exponent_digits.setter
1722 def exponent_digits(self, exponent_digits):
82839121
PP
1723 """
1724 Set the number of exponent digits to use to store the floating point field.
1725 The only values currently supported are FLT_EXP_DIG and DBL_EXP_DIG which
1726 are defined as constants of this class.
1727 """
1728
1729 ret = nbt._bt_ctf_field_type_floating_point_set_exponent_digits(self._ft,
1730 exponent_digits)
1731
6fd49698
PP
1732 if ret < 0:
1733 raise ValueError("Could not set exponent digit count.")
1734
6fd49698
PP
1735 @property
1736 def mantissa_digits(self):
82839121
PP
1737 """
1738 Get the number of mantissa digits used to store the floating point field.
1739 """
1740
1741 ret = nbt._bt_ctf_field_type_floating_point_get_mantissa_digits(self._ft)
1742
6fd49698 1743 if ret < 0:
82839121
PP
1744 raise TypeError("Could not get Floating point mantissa digit count")
1745
6fd49698
PP
1746 return ret
1747
6fd49698
PP
1748 @mantissa_digits.setter
1749 def mantissa_digits(self, mantissa_digits):
82839121
PP
1750 """
1751 Set the number of mantissa digits to use to store the floating point field.
1752 The only values currently supported are FLT_MANT_DIG and DBL_MANT_DIG which
1753 are defined as constants of this class.
1754 """
1755
1756 ret = nbt._bt_ctf_field_type_floating_point_set_mantissa_digits(self._ft,
1757 mantissa_digits)
1758
6fd49698
PP
1759 if ret < 0:
1760 raise ValueError("Could not set mantissa digit count.")
1761
da43007d
PP
1762 class FloatingPointFieldDeclaration(FloatFieldDeclaration):
1763 pass
1764
6fd49698 1765 class StructureFieldDeclaration(FieldDeclaration):
6fd49698 1766 def __init__(self):
82839121
PP
1767 """
1768 Create a new structure field declaration.
1769 """
1770
6fd49698
PP
1771 self._ft = nbt._bt_ctf_field_type_structure_create()
1772 super().__init__()
1773
6fd49698 1774 def add_field(self, field_type, field_name):
82839121
PP
1775 """
1776 Add a field of type "field_type" to the structure.
1777 """
1778
1779 ret = nbt._bt_ctf_field_type_structure_add_field(self._ft,
1780 field_type._ft,
1781 str(field_name))
1782
6fd49698
PP
1783 if ret < 0:
1784 raise ValueError("Could not add field to structure.")
1785
6fd49698
PP
1786 @property
1787 def fields(self):
82839121
PP
1788 """
1789 Generator returning the structure's field as tuples of (field name, field declaration).
1790 """
1791
6fd49698 1792 count = nbt._bt_ctf_field_type_structure_get_field_count(self._ft)
82839121 1793
6fd49698
PP
1794 if count < 0:
1795 raise TypeError("Could not get Structure field count")
1796
1797 for i in range(count):
82839121
PP
1798 field_name = nbt._bt_python_ctf_field_type_structure_get_field_name(self._ft, i)
1799
6fd49698 1800 if field_name is None:
82839121
PP
1801 msg = "Could not get Structure field name at index {}".format(i)
1802 raise TypeError(msg)
1803
1804 field_type_native = nbt._bt_python_ctf_field_type_structure_get_field_type(self._ft, i)
6fd49698 1805
6fd49698 1806 if field_type_native is None:
82839121
PP
1807 msg = "Could not get Structure field type at index {}".format(i)
1808 raise TypeError(msg)
6fd49698 1809
82839121 1810 field_type = CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698
PP
1811 yield (field_name, field_type)
1812
6fd49698 1813 def get_field_by_name(self, name):
82839121
PP
1814 """
1815 Get a field declaration by name (FieldDeclaration).
1816 """
6fd49698 1817
82839121 1818 field_type_native = nbt._bt_ctf_field_type_structure_get_field_type_by_name(self._ft, name)
6fd49698 1819
82839121
PP
1820 if field_type_native is None:
1821 msg = "Could not find Structure field with name {}".format(name)
1822 raise TypeError(msg)
6fd49698 1823
82839121 1824 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698 1825
82839121 1826 class VariantFieldDeclaration(FieldDeclaration):
6fd49698 1827 def __init__(self, enum_tag, tag_name):
82839121
PP
1828 """
1829 Create a new variant field declaration.
1830 """
1831
1832 isinst = isinstance(enum_tag, CTFWriter.EnumerationFieldDeclaration)
1833 if enum_tag is None or not isinst:
1834 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
6fd49698 1835
82839121
PP
1836 self._ft = nbt._bt_ctf_field_type_variant_create(enum_tag._ft,
1837 str(tag_name))
6fd49698
PP
1838 super().__init__()
1839
6fd49698
PP
1840 @property
1841 def tag_name(self):
82839121
PP
1842 """
1843 Get the variant's tag name.
1844 """
1845
6fd49698 1846 ret = nbt._bt_ctf_field_type_variant_get_tag_name(self._ft)
82839121 1847
6fd49698
PP
1848 if ret is None:
1849 raise TypeError("Could not get Variant tag name")
82839121 1850
6fd49698
PP
1851 return ret
1852
6fd49698
PP
1853 @property
1854 def tag_type(self):
82839121
PP
1855 """
1856 Get the variant's tag type.
1857 """
1858
6fd49698 1859 ret = nbt._bt_ctf_field_type_variant_get_tag_type(self._ft)
82839121 1860
6fd49698
PP
1861 if ret is None:
1862 raise TypeError("Could not get Variant tag type")
6fd49698 1863
82839121 1864 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(ret)
6fd49698
PP
1865
1866 def add_field(self, field_type, field_name):
82839121
PP
1867 """
1868 Add a field of type "field_type" to the variant.
1869 """
1870
1871 ret = nbt._bt_ctf_field_type_variant_add_field(self._ft,
1872 field_type._ft,
1873 str(field_name))
1874
6fd49698
PP
1875 if ret < 0:
1876 raise ValueError("Could not add field to variant.")
1877
6fd49698
PP
1878 @property
1879 def fields(self):
82839121
PP
1880 """
1881 Generator returning the variant's field as tuples of (field name, field declaration).
1882 """
1883
6fd49698 1884 count = nbt._bt_ctf_field_type_variant_get_field_count(self._ft)
82839121 1885
6fd49698
PP
1886 if count < 0:
1887 raise TypeError("Could not get Variant field count")
1888
1889 for i in range(count):
82839121
PP
1890 field_name = nbt._bt_python_ctf_field_type_variant_get_field_name(self._ft, i)
1891
6fd49698 1892 if field_name is None:
82839121
PP
1893 msg = "Could not get Variant field name at index {}".format(i)
1894 raise TypeError(msg)
1895
1896 field_type_native = nbt._bt_python_ctf_field_type_variant_get_field_type(self._ft, i)
6fd49698 1897
6fd49698 1898 if field_type_native is None:
82839121
PP
1899 msg = "Could not get Variant field type at index {}".format(i)
1900 raise TypeError(msg)
6fd49698 1901
82839121 1902 field_type = CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698
PP
1903 yield (field_name, field_type)
1904
6fd49698 1905 def get_field_by_name(self, name):
82839121
PP
1906 """
1907 Get a field declaration by name (FieldDeclaration).
1908 """
6fd49698 1909
82839121
PP
1910 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_by_name(self._ft,
1911 name)
6fd49698 1912
82839121
PP
1913 if field_type_native is None:
1914 msg = "Could not find Variant field with name {}".format(name)
1915 raise TypeError(msg)
1916
1917 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698
PP
1918
1919 def get_field_from_tag(self, tag):
82839121
PP
1920 """
1921 Get a field declaration from tag (EnumerationField).
1922 """
6fd49698 1923
82839121 1924 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_from_tag(self._ft, tag._f)
6fd49698 1925
82839121
PP
1926 if field_type_native is None:
1927 msg = "Could not find Variant field with tag value {}".format(tag.value)
1928 raise TypeError(msg)
6fd49698 1929
82839121 1930 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698 1931
82839121 1932 class ArrayFieldDeclaration(FieldDeclaration):
6fd49698 1933 def __init__(self, element_type, length):
82839121
PP
1934 """
1935 Create a new array field declaration.
1936 """
1937
1938 self._ft = nbt._bt_ctf_field_type_array_create(element_type._ft,
1939 length)
6fd49698
PP
1940 super().__init__()
1941
6fd49698
PP
1942 @property
1943 def element_type(self):
82839121
PP
1944 """
1945 Get the array's element type.
1946 """
1947
6fd49698 1948 ret = nbt._bt_ctf_field_type_array_get_element_type(self._ft)
82839121 1949
6fd49698
PP
1950 if ret is None:
1951 raise TypeError("Could not get Array element type")
6fd49698 1952
82839121
PP
1953 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(ret)
1954
6fd49698
PP
1955 @property
1956 def length(self):
82839121
PP
1957 """
1958 Get the array's length.
1959 """
1960
6fd49698 1961 ret = nbt._bt_ctf_field_type_array_get_length(self._ft)
82839121 1962
6fd49698
PP
1963 if ret < 0:
1964 raise TypeError("Could not get Array length")
82839121 1965
6fd49698
PP
1966 return ret
1967
1968 class SequenceFieldDeclaration(FieldDeclaration):
6fd49698 1969 def __init__(self, element_type, length_field_name):
82839121
PP
1970 """
1971 Create a new sequence field declaration.
1972 """
1973
1974 self._ft = nbt._bt_ctf_field_type_sequence_create(element_type._ft,
1975 str(length_field_name))
6fd49698
PP
1976 super().__init__()
1977
6fd49698
PP
1978 @property
1979 def element_type(self):
82839121
PP
1980 """
1981 Get the sequence's element type.
1982 """
1983
6fd49698 1984 ret = nbt._bt_ctf_field_type_sequence_get_element_type(self._ft)
82839121 1985
6fd49698
PP
1986 if ret is None:
1987 raise TypeError("Could not get Sequence element type")
6fd49698 1988
82839121
PP
1989 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(ret)
1990
6fd49698
PP
1991 @property
1992 def length_field_name(self):
82839121
PP
1993 """
1994 Get the sequence's length field name.
1995 """
1996
6fd49698 1997 ret = nbt._bt_ctf_field_type_sequence_get_length_field_name(self._ft)
82839121 1998
6fd49698
PP
1999 if ret is None:
2000 raise TypeError("Could not get Sequence length field name")
82839121 2001
6fd49698
PP
2002 return ret
2003
2004 class StringFieldDeclaration(FieldDeclaration):
6fd49698 2005 def __init__(self):
82839121
PP
2006 """
2007 Create a new string field declaration.
2008 """
2009
6fd49698
PP
2010 self._ft = nbt._bt_ctf_field_type_string_create()
2011 super().__init__()
2012
6fd49698
PP
2013 @property
2014 def encoding(self):
82839121
PP
2015 """
2016 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
2017 """
2018
6fd49698
PP
2019 return nbt._bt_ctf_field_type_string_get_encoding(self._ft)
2020
6fd49698
PP
2021 @encoding.setter
2022 def encoding(self, encoding):
82839121
PP
2023 """
2024 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
2025 """
2026
6fd49698
PP
2027 ret = nbt._bt_ctf_field_type_string_set_encoding(self._ft, encoding)
2028 if ret < 0:
2029 raise ValueError("Could not set string encoding.")
2030
6fd49698
PP
2031 @staticmethod
2032 def create_field(field_type):
82839121
PP
2033 """
2034 Create an instance of a field.
2035 """
2036 isinst = isinstance(field_type, CTFWriter.FieldDeclaration)
2037
2038 if field_type is None or not isinst:
2039 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
6fd49698
PP
2040
2041 if isinstance(field_type, CTFWriter.IntegerFieldDeclaration):
2042 return CTFWriter.IntegerField(field_type)
2043 elif isinstance(field_type, CTFWriter.EnumerationFieldDeclaration):
2044 return CTFWriter.EnumerationField(field_type)
2045 elif isinstance(field_type, CTFWriter.FloatFieldDeclaration):
60318a5f 2046 return CTFWriter.FloatingPointField(field_type)
6fd49698
PP
2047 elif isinstance(field_type, CTFWriter.StructureFieldDeclaration):
2048 return CTFWriter.StructureField(field_type)
2049 elif isinstance(field_type, CTFWriter.VariantFieldDeclaration):
2050 return CTFWriter.VariantField(field_type)
2051 elif isinstance(field_type, CTFWriter.ArrayFieldDeclaration):
2052 return CTFWriter.ArrayField(field_type)
2053 elif isinstance(field_type, CTFWriter.SequenceFieldDeclaration):
2054 return CTFWriter.SequenceField(field_type)
2055 elif isinstance(field_type, CTFWriter.StringFieldDeclaration):
2056 return CTFWriter.StringField(field_type)
2057
2058 class Field:
6fd49698
PP
2059 """
2060 Base class, do not instantiate.
2061 """
2062
2063 def __init__(self, field_type):
2064 if not isinstance(field_type, CTFWriter.FieldDeclaration):
2065 raise TypeError("Invalid field_type argument.")
2066
2067 self._f = nbt._bt_ctf_field_create(field_type._ft)
82839121 2068
6fd49698
PP
2069 if self._f is None:
2070 raise ValueError("Field creation failed.")
2071
2072 def __del__(self):
2073 nbt._bt_ctf_field_put(self._f)
2074
2075 @staticmethod
2076 def _create_field_from_native_instance(native_field_instance):
2077 type_dict = {
2078 CTFTypeId.INTEGER: CTFWriter.IntegerField,
60318a5f 2079 CTFTypeId.FLOAT: CTFWriter.FloatingPointField,
6fd49698
PP
2080 CTFTypeId.ENUM: CTFWriter.EnumerationField,
2081 CTFTypeId.STRING: CTFWriter.StringField,
2082 CTFTypeId.STRUCT: CTFWriter.StructureField,
2083 CTFTypeId.VARIANT: CTFWriter.VariantField,
2084 CTFTypeId.ARRAY: CTFWriter.ArrayField,
2085 CTFTypeId.SEQUENCE: CTFWriter.SequenceField
2086 }
2087
2088 field_type = nbt._bt_python_get_field_type(native_field_instance)
82839121 2089
6fd49698
PP
2090 if field_type == CTFTypeId.UNKNOWN:
2091 raise TypeError("Invalid field instance")
2092
2093 field = CTFWriter.Field.__new__(CTFWriter.Field)
2094 field._f = native_field_instance
2095 field.__class__ = type_dict[field_type]
82839121 2096
6fd49698
PP
2097 return field
2098
2099 @property
2100 def declaration(self):
2101 native_field_type = nbt._bt_ctf_field_get_type(self._f)
82839121 2102
6fd49698
PP
2103 if native_field_type is None:
2104 raise TypeError("Invalid field instance")
2105 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(
2106 native_field_type)
2107
2108 class IntegerField(Field):
6fd49698
PP
2109 @property
2110 def value(self):
82839121
PP
2111 """
2112 Get an integer field's value.
2113 """
2114
6fd49698 2115 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
82839121 2116
6fd49698
PP
2117 if signedness < 0:
2118 raise TypeError("Invalid integer instance.")
2119
2120 if signedness == 0:
2121 ret, value = nbt._bt_ctf_field_unsigned_integer_get_value(self._f)
2122 else:
2123 ret, value = nbt._bt_ctf_field_signed_integer_get_value(self._f)
2124
2125 if ret < 0:
2126 raise ValueError("Could not get integer field value.")
82839121 2127
6fd49698
PP
2128 return value
2129
6fd49698
PP
2130 @value.setter
2131 def value(self, value):
82839121
PP
2132 """
2133 Set an integer field's value.
2134 """
2135
6fd49698
PP
2136 if not isinstance(value, int):
2137 raise TypeError("IntegerField's value must be an int")
2138
2139 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
2140 if signedness < 0:
2141 raise TypeError("Invalid integer instance.")
2142
2143 if signedness == 0:
2144 ret = nbt._bt_ctf_field_unsigned_integer_set_value(self._f, value)
2145 else:
2146 ret = nbt._bt_ctf_field_signed_integer_set_value(self._f, value)
2147
2148 if ret < 0:
2149 raise ValueError("Could not set integer field value.")
2150
2151 class EnumerationField(Field):
6fd49698
PP
2152 @property
2153 def container(self):
82839121
PP
2154 """
2155 Return the enumeration's underlying container field (an integer field).
2156 """
2157
6fd49698
PP
2158 container = CTFWriter.IntegerField.__new__(CTFWriter.IntegerField)
2159 container._f = nbt._bt_ctf_field_enumeration_get_container(self._f)
82839121 2160
6fd49698
PP
2161 if container._f is None:
2162 raise TypeError("Invalid enumeration field type.")
82839121 2163
6fd49698
PP
2164 return container
2165
6fd49698
PP
2166 @property
2167 def value(self):
82839121
PP
2168 """
2169 Get the enumeration field's mapping name.
2170 """
2171
6fd49698 2172 value = nbt._bt_ctf_field_enumeration_get_mapping_name(self._f)
82839121 2173
6fd49698
PP
2174 if value is None:
2175 raise ValueError("Could not get enumeration's mapping name.")
82839121 2176
6fd49698
PP
2177 return value
2178
6fd49698
PP
2179 @value.setter
2180 def value(self, value):
82839121
PP
2181 """
2182 Set the enumeration field's value. Must be an integer as mapping names
2183 may be ambiguous.
2184 """
2185
6fd49698
PP
2186 if not isinstance(value, int):
2187 raise TypeError("EnumerationField value must be an int")
82839121 2188
6fd49698
PP
2189 self.container.value = value
2190
60318a5f 2191 class FloatingPointField(Field):
6fd49698
PP
2192 @property
2193 def value(self):
82839121
PP
2194 """
2195 Get a floating point field's value.
2196 """
2197
6fd49698 2198 ret, value = nbt._bt_ctf_field_floating_point_get_value(self._f)
82839121 2199
6fd49698
PP
2200 if ret < 0:
2201 raise ValueError("Could not get floating point field value.")
82839121 2202
6fd49698
PP
2203 return value
2204
6fd49698
PP
2205 @value.setter
2206 def value(self, value):
82839121
PP
2207 """
2208 Set a floating point field's value.
2209 """
2210
6fd49698
PP
2211 if not isinstance(value, int) and not isinstance(value, float):
2212 raise TypeError("Value must be either a float or an int")
2213
2214 ret = nbt._bt_ctf_field_floating_point_set_value(self._f, float(value))
82839121 2215
6fd49698
PP
2216 if ret < 0:
2217 raise ValueError("Could not set floating point field value.")
2218
60318a5f
PP
2219 # oops!! This class is provided to ensure backward-compatibility since
2220 # a stable release publicly exposed this abomination.
2221 class FloatFieldingPoint(FloatingPointField):
2222 pass
2223
6fd49698 2224 class StructureField(Field):
82839121
PP
2225 def field(self, field_name):
2226 """
2227 Get the structure's field corresponding to the provided field name.
2228 """
6fd49698 2229
82839121
PP
2230 native_instance = nbt._bt_ctf_field_structure_get_field(self._f,
2231 str(field_name))
6fd49698 2232
6fd49698
PP
2233 if native_instance is None:
2234 raise ValueError("Invalid field_name provided.")
6fd49698 2235
82839121 2236 return CTFWriter.Field._create_field_from_native_instance(native_instance)
6fd49698 2237
82839121 2238 class VariantField(Field):
6fd49698 2239 def field(self, tag):
82839121
PP
2240 """
2241 Return the variant's selected field. The "tag" field is the selector enum field.
2242 """
2243
6fd49698 2244 native_instance = nbt._bt_ctf_field_variant_get_field(self._f, tag._f)
82839121 2245
6fd49698
PP
2246 if native_instance is None:
2247 raise ValueError("Invalid tag provided.")
6fd49698 2248
82839121 2249 return CTFWriter.Field._create_field_from_native_instance(native_instance)
6fd49698 2250
82839121 2251 class ArrayField(Field):
6fd49698 2252 def field(self, index):
82839121
PP
2253 """
2254 Return the array's field at position "index".
2255 """
2256
6fd49698 2257 native_instance = nbt._bt_ctf_field_array_get_field(self._f, index)
82839121 2258
6fd49698
PP
2259 if native_instance is None:
2260 raise IndexError("Invalid index provided.")
6fd49698 2261
82839121 2262 return CTFWriter.Field._create_field_from_native_instance(native_instance)
6fd49698 2263
82839121 2264 class SequenceField(Field):
6fd49698
PP
2265 @property
2266 def length(self):
82839121
PP
2267 """
2268 Get the sequence's length field (IntegerField).
2269 """
2270
6fd49698 2271 native_instance = nbt._bt_ctf_field_sequence_get_length(self._f)
82839121 2272
6fd49698
PP
2273 if native_instance is None:
2274 length = -1
6fd49698 2275
82839121
PP
2276 return CTFWriter.Field._create_field_from_native_instance(native_instance)
2277
6fd49698
PP
2278 @length.setter
2279 def length(self, length_field):
82839121
PP
2280 """
2281 Set the sequence's length field (IntegerField).
2282 """
2283
6fd49698
PP
2284 if not isinstance(length_field, CTFWriter.IntegerField):
2285 raise TypeError("Invalid length field.")
82839121 2286
6fd49698
PP
2287 if length_field.declaration.signed:
2288 raise TypeError("Sequence field length must be unsigned")
82839121 2289
6fd49698 2290 ret = nbt._bt_ctf_field_sequence_set_length(self._f, length_field._f)
82839121 2291
6fd49698
PP
2292 if ret < 0:
2293 raise ValueError("Could not set sequence length.")
2294
6fd49698 2295 def field(self, index):
82839121
PP
2296 """
2297 Return the sequence's field at position "index".
2298 """
2299
6fd49698 2300 native_instance = nbt._bt_ctf_field_sequence_get_field(self._f, index)
82839121 2301
6fd49698
PP
2302 if native_instance is None:
2303 raise ValueError("Could not get sequence element at index.")
6fd49698 2304
82839121 2305 return CTFWriter.Field._create_field_from_native_instance(native_instance)
6fd49698 2306
82839121 2307 class StringField(Field):
6fd49698
PP
2308 @property
2309 def value(self):
82839121
PP
2310 """
2311 Get a string field's value.
2312 """
2313
6fd49698
PP
2314 return nbt._bt_ctf_field_string_get_value(self._f)
2315
6fd49698
PP
2316 @value.setter
2317 def value(self, value):
82839121
PP
2318 """
2319 Set a string field's value.
2320 """
2321
6fd49698 2322 ret = nbt._bt_ctf_field_string_set_value(self._f, str(value))
82839121 2323
6fd49698
PP
2324 if ret < 0:
2325 raise ValueError("Could not set string field value.")
2326
2327 class EventClass:
6fd49698 2328 def __init__(self, name):
82839121
PP
2329 """
2330 Create a new event class of the given name.
2331 """
2332
6fd49698 2333 self._ec = nbt._bt_ctf_event_class_create(name)
82839121 2334
6fd49698
PP
2335 if self._ec is None:
2336 raise ValueError("Event class creation failed.")
2337
2338 def __del__(self):
2339 nbt._bt_ctf_event_class_put(self._ec)
2340
6fd49698 2341 def add_field(self, field_type, field_name):
82839121
PP
2342 """
2343 Add a field of type "field_type" to the event class.
2344 """
2345
2346 ret = nbt._bt_ctf_event_class_add_field(self._ec, field_type._ft,
2347 str(field_name))
2348
6fd49698
PP
2349 if ret < 0:
2350 raise ValueError("Could not add field to event class.")
2351
6fd49698
PP
2352 @property
2353 def name(self):
82839121
PP
2354 """
2355 Get the event class' name.
2356 """
2357
6fd49698 2358 name = nbt._bt_ctf_event_class_get_name(self._ec)
82839121 2359
6fd49698
PP
2360 if name is None:
2361 raise TypeError("Could not get EventClass name")
82839121 2362
6fd49698
PP
2363 return name
2364
6fd49698
PP
2365 @property
2366 def id(self):
82839121
PP
2367 """
2368 Get the event class' id. Returns a negative value if unset.
2369 """
2370
6fd49698 2371 id = nbt._bt_ctf_event_class_get_id(self._ec)
82839121 2372
6fd49698
PP
2373 if id < 0:
2374 raise TypeError("Could not get EventClass id")
82839121 2375
6fd49698
PP
2376 return id
2377
6fd49698
PP
2378 @id.setter
2379 def id(self, id):
82839121
PP
2380 """
2381 Set the event class' id. Throws a TypeError if the event class
2382 is already registered to a stream class.
2383 """
2384
6fd49698 2385 ret = nbt._bt_ctf_event_class_set_id(self._ec, id)
82839121 2386
6fd49698 2387 if ret < 0:
82839121 2388 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
6fd49698 2389
6fd49698
PP
2390 @property
2391 def stream_class(self):
82839121
PP
2392 """
2393 Get the event class' stream class. Returns None if unset.
2394 """
2395 stream_class_native = nbt._bt_ctf_event_class_get_stream_class(self._ec)
2396
6fd49698
PP
2397 if stream_class_native is None:
2398 return None
82839121 2399
6fd49698
PP
2400 stream_class = CTFWriter.StreamClass.__new__(CTFWriter.StreamClass)
2401 stream_class._sc = stream_class_native
82839121 2402
6fd49698
PP
2403 return stream_class
2404
6fd49698
PP
2405 @property
2406 def fields(self):
82839121
PP
2407 """
2408 Generator returning the event class' fields as tuples of (field name, field declaration).
2409 """
2410
6fd49698 2411 count = nbt._bt_ctf_event_class_get_field_count(self._ec)
82839121 2412
6fd49698
PP
2413 if count < 0:
2414 raise TypeError("Could not get EventClass' field count")
2415
2416 for i in range(count):
82839121
PP
2417 field_name = nbt._bt_python_ctf_event_class_get_field_name(self._ec, i)
2418
6fd49698 2419 if field_name is None:
82839121
PP
2420 msg = "Could not get EventClass' field name at index {}".format(i)
2421 raise TypeError(msg)
2422
2423 field_type_native = nbt._bt_python_ctf_event_class_get_field_type(self._ec, i)
6fd49698 2424
6fd49698 2425 if field_type_native is None:
82839121
PP
2426 msg = "Could not get EventClass' field type at index {}".format(i)
2427 raise TypeError(msg)
6fd49698 2428
82839121 2429 field_type = CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
6fd49698
PP
2430 yield (field_name, field_type)
2431
6fd49698 2432 def get_field_by_name(self, name):
82839121
PP
2433 """
2434 Get a field declaration by name (FieldDeclaration).
2435 """
6fd49698 2436
82839121 2437 field_type_native = nbt._bt_ctf_event_class_get_field_by_name(self._ec, name)
6fd49698 2438
82839121
PP
2439 if field_type_native is None:
2440 msg = "Could not find EventClass field with name {}".format(name)
2441 raise TypeError(msg)
6fd49698 2442
82839121
PP
2443 return CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
2444
2445 class Event:
6fd49698 2446 def __init__(self, event_class):
82839121
PP
2447 """
2448 Create a new event of the given event class.
2449 """
2450
6fd49698
PP
2451 if not isinstance(event_class, CTFWriter.EventClass):
2452 raise TypeError("Invalid event_class argument.")
2453
2454 self._e = nbt._bt_ctf_event_create(event_class._ec)
82839121 2455
6fd49698
PP
2456 if self._e is None:
2457 raise ValueError("Event creation failed.")
2458
2459 def __del__(self):
2460 nbt._bt_ctf_event_put(self._e)
2461
6fd49698
PP
2462 @property
2463 def event_class(self):
82839121
PP
2464 """
2465 Get the event's class.
2466 """
2467
6fd49698 2468 event_class_native = nbt._bt_ctf_event_get_class(self._e)
82839121 2469
6fd49698
PP
2470 if event_class_native is None:
2471 return None
82839121 2472
6fd49698
PP
2473 event_class = CTFWriter.EventClass.__new__(CTFWriter.EventClass)
2474 event_class._ec = event_class_native
6fd49698 2475
82839121 2476 return event_class
6fd49698
PP
2477
2478 def clock(self):
82839121
PP
2479 """
2480 Get a clock from event. Returns None if the event's class
2481 is not registered to a stream class.
2482 """
2483
6fd49698 2484 clock_instance = nbt._bt_ctf_event_get_clock(self._e)
82839121 2485
6fd49698
PP
2486 if clock_instance is None:
2487 return None
82839121 2488
6fd49698
PP
2489 clock = CTFWriter.Clock.__new__(CTFWriter.Clock)
2490 clock._c = clock_instance
6fd49698 2491
82839121 2492 return clock
6fd49698
PP
2493
2494 def payload(self, field_name):
82839121
PP
2495 """
2496 Get a field from event.
2497 """
2498
2499 native_instance = nbt._bt_ctf_event_get_payload(self._e,
2500 str(field_name))
2501
6fd49698
PP
2502 if native_instance is None:
2503 raise ValueError("Could not get event payload.")
6fd49698 2504
82839121 2505 return CTFWriter.Field._create_field_from_native_instance(native_instance)
6fd49698
PP
2506
2507 def set_payload(self, field_name, value_field):
82839121
PP
2508 """
2509 Set a manually created field as an event's payload.
2510 """
2511
6fd49698
PP
2512 if not isinstance(value, CTFWriter.Field):
2513 raise TypeError("Invalid value type.")
82839121
PP
2514
2515 ret = nbt._bt_ctf_event_set_payload(self._e, str(field_name),
2516 value_field._f)
2517
6fd49698
PP
2518 if ret < 0:
2519 raise ValueError("Could not set event field payload.")
2520
2521 class StreamClass:
6fd49698 2522 def __init__(self, name):
82839121
PP
2523 """
2524 Create a new stream class of the given name.
2525 """
2526
6fd49698 2527 self._sc = nbt._bt_ctf_stream_class_create(name)
82839121 2528
6fd49698
PP
2529 if self._sc is None:
2530 raise ValueError("Stream class creation failed.")
2531
2532 def __del__(self):
2533 nbt._bt_ctf_stream_class_put(self._sc)
2534
6fd49698
PP
2535 @property
2536 def name(self):
82839121
PP
2537 """
2538 Get a stream class' name.
2539 """
2540
6fd49698 2541 name = nbt._bt_ctf_stream_class_get_name(self._sc)
82839121 2542
6fd49698
PP
2543 if name is None:
2544 raise TypeError("Could not get StreamClass name")
82839121 2545
6fd49698
PP
2546 return name
2547
6fd49698
PP
2548 @property
2549 def clock(self):
82839121
PP
2550 """
2551 Get a stream class' clock.
2552 """
2553
6fd49698 2554 clock_instance = nbt._bt_ctf_stream_class_get_clock(self._sc)
82839121 2555
6fd49698
PP
2556 if clock_instance is None:
2557 return None
82839121 2558
6fd49698
PP
2559 clock = CTFWriter.Clock.__new__(CTFWriter.Clock)
2560 clock._c = clock_instance
82839121 2561
6fd49698
PP
2562 return clock
2563
6fd49698
PP
2564 @clock.setter
2565 def clock(self, clock):
82839121
PP
2566 """
2567 Assign a clock to a stream class.
2568 """
2569
6fd49698
PP
2570 if not isinstance(clock, CTFWriter.Clock):
2571 raise TypeError("Invalid clock type.")
2572
2573 ret = nbt._bt_ctf_stream_class_set_clock(self._sc, clock._c)
82839121 2574
6fd49698
PP
2575 if ret < 0:
2576 raise ValueError("Could not set stream class clock.")
2577
6fd49698
PP
2578 @property
2579 def id(self):
82839121
PP
2580 """
2581 Get a stream class' id.
2582 """
2583
6fd49698 2584 ret = nbt._bt_ctf_stream_class_get_id(self._sc)
82839121 2585
6fd49698
PP
2586 if ret < 0:
2587 raise TypeError("Could not get StreamClass id")
82839121 2588
6fd49698
PP
2589 return ret
2590
6fd49698
PP
2591 @id.setter
2592 def id(self, id):
82839121
PP
2593 """
2594 Assign an id to a stream class.
2595 """
2596
6fd49698 2597 ret = nbt._bt_ctf_stream_class_set_id(self._sc, id)
82839121 2598
6fd49698
PP
2599 if ret < 0:
2600 raise TypeError("Could not set stream class id.")
2601
6fd49698
PP
2602 @property
2603 def event_classes(self):
82839121
PP
2604 """
2605 Generator returning the stream class' event classes.
2606 """
2607
6fd49698 2608 count = nbt._bt_ctf_stream_class_get_event_class_count(self._sc)
82839121 2609
6fd49698
PP
2610 if count < 0:
2611 raise TypeError("Could not get StreamClass' event class count")
2612
2613 for i in range(count):
82839121
PP
2614 event_class_native = nbt._bt_ctf_stream_class_get_event_class(self._sc, i)
2615
6fd49698 2616 if event_class_native is None:
82839121
PP
2617 msg = "Could not get StreamClass' event class at index {}".format(i)
2618 raise TypeError(msg)
6fd49698 2619
82839121 2620 event_class = CTFWriter.EventClass.__new__(CTFWriter.EventClass)
6fd49698
PP
2621 event_class._ec = event_class_native
2622 yield event_class
2623
6fd49698 2624 def add_event_class(self, event_class):
82839121
PP
2625 """
2626 Add an event class to a stream class. New events can be added even after a
2627 stream has been instantiated and events have been appended. However, a stream
2628 will not accept events of a class that has not been added to the stream
2629 class beforehand.
2630 """
2631
6fd49698
PP
2632 if not isinstance(event_class, CTFWriter.EventClass):
2633 raise TypeError("Invalid event_class type.")
2634
82839121
PP
2635 ret = nbt._bt_ctf_stream_class_add_event_class(self._sc,
2636 event_class._ec)
2637
6fd49698
PP
2638 if ret < 0:
2639 raise ValueError("Could not add event class.")
2640
6fd49698
PP
2641 @property
2642 def packet_context_type(self):
82839121
PP
2643 """
2644 Get the StreamClass' packet context type (StructureFieldDeclaration)
2645 """
2646
2647 field_type_native = nbt._bt_ctf_stream_class_get_packet_context_type(self._sc)
2648
6fd49698
PP
2649 if field_type_native is None:
2650 raise ValueError("Invalid StreamClass")
82839121
PP
2651
2652 field_type = CTFWriter.FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
2653
6fd49698
PP
2654 return field_type
2655
6fd49698
PP
2656 @packet_context_type.setter
2657 def packet_context_type(self, field_type):
82839121
PP
2658 """
2659 Set a StreamClass' packet context type. Must be of type
2660 StructureFieldDeclaration.
2661 """
2662
6fd49698 2663 if not isinstance(field_type, CTFWriter.StructureFieldDeclaration):
82839121
PP
2664 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
2665
2666 ret = nbt._bt_ctf_stream_class_set_packet_context_type(self._sc,
2667 field_type._ft)
2668
6fd49698
PP
2669 if ret < 0:
2670 raise ValueError("Failed to set packet context type.")
2671
2672 class Stream:
9f8e803f
PP
2673 def __init__(self):
2674 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
6fd49698
PP
2675
2676 def __del__(self):
2677 nbt._bt_ctf_stream_put(self._s)
2678
6fd49698
PP
2679 @property
2680 def discarded_events(self):
82839121
PP
2681 """
2682 Get a stream's discarded event count.
2683 """
2684
6fd49698 2685 ret, count = nbt._bt_ctf_stream_get_discarded_events_count(self._s)
82839121 2686
6fd49698 2687 if ret < 0:
82839121 2688 raise ValueError("Could not get the stream's discarded events count")
6fd49698 2689
82839121 2690 return count
6fd49698
PP
2691
2692 def append_discarded_events(self, event_count):
82839121
PP
2693 """
2694 Increase the current packet's discarded event count.
2695 """
6fd49698 2696
82839121 2697 nbt._bt_ctf_stream_append_discarded_events(self._s, event_count)
6fd49698
PP
2698
2699 def append_event(self, event):
82839121
PP
2700 """
2701 Append "event" to the stream's current packet. The stream's associated clock
2702 will be sampled during this call. The event shall not be modified after
2703 being appended to a stream.
2704 """
2705
6fd49698 2706 ret = nbt._bt_ctf_stream_append_event(self._s, event._e)
82839121 2707
6fd49698
PP
2708 if ret < 0:
2709 raise ValueError("Could not append event to stream.")
2710
6fd49698
PP
2711 @property
2712 def packet_context(self):
82839121
PP
2713 """
2714 Get a Stream's packet context field (a StructureField).
2715 """
2716
6fd49698 2717 native_field = nbt._bt_ctf_stream_get_packet_context(self._s)
82839121 2718
6fd49698
PP
2719 if native_field is None:
2720 raise ValueError("Invalid Stream.")
6fd49698 2721
82839121
PP
2722 return CTFWriter.Field._create_field_from_native_instance(native_field)
2723
6fd49698
PP
2724 @packet_context.setter
2725 def packet_context(self, field):
82839121
PP
2726 """
2727 Set a Stream's packet context field (must be a StructureField).
2728 """
2729
6fd49698 2730 if not isinstance(field, CTFWriter.StructureField):
82839121
PP
2731 raise TypeError("Argument field must be of type StructureField")
2732
6fd49698 2733 ret = nbt._bt_ctf_stream_set_packet_context(self._s, field._f)
82839121 2734
6fd49698
PP
2735 if ret < 0:
2736 raise ValueError("Invalid packet context field.")
2737
6fd49698 2738 def flush(self):
82839121
PP
2739 """
2740 The stream's current packet's events will be flushed to disk. Events
2741 subsequently appended to the stream will be added to a new packet.
2742 """
2743
6fd49698 2744 ret = nbt._bt_ctf_stream_flush(self._s)
82839121 2745
6fd49698
PP
2746 if ret < 0:
2747 raise ValueError("Could not flush stream.")
2748
2749 class Writer:
6fd49698 2750 def __init__(self, path):
82839121
PP
2751 """
2752 Create a new writer that will produce a trace in the given path.
2753 """
2754
6fd49698 2755 self._w = nbt._bt_ctf_writer_create(path)
82839121 2756
6fd49698
PP
2757 if self._w is None:
2758 raise ValueError("Writer creation failed.")
2759
2760 def __del__(self):
2761 nbt._bt_ctf_writer_put(self._w)
2762
6fd49698 2763 def create_stream(self, stream_class):
82839121
PP
2764 """
2765 Create a new stream instance and register it to the writer.
2766 """
2767
6fd49698
PP
2768 if not isinstance(stream_class, CTFWriter.StreamClass):
2769 raise TypeError("Invalid stream_class type.")
2770
2771 stream = CTFWriter.Stream.__new__(CTFWriter.Stream)
2772 stream._s = nbt._bt_ctf_writer_create_stream(self._w, stream_class._sc)
6fd49698 2773
82839121 2774 return stream
6fd49698
PP
2775
2776 def add_environment_field(self, name, value):
82839121
PP
2777 """
2778 Add an environment field to the trace.
2779 """
2780
2781 ret = nbt._bt_ctf_writer_add_environment_field(self._w, str(name),
2782 str(value))
2783
6fd49698
PP
2784 if ret < 0:
2785 raise ValueError("Could not add environment field to trace.")
2786
6fd49698 2787 def add_clock(self, clock):
82839121
PP
2788 """
2789 Add a clock to the trace. Clocks assigned to stream classes must be
2790 registered to the writer.
2791 """
2792
6fd49698 2793 ret = nbt._bt_ctf_writer_add_clock(self._w, clock._c)
82839121 2794
6fd49698
PP
2795 if ret < 0:
2796 raise ValueError("Could not add clock to Writer.")
2797
6fd49698
PP
2798 @property
2799 def metadata(self):
82839121
PP
2800 """
2801 Get the trace's TSDL meta-data.
2802 """
6fd49698 2803
82839121 2804 return nbt._bt_ctf_writer_get_metadata_string(self._w)
6fd49698
PP
2805
2806 def flush_metadata(self):
82839121
PP
2807 """
2808 Flush the trace's metadata to the metadata file.
2809 """
2810
6fd49698
PP
2811 nbt._bt_ctf_writer_flush_metadata(self._w)
2812
6fd49698
PP
2813 @property
2814 def byte_order(self):
82839121
PP
2815 """
2816 Get the trace's byte order. Must be a constant from the ByteOrder
2817 class.
2818 """
2819
6fd49698
PP
2820 raise NotImplementedError("Getter not implemented.")
2821
6fd49698
PP
2822 @byte_order.setter
2823 def byte_order(self, byte_order):
82839121
PP
2824 """
2825 Set the trace's byte order. Must be a constant from the ByteOrder
2826 class. Defaults to the host machine's endianness
2827 """
2828
6fd49698 2829 ret = nbt._bt_ctf_writer_set_byte_order(self._w, byte_order)
82839121 2830
6fd49698
PP
2831 if ret < 0:
2832 raise ValueError("Could not set trace's byte order.")
This page took 0.150974 seconds and 4 git commands to generate.