Python: document writer.ArrayFieldDeclaration
[babeltrace.git] / bindings / python / writer.py
CommitLineData
be5a4e67
PP
1# writer.py
2#
3# Babeltrace writer interface Python module
4#
5# Copyright 2012-2015 EfficiOS Inc.
6#
7# Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
8#
9# Permission is hereby granted, free of charge, to any person obtaining a copy
10# of this software and associated documentation files (the "Software"), to deal
11# in the Software without restriction, including without limitation the rights
12# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13# copies of the Software, and to permit persons to whom the Software is
14# furnished to do so, subject to the following conditions:
15#
16# The above copyright notice and this permission notice shall be included in
17# all copies or substantial portions of the Software.
18#
19# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25# SOFTWARE.
26
27import babeltrace.nativebt as nbt
28import babeltrace.common as common
29from uuid import UUID
30
31
32# Used to compare to -1ULL in error checks
33_MAX_UINT64 = 0xFFFFFFFFFFFFFFFF
34
35
36class EnumerationMapping:
37 """
1759e132 38 Mapping from an enumeration label to a range of integers.
be5a4e67
PP
39 """
40
41 def __init__(self, name, start, end):
1759e132
PP
42 """
43 Creates an enumeration mapping, where label *name* is mapped to
44 the [*start*, *end*] range of integers (*end* is included).
45
46 Set *start* and *end* to the same value to create an enumeration
47 mapping to a single value.
48 """
49
be5a4e67
PP
50 self.name = name
51 self.start = start
52 self.end = end
53
54
55class Clock:
4d7ac86a
PP
56 """
57 A CTF clock allows the description of the system's clock topology, as
58 well as the definition of each clock's parameters.
59
60 :class:`Clock` objects must be registered to a :class:`Writer`
61 object (see :meth:`Writer.add_clock`), as well as be registered to
62 a :class:`StreamClass` object (see :attr:`StreamClass.clock`).
63 """
64
be5a4e67 65 def __init__(self, name):
4d7ac86a
PP
66 """
67 Creates a default CTF clock named *name*.
68
69 :exc:`ValueError` is raised on error.
70 """
71
be5a4e67
PP
72 self._c = nbt._bt_ctf_clock_create(name)
73
74 if self._c is None:
75 raise ValueError("Invalid clock name.")
76
77 def __del__(self):
78 nbt._bt_ctf_clock_put(self._c)
79
80 @property
81 def name(self):
82 """
4d7ac86a
PP
83 Clock name.
84
85 Set this attribute to change the clock's name.
86
87 :exc:`ValueError` is raised on error.
be5a4e67
PP
88 """
89
90 name = nbt._bt_ctf_clock_get_name(self._c)
91
92 if name is None:
93 raise ValueError("Invalid clock instance.")
94
95 return name
96
97 @property
98 def description(self):
99 """
4d7ac86a
PP
100 Clock description (string).
101
102 Set this attribute to change the clock's description.
103
104 :exc:`ValueError` is raised on error.
be5a4e67
PP
105 """
106
107 return nbt._bt_ctf_clock_get_description(self._c)
108
109 @description.setter
110 def description(self, desc):
be5a4e67
PP
111 ret = nbt._bt_ctf_clock_set_description(self._c, str(desc))
112
113 if ret < 0:
114 raise ValueError("Invalid clock description.")
115
116 @property
117 def frequency(self):
118 """
4d7ac86a
PP
119 Clock frequency in Hz (integer).
120
121 Set this attribute to change the clock's frequency.
122
123 :exc:`ValueError` is raised on error.
be5a4e67
PP
124 """
125
126 freq = nbt._bt_ctf_clock_get_frequency(self._c)
127
128 if freq == _MAX_UINT64:
129 raise ValueError("Invalid clock instance")
130
131 return freq
132
133 @frequency.setter
134 def frequency(self, freq):
be5a4e67
PP
135 ret = nbt._bt_ctf_clock_set_frequency(self._c, freq)
136
137 if ret < 0:
138 raise ValueError("Invalid frequency value.")
139
140 @property
141 def precision(self):
142 """
4d7ac86a
PP
143 Clock precision in clock ticks (integer).
144
145 Set this attribute to change the clock's precision.
146
147 :exc:`ValueError` is raised on error.
be5a4e67
PP
148 """
149
150 precision = nbt._bt_ctf_clock_get_precision(self._c)
151
152 if precision == _MAX_UINT64:
153 raise ValueError("Invalid clock instance")
154
155 return precision
156
157 @precision.setter
158 def precision(self, precision):
be5a4e67
PP
159 ret = nbt._bt_ctf_clock_set_precision(self._c, precision)
160
161 @property
162 def offset_seconds(self):
163 """
4d7ac86a
PP
164 Clock offset in seconds since POSIX.1 Epoch (integer).
165
166 Set this attribute to change the clock's offset in seconds.
167
168 :exc:`ValueError` is raised on error.
be5a4e67
PP
169 """
170
171 offset_s = nbt._bt_ctf_clock_get_offset_s(self._c)
172
173 if offset_s == _MAX_UINT64:
174 raise ValueError("Invalid clock instance")
175
176 return offset_s
177
178 @offset_seconds.setter
179 def offset_seconds(self, offset_s):
be5a4e67
PP
180 ret = nbt._bt_ctf_clock_set_offset_s(self._c, offset_s)
181
182 if ret < 0:
183 raise ValueError("Invalid offset value.")
184
185 @property
186 def offset(self):
187 """
4d7ac86a
PP
188 Clock offset in ticks since (POSIX.1 Epoch +
189 :attr:`offset_seconds`).
190
191 Set this attribute to change the clock's offset.
192
193 :exc:`ValueError` is raised on error.
be5a4e67
PP
194 """
195
196 offset = nbt._bt_ctf_clock_get_offset(self._c)
197
198 if offset == _MAX_UINT64:
199 raise ValueError("Invalid clock instance")
200
201 return offset
202
203 @offset.setter
204 def offset(self, offset):
be5a4e67
PP
205 ret = nbt._bt_ctf_clock_set_offset(self._c, offset)
206
207 if ret < 0:
208 raise ValueError("Invalid offset value.")
209
210 @property
211 def absolute(self):
212 """
4d7ac86a
PP
213 ``True`` if this clock is absolute, i.e. if the clock is a
214 global reference across the other clocks of the trace.
215
216 Set this attribute to change the clock's absolute state
217 (boolean).
218
219 :exc:`ValueError` is raised on error.
be5a4e67
PP
220 """
221
222 is_absolute = nbt._bt_ctf_clock_get_is_absolute(self._c)
223
224 if is_absolute == -1:
225 raise ValueError("Invalid clock instance")
226
227 return False if is_absolute == 0 else True
228
229 @absolute.setter
230 def absolute(self, is_absolute):
be5a4e67
PP
231 ret = nbt._bt_ctf_clock_set_is_absolute(self._c, int(is_absolute))
232
233 if ret < 0:
4d7ac86a 234 raise ValueError("Could not set the clock absolute attribute.")
be5a4e67
PP
235
236 @property
237 def uuid(self):
238 """
4d7ac86a
PP
239 Clock UUID (an :class:`uuid.UUID` object).
240
241 Set this attribute to change the clock's UUID.
242
243 :exc:`ValueError` is raised on error.
be5a4e67
PP
244 """
245
246 uuid_list = []
247
248 for i in range(16):
249 ret, value = nbt._bt_python_ctf_clock_get_uuid_index(self._c, i)
250
251 if ret < 0:
252 raise ValueError("Invalid clock instance")
253
254 uuid_list.append(value)
255
256 return UUID(bytes=bytes(uuid_list))
257
258 @uuid.setter
259 def uuid(self, uuid):
be5a4e67
PP
260 uuid_bytes = uuid.bytes
261
262 if len(uuid_bytes) != 16:
263 raise ValueError("Invalid UUID provided. UUID length must be 16 bytes")
264
265 for i in range(len(uuid_bytes)):
266 ret = nbt._bt_python_ctf_clock_set_uuid_index(self._c, i,
267 uuid_bytes[i])
268
269 if ret < 0:
270 raise ValueError("Invalid clock instance")
271
272 @property
273 def time(self):
274 """
4d7ac86a
PP
275 Clock current time; nanoseconds (integer) since clock origin
276 (POSIX.1 Epoch + :attr:`offset_seconds` + :attr:`offset`).
277
278 Set this attribute to change the clock's current time.
279
280 :exc:`ValueError` is raised on error.
be5a4e67
PP
281 """
282
283 time = nbt._bt_ctf_clock_get_time(self._c)
284
285 if time == _MAX_UINT64:
286 raise ValueError("Invalid clock instance")
287
288 return time
289
290 @time.setter
291 def time(self, time):
be5a4e67
PP
292 ret = nbt._bt_ctf_clock_set_time(self._c, time)
293
294 if ret < 0:
295 raise ValueError("Invalid time value.")
296
297
fe9f5df1
PP
298class IntegerBase:
299 """
300 Display base of an integer.
301 """
302
303 #: Unknown
304 INTEGER_BASE_UNKNOWN = -1
305
306 #: Binary
307 INTEGER_BASE_BINARY = 2
308
309 #: Octal
310 INTEGER_BASE_OCTAL = 8
311
312 #: Decimal
313 INTEGER_BASE_DECIMAL = 10
314
315 #: Hexadecimal
316 INTEGER_BASE_HEXADECIMAL = 16
317
318
be5a4e67
PP
319class FieldDeclaration:
320 """
a20c2934
PP
321 Base class of all field declarations. This class is not meant to
322 be instantiated by the user; use one of the concrete field
323 declaration subclasses instead.
be5a4e67
PP
324 """
325
fe9f5df1
PP
326 class IntegerBase(IntegerBase):
327 pass
be5a4e67
PP
328
329 def __init__(self):
330 if self._ft is None:
331 raise ValueError("FieldDeclaration creation failed.")
332
333 def __del__(self):
334 nbt._bt_ctf_field_type_put(self._ft)
335
336 @staticmethod
337 def _create_field_declaration_from_native_instance(
338 native_field_declaration):
339 type_dict = {
340 common.CTFTypeId.INTEGER: IntegerFieldDeclaration,
341 common.CTFTypeId.FLOAT: FloatFieldDeclaration,
342 common.CTFTypeId.ENUM: EnumerationFieldDeclaration,
343 common.CTFTypeId.STRING: StringFieldDeclaration,
344 common.CTFTypeId.STRUCT: StructureFieldDeclaration,
345 common.CTFTypeId.VARIANT: VariantFieldDeclaration,
346 common.CTFTypeId.ARRAY: ArrayFieldDeclaration,
347 common.CTFTypeId.SEQUENCE: SequenceFieldDeclaration
348 }
349
350 field_type_id = nbt._bt_ctf_field_type_get_type_id(native_field_declaration)
351
352 if field_type_id == common.CTFTypeId.UNKNOWN:
353 raise TypeError("Invalid field instance")
354
355 declaration = Field.__new__(Field)
356 declaration._ft = native_field_declaration
357 declaration.__class__ = type_dict[field_type_id]
358
359 return declaration
360
361 @property
362 def alignment(self):
363 """
a20c2934
PP
364 Field alignment in bits (integer).
365
366 Set this attribute to change this field's alignment.
367
368 :exc:`ValueError` is raised on error.
be5a4e67
PP
369 """
370
371 return nbt._bt_ctf_field_type_get_alignment(self._ft)
372
373 @alignment.setter
374 def alignment(self, alignment):
be5a4e67
PP
375 ret = nbt._bt_ctf_field_type_set_alignment(self._ft, alignment)
376
377 if ret < 0:
378 raise ValueError("Invalid alignment value.")
379
380 @property
381 def byte_order(self):
382 """
a20c2934
PP
383 Field byte order (one of :class:`babeltrace.common.ByteOrder`
384 constants).
385
386 Set this attribute to change this field's byte order.
387
388 :exc:`ValueError` is raised on error.
be5a4e67
PP
389 """
390
391 return nbt._bt_ctf_field_type_get_byte_order(self._ft)
392
393 @byte_order.setter
394 def byte_order(self, byte_order):
be5a4e67
PP
395 ret = nbt._bt_ctf_field_type_set_byte_order(self._ft, byte_order)
396
397 if ret < 0:
398 raise ValueError("Could not set byte order value.")
399
400
401class IntegerFieldDeclaration(FieldDeclaration):
7d06a31a
PP
402 """
403 Integer field declaration.
404 """
405
be5a4e67
PP
406 def __init__(self, size):
407 """
7d06a31a
PP
408 Creates an integer field declaration of size *size* bits.
409
410 :exc:`ValueError` is raised on error.
be5a4e67 411 """
7d06a31a 412
be5a4e67
PP
413 self._ft = nbt._bt_ctf_field_type_integer_create(size)
414 super().__init__()
415
416 @property
417 def size(self):
418 """
7d06a31a
PP
419 Integer size in bits (integer).
420
421 Set this attribute to change this integer's size.
422
423 :exc:`ValueError` is raised on error.
be5a4e67
PP
424 """
425
426 ret = nbt._bt_ctf_field_type_integer_get_size(self._ft)
427
428 if ret < 0:
7d06a31a 429 raise ValueError("Could not get Integer size attribute.")
be5a4e67
PP
430 else:
431 return ret
432
433 @property
434 def signed(self):
435 """
7d06a31a
PP
436 ``True`` if this integer is signed.
437
438 Set this attribute to change this integer's signedness
439 (boolean).
440
441 :exc:`ValueError` is raised on error.
be5a4e67
PP
442 """
443
444 ret = nbt._bt_ctf_field_type_integer_get_signed(self._ft)
445
446 if ret < 0:
7d06a31a 447 raise ValueError("Could not get Integer signed attribute.")
be5a4e67
PP
448 elif ret > 0:
449 return True
450 else:
451 return False
452
453 @signed.setter
454 def signed(self, signed):
be5a4e67
PP
455 ret = nbt._bt_ctf_field_type_integer_set_signed(self._ft, signed)
456
457 if ret < 0:
7d06a31a 458 raise ValueError("Could not set Integer signed attribute.")
be5a4e67
PP
459
460 @property
461 def base(self):
462 """
7d06a31a
PP
463 Integer display base (one of :class:`IntegerBase` constants).
464
465 Set this attribute to change this integer's display base.
466
467 :exc:`ValueError` is raised on error.
be5a4e67
PP
468 """
469
470 return nbt._bt_ctf_field_type_integer_get_base(self._ft)
471
472 @base.setter
473 def base(self, base):
be5a4e67
PP
474 ret = nbt._bt_ctf_field_type_integer_set_base(self._ft, base)
475
476 if ret < 0:
7d06a31a 477 raise ValueError("Could not set Integer base.")
be5a4e67
PP
478
479 @property
480 def encoding(self):
481 """
7d06a31a
PP
482 Integer encoding (one of
483 :class:`babeltrace.common.CTFStringEncoding` constants).
484
485 Set this attribute to change this integer's encoding.
486
487 :exc:`ValueError` is raised on error.
be5a4e67
PP
488 """
489
490 return nbt._bt_ctf_field_type_integer_get_encoding(self._ft)
491
492 @encoding.setter
493 def encoding(self, encoding):
be5a4e67
PP
494 ret = nbt._bt_ctf_field_type_integer_set_encoding(self._ft, encoding)
495
496 if ret < 0:
7d06a31a 497 raise ValueError("Could not set Integer encoding.")
be5a4e67
PP
498
499
500class EnumerationFieldDeclaration(FieldDeclaration):
6d4014ed
PP
501 """
502 Enumeration field declaration. A CTF enumeration maps labels to
503 ranges of integers.
504 """
505
be5a4e67
PP
506 def __init__(self, integer_type):
507 """
6d4014ed
PP
508 Creates an enumeration field declaration, with *integer_type*
509 being the underlying :class:`IntegerFieldDeclaration` for storing
510 the integer.
511
512 :exc:`ValueError` is raised on error.
be5a4e67 513 """
6d4014ed 514
be5a4e67
PP
515 isinst = isinstance(integer_type, IntegerFieldDeclaration)
516
517 if integer_type is None or not isinst:
518 raise TypeError("Invalid integer container.")
519
520 self._ft = nbt._bt_ctf_field_type_enumeration_create(integer_type._ft)
521 super().__init__()
522
523 @property
524 def container(self):
525 """
6d4014ed
PP
526 Underlying container (:class:`IntegerFieldDeclaration`).
527
528 :exc:`TypeError` is raised on error.
be5a4e67
PP
529 """
530
531 ret = nbt._bt_ctf_field_type_enumeration_get_container_type(self._ft)
532
533 if ret is None:
534 raise TypeError("Invalid enumeration declaration")
535
536 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
537
538 def add_mapping(self, name, range_start, range_end):
539 """
6d4014ed
PP
540 Adds a mapping to the enumeration field declaration, from the
541 label named *name* to range [*range_start*, *range_end*], where
542 *range_start* and *range_end* are integers included in the
543 range.
544
545 :exc:`ValueError` is raised on error.
be5a4e67
PP
546 """
547
548 if range_start < 0 or range_end < 0:
549 ret = nbt._bt_ctf_field_type_enumeration_add_mapping(self._ft,
550 str(name),
551 range_start,
552 range_end)
553 else:
554 ret = nbt._bt_ctf_field_type_enumeration_add_mapping_unsigned(self._ft,
555 str(name),
556 range_start,
557 range_end)
558
559 if ret < 0:
560 raise ValueError("Could not add mapping to enumeration declaration.")
561
562 @property
563 def mappings(self):
564 """
6d4014ed
PP
565 Generates the mappings of this enumeration field declaration
566 (:class:`EnumerationMapping` objects).
567
568 :exc:`TypeError` is raised on error.
be5a4e67
PP
569 """
570
571 signed = self.container.signed
572
573 count = nbt._bt_ctf_field_type_enumeration_get_mapping_count(self._ft)
574
575 for i in range(count):
576 if signed:
577 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, i)
578 else:
579 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, i)
580
581 if len(ret) != 3:
582 msg = "Could not get Enumeration mapping at index {}".format(i)
583 raise TypeError(msg)
584
585 name, range_start, range_end = ret
586 yield EnumerationMapping(name, range_start, range_end)
587
588 def get_mapping_by_name(self, name):
589 """
6d4014ed
PP
590 Returns the :class:`EnumerationMapping` object for the label
591 named *name*.
592
593 :exc:`TypeError` is raised on error.
be5a4e67
PP
594 """
595
596 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_name(self._ft, name)
597
598 if index < 0:
599 return None
600
601 if self.container.signed:
602 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, index)
603 else:
604 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, index)
605
606 if len(ret) != 3:
607 msg = "Could not get Enumeration mapping at index {}".format(i)
608 raise TypeError(msg)
609
610 name, range_start, range_end = ret
611
612 return EnumerationMapping(name, range_start, range_end)
613
614 def get_mapping_by_value(self, value):
615 """
6d4014ed
PP
616 Returns the :class:`EnumerationMapping` object for the value
617 *value* (integer).
618
619 :exc:`TypeError` is raised on error.
be5a4e67
PP
620 """
621
622 if value < 0:
623 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_value(self._ft, value)
624 else:
625 index = nbt._bt_ctf_field_type_enumeration_get_mapping_index_by_unsigned_value(self._ft, value)
626
627 if index < 0:
628 return None
629
630 if self.container.signed:
631 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping(self._ft, index)
632 else:
633 ret = nbt._bt_python_ctf_field_type_enumeration_get_mapping_unsigned(self._ft, index)
634
635 if len(ret) != 3:
636 msg = "Could not get Enumeration mapping at index {}".format(i)
637 raise TypeError(msg)
638
639 name, range_start, range_end = ret
640
641 return EnumerationMapping(name, range_start, range_end)
642
643
a777c99f
PP
644class FloatingPointFieldDeclaration(FieldDeclaration):
645 """
646 Floating point number field declaration.
647
648 A CTF floating point number is a made of three sections: the sign
649 bit, the exponent bits, and the mantissa bits. The most significant
650 bit of the resulting binary word is the sign bit, and is included
651 in the number of mantissa bits.
652
653 For example, the
654 `IEEE 754 <http://en.wikipedia.org/wiki/IEEE_floating_point>`_
655 single precision floating point number is represented on a 32-bit
656 word using an 8-bit exponent (``e``) and a 24-bit mantissa (``m``),
657 the latter count including the sign bit (``s``)::
658
659 s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
660
661 The IEEE 754 double precision floating point number uses an
662 11-bit exponent and a 53-bit mantissa.
663 """
664
665 #: IEEE 754 single precision floating point number exponent size
be5a4e67 666 FLT_EXP_DIG = 8
a777c99f
PP
667
668 #: IEEE 754 double precision floating point number exponent size
be5a4e67 669 DBL_EXP_DIG = 11
a777c99f
PP
670
671 #: IEEE 754 single precision floating point number mantissa size
be5a4e67 672 FLT_MANT_DIG = 24
a777c99f
PP
673
674 #: IEEE 754 double precision floating point number mantissa size
be5a4e67
PP
675 DBL_MANT_DIG = 53
676
677 def __init__(self):
678 """
a777c99f
PP
679 Creates a floating point number field declaration.
680
681 :exc:`ValueError` is raised on error.
be5a4e67
PP
682 """
683
684 self._ft = nbt._bt_ctf_field_type_floating_point_create()
685 super().__init__()
686
687 @property
688 def exponent_digits(self):
689 """
a777c99f
PP
690 Floating point number exponent section size in bits (integer).
691
692 Set this attribute to change the floating point number's
693 exponent section's size. You may use :attr:`FLT_EXP_DIG` or
694 :attr:`DBL_EXP_DIG` for IEEE 754 floating point numbers.
695
696 :exc:`ValueError` is raised on error.
be5a4e67
PP
697 """
698
699 ret = nbt._bt_ctf_field_type_floating_point_get_exponent_digits(self._ft)
700
701 if ret < 0:
702 raise TypeError(
703 "Could not get Floating point exponent digit count")
704
705 return ret
706
707 @exponent_digits.setter
708 def exponent_digits(self, exponent_digits):
be5a4e67
PP
709 ret = nbt._bt_ctf_field_type_floating_point_set_exponent_digits(self._ft,
710 exponent_digits)
711
712 if ret < 0:
713 raise ValueError("Could not set exponent digit count.")
714
715 @property
716 def mantissa_digits(self):
717 """
a777c99f
PP
718 Floating point number mantissa section size in bits (integer).
719
720 Set this attribute to change the floating point number's
721 mantissa section's size. You may use :attr:`FLT_MANT_DIG` or
722 :attr:`DBL_MANT_DIG` for IEEE 754 floating point numbers.
723
724 :exc:`ValueError` is raised on error.
be5a4e67
PP
725 """
726
727 ret = nbt._bt_ctf_field_type_floating_point_get_mantissa_digits(self._ft)
728
729 if ret < 0:
730 raise TypeError("Could not get Floating point mantissa digit count")
731
732 return ret
733
734 @mantissa_digits.setter
735 def mantissa_digits(self, mantissa_digits):
be5a4e67
PP
736 ret = nbt._bt_ctf_field_type_floating_point_set_mantissa_digits(self._ft,
737 mantissa_digits)
738
739 if ret < 0:
740 raise ValueError("Could not set mantissa digit count.")
741
742
a777c99f 743class FloatFieldDeclaration(FloatingPointFieldDeclaration):
be5a4e67
PP
744 pass
745
746
747class StructureFieldDeclaration(FieldDeclaration):
18449dbf
PP
748 """
749 Structure field declaration, i.e. an ordered mapping from field
750 names to field declarations.
751 """
752
be5a4e67
PP
753 def __init__(self):
754 """
18449dbf
PP
755 Creates an empty structure field declaration.
756
757 :exc:`ValueError` is raised on error.
be5a4e67
PP
758 """
759
760 self._ft = nbt._bt_ctf_field_type_structure_create()
761 super().__init__()
762
763 def add_field(self, field_type, field_name):
764 """
18449dbf
PP
765 Appends one :class:`FieldDeclaration` *field_type* named
766 *field_name* to the structure's ordered map.
767
768 :exc:`ValueError` is raised on error.
be5a4e67
PP
769 """
770
771 ret = nbt._bt_ctf_field_type_structure_add_field(self._ft,
772 field_type._ft,
773 str(field_name))
774
775 if ret < 0:
776 raise ValueError("Could not add field to structure.")
777
778 @property
779 def fields(self):
780 """
18449dbf
PP
781 Generates the (field name, :class:`FieldDeclaration`) pairs
782 of this structure.
783
784 :exc:`TypeError` is raised on error.
be5a4e67
PP
785 """
786
787 count = nbt._bt_ctf_field_type_structure_get_field_count(self._ft)
788
789 if count < 0:
790 raise TypeError("Could not get Structure field count")
791
792 for i in range(count):
793 field_name = nbt._bt_python_ctf_field_type_structure_get_field_name(self._ft, i)
794
795 if field_name is None:
796 msg = "Could not get Structure field name at index {}".format(i)
797 raise TypeError(msg)
798
799 field_type_native = nbt._bt_python_ctf_field_type_structure_get_field_type(self._ft, i)
800
801 if field_type_native is None:
802 msg = "Could not get Structure field type at index {}".format(i)
803 raise TypeError(msg)
804
805 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
806 yield (field_name, field_type)
807
808 def get_field_by_name(self, name):
809 """
18449dbf
PP
810 Returns the :class:`FieldDeclaration` mapped to the field name
811 *name* in this structure.
812
813 :exc:`TypeError` is raised on error.
be5a4e67
PP
814 """
815
816 field_type_native = nbt._bt_ctf_field_type_structure_get_field_type_by_name(self._ft, name)
817
818 if field_type_native is None:
819 msg = "Could not find Structure field with name {}".format(name)
820 raise TypeError(msg)
821
822 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
823
824
825class VariantFieldDeclaration(FieldDeclaration):
62d7eb34
PP
826 """
827 Variant field declaration.
828
829 A CTF variant is a dynamic selection between different fields.
830 The value of a *tag* (a CTF enumeration) determines what is the
831 current selected field. All the possible fields must be added to
832 its field declaration before using an actual variant field.
833 """
834
be5a4e67
PP
835 def __init__(self, enum_tag, tag_name):
836 """
62d7eb34
PP
837 Creates an empty variant field declaration with tag field
838 declaration *enum_tag* (instance of
839 :class:`EnumerationFieldDeclaration`) named *tag_name*
840 (string).
841
842 :exc:`ValueError` is raised on error.
be5a4e67
PP
843 """
844
845 isinst = isinstance(enum_tag, EnumerationFieldDeclaration)
846 if enum_tag is None or not isinst:
847 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
848
849 self._ft = nbt._bt_ctf_field_type_variant_create(enum_tag._ft,
850 str(tag_name))
851 super().__init__()
852
853 @property
854 def tag_name(self):
855 """
62d7eb34
PP
856 Variant field declaration tag name.
857
858 :exc:`TypeError` is raised on error.
be5a4e67
PP
859 """
860
861 ret = nbt._bt_ctf_field_type_variant_get_tag_name(self._ft)
862
863 if ret is None:
864 raise TypeError("Could not get Variant tag name")
865
866 return ret
867
868 @property
869 def tag_type(self):
870 """
62d7eb34
PP
871 Variant field declaration tag field declaration
872 (:class:`EnumerationFieldDeclaration` object).
873
874 :exc:`TypeError` is raised on error.
be5a4e67
PP
875 """
876
877 ret = nbt._bt_ctf_field_type_variant_get_tag_type(self._ft)
878
879 if ret is None:
880 raise TypeError("Could not get Variant tag type")
881
882 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
883
884 def add_field(self, field_type, field_name):
885 """
62d7eb34
PP
886 Registers the :class:`FieldDeclaration` object *field_type*
887 as the variant's selected type when the variant's tag's current
888 label is *field_name*.
889
890 :exc:`ValueError` is raised on error.
be5a4e67
PP
891 """
892
893 ret = nbt._bt_ctf_field_type_variant_add_field(self._ft,
894 field_type._ft,
895 str(field_name))
896
897 if ret < 0:
898 raise ValueError("Could not add field to variant.")
899
900 @property
901 def fields(self):
902 """
62d7eb34
PP
903 Generates the (field name, :class:`FieldDeclaration`) pairs
904 of this variant field declaration.
905
906 :exc:`TypeError` is raised on error.
be5a4e67
PP
907 """
908
909 count = nbt._bt_ctf_field_type_variant_get_field_count(self._ft)
910
911 if count < 0:
912 raise TypeError("Could not get Variant field count")
913
914 for i in range(count):
915 field_name = nbt._bt_python_ctf_field_type_variant_get_field_name(self._ft, i)
916
917 if field_name is None:
918 msg = "Could not get Variant field name at index {}".format(i)
919 raise TypeError(msg)
920
921 field_type_native = nbt._bt_python_ctf_field_type_variant_get_field_type(self._ft, i)
922
923 if field_type_native is None:
924 msg = "Could not get Variant field type at index {}".format(i)
925 raise TypeError(msg)
926
927 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
928 yield (field_name, field_type)
929
930 def get_field_by_name(self, name):
931 """
62d7eb34
PP
932 Returns the :class:`FieldDeclaration` selected when the
933 variant's tag's current label is *name*.
934
935 :exc:`TypeError` is raised on error.
be5a4e67
PP
936 """
937
938 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_by_name(self._ft,
939 name)
940
941 if field_type_native is None:
942 msg = "Could not find Variant field with name {}".format(name)
943 raise TypeError(msg)
944
945 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
946
947 def get_field_from_tag(self, tag):
948 """
62d7eb34
PP
949 Returns the :class:`FieldDeclaration` selected by the current
950 label of the :class:`EnumerationField` *tag*.
951
952 :exc:`TypeError` is raised on error.
be5a4e67
PP
953 """
954
955 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_from_tag(self._ft, tag._f)
956
957 if field_type_native is None:
958 msg = "Could not find Variant field with tag value {}".format(tag.value)
959 raise TypeError(msg)
960
961 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
962
963
964class ArrayFieldDeclaration(FieldDeclaration):
ee77cc15
PP
965 """
966 Static array field declaration.
967 """
968
be5a4e67
PP
969 def __init__(self, element_type, length):
970 """
ee77cc15
PP
971 Creates a static array field declaration of *length*
972 elements of type *element_type* (:class:`FieldDeclaration`).
973
974 :exc:`ValueError` is raised on error.
be5a4e67
PP
975 """
976
977 self._ft = nbt._bt_ctf_field_type_array_create(element_type._ft,
978 length)
979 super().__init__()
980
981 @property
982 def element_type(self):
983 """
ee77cc15
PP
984 Type of the elements of this this static array (subclass of
985 :class:`FieldDeclaration`).
986
987 :exc:`TypeError` is raised on error.
be5a4e67
PP
988 """
989
990 ret = nbt._bt_ctf_field_type_array_get_element_type(self._ft)
991
992 if ret is None:
993 raise TypeError("Could not get Array element type")
994
995 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
996
997 @property
998 def length(self):
999 """
ee77cc15
PP
1000 Length of this static array (integer).
1001
1002 :exc:`TypeError` is raised on error.
be5a4e67
PP
1003 """
1004
1005 ret = nbt._bt_ctf_field_type_array_get_length(self._ft)
1006
1007 if ret < 0:
1008 raise TypeError("Could not get Array length")
1009
1010 return ret
1011
1012
1013class SequenceFieldDeclaration(FieldDeclaration):
1014 def __init__(self, element_type, length_field_name):
1015 """
1016 Create a new sequence field declaration.
1017 """
1018
1019 self._ft = nbt._bt_ctf_field_type_sequence_create(element_type._ft,
1020 str(length_field_name))
1021 super().__init__()
1022
1023 @property
1024 def element_type(self):
1025 """
1026 Get the sequence's element type.
1027 """
1028
1029 ret = nbt._bt_ctf_field_type_sequence_get_element_type(self._ft)
1030
1031 if ret is None:
1032 raise TypeError("Could not get Sequence element type")
1033
1034 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
1035
1036 @property
1037 def length_field_name(self):
1038 """
1039 Get the sequence's length field name.
1040 """
1041
1042 ret = nbt._bt_ctf_field_type_sequence_get_length_field_name(self._ft)
1043
1044 if ret is None:
1045 raise TypeError("Could not get Sequence length field name")
1046
1047 return ret
1048
1049
1050class StringFieldDeclaration(FieldDeclaration):
1051 def __init__(self):
1052 """
1053 Create a new string field declaration.
1054 """
1055
1056 self._ft = nbt._bt_ctf_field_type_string_create()
1057 super().__init__()
1058
1059 @property
1060 def encoding(self):
1061 """
1062 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
1063 """
1064
1065 return nbt._bt_ctf_field_type_string_get_encoding(self._ft)
1066
1067 @encoding.setter
1068 def encoding(self, encoding):
1069 """
1070 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
1071 """
1072
1073 ret = nbt._bt_ctf_field_type_string_set_encoding(self._ft, encoding)
1074 if ret < 0:
1075 raise ValueError("Could not set string encoding.")
1076
1077
1078@staticmethod
1079def create_field(field_type):
1080 """
1081 Create an instance of a field.
1082 """
1083 isinst = isinstance(field_type, FieldDeclaration)
1084
1085 if field_type is None or not isinst:
1086 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
1087
1088 if isinstance(field_type, IntegerFieldDeclaration):
1089 return IntegerField(field_type)
1090 elif isinstance(field_type, EnumerationFieldDeclaration):
1091 return EnumerationField(field_type)
1092 elif isinstance(field_type, FloatFieldDeclaration):
1093 return FloatingPointField(field_type)
1094 elif isinstance(field_type, StructureFieldDeclaration):
1095 return StructureField(field_type)
1096 elif isinstance(field_type, VariantFieldDeclaration):
1097 return VariantField(field_type)
1098 elif isinstance(field_type, ArrayFieldDeclaration):
1099 return ArrayField(field_type)
1100 elif isinstance(field_type, SequenceFieldDeclaration):
1101 return SequenceField(field_type)
1102 elif isinstance(field_type, StringFieldDeclaration):
1103 return StringField(field_type)
1104
1105
1106class Field:
1107 """
1108 Base class, do not instantiate.
1109 """
1110
1111 def __init__(self, field_type):
1112 if not isinstance(field_type, FieldDeclaration):
1113 raise TypeError("Invalid field_type argument.")
1114
1115 self._f = nbt._bt_ctf_field_create(field_type._ft)
1116
1117 if self._f is None:
1118 raise ValueError("Field creation failed.")
1119
1120 def __del__(self):
1121 nbt._bt_ctf_field_put(self._f)
1122
1123 @staticmethod
1124 def _create_field_from_native_instance(native_field_instance):
1125 type_dict = {
1126 common.CTFTypeId.INTEGER: IntegerField,
1127 common.CTFTypeId.FLOAT: FloatingPointField,
1128 common.CTFTypeId.ENUM: EnumerationField,
1129 common.CTFTypeId.STRING: StringField,
1130 common.CTFTypeId.STRUCT: StructureField,
1131 common.CTFTypeId.VARIANT: VariantField,
1132 common.CTFTypeId.ARRAY: ArrayField,
1133 common.CTFTypeId.SEQUENCE: SequenceField
1134 }
1135
1136 field_type = nbt._bt_python_get_field_type(native_field_instance)
1137
1138 if field_type == common.CTFTypeId.UNKNOWN:
1139 raise TypeError("Invalid field instance")
1140
1141 field = Field.__new__(Field)
1142 field._f = native_field_instance
1143 field.__class__ = type_dict[field_type]
1144
1145 return field
1146
1147 @property
1148 def declaration(self):
1149 native_field_type = nbt._bt_ctf_field_get_type(self._f)
1150
1151 if native_field_type is None:
1152 raise TypeError("Invalid field instance")
1153 return FieldDeclaration._create_field_declaration_from_native_instance(
1154 native_field_type)
1155
1156
1157class IntegerField(Field):
1158 @property
1159 def value(self):
1160 """
1161 Get an integer field's value.
1162 """
1163
1164 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
1165
1166 if signedness < 0:
1167 raise TypeError("Invalid integer instance.")
1168
1169 if signedness == 0:
1170 ret, value = nbt._bt_ctf_field_unsigned_integer_get_value(self._f)
1171 else:
1172 ret, value = nbt._bt_ctf_field_signed_integer_get_value(self._f)
1173
1174 if ret < 0:
1175 raise ValueError("Could not get integer field value.")
1176
1177 return value
1178
1179 @value.setter
1180 def value(self, value):
1181 """
1182 Set an integer field's value.
1183 """
1184
1185 if not isinstance(value, int):
1186 raise TypeError("IntegerField's value must be an int")
1187
1188 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
1189 if signedness < 0:
1190 raise TypeError("Invalid integer instance.")
1191
1192 if signedness == 0:
1193 ret = nbt._bt_ctf_field_unsigned_integer_set_value(self._f, value)
1194 else:
1195 ret = nbt._bt_ctf_field_signed_integer_set_value(self._f, value)
1196
1197 if ret < 0:
1198 raise ValueError("Could not set integer field value.")
1199
1200
1201class EnumerationField(Field):
1202 @property
1203 def container(self):
1204 """
1205 Return the enumeration's underlying container field (an integer field).
1206 """
1207
1208 container = IntegerField.__new__(IntegerField)
1209 container._f = nbt._bt_ctf_field_enumeration_get_container(self._f)
1210
1211 if container._f is None:
1212 raise TypeError("Invalid enumeration field type.")
1213
1214 return container
1215
1216 @property
1217 def value(self):
1218 """
1219 Get the enumeration field's mapping name.
1220 """
1221
1222 value = nbt._bt_ctf_field_enumeration_get_mapping_name(self._f)
1223
1224 if value is None:
1225 raise ValueError("Could not get enumeration's mapping name.")
1226
1227 return value
1228
1229 @value.setter
1230 def value(self, value):
1231 """
1232 Set the enumeration field's value. Must be an integer as mapping names
1233 may be ambiguous.
1234 """
1235
1236 if not isinstance(value, int):
1237 raise TypeError("EnumerationField value must be an int")
1238
1239 self.container.value = value
1240
1241
1242class FloatingPointField(Field):
1243 @property
1244 def value(self):
1245 """
1246 Get a floating point field's value.
1247 """
1248
1249 ret, value = nbt._bt_ctf_field_floating_point_get_value(self._f)
1250
1251 if ret < 0:
1252 raise ValueError("Could not get floating point field value.")
1253
1254 return value
1255
1256 @value.setter
1257 def value(self, value):
1258 """
1259 Set a floating point field's value.
1260 """
1261
1262 if not isinstance(value, int) and not isinstance(value, float):
1263 raise TypeError("Value must be either a float or an int")
1264
1265 ret = nbt._bt_ctf_field_floating_point_set_value(self._f, float(value))
1266
1267 if ret < 0:
1268 raise ValueError("Could not set floating point field value.")
1269
1270
1271# oops!! This class is provided to ensure backward-compatibility since
1272# a stable release publicly exposed this abomination.
1273class FloatFieldingPoint(FloatingPointField):
1274 pass
1275
1276
1277class StructureField(Field):
1278 def field(self, field_name):
1279 """
1280 Get the structure's field corresponding to the provided field name.
1281 """
1282
1283 native_instance = nbt._bt_ctf_field_structure_get_field(self._f,
1284 str(field_name))
1285
1286 if native_instance is None:
1287 raise ValueError("Invalid field_name provided.")
1288
1289 return Field._create_field_from_native_instance(native_instance)
1290
1291
1292class VariantField(Field):
1293 def field(self, tag):
1294 """
1295 Return the variant's selected field. The "tag" field is the selector enum field.
1296 """
1297
1298 native_instance = nbt._bt_ctf_field_variant_get_field(self._f, tag._f)
1299
1300 if native_instance is None:
1301 raise ValueError("Invalid tag provided.")
1302
1303 return Field._create_field_from_native_instance(native_instance)
1304
1305
1306class ArrayField(Field):
1307 def field(self, index):
1308 """
1309 Return the array's field at position "index".
1310 """
1311
1312 native_instance = nbt._bt_ctf_field_array_get_field(self._f, index)
1313
1314 if native_instance is None:
1315 raise IndexError("Invalid index provided.")
1316
1317 return Field._create_field_from_native_instance(native_instance)
1318
1319
1320class SequenceField(Field):
1321 @property
1322 def length(self):
1323 """
1324 Get the sequence's length field (IntegerField).
1325 """
1326
1327 native_instance = nbt._bt_ctf_field_sequence_get_length(self._f)
1328
1329 if native_instance is None:
1330 length = -1
1331
1332 return Field._create_field_from_native_instance(native_instance)
1333
1334 @length.setter
1335 def length(self, length_field):
1336 """
1337 Set the sequence's length field (IntegerField).
1338 """
1339
1340 if not isinstance(length_field, IntegerField):
1341 raise TypeError("Invalid length field.")
1342
1343 if length_field.declaration.signed:
1344 raise TypeError("Sequence field length must be unsigned")
1345
1346 ret = nbt._bt_ctf_field_sequence_set_length(self._f, length_field._f)
1347
1348 if ret < 0:
1349 raise ValueError("Could not set sequence length.")
1350
1351 def field(self, index):
1352 """
1353 Return the sequence's field at position "index".
1354 """
1355
1356 native_instance = nbt._bt_ctf_field_sequence_get_field(self._f, index)
1357
1358 if native_instance is None:
1359 raise ValueError("Could not get sequence element at index.")
1360
1361 return Field._create_field_from_native_instance(native_instance)
1362
1363
1364class StringField(Field):
1365 @property
1366 def value(self):
1367 """
1368 Get a string field's value.
1369 """
1370
1371 return nbt._bt_ctf_field_string_get_value(self._f)
1372
1373 @value.setter
1374 def value(self, value):
1375 """
1376 Set a string field's value.
1377 """
1378
1379 ret = nbt._bt_ctf_field_string_set_value(self._f, str(value))
1380
1381 if ret < 0:
1382 raise ValueError("Could not set string field value.")
1383
1384
1385class EventClass:
1386 def __init__(self, name):
1387 """
1388 Create a new event class of the given name.
1389 """
1390
1391 self._ec = nbt._bt_ctf_event_class_create(name)
1392
1393 if self._ec is None:
1394 raise ValueError("Event class creation failed.")
1395
1396 def __del__(self):
1397 nbt._bt_ctf_event_class_put(self._ec)
1398
1399 def add_field(self, field_type, field_name):
1400 """
1401 Add a field of type "field_type" to the event class.
1402 """
1403
1404 ret = nbt._bt_ctf_event_class_add_field(self._ec, field_type._ft,
1405 str(field_name))
1406
1407 if ret < 0:
1408 raise ValueError("Could not add field to event class.")
1409
1410 @property
1411 def name(self):
1412 """
1413 Get the event class' name.
1414 """
1415
1416 name = nbt._bt_ctf_event_class_get_name(self._ec)
1417
1418 if name is None:
1419 raise TypeError("Could not get EventClass name")
1420
1421 return name
1422
1423 @property
1424 def id(self):
1425 """
1426 Get the event class' id. Returns a negative value if unset.
1427 """
1428
1429 id = nbt._bt_ctf_event_class_get_id(self._ec)
1430
1431 if id < 0:
1432 raise TypeError("Could not get EventClass id")
1433
1434 return id
1435
1436 @id.setter
1437 def id(self, id):
1438 """
1439 Set the event class' id. Throws a TypeError if the event class
1440 is already registered to a stream class.
1441 """
1442
1443 ret = nbt._bt_ctf_event_class_set_id(self._ec, id)
1444
1445 if ret < 0:
1446 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
1447
1448 @property
1449 def stream_class(self):
1450 """
1451 Get the event class' stream class. Returns None if unset.
1452 """
1453 stream_class_native = nbt._bt_ctf_event_class_get_stream_class(self._ec)
1454
1455 if stream_class_native is None:
1456 return None
1457
1458 stream_class = StreamClass.__new__(StreamClass)
1459 stream_class._sc = stream_class_native
1460
1461 return stream_class
1462
1463 @property
1464 def fields(self):
1465 """
1466 Generator returning the event class' fields as tuples of (field name, field declaration).
1467 """
1468
1469 count = nbt._bt_ctf_event_class_get_field_count(self._ec)
1470
1471 if count < 0:
1472 raise TypeError("Could not get EventClass' field count")
1473
1474 for i in range(count):
1475 field_name = nbt._bt_python_ctf_event_class_get_field_name(self._ec, i)
1476
1477 if field_name is None:
1478 msg = "Could not get EventClass' field name at index {}".format(i)
1479 raise TypeError(msg)
1480
1481 field_type_native = nbt._bt_python_ctf_event_class_get_field_type(self._ec, i)
1482
1483 if field_type_native is None:
1484 msg = "Could not get EventClass' field type at index {}".format(i)
1485 raise TypeError(msg)
1486
1487 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1488 yield (field_name, field_type)
1489
1490 def get_field_by_name(self, name):
1491 """
1492 Get a field declaration by name (FieldDeclaration).
1493 """
1494
1495 field_type_native = nbt._bt_ctf_event_class_get_field_by_name(self._ec, name)
1496
1497 if field_type_native is None:
1498 msg = "Could not find EventClass field with name {}".format(name)
1499 raise TypeError(msg)
1500
1501 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1502
1503
1504class Event:
1505 def __init__(self, event_class):
1506 """
1507 Create a new event of the given event class.
1508 """
1509
1510 if not isinstance(event_class, EventClass):
1511 raise TypeError("Invalid event_class argument.")
1512
1513 self._e = nbt._bt_ctf_event_create(event_class._ec)
1514
1515 if self._e is None:
1516 raise ValueError("Event creation failed.")
1517
1518 def __del__(self):
1519 nbt._bt_ctf_event_put(self._e)
1520
1521 @property
1522 def event_class(self):
1523 """
1524 Get the event's class.
1525 """
1526
1527 event_class_native = nbt._bt_ctf_event_get_class(self._e)
1528
1529 if event_class_native is None:
1530 return None
1531
1532 event_class = EventClass.__new__(EventClass)
1533 event_class._ec = event_class_native
1534
1535 return event_class
1536
1537 def clock(self):
1538 """
1539 Get a clock from event. Returns None if the event's class
1540 is not registered to a stream class.
1541 """
1542
1543 clock_instance = nbt._bt_ctf_event_get_clock(self._e)
1544
1545 if clock_instance is None:
1546 return None
1547
1548 clock = Clock.__new__(Clock)
1549 clock._c = clock_instance
1550
1551 return clock
1552
1553 def payload(self, field_name):
1554 """
1555 Get a field from event.
1556 """
1557
1558 native_instance = nbt._bt_ctf_event_get_payload(self._e,
1559 str(field_name))
1560
1561 if native_instance is None:
1562 raise ValueError("Could not get event payload.")
1563
1564 return Field._create_field_from_native_instance(native_instance)
1565
1566 def set_payload(self, field_name, value_field):
1567 """
1568 Set a manually created field as an event's payload.
1569 """
1570
1571 if not isinstance(value, Field):
1572 raise TypeError("Invalid value type.")
1573
1574 ret = nbt._bt_ctf_event_set_payload(self._e, str(field_name),
1575 value_field._f)
1576
1577 if ret < 0:
1578 raise ValueError("Could not set event field payload.")
1579
1580
1581class StreamClass:
1582 def __init__(self, name):
1583 """
1584 Create a new stream class of the given name.
1585 """
1586
1587 self._sc = nbt._bt_ctf_stream_class_create(name)
1588
1589 if self._sc is None:
1590 raise ValueError("Stream class creation failed.")
1591
1592 def __del__(self):
1593 nbt._bt_ctf_stream_class_put(self._sc)
1594
1595 @property
1596 def name(self):
1597 """
1598 Get a stream class' name.
1599 """
1600
1601 name = nbt._bt_ctf_stream_class_get_name(self._sc)
1602
1603 if name is None:
1604 raise TypeError("Could not get StreamClass name")
1605
1606 return name
1607
1608 @property
1609 def clock(self):
1610 """
1611 Get a stream class' clock.
1612 """
1613
1614 clock_instance = nbt._bt_ctf_stream_class_get_clock(self._sc)
1615
1616 if clock_instance is None:
1617 return None
1618
1619 clock = Clock.__new__(Clock)
1620 clock._c = clock_instance
1621
1622 return clock
1623
1624 @clock.setter
1625 def clock(self, clock):
1626 """
1627 Assign a clock to a stream class.
1628 """
1629
1630 if not isinstance(clock, Clock):
1631 raise TypeError("Invalid clock type.")
1632
1633 ret = nbt._bt_ctf_stream_class_set_clock(self._sc, clock._c)
1634
1635 if ret < 0:
1636 raise ValueError("Could not set stream class clock.")
1637
1638 @property
1639 def id(self):
1640 """
1641 Get a stream class' id.
1642 """
1643
1644 ret = nbt._bt_ctf_stream_class_get_id(self._sc)
1645
1646 if ret < 0:
1647 raise TypeError("Could not get StreamClass id")
1648
1649 return ret
1650
1651 @id.setter
1652 def id(self, id):
1653 """
1654 Assign an id to a stream class.
1655 """
1656
1657 ret = nbt._bt_ctf_stream_class_set_id(self._sc, id)
1658
1659 if ret < 0:
1660 raise TypeError("Could not set stream class id.")
1661
1662 @property
1663 def event_classes(self):
1664 """
1665 Generator returning the stream class' event classes.
1666 """
1667
1668 count = nbt._bt_ctf_stream_class_get_event_class_count(self._sc)
1669
1670 if count < 0:
1671 raise TypeError("Could not get StreamClass' event class count")
1672
1673 for i in range(count):
1674 event_class_native = nbt._bt_ctf_stream_class_get_event_class(self._sc, i)
1675
1676 if event_class_native is None:
1677 msg = "Could not get StreamClass' event class at index {}".format(i)
1678 raise TypeError(msg)
1679
1680 event_class = EventClass.__new__(EventClass)
1681 event_class._ec = event_class_native
1682 yield event_class
1683
1684 def add_event_class(self, event_class):
1685 """
1686 Add an event class to a stream class. New events can be added even after a
1687 stream has been instantiated and events have been appended. However, a stream
1688 will not accept events of a class that has not been added to the stream
1689 class beforehand.
1690 """
1691
1692 if not isinstance(event_class, EventClass):
1693 raise TypeError("Invalid event_class type.")
1694
1695 ret = nbt._bt_ctf_stream_class_add_event_class(self._sc,
1696 event_class._ec)
1697
1698 if ret < 0:
1699 raise ValueError("Could not add event class.")
1700
1701 @property
1702 def packet_context_type(self):
1703 """
1704 Get the StreamClass' packet context type (StructureFieldDeclaration)
1705 """
1706
1707 field_type_native = nbt._bt_ctf_stream_class_get_packet_context_type(self._sc)
1708
1709 if field_type_native is None:
1710 raise ValueError("Invalid StreamClass")
1711
1712 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1713
1714 return field_type
1715
1716 @packet_context_type.setter
1717 def packet_context_type(self, field_type):
1718 """
1719 Set a StreamClass' packet context type. Must be of type
1720 StructureFieldDeclaration.
1721 """
1722
1723 if not isinstance(field_type, StructureFieldDeclaration):
1724 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1725
1726 ret = nbt._bt_ctf_stream_class_set_packet_context_type(self._sc,
1727 field_type._ft)
1728
1729 if ret < 0:
1730 raise ValueError("Failed to set packet context type.")
1731
1732
1733class Stream:
1734 def __init__(self):
1735 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
1736
1737 def __del__(self):
1738 nbt._bt_ctf_stream_put(self._s)
1739
1740 @property
1741 def discarded_events(self):
1742 """
1743 Get a stream's discarded event count.
1744 """
1745
1746 ret, count = nbt._bt_ctf_stream_get_discarded_events_count(self._s)
1747
1748 if ret < 0:
1749 raise ValueError("Could not get the stream's discarded events count")
1750
1751 return count
1752
1753 def append_discarded_events(self, event_count):
1754 """
1755 Increase the current packet's discarded event count.
1756 """
1757
1758 nbt._bt_ctf_stream_append_discarded_events(self._s, event_count)
1759
1760 def append_event(self, event):
1761 """
1762 Append "event" to the stream's current packet. The stream's associated clock
1763 will be sampled during this call. The event shall not be modified after
1764 being appended to a stream.
1765 """
1766
1767 ret = nbt._bt_ctf_stream_append_event(self._s, event._e)
1768
1769 if ret < 0:
1770 raise ValueError("Could not append event to stream.")
1771
1772 @property
1773 def packet_context(self):
1774 """
1775 Get a Stream's packet context field (a StructureField).
1776 """
1777
1778 native_field = nbt._bt_ctf_stream_get_packet_context(self._s)
1779
1780 if native_field is None:
1781 raise ValueError("Invalid Stream.")
1782
1783 return Field._create_field_from_native_instance(native_field)
1784
1785 @packet_context.setter
1786 def packet_context(self, field):
1787 """
1788 Set a Stream's packet context field (must be a StructureField).
1789 """
1790
1791 if not isinstance(field, StructureField):
1792 raise TypeError("Argument field must be of type StructureField")
1793
1794 ret = nbt._bt_ctf_stream_set_packet_context(self._s, field._f)
1795
1796 if ret < 0:
1797 raise ValueError("Invalid packet context field.")
1798
1799 def flush(self):
1800 """
1801 The stream's current packet's events will be flushed to disk. Events
1802 subsequently appended to the stream will be added to a new packet.
1803 """
1804
1805 ret = nbt._bt_ctf_stream_flush(self._s)
1806
1807 if ret < 0:
1808 raise ValueError("Could not flush stream.")
1809
1810
1811class Writer:
1812 def __init__(self, path):
1813 """
1814 Create a new writer that will produce a trace in the given path.
1815 """
1816
1817 self._w = nbt._bt_ctf_writer_create(path)
1818
1819 if self._w is None:
1820 raise ValueError("Writer creation failed.")
1821
1822 def __del__(self):
1823 nbt._bt_ctf_writer_put(self._w)
1824
1825 def create_stream(self, stream_class):
1826 """
1827 Create a new stream instance and register it to the writer.
1828 """
1829
1830 if not isinstance(stream_class, StreamClass):
1831 raise TypeError("Invalid stream_class type.")
1832
1833 stream = Stream.__new__(Stream)
1834 stream._s = nbt._bt_ctf_writer_create_stream(self._w, stream_class._sc)
1835
1836 return stream
1837
1838 def add_environment_field(self, name, value):
1839 """
1840 Add an environment field to the trace.
1841 """
1842
1843 ret = nbt._bt_ctf_writer_add_environment_field(self._w, str(name),
1844 str(value))
1845
1846 if ret < 0:
1847 raise ValueError("Could not add environment field to trace.")
1848
1849 def add_clock(self, clock):
1850 """
1851 Add a clock to the trace. Clocks assigned to stream classes must be
1852 registered to the writer.
1853 """
1854
1855 ret = nbt._bt_ctf_writer_add_clock(self._w, clock._c)
1856
1857 if ret < 0:
1858 raise ValueError("Could not add clock to Writer.")
1859
1860 @property
1861 def metadata(self):
1862 """
1863 Get the trace's TSDL meta-data.
1864 """
1865
1866 return nbt._bt_ctf_writer_get_metadata_string(self._w)
1867
1868 def flush_metadata(self):
1869 """
1870 Flush the trace's metadata to the metadata file.
1871 """
1872
1873 nbt._bt_ctf_writer_flush_metadata(self._w)
1874
1875 @property
1876 def byte_order(self):
1877 """
1878 Get the trace's byte order. Must be a constant from the ByteOrder
1879 class.
1880 """
1881
1882 raise NotImplementedError("Getter not implemented.")
1883
1884 @byte_order.setter
1885 def byte_order(self, byte_order):
1886 """
1887 Set the trace's byte order. Must be a constant from the ByteOrder
1888 class. Defaults to the host machine's endianness
1889 """
1890
1891 ret = nbt._bt_ctf_writer_set_byte_order(self._w, byte_order)
1892
1893 if ret < 0:
1894 raise ValueError("Could not set trace's byte order.")
This page took 0.095668 seconds and 4 git commands to generate.