1 # The MIT License (MIT)
3 # Copyright (c) 2016 Philippe Proulx <pproulx@efficios.com>
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 from bt2
import native_bt
, object, utils
24 import collections
.abc
30 def _create_from_ptr(ptr
):
31 typeid
= native_bt
.ctf_field_type_get_type_id(ptr
)
32 return _TYPE_ID_TO_OBJ
[typeid
]._create
_from
_ptr
(ptr
)
35 class _FieldType(object._Object
, metaclass
=abc
.ABCMeta
):
36 def __init__(self
, ptr
):
39 def __eq__(self
, other
):
40 if not isinstance(other
, self
.__class
__):
41 # not comparing apples to apples
44 if self
.addr
== other
.addr
:
47 ret
= native_bt
.ctf_field_type_compare(self
._ptr
, other
._ptr
)
48 utils
._handle
_ret
(ret
, "cannot compare field types")
51 def _check_create_status(self
, ptr
):
53 raise bt2
.CreationError('cannot create {} field type object'.format(self
._NAME
.lower()))
56 ptr
= native_bt
.ctf_field_type_copy(self
._ptr
)
57 utils
._handle
_ptr
(ptr
, 'cannot copy {} field type object'.format(self
._NAME
.lower()))
58 return _create_from_ptr(ptr
)
60 def __deepcopy__(self
, memo
):
65 def __call__(self
, value
=None):
66 field_ptr
= native_bt
.ctf_field_create(self
._ptr
)
69 raise bt2
.CreationError('cannot create {} field object'.format(self
._NAME
.lower()))
71 field
= bt2
.fields
._create
_from
_ptr
(field_ptr
)
74 if not isinstance(field
, (bt2
.fields
._IntegerField
, bt2
.fields
._FloatingPointNumberField
, bt2
.fields
._StringField
)):
75 raise bt2
.Error('cannot assign an initial value to a {} field object'.format(field
._NAME
))
83 NATIVE
= native_bt
.CTF_BYTE_ORDER_NATIVE
84 LITTLE_ENDIAN
= native_bt
.CTF_BYTE_ORDER_LITTLE_ENDIAN
85 BIG_ENDIAN
= native_bt
.CTF_BYTE_ORDER_BIG_ENDIAN
86 NETWORK
= native_bt
.CTF_BYTE_ORDER_NETWORK
90 NONE
= native_bt
.CTF_STRING_ENCODING_NONE
91 UTF8
= native_bt
.CTF_STRING_ENCODING_UTF8
92 ASCII
= native_bt
.CTF_STRING_ENCODING_ASCII
96 BINARY
= native_bt
.CTF_INTEGER_BASE_BINARY
97 OCTAL
= native_bt
.CTF_INTEGER_BASE_OCTAL
98 DECIMAL
= native_bt
.CTF_INTEGER_BASE_DECIMAL
99 HEXADECIMAL
= native_bt
.CTF_INTEGER_BASE_HEXADECIMAL
102 class _AlignmentProp
:
105 alignment
= native_bt
.ctf_field_type_get_alignment(self
._ptr
)
106 utils
._handle
_ret
(alignment
, "cannot get field type object's alignment")
110 def alignment(self
, alignment
):
111 utils
._check
_alignment
(alignment
)
112 ret
= native_bt
.ctf_field_type_set_alignment(self
._ptr
, alignment
)
113 utils
._handle
_ret
(ret
, "cannot set field type object's alignment")
116 class _ByteOrderProp
:
118 def byte_order(self
):
119 bo
= native_bt
.ctf_field_type_get_byte_order(self
._ptr
)
120 utils
._handle
_ret
(bo
, "cannot get field type object's byte order")
124 def byte_order(self
, byte_order
):
125 utils
._check
_int
(byte_order
)
126 ret
= native_bt
.ctf_field_type_set_byte_order(self
._ptr
, byte_order
)
127 utils
._handle
_ret
(ret
, "cannot set field type object's byte order")
130 class IntegerFieldType(_FieldType
, _AlignmentProp
, _ByteOrderProp
):
133 def __init__(self
, size
, alignment
=None, byte_order
=None, is_signed
=None,
134 base
=None, encoding
=None, mapped_clock_class
=None):
135 utils
._check
_uint
64(size
)
138 raise ValueError('size is 0 bits')
140 ptr
= native_bt
.ctf_field_type_integer_create(size
)
141 self
._check
_create
_status
(ptr
)
142 super().__init
__(ptr
)
144 if alignment
is not None:
145 self
.alignment
= alignment
147 if byte_order
is not None:
148 self
.byte_order
= byte_order
150 if is_signed
is not None:
151 self
.is_signed
= is_signed
156 if encoding
is not None:
157 self
.encoding
= encoding
159 if mapped_clock_class
is not None:
160 self
.mapped_clock_class
= mapped_clock_class
164 size
= native_bt
.ctf_field_type_integer_get_size(self
._ptr
)
165 utils
._handle
_ret
(size
, "cannot get integer field type object's size")
170 is_signed
= native_bt
.ctf_field_type_integer_get_signed(self
._ptr
)
171 utils
._handle
_ret
(is_signed
,
172 "cannot get integer field type object's signedness")
176 def is_signed(self
, is_signed
):
177 utils
._check
_bool
(is_signed
)
178 ret
= native_bt
.ctf_field_type_integer_set_signed(self
._ptr
, int(is_signed
))
179 utils
._handle
_ret
(ret
, "cannot set integer field type object's signedness")
183 base
= native_bt
.ctf_field_type_integer_get_base(self
._ptr
)
184 utils
._handle
_ret
(base
, "cannot get integer field type object's base")
188 def base(self
, base
):
189 utils
._check
_int
(base
)
190 ret
= native_bt
.ctf_field_type_integer_set_base(self
._ptr
, base
)
191 utils
._handle
_ret
(ret
, "cannot set integer field type object's base")
195 encoding
= native_bt
.ctf_field_type_integer_get_encoding(self
._ptr
)
196 utils
._handle
_ret
(encoding
, "cannot get integer field type object's encoding")
200 def encoding(self
, encoding
):
201 utils
._check
_int
(encoding
)
202 ret
= native_bt
.ctf_field_type_integer_set_encoding(self
._ptr
, encoding
)
203 utils
._handle
_ret
(ret
, "cannot set integer field type object's encoding")
206 def mapped_clock_class(self
):
207 ptr
= native_bt
.ctf_field_type_integer_get_mapped_clock_class(self
._ptr
)
208 utils
._handle
_ptr
(ptr
, "cannot get integer field type object's mapped clock class")
209 return bt2
.ClockClass
._create
_from
_ptr
(ptr
)
211 @mapped_clock_class.setter
212 def mapped_clock_class(self
, clock_class
):
213 utils
._check
_type
(clock_class
, bt2
.ClockClass
)
214 ret
= native_bt
.ctf_field_type_integer_set_mapped_clock_class(self
._ptr
, clock_class
._ptr
)
215 utils
._handle
_ret
(ret
, "cannot set integer field type object's mapped clock class")
218 class FloatingPointNumberFieldType(_FieldType
, _AlignmentProp
, _ByteOrderProp
):
219 _NAME
= 'Floating point number'
221 def __init__(self
, alignment
=None, byte_order
=None, exponent_size
=None,
223 ptr
= native_bt
.ctf_field_type_floating_point_create()
224 self
._check
_create
_status
(ptr
)
225 super().__init
__(ptr
)
227 if alignment
is not None:
228 self
.alignment
= alignment
230 if byte_order
is not None:
231 self
.byte_order
= byte_order
233 if exponent_size
is not None:
234 self
.exponent_size
= exponent_size
236 if mantissa_size
is not None:
237 self
.mantissa_size
= mantissa_size
240 def exponent_size(self
):
241 exp_size
= native_bt
.ctf_field_type_floating_point_get_exponent_digits(self
._ptr
)
242 utils
._handle
_ret
(exp_size
, "cannot get floating point number field type object's exponent size")
245 @exponent_size.setter
246 def exponent_size(self
, exponent_size
):
247 utils
._check
_uint
64(exponent_size
)
248 ret
= native_bt
.ctf_field_type_floating_point_set_exponent_digits(self
._ptr
, exponent_size
)
249 utils
._handle
_ret
(ret
, "cannot set floating point number field type object's exponent size")
252 def mantissa_size(self
):
253 exp_size
= native_bt
.ctf_field_type_floating_point_get_mantissa_digits(self
._ptr
)
254 utils
._handle
_ret
(exp_size
, "cannot get floating point number field type object's mantissa size")
257 @mantissa_size.setter
258 def mantissa_size(self
, mantissa_size
):
259 utils
._check
_uint
64(mantissa_size
)
260 ret
= native_bt
.ctf_field_type_floating_point_set_mantissa_digits(self
._ptr
, mantissa_size
)
261 utils
._handle
_ret
(ret
, "cannot set floating point number field type object's mantissa size")
264 class _EnumerationFieldTypeMapping
:
265 def __init__(self
, name
, lower
, upper
):
282 def __eq__(self
, other
):
283 if type(other
) is not self
.__class
__:
286 return (self
.name
, self
.lower
, self
.upper
) == (other
.name
, other
.lower
, other
.upper
)
289 class _EnumerationFieldTypeMappingIterator(object._Object
,
290 collections
.abc
.Iterator
):
291 def __init__(self
, iter_ptr
, is_signed
):
292 super().__init
__(iter_ptr
)
293 self
._is
_signed
= is_signed
294 self
._done
= (iter_ptr
is None)
301 ret
, name
, lower
, upper
= native_bt
.ctf_field_type_enumeration_mapping_iterator_get_signed(self
._ptr
)
303 ret
, name
, lower
, upper
= native_bt
.ctf_field_type_enumeration_mapping_iterator_get_unsigned(self
._ptr
)
305 utils
._handle
_ret
(ret
, "cannot get enumeration field type mapping iterator object's current mapping")
306 mapping
= _EnumerationFieldTypeMapping(name
, lower
, upper
)
307 ret
= native_bt
.ctf_field_type_enumeration_mapping_iterator_next(self
._ptr
)
315 class EnumerationFieldType(IntegerFieldType
, collections
.abc
.Sequence
):
316 _NAME
= 'Enumeration'
318 def __init__(self
, int_field_type
=None, size
=None, alignment
=None,
319 byte_order
=None, is_signed
=None, base
=None, encoding
=None,
320 mapped_clock_class
=None):
321 if int_field_type
is None:
322 int_field_type
= IntegerFieldType(size
=size
, alignment
=alignment
,
323 byte_order
=byte_order
,
324 is_signed
=is_signed
, base
=base
,
326 mapped_clock_class
=mapped_clock_class
)
328 utils
._check
_type
(int_field_type
, IntegerFieldType
)
329 ptr
= native_bt
.ctf_field_type_enumeration_create(int_field_type
._ptr
)
330 self
._check
_create
_status
(ptr
)
331 _FieldType
.__init
__(self
, ptr
)
334 def integer_field_type(self
):
335 ptr
= native_bt
.ctf_field_type_enumeration_get_container_type(self
._ptr
)
336 utils
._handle
_ptr
(ptr
, "cannot get enumeration field type object's integer field type")
337 return _create_from_ptr(ptr
)
341 return self
.integer_field_type
.size
345 return self
.integer_field_type
.alignment
348 def alignment(self
, alignment
):
349 self
.integer_field_type
.alignment
= alignment
352 def byte_order(self
):
353 return self
.integer_field_type
.byte_order
356 def byte_order(self
, byte_order
):
357 self
.integer_field_type
.byte_order
= byte_order
361 return self
.integer_field_type
.is_signed
364 def is_signed(self
, is_signed
):
365 self
.integer_field_type
.is_signed
= is_signed
369 return self
.integer_field_type
.base
372 def base(self
, base
):
373 self
.integer_field_type
.base
= base
377 return self
.integer_field_type
.encoding
380 def encoding(self
, encoding
):
381 self
.integer_field_type
.encoding
= encoding
384 def mapped_clock_class(self
):
385 return self
.integer_field_type
.mapped_clock_class
387 @mapped_clock_class.setter
388 def mapped_clock_class(self
, mapped_clock_class
):
389 self
.integer_field_type
.mapped_clock_class
= mapped_clock_class
392 count
= native_bt
.ctf_field_type_enumeration_get_mapping_count(self
._ptr
)
393 utils
._handle
_ret
(count
, "cannot get enumeration field type object's mapping count")
396 def __getitem__(self
, index
):
397 utils
._check
_uint
64(index
)
399 if index
>= len(self
):
403 get_fn
= native_bt
.ctf_field_type_enumeration_get_mapping_signed
405 get_fn
= native_bt
.ctf_field_type_enumeration_get_mapping_unsigned
407 ret
, name
, lower
, upper
= get_fn(self
._ptr
, index
)
408 utils
._handle
_ret
(ret
, "cannot get enumeration field type object's mapping")
409 return _EnumerationFieldTypeMapping(name
, lower
, upper
)
411 def _get_mapping_iter(self
, iter_ptr
):
412 return _EnumerationFieldTypeMappingIterator(iter_ptr
, self
.is_signed
)
414 def mappings_by_name(self
, name
):
415 utils
._check
_str
(name
)
416 iter_ptr
= native_bt
.ctf_field_type_enumeration_find_mappings_by_name(self
._ptr
, name
)
417 return self
._get
_mapping
_iter
(iter_ptr
)
419 def mappings_by_value(self
, value
):
421 utils
._check
_int
64(value
)
422 iter_ptr
= native_bt
.ctf_field_type_enumeration_find_mappings_by_signed_value(self
._ptr
, value
)
424 utils
._check
_uint
64(value
)
425 iter_ptr
= native_bt
.ctf_field_type_enumeration_find_mappings_by_unsigned_value(self
._ptr
, value
)
427 return self
._get
_mapping
_iter
(iter_ptr
)
429 def append_mapping(self
, name
, lower
, upper
=None):
430 utils
._check
_str
(name
)
436 add_fn
= native_bt
.ctf_field_type_enumeration_add_mapping
437 utils
._check
_int
64(lower
)
438 utils
._check
_int
64(upper
)
440 add_fn
= native_bt
.ctf_field_type_enumeration_add_mapping_unsigned
441 utils
._check
_uint
64(lower
)
442 utils
._check
_uint
64(upper
)
444 ret
= add_fn(self
._ptr
, name
, lower
, upper
)
445 utils
._handle
_ret
(ret
, "cannot add mapping to enumeration field type object")
447 def __iadd__(self
, mappings
):
448 for mapping
in mappings
:
449 self
.append_mapping(mapping
.name
, mapping
.lower
, mapping
.upper
)
454 class StringFieldType(_FieldType
):
457 def __init__(self
, encoding
=None):
458 ptr
= native_bt
.ctf_field_type_string_create()
459 self
._check
_create
_status
(ptr
)
460 super().__init
__(ptr
)
462 if encoding
is not None:
463 self
.encoding
= encoding
467 encoding
= native_bt
.ctf_field_type_string_get_encoding(self
._ptr
)
468 utils
._handle
_ret
(encoding
, "cannot get string field type object's encoding")
472 def encoding(self
, encoding
):
473 utils
._check
_int
(encoding
)
474 ret
= native_bt
.ctf_field_type_string_set_encoding(self
._ptr
, encoding
)
475 utils
._handle
_ret
(ret
, "cannot set string field type object's encoding")
478 class _FieldContainer(collections
.abc
.Mapping
):
480 count
= self
._count
()
481 utils
._handle
_ret
(count
, "cannot get {} field type object's field count".format(self
._NAME
.lower()))
484 def __getitem__(self
, key
):
485 if not isinstance(key
, str):
486 raise TypeError("'{}' is not a 'str' object".format(key
.__class
__.__name
__))
488 ptr
= self
._get
_field
_by
_name
(key
)
493 return _create_from_ptr(ptr
)
496 return self
._ITER
_CLS
(self
)
498 def append_field(self
, name
, field_type
):
499 utils
._check
_str
(name
)
500 utils
._check
_type
(field_type
, _FieldType
)
501 ret
= self
._add
_field
(field_type
._ptr
, name
)
502 utils
._handle
_ret
(ret
, "cannot add field to {} field type object".format(self
._NAME
.lower()))
504 def __iadd__(self
, fields
):
505 for name
, field_type
in fields
.items():
506 self
.append_field(name
, field_type
)
510 def at_index(self
, index
):
511 utils
._check
_uint
64(index
)
512 return self
._at
(index
)
515 class _StructureFieldTypeFieldIterator(collections
.abc
.Iterator
):
516 def __init__(self
, struct_field_type
):
517 self
._struct
_field
_type
= struct_field_type
521 if self
._at
== len(self
._struct
_field
_type
):
524 ret
, name
, field_type_ptr
= native_bt
.ctf_field_type_structure_get_field(self
._struct
_field
_type
._ptr
, self
._at
)
525 utils
._handle
_ret
(ret
, "cannot get structure field type object's field")
526 native_bt
.put(field_type_ptr
)
531 class StructureFieldType(_FieldType
, _FieldContainer
, _AlignmentProp
):
533 _ITER_CLS
= _StructureFieldTypeFieldIterator
535 def __init__(self
, min_alignment
=None):
536 ptr
= native_bt
.ctf_field_type_structure_create()
537 self
._check
_create
_status
(ptr
)
538 super().__init
__(ptr
)
540 if min_alignment
is not None:
541 self
.min_alignment
= min_alignment
544 return native_bt
.ctf_field_type_structure_get_field_count(self
._ptr
)
546 def _get_field_by_name(self
, key
):
547 return native_bt
.ctf_field_type_structure_get_field_type_by_name(self
._ptr
, key
)
549 def _add_field(self
, ptr
, name
):
550 return native_bt
.ctf_field_type_structure_add_field(self
._ptr
, ptr
,
553 def _at(self
, index
):
554 ret
, name
, field_type_ptr
= native_bt
.ctf_field_type_structure_get_field(self
._ptr
, index
)
555 utils
._handle
_ret
(ret
, "cannot get structure field type object's field")
556 return _create_from_ptr(field_type_ptr
)
559 StructureFieldType
.min_alignment
= property(fset
=StructureFieldType
.alignment
.fset
)
560 StructureFieldType
.alignment
= property(fget
=StructureFieldType
.alignment
.fget
)
563 class _VariantFieldTypeFieldIterator(collections
.abc
.Iterator
):
564 def __init__(self
, variant_field_type
):
565 self
._variant
_field
_type
= variant_field_type
569 if self
._at
== len(self
._variant
_field
_type
):
572 ret
, name
, field_type_ptr
= native_bt
.ctf_field_type_variant_get_field(self
._variant
_field
_type
._ptr
, self
._at
)
573 utils
._handle
_ret
(ret
, "cannot get variant field type object's field")
574 native_bt
.put(field_type_ptr
)
579 class VariantFieldType(_FieldType
, _FieldContainer
, _AlignmentProp
):
581 _ITER_CLS
= _VariantFieldTypeFieldIterator
583 def __init__(self
, tag_name
):
584 utils
._check
_str
(tag_name
)
585 ptr
= native_bt
.ctf_field_type_variant_create(None, tag_name
)
586 self
._check
_create
_status
(ptr
)
587 super().__init
__(ptr
)
591 tag_name
= native_bt
.ctf_field_type_variant_get_tag_name(self
._ptr
)
592 utils
._handle
_ptr
(tag_name
, "cannot get variant field type object's tag name")
596 def tag_name(self
, tag_name
):
597 utils
._check
_str
(tag_name
)
598 ret
= native_bt
.ctf_field_type_variant_set_tag_name(self
._ptr
, tag_name
)
599 utils
._handle
_ret
(ret
, "cannot set variant field type object's tag name")
602 return native_bt
.ctf_field_type_variant_get_field_count(self
._ptr
)
604 def _get_field_by_name(self
, key
):
605 return native_bt
.ctf_field_type_variant_get_field_type_by_name(self
._ptr
, key
)
607 def _add_field(self
, ptr
, name
):
608 return native_bt
.ctf_field_type_variant_add_field(self
._ptr
, ptr
, name
)
610 def _at(self
, index
):
611 ret
, name
, field_type_ptr
= native_bt
.ctf_field_type_variant_get_field(self
._ptr
, index
)
612 utils
._handle
_ret
(ret
, "cannot get variant field type object's field")
613 return _create_from_ptr(field_type_ptr
)
616 class ArrayFieldType(_FieldType
):
619 def __init__(self
, element_field_type
, length
):
620 utils
._check
_type
(element_field_type
, _FieldType
)
621 utils
._check
_uint
64(length
)
622 ptr
= native_bt
.ctf_field_type_array_create(element_field_type
._ptr
, length
)
623 self
._check
_create
_status
(ptr
)
624 super().__init
__(ptr
)
628 length
= native_bt
.ctf_field_type_array_get_length(self
._ptr
)
629 utils
._handle
_ret
(length
, "cannot get array field type object's length")
633 def element_field_type(self
):
634 ptr
= native_bt
.ctf_field_type_array_get_element_type(self
._ptr
)
635 utils
._handle
_ptr
(ptr
, "cannot get array field type object's element field type")
636 return _create_from_ptr(ptr
)
639 class SequenceFieldType(_FieldType
):
642 def __init__(self
, element_field_type
, length_name
):
643 utils
._check
_type
(element_field_type
, _FieldType
)
644 utils
._check
_str
(length_name
)
645 ptr
= native_bt
.ctf_field_type_sequence_create(element_field_type
._ptr
,
647 self
._check
_create
_status
(ptr
)
648 super().__init
__(ptr
)
651 def length_name(self
):
652 length_name
= native_bt
.ctf_field_type_sequence_get_length_field_name(self
._ptr
)
653 utils
._handle
_ptr
(length_name
, "cannot get sequence field type object's length name")
657 def element_field_type(self
):
658 ptr
= native_bt
.ctf_field_type_sequence_get_element_type(self
._ptr
)
659 utils
._handle
_ptr
(ptr
, "cannot get sequence field type object's element field type")
660 return _create_from_ptr(ptr
)
664 native_bt
.CTF_TYPE_ID_INTEGER
: IntegerFieldType
,
665 native_bt
.CTF_TYPE_ID_FLOAT
: FloatingPointNumberFieldType
,
666 native_bt
.CTF_TYPE_ID_ENUM
: EnumerationFieldType
,
667 native_bt
.CTF_TYPE_ID_STRING
: StringFieldType
,
668 native_bt
.CTF_TYPE_ID_STRUCT
: StructureFieldType
,
669 native_bt
.CTF_TYPE_ID_ARRAY
: ArrayFieldType
,
670 native_bt
.CTF_TYPE_ID_SEQUENCE
: SequenceFieldType
,
671 native_bt
.CTF_TYPE_ID_VARIANT
: VariantFieldType
,
672 native_bt
.CTF_TYPE_ID_UNTAGGED_VARIANT
: VariantFieldType
,