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