Python: document writer.FloatingPointFieldDeclaration
[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):
748 def __init__(self):
749 """
750 Create a new structure field declaration.
751 """
752
753 self._ft = nbt._bt_ctf_field_type_structure_create()
754 super().__init__()
755
756 def add_field(self, field_type, field_name):
757 """
758 Add a field of type "field_type" to the structure.
759 """
760
761 ret = nbt._bt_ctf_field_type_structure_add_field(self._ft,
762 field_type._ft,
763 str(field_name))
764
765 if ret < 0:
766 raise ValueError("Could not add field to structure.")
767
768 @property
769 def fields(self):
770 """
771 Generator returning the structure's field as tuples of (field name, field declaration).
772 """
773
774 count = nbt._bt_ctf_field_type_structure_get_field_count(self._ft)
775
776 if count < 0:
777 raise TypeError("Could not get Structure field count")
778
779 for i in range(count):
780 field_name = nbt._bt_python_ctf_field_type_structure_get_field_name(self._ft, i)
781
782 if field_name is None:
783 msg = "Could not get Structure field name at index {}".format(i)
784 raise TypeError(msg)
785
786 field_type_native = nbt._bt_python_ctf_field_type_structure_get_field_type(self._ft, i)
787
788 if field_type_native is None:
789 msg = "Could not get Structure field type at index {}".format(i)
790 raise TypeError(msg)
791
792 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
793 yield (field_name, field_type)
794
795 def get_field_by_name(self, name):
796 """
797 Get a field declaration by name (FieldDeclaration).
798 """
799
800 field_type_native = nbt._bt_ctf_field_type_structure_get_field_type_by_name(self._ft, name)
801
802 if field_type_native is None:
803 msg = "Could not find Structure field with name {}".format(name)
804 raise TypeError(msg)
805
806 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
807
808
809class VariantFieldDeclaration(FieldDeclaration):
810 def __init__(self, enum_tag, tag_name):
811 """
812 Create a new variant field declaration.
813 """
814
815 isinst = isinstance(enum_tag, EnumerationFieldDeclaration)
816 if enum_tag is None or not isinst:
817 raise TypeError("Invalid tag type; must be of type EnumerationFieldDeclaration.")
818
819 self._ft = nbt._bt_ctf_field_type_variant_create(enum_tag._ft,
820 str(tag_name))
821 super().__init__()
822
823 @property
824 def tag_name(self):
825 """
826 Get the variant's tag name.
827 """
828
829 ret = nbt._bt_ctf_field_type_variant_get_tag_name(self._ft)
830
831 if ret is None:
832 raise TypeError("Could not get Variant tag name")
833
834 return ret
835
836 @property
837 def tag_type(self):
838 """
839 Get the variant's tag type.
840 """
841
842 ret = nbt._bt_ctf_field_type_variant_get_tag_type(self._ft)
843
844 if ret is None:
845 raise TypeError("Could not get Variant tag type")
846
847 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
848
849 def add_field(self, field_type, field_name):
850 """
851 Add a field of type "field_type" to the variant.
852 """
853
854 ret = nbt._bt_ctf_field_type_variant_add_field(self._ft,
855 field_type._ft,
856 str(field_name))
857
858 if ret < 0:
859 raise ValueError("Could not add field to variant.")
860
861 @property
862 def fields(self):
863 """
864 Generator returning the variant's field as tuples of (field name, field declaration).
865 """
866
867 count = nbt._bt_ctf_field_type_variant_get_field_count(self._ft)
868
869 if count < 0:
870 raise TypeError("Could not get Variant field count")
871
872 for i in range(count):
873 field_name = nbt._bt_python_ctf_field_type_variant_get_field_name(self._ft, i)
874
875 if field_name is None:
876 msg = "Could not get Variant field name at index {}".format(i)
877 raise TypeError(msg)
878
879 field_type_native = nbt._bt_python_ctf_field_type_variant_get_field_type(self._ft, i)
880
881 if field_type_native is None:
882 msg = "Could not get Variant field type at index {}".format(i)
883 raise TypeError(msg)
884
885 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
886 yield (field_name, field_type)
887
888 def get_field_by_name(self, name):
889 """
890 Get a field declaration by name (FieldDeclaration).
891 """
892
893 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_by_name(self._ft,
894 name)
895
896 if field_type_native is None:
897 msg = "Could not find Variant field with name {}".format(name)
898 raise TypeError(msg)
899
900 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
901
902 def get_field_from_tag(self, tag):
903 """
904 Get a field declaration from tag (EnumerationField).
905 """
906
907 field_type_native = nbt._bt_ctf_field_type_variant_get_field_type_from_tag(self._ft, tag._f)
908
909 if field_type_native is None:
910 msg = "Could not find Variant field with tag value {}".format(tag.value)
911 raise TypeError(msg)
912
913 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
914
915
916class ArrayFieldDeclaration(FieldDeclaration):
917 def __init__(self, element_type, length):
918 """
919 Create a new array field declaration.
920 """
921
922 self._ft = nbt._bt_ctf_field_type_array_create(element_type._ft,
923 length)
924 super().__init__()
925
926 @property
927 def element_type(self):
928 """
929 Get the array's element type.
930 """
931
932 ret = nbt._bt_ctf_field_type_array_get_element_type(self._ft)
933
934 if ret is None:
935 raise TypeError("Could not get Array element type")
936
937 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
938
939 @property
940 def length(self):
941 """
942 Get the array's length.
943 """
944
945 ret = nbt._bt_ctf_field_type_array_get_length(self._ft)
946
947 if ret < 0:
948 raise TypeError("Could not get Array length")
949
950 return ret
951
952
953class SequenceFieldDeclaration(FieldDeclaration):
954 def __init__(self, element_type, length_field_name):
955 """
956 Create a new sequence field declaration.
957 """
958
959 self._ft = nbt._bt_ctf_field_type_sequence_create(element_type._ft,
960 str(length_field_name))
961 super().__init__()
962
963 @property
964 def element_type(self):
965 """
966 Get the sequence's element type.
967 """
968
969 ret = nbt._bt_ctf_field_type_sequence_get_element_type(self._ft)
970
971 if ret is None:
972 raise TypeError("Could not get Sequence element type")
973
974 return FieldDeclaration._create_field_declaration_from_native_instance(ret)
975
976 @property
977 def length_field_name(self):
978 """
979 Get the sequence's length field name.
980 """
981
982 ret = nbt._bt_ctf_field_type_sequence_get_length_field_name(self._ft)
983
984 if ret is None:
985 raise TypeError("Could not get Sequence length field name")
986
987 return ret
988
989
990class StringFieldDeclaration(FieldDeclaration):
991 def __init__(self):
992 """
993 Create a new string field declaration.
994 """
995
996 self._ft = nbt._bt_ctf_field_type_string_create()
997 super().__init__()
998
999 @property
1000 def encoding(self):
1001 """
1002 Get a string declaration's encoding (a constant from the CTFStringEncoding class).
1003 """
1004
1005 return nbt._bt_ctf_field_type_string_get_encoding(self._ft)
1006
1007 @encoding.setter
1008 def encoding(self, encoding):
1009 """
1010 Set a string declaration's encoding. Must be a constant from the CTFStringEncoding class.
1011 """
1012
1013 ret = nbt._bt_ctf_field_type_string_set_encoding(self._ft, encoding)
1014 if ret < 0:
1015 raise ValueError("Could not set string encoding.")
1016
1017
1018@staticmethod
1019def create_field(field_type):
1020 """
1021 Create an instance of a field.
1022 """
1023 isinst = isinstance(field_type, FieldDeclaration)
1024
1025 if field_type is None or not isinst:
1026 raise TypeError("Invalid field_type. Type must be a FieldDeclaration-derived class.")
1027
1028 if isinstance(field_type, IntegerFieldDeclaration):
1029 return IntegerField(field_type)
1030 elif isinstance(field_type, EnumerationFieldDeclaration):
1031 return EnumerationField(field_type)
1032 elif isinstance(field_type, FloatFieldDeclaration):
1033 return FloatingPointField(field_type)
1034 elif isinstance(field_type, StructureFieldDeclaration):
1035 return StructureField(field_type)
1036 elif isinstance(field_type, VariantFieldDeclaration):
1037 return VariantField(field_type)
1038 elif isinstance(field_type, ArrayFieldDeclaration):
1039 return ArrayField(field_type)
1040 elif isinstance(field_type, SequenceFieldDeclaration):
1041 return SequenceField(field_type)
1042 elif isinstance(field_type, StringFieldDeclaration):
1043 return StringField(field_type)
1044
1045
1046class Field:
1047 """
1048 Base class, do not instantiate.
1049 """
1050
1051 def __init__(self, field_type):
1052 if not isinstance(field_type, FieldDeclaration):
1053 raise TypeError("Invalid field_type argument.")
1054
1055 self._f = nbt._bt_ctf_field_create(field_type._ft)
1056
1057 if self._f is None:
1058 raise ValueError("Field creation failed.")
1059
1060 def __del__(self):
1061 nbt._bt_ctf_field_put(self._f)
1062
1063 @staticmethod
1064 def _create_field_from_native_instance(native_field_instance):
1065 type_dict = {
1066 common.CTFTypeId.INTEGER: IntegerField,
1067 common.CTFTypeId.FLOAT: FloatingPointField,
1068 common.CTFTypeId.ENUM: EnumerationField,
1069 common.CTFTypeId.STRING: StringField,
1070 common.CTFTypeId.STRUCT: StructureField,
1071 common.CTFTypeId.VARIANT: VariantField,
1072 common.CTFTypeId.ARRAY: ArrayField,
1073 common.CTFTypeId.SEQUENCE: SequenceField
1074 }
1075
1076 field_type = nbt._bt_python_get_field_type(native_field_instance)
1077
1078 if field_type == common.CTFTypeId.UNKNOWN:
1079 raise TypeError("Invalid field instance")
1080
1081 field = Field.__new__(Field)
1082 field._f = native_field_instance
1083 field.__class__ = type_dict[field_type]
1084
1085 return field
1086
1087 @property
1088 def declaration(self):
1089 native_field_type = nbt._bt_ctf_field_get_type(self._f)
1090
1091 if native_field_type is None:
1092 raise TypeError("Invalid field instance")
1093 return FieldDeclaration._create_field_declaration_from_native_instance(
1094 native_field_type)
1095
1096
1097class IntegerField(Field):
1098 @property
1099 def value(self):
1100 """
1101 Get an integer field's value.
1102 """
1103
1104 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
1105
1106 if signedness < 0:
1107 raise TypeError("Invalid integer instance.")
1108
1109 if signedness == 0:
1110 ret, value = nbt._bt_ctf_field_unsigned_integer_get_value(self._f)
1111 else:
1112 ret, value = nbt._bt_ctf_field_signed_integer_get_value(self._f)
1113
1114 if ret < 0:
1115 raise ValueError("Could not get integer field value.")
1116
1117 return value
1118
1119 @value.setter
1120 def value(self, value):
1121 """
1122 Set an integer field's value.
1123 """
1124
1125 if not isinstance(value, int):
1126 raise TypeError("IntegerField's value must be an int")
1127
1128 signedness = nbt._bt_python_field_integer_get_signedness(self._f)
1129 if signedness < 0:
1130 raise TypeError("Invalid integer instance.")
1131
1132 if signedness == 0:
1133 ret = nbt._bt_ctf_field_unsigned_integer_set_value(self._f, value)
1134 else:
1135 ret = nbt._bt_ctf_field_signed_integer_set_value(self._f, value)
1136
1137 if ret < 0:
1138 raise ValueError("Could not set integer field value.")
1139
1140
1141class EnumerationField(Field):
1142 @property
1143 def container(self):
1144 """
1145 Return the enumeration's underlying container field (an integer field).
1146 """
1147
1148 container = IntegerField.__new__(IntegerField)
1149 container._f = nbt._bt_ctf_field_enumeration_get_container(self._f)
1150
1151 if container._f is None:
1152 raise TypeError("Invalid enumeration field type.")
1153
1154 return container
1155
1156 @property
1157 def value(self):
1158 """
1159 Get the enumeration field's mapping name.
1160 """
1161
1162 value = nbt._bt_ctf_field_enumeration_get_mapping_name(self._f)
1163
1164 if value is None:
1165 raise ValueError("Could not get enumeration's mapping name.")
1166
1167 return value
1168
1169 @value.setter
1170 def value(self, value):
1171 """
1172 Set the enumeration field's value. Must be an integer as mapping names
1173 may be ambiguous.
1174 """
1175
1176 if not isinstance(value, int):
1177 raise TypeError("EnumerationField value must be an int")
1178
1179 self.container.value = value
1180
1181
1182class FloatingPointField(Field):
1183 @property
1184 def value(self):
1185 """
1186 Get a floating point field's value.
1187 """
1188
1189 ret, value = nbt._bt_ctf_field_floating_point_get_value(self._f)
1190
1191 if ret < 0:
1192 raise ValueError("Could not get floating point field value.")
1193
1194 return value
1195
1196 @value.setter
1197 def value(self, value):
1198 """
1199 Set a floating point field's value.
1200 """
1201
1202 if not isinstance(value, int) and not isinstance(value, float):
1203 raise TypeError("Value must be either a float or an int")
1204
1205 ret = nbt._bt_ctf_field_floating_point_set_value(self._f, float(value))
1206
1207 if ret < 0:
1208 raise ValueError("Could not set floating point field value.")
1209
1210
1211# oops!! This class is provided to ensure backward-compatibility since
1212# a stable release publicly exposed this abomination.
1213class FloatFieldingPoint(FloatingPointField):
1214 pass
1215
1216
1217class StructureField(Field):
1218 def field(self, field_name):
1219 """
1220 Get the structure's field corresponding to the provided field name.
1221 """
1222
1223 native_instance = nbt._bt_ctf_field_structure_get_field(self._f,
1224 str(field_name))
1225
1226 if native_instance is None:
1227 raise ValueError("Invalid field_name provided.")
1228
1229 return Field._create_field_from_native_instance(native_instance)
1230
1231
1232class VariantField(Field):
1233 def field(self, tag):
1234 """
1235 Return the variant's selected field. The "tag" field is the selector enum field.
1236 """
1237
1238 native_instance = nbt._bt_ctf_field_variant_get_field(self._f, tag._f)
1239
1240 if native_instance is None:
1241 raise ValueError("Invalid tag provided.")
1242
1243 return Field._create_field_from_native_instance(native_instance)
1244
1245
1246class ArrayField(Field):
1247 def field(self, index):
1248 """
1249 Return the array's field at position "index".
1250 """
1251
1252 native_instance = nbt._bt_ctf_field_array_get_field(self._f, index)
1253
1254 if native_instance is None:
1255 raise IndexError("Invalid index provided.")
1256
1257 return Field._create_field_from_native_instance(native_instance)
1258
1259
1260class SequenceField(Field):
1261 @property
1262 def length(self):
1263 """
1264 Get the sequence's length field (IntegerField).
1265 """
1266
1267 native_instance = nbt._bt_ctf_field_sequence_get_length(self._f)
1268
1269 if native_instance is None:
1270 length = -1
1271
1272 return Field._create_field_from_native_instance(native_instance)
1273
1274 @length.setter
1275 def length(self, length_field):
1276 """
1277 Set the sequence's length field (IntegerField).
1278 """
1279
1280 if not isinstance(length_field, IntegerField):
1281 raise TypeError("Invalid length field.")
1282
1283 if length_field.declaration.signed:
1284 raise TypeError("Sequence field length must be unsigned")
1285
1286 ret = nbt._bt_ctf_field_sequence_set_length(self._f, length_field._f)
1287
1288 if ret < 0:
1289 raise ValueError("Could not set sequence length.")
1290
1291 def field(self, index):
1292 """
1293 Return the sequence's field at position "index".
1294 """
1295
1296 native_instance = nbt._bt_ctf_field_sequence_get_field(self._f, index)
1297
1298 if native_instance is None:
1299 raise ValueError("Could not get sequence element at index.")
1300
1301 return Field._create_field_from_native_instance(native_instance)
1302
1303
1304class StringField(Field):
1305 @property
1306 def value(self):
1307 """
1308 Get a string field's value.
1309 """
1310
1311 return nbt._bt_ctf_field_string_get_value(self._f)
1312
1313 @value.setter
1314 def value(self, value):
1315 """
1316 Set a string field's value.
1317 """
1318
1319 ret = nbt._bt_ctf_field_string_set_value(self._f, str(value))
1320
1321 if ret < 0:
1322 raise ValueError("Could not set string field value.")
1323
1324
1325class EventClass:
1326 def __init__(self, name):
1327 """
1328 Create a new event class of the given name.
1329 """
1330
1331 self._ec = nbt._bt_ctf_event_class_create(name)
1332
1333 if self._ec is None:
1334 raise ValueError("Event class creation failed.")
1335
1336 def __del__(self):
1337 nbt._bt_ctf_event_class_put(self._ec)
1338
1339 def add_field(self, field_type, field_name):
1340 """
1341 Add a field of type "field_type" to the event class.
1342 """
1343
1344 ret = nbt._bt_ctf_event_class_add_field(self._ec, field_type._ft,
1345 str(field_name))
1346
1347 if ret < 0:
1348 raise ValueError("Could not add field to event class.")
1349
1350 @property
1351 def name(self):
1352 """
1353 Get the event class' name.
1354 """
1355
1356 name = nbt._bt_ctf_event_class_get_name(self._ec)
1357
1358 if name is None:
1359 raise TypeError("Could not get EventClass name")
1360
1361 return name
1362
1363 @property
1364 def id(self):
1365 """
1366 Get the event class' id. Returns a negative value if unset.
1367 """
1368
1369 id = nbt._bt_ctf_event_class_get_id(self._ec)
1370
1371 if id < 0:
1372 raise TypeError("Could not get EventClass id")
1373
1374 return id
1375
1376 @id.setter
1377 def id(self, id):
1378 """
1379 Set the event class' id. Throws a TypeError if the event class
1380 is already registered to a stream class.
1381 """
1382
1383 ret = nbt._bt_ctf_event_class_set_id(self._ec, id)
1384
1385 if ret < 0:
1386 raise TypeError("Can't change an Event Class's id after it has been assigned to a stream class")
1387
1388 @property
1389 def stream_class(self):
1390 """
1391 Get the event class' stream class. Returns None if unset.
1392 """
1393 stream_class_native = nbt._bt_ctf_event_class_get_stream_class(self._ec)
1394
1395 if stream_class_native is None:
1396 return None
1397
1398 stream_class = StreamClass.__new__(StreamClass)
1399 stream_class._sc = stream_class_native
1400
1401 return stream_class
1402
1403 @property
1404 def fields(self):
1405 """
1406 Generator returning the event class' fields as tuples of (field name, field declaration).
1407 """
1408
1409 count = nbt._bt_ctf_event_class_get_field_count(self._ec)
1410
1411 if count < 0:
1412 raise TypeError("Could not get EventClass' field count")
1413
1414 for i in range(count):
1415 field_name = nbt._bt_python_ctf_event_class_get_field_name(self._ec, i)
1416
1417 if field_name is None:
1418 msg = "Could not get EventClass' field name at index {}".format(i)
1419 raise TypeError(msg)
1420
1421 field_type_native = nbt._bt_python_ctf_event_class_get_field_type(self._ec, i)
1422
1423 if field_type_native is None:
1424 msg = "Could not get EventClass' field type at index {}".format(i)
1425 raise TypeError(msg)
1426
1427 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1428 yield (field_name, field_type)
1429
1430 def get_field_by_name(self, name):
1431 """
1432 Get a field declaration by name (FieldDeclaration).
1433 """
1434
1435 field_type_native = nbt._bt_ctf_event_class_get_field_by_name(self._ec, name)
1436
1437 if field_type_native is None:
1438 msg = "Could not find EventClass field with name {}".format(name)
1439 raise TypeError(msg)
1440
1441 return FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1442
1443
1444class Event:
1445 def __init__(self, event_class):
1446 """
1447 Create a new event of the given event class.
1448 """
1449
1450 if not isinstance(event_class, EventClass):
1451 raise TypeError("Invalid event_class argument.")
1452
1453 self._e = nbt._bt_ctf_event_create(event_class._ec)
1454
1455 if self._e is None:
1456 raise ValueError("Event creation failed.")
1457
1458 def __del__(self):
1459 nbt._bt_ctf_event_put(self._e)
1460
1461 @property
1462 def event_class(self):
1463 """
1464 Get the event's class.
1465 """
1466
1467 event_class_native = nbt._bt_ctf_event_get_class(self._e)
1468
1469 if event_class_native is None:
1470 return None
1471
1472 event_class = EventClass.__new__(EventClass)
1473 event_class._ec = event_class_native
1474
1475 return event_class
1476
1477 def clock(self):
1478 """
1479 Get a clock from event. Returns None if the event's class
1480 is not registered to a stream class.
1481 """
1482
1483 clock_instance = nbt._bt_ctf_event_get_clock(self._e)
1484
1485 if clock_instance is None:
1486 return None
1487
1488 clock = Clock.__new__(Clock)
1489 clock._c = clock_instance
1490
1491 return clock
1492
1493 def payload(self, field_name):
1494 """
1495 Get a field from event.
1496 """
1497
1498 native_instance = nbt._bt_ctf_event_get_payload(self._e,
1499 str(field_name))
1500
1501 if native_instance is None:
1502 raise ValueError("Could not get event payload.")
1503
1504 return Field._create_field_from_native_instance(native_instance)
1505
1506 def set_payload(self, field_name, value_field):
1507 """
1508 Set a manually created field as an event's payload.
1509 """
1510
1511 if not isinstance(value, Field):
1512 raise TypeError("Invalid value type.")
1513
1514 ret = nbt._bt_ctf_event_set_payload(self._e, str(field_name),
1515 value_field._f)
1516
1517 if ret < 0:
1518 raise ValueError("Could not set event field payload.")
1519
1520
1521class StreamClass:
1522 def __init__(self, name):
1523 """
1524 Create a new stream class of the given name.
1525 """
1526
1527 self._sc = nbt._bt_ctf_stream_class_create(name)
1528
1529 if self._sc is None:
1530 raise ValueError("Stream class creation failed.")
1531
1532 def __del__(self):
1533 nbt._bt_ctf_stream_class_put(self._sc)
1534
1535 @property
1536 def name(self):
1537 """
1538 Get a stream class' name.
1539 """
1540
1541 name = nbt._bt_ctf_stream_class_get_name(self._sc)
1542
1543 if name is None:
1544 raise TypeError("Could not get StreamClass name")
1545
1546 return name
1547
1548 @property
1549 def clock(self):
1550 """
1551 Get a stream class' clock.
1552 """
1553
1554 clock_instance = nbt._bt_ctf_stream_class_get_clock(self._sc)
1555
1556 if clock_instance is None:
1557 return None
1558
1559 clock = Clock.__new__(Clock)
1560 clock._c = clock_instance
1561
1562 return clock
1563
1564 @clock.setter
1565 def clock(self, clock):
1566 """
1567 Assign a clock to a stream class.
1568 """
1569
1570 if not isinstance(clock, Clock):
1571 raise TypeError("Invalid clock type.")
1572
1573 ret = nbt._bt_ctf_stream_class_set_clock(self._sc, clock._c)
1574
1575 if ret < 0:
1576 raise ValueError("Could not set stream class clock.")
1577
1578 @property
1579 def id(self):
1580 """
1581 Get a stream class' id.
1582 """
1583
1584 ret = nbt._bt_ctf_stream_class_get_id(self._sc)
1585
1586 if ret < 0:
1587 raise TypeError("Could not get StreamClass id")
1588
1589 return ret
1590
1591 @id.setter
1592 def id(self, id):
1593 """
1594 Assign an id to a stream class.
1595 """
1596
1597 ret = nbt._bt_ctf_stream_class_set_id(self._sc, id)
1598
1599 if ret < 0:
1600 raise TypeError("Could not set stream class id.")
1601
1602 @property
1603 def event_classes(self):
1604 """
1605 Generator returning the stream class' event classes.
1606 """
1607
1608 count = nbt._bt_ctf_stream_class_get_event_class_count(self._sc)
1609
1610 if count < 0:
1611 raise TypeError("Could not get StreamClass' event class count")
1612
1613 for i in range(count):
1614 event_class_native = nbt._bt_ctf_stream_class_get_event_class(self._sc, i)
1615
1616 if event_class_native is None:
1617 msg = "Could not get StreamClass' event class at index {}".format(i)
1618 raise TypeError(msg)
1619
1620 event_class = EventClass.__new__(EventClass)
1621 event_class._ec = event_class_native
1622 yield event_class
1623
1624 def add_event_class(self, event_class):
1625 """
1626 Add an event class to a stream class. New events can be added even after a
1627 stream has been instantiated and events have been appended. However, a stream
1628 will not accept events of a class that has not been added to the stream
1629 class beforehand.
1630 """
1631
1632 if not isinstance(event_class, EventClass):
1633 raise TypeError("Invalid event_class type.")
1634
1635 ret = nbt._bt_ctf_stream_class_add_event_class(self._sc,
1636 event_class._ec)
1637
1638 if ret < 0:
1639 raise ValueError("Could not add event class.")
1640
1641 @property
1642 def packet_context_type(self):
1643 """
1644 Get the StreamClass' packet context type (StructureFieldDeclaration)
1645 """
1646
1647 field_type_native = nbt._bt_ctf_stream_class_get_packet_context_type(self._sc)
1648
1649 if field_type_native is None:
1650 raise ValueError("Invalid StreamClass")
1651
1652 field_type = FieldDeclaration._create_field_declaration_from_native_instance(field_type_native)
1653
1654 return field_type
1655
1656 @packet_context_type.setter
1657 def packet_context_type(self, field_type):
1658 """
1659 Set a StreamClass' packet context type. Must be of type
1660 StructureFieldDeclaration.
1661 """
1662
1663 if not isinstance(field_type, StructureFieldDeclaration):
1664 raise TypeError("field_type argument must be of type StructureFieldDeclaration.")
1665
1666 ret = nbt._bt_ctf_stream_class_set_packet_context_type(self._sc,
1667 field_type._ft)
1668
1669 if ret < 0:
1670 raise ValueError("Failed to set packet context type.")
1671
1672
1673class Stream:
1674 def __init__(self):
1675 raise NotImplementedError("Stream cannot be instantiated; use Writer.create_stream()")
1676
1677 def __del__(self):
1678 nbt._bt_ctf_stream_put(self._s)
1679
1680 @property
1681 def discarded_events(self):
1682 """
1683 Get a stream's discarded event count.
1684 """
1685
1686 ret, count = nbt._bt_ctf_stream_get_discarded_events_count(self._s)
1687
1688 if ret < 0:
1689 raise ValueError("Could not get the stream's discarded events count")
1690
1691 return count
1692
1693 def append_discarded_events(self, event_count):
1694 """
1695 Increase the current packet's discarded event count.
1696 """
1697
1698 nbt._bt_ctf_stream_append_discarded_events(self._s, event_count)
1699
1700 def append_event(self, event):
1701 """
1702 Append "event" to the stream's current packet. The stream's associated clock
1703 will be sampled during this call. The event shall not be modified after
1704 being appended to a stream.
1705 """
1706
1707 ret = nbt._bt_ctf_stream_append_event(self._s, event._e)
1708
1709 if ret < 0:
1710 raise ValueError("Could not append event to stream.")
1711
1712 @property
1713 def packet_context(self):
1714 """
1715 Get a Stream's packet context field (a StructureField).
1716 """
1717
1718 native_field = nbt._bt_ctf_stream_get_packet_context(self._s)
1719
1720 if native_field is None:
1721 raise ValueError("Invalid Stream.")
1722
1723 return Field._create_field_from_native_instance(native_field)
1724
1725 @packet_context.setter
1726 def packet_context(self, field):
1727 """
1728 Set a Stream's packet context field (must be a StructureField).
1729 """
1730
1731 if not isinstance(field, StructureField):
1732 raise TypeError("Argument field must be of type StructureField")
1733
1734 ret = nbt._bt_ctf_stream_set_packet_context(self._s, field._f)
1735
1736 if ret < 0:
1737 raise ValueError("Invalid packet context field.")
1738
1739 def flush(self):
1740 """
1741 The stream's current packet's events will be flushed to disk. Events
1742 subsequently appended to the stream will be added to a new packet.
1743 """
1744
1745 ret = nbt._bt_ctf_stream_flush(self._s)
1746
1747 if ret < 0:
1748 raise ValueError("Could not flush stream.")
1749
1750
1751class Writer:
1752 def __init__(self, path):
1753 """
1754 Create a new writer that will produce a trace in the given path.
1755 """
1756
1757 self._w = nbt._bt_ctf_writer_create(path)
1758
1759 if self._w is None:
1760 raise ValueError("Writer creation failed.")
1761
1762 def __del__(self):
1763 nbt._bt_ctf_writer_put(self._w)
1764
1765 def create_stream(self, stream_class):
1766 """
1767 Create a new stream instance and register it to the writer.
1768 """
1769
1770 if not isinstance(stream_class, StreamClass):
1771 raise TypeError("Invalid stream_class type.")
1772
1773 stream = Stream.__new__(Stream)
1774 stream._s = nbt._bt_ctf_writer_create_stream(self._w, stream_class._sc)
1775
1776 return stream
1777
1778 def add_environment_field(self, name, value):
1779 """
1780 Add an environment field to the trace.
1781 """
1782
1783 ret = nbt._bt_ctf_writer_add_environment_field(self._w, str(name),
1784 str(value))
1785
1786 if ret < 0:
1787 raise ValueError("Could not add environment field to trace.")
1788
1789 def add_clock(self, clock):
1790 """
1791 Add a clock to the trace. Clocks assigned to stream classes must be
1792 registered to the writer.
1793 """
1794
1795 ret = nbt._bt_ctf_writer_add_clock(self._w, clock._c)
1796
1797 if ret < 0:
1798 raise ValueError("Could not add clock to Writer.")
1799
1800 @property
1801 def metadata(self):
1802 """
1803 Get the trace's TSDL meta-data.
1804 """
1805
1806 return nbt._bt_ctf_writer_get_metadata_string(self._w)
1807
1808 def flush_metadata(self):
1809 """
1810 Flush the trace's metadata to the metadata file.
1811 """
1812
1813 nbt._bt_ctf_writer_flush_metadata(self._w)
1814
1815 @property
1816 def byte_order(self):
1817 """
1818 Get the trace's byte order. Must be a constant from the ByteOrder
1819 class.
1820 """
1821
1822 raise NotImplementedError("Getter not implemented.")
1823
1824 @byte_order.setter
1825 def byte_order(self, byte_order):
1826 """
1827 Set the trace's byte order. Must be a constant from the ByteOrder
1828 class. Defaults to the host machine's endianness
1829 """
1830
1831 ret = nbt._bt_ctf_writer_set_byte_order(self._w, byte_order)
1832
1833 if ret < 0:
1834 raise ValueError("Could not set trace's byte order.")
This page took 0.101691 seconds and 4 git commands to generate.