1 # The MIT License (MIT)
3 # Copyright (c) 2017 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_field_class_from_ptr_and_get_ref(ptr
):
31 typeid
= native_bt
.field_class_get_type(ptr
)
32 return _FIELD_CLASS_TYPE_TO_OBJ
[typeid
]._create
_from
_ptr
_and
_get
_ref
(ptr
)
35 class _FieldClass(object._SharedObject
, metaclass
=abc
.ABCMeta
):
36 _get_ref
= staticmethod(native_bt
.field_class_get_ref
)
37 _put_ref
= staticmethod(native_bt
.field_class_put_ref
)
39 def __init__(self
, ptr
):
42 def __eq__(self
, other
):
43 if not isinstance(other
, self
.__class
__):
44 # not comparing apples to apples
47 if self
.addr
== other
.addr
:
50 ret
= native_bt
.field_class_compare(self
._ptr
, other
._ptr
)
51 utils
._handle
_ret
(ret
, "cannot compare field classes")
54 def _check_create_status(self
, ptr
):
56 raise bt2
.CreationError('cannot create {} field class object'.format(self
._NAME
.lower()))
59 ptr
= native_bt
.field_class_copy(self
._ptr
)
60 utils
._handle
_ptr
(ptr
, 'cannot copy {} field class object'.format(self
._NAME
.lower()))
61 return _create_from_ptr(ptr
)
63 def __deepcopy__(self
, memo
):
68 def __call__(self
, value
=None):
69 field_ptr
= native_bt
.field_create(self
._ptr
)
72 raise bt2
.CreationError('cannot create {} field object'.format(self
._NAME
.lower()))
74 field
= bt2
.field
._create
_from
_ptr
(field_ptr
)
77 if not isinstance(field
, (bt2
.field
._IntegerField
, bt2
.field
._FloatingPointNumberField
, bt2
.field
._StringField
)):
78 raise bt2
.Error('cannot assign an initial value to a {} field object'.format(field
._NAME
))
88 alignment
= native_bt
.field_class_get_alignment(self
._ptr
)
89 assert(alignment
>= 0)
93 def alignment(self
, alignment
):
94 utils
._check
_alignment
(alignment
)
95 ret
= native_bt
.field_class_set_alignment(self
._ptr
, alignment
)
96 utils
._handle
_ret
(ret
, "cannot set field class object's alignment")
101 def byte_order(self
):
102 bo
= native_bt
.field_class_get_byte_order(self
._ptr
)
107 def byte_order(self
, byte_order
):
108 utils
._check
_int
(byte_order
)
109 ret
= native_bt
.field_class_set_byte_order(self
._ptr
, byte_order
)
110 utils
._handle
_ret
(ret
, "cannot set field class object's byte order")
113 class _IntegerFieldClass(_FieldClass
):
115 def __init__(self
, size
, alignment
=None, byte_order
=None, is_signed
=None,
116 base
=None, encoding
=None, mapped_clock_class
=None):
117 utils
._check
_uint
64(size
)
120 raise ValueError('size is 0 bits')
122 ptr
= native_bt
.field_class_integer_create(size
)
123 self
._check
_create
_status
(ptr
)
124 super().__init
__(ptr
)
126 if alignment
is not None:
127 self
.alignment
= alignment
129 if byte_order
is not None:
130 self
.byte_order
= byte_order
132 if is_signed
is not None:
133 self
.is_signed
= is_signed
138 if encoding
is not None:
139 self
.encoding
= encoding
141 if mapped_clock_class
is not None:
142 self
.mapped_clock_class
= mapped_clock_class
146 size
= native_bt
.field_class_integer_get_size(self
._ptr
)
152 is_signed
= native_bt
.field_class_integer_is_signed(self
._ptr
)
153 assert(is_signed
>= 0)
157 def is_signed(self
, is_signed
):
158 utils
._check
_bool
(is_signed
)
159 ret
= native_bt
.field_class_integer_set_is_signed(self
._ptr
, int(is_signed
))
160 utils
._handle
_ret
(ret
, "cannot set integer field class object's signedness")
164 base
= native_bt
.field_class_integer_get_base(self
._ptr
)
169 def base(self
, base
):
170 utils
._check
_int
(base
)
171 ret
= native_bt
.field_class_integer_set_base(self
._ptr
, base
)
172 utils
._handle
_ret
(ret
, "cannot set integer field class object's base")
176 encoding
= native_bt
.field_class_integer_get_encoding(self
._ptr
)
177 assert(encoding
>= 0)
181 def encoding(self
, encoding
):
182 utils
._check
_int
(encoding
)
183 ret
= native_bt
.field_class_integer_set_encoding(self
._ptr
, encoding
)
184 utils
._handle
_ret
(ret
, "cannot set integer field class object's encoding")
187 def mapped_clock_class(self
):
188 ptr
= native_bt
.field_class_integer_get_mapped_clock_class(self
._ptr
)
193 return bt2
.ClockClass
._create
_from
_ptr
(ptr
)
195 @mapped_clock_class.setter
196 def mapped_clock_class(self
, clock_class
):
197 utils
._check
_type
(clock_class
, bt2
.ClockClass
)
198 ret
= native_bt
.field_class_integer_set_mapped_clock_class(self
._ptr
, clock_class
._ptr
)
199 utils
._handle
_ret
(ret
, "cannot set integer field class object's mapped clock class")
202 class _UnsignedIntegerFieldClass(_IntegerFieldClass
):
206 class _SignedIntegerFieldClass(_IntegerFieldClass
):
210 class UnsignedIntegerFieldClass(_UnsignedIntegerFieldClass
):
211 _NAME
= 'UnsignedInteger'
214 class SignedIntegerFieldClass(_SignedIntegerFieldClass
):
215 _NAME
= 'SignedInteger'
218 class RealFieldClass(_FieldClass
):
221 def __init__(self
, alignment
=None, byte_order
=None, exponent_size
=None,
223 ptr
= native_bt
.field_class_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
.field_class_floating_point_get_exponent_digits(self
._ptr
)
242 assert(exp_size
>= 0)
245 @exponent_size.setter
246 def exponent_size(self
, exponent_size
):
247 utils
._check
_uint
64(exponent_size
)
248 ret
= native_bt
.field_class_floating_point_set_exponent_digits(self
._ptr
, exponent_size
)
249 utils
._handle
_ret
(ret
, "cannot set floating point number field class object's exponent size")
252 def mantissa_size(self
):
253 mant_size
= native_bt
.field_class_floating_point_get_mantissa_digits(self
._ptr
)
254 assert(mant_size
>= 0)
257 @mantissa_size.setter
258 def mantissa_size(self
, mantissa_size
):
259 utils
._check
_uint
64(mantissa_size
)
260 ret
= native_bt
.field_class_floating_point_set_mantissa_digits(self
._ptr
, mantissa_size
)
261 utils
._handle
_ret
(ret
, "cannot set floating point number field class object's mantissa size")
264 class _EnumerationFieldClassMapping
:
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 _EnumerationFieldClassMappingIterator(object._SharedObject
,
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)
300 ret
= native_bt
.field_class_enumeration_mapping_iterator_next(self
._ptr
)
306 ret
, name
, lower
, upper
= native_bt
.field_class_enumeration_mapping_iterator_get_signed(self
._ptr
)
308 ret
, name
, lower
, upper
= native_bt
.field_class_enumeration_mapping_iterator_get_unsigned(self
._ptr
)
311 mapping
= _EnumerationFieldClassMapping(name
, lower
, upper
)
316 class EnumerationFieldClass(_IntegerFieldClass
, collections
.abc
.Sequence
):
317 _NAME
= 'Enumeration'
319 def __init__(self
, int_field_class
=None, size
=None, alignment
=None,
320 byte_order
=None, is_signed
=None, base
=None, encoding
=None,
321 mapped_clock_class
=None):
322 if int_field_class
is None:
323 int_field_class
= IntegerFieldClass(size
=size
, alignment
=alignment
,
324 byte_order
=byte_order
,
325 is_signed
=is_signed
, base
=base
,
327 mapped_clock_class
=mapped_clock_class
)
329 utils
._check
_type
(int_field_class
, IntegerFieldClass
)
330 ptr
= native_bt
.field_class_enumeration_create(int_field_class
._ptr
)
331 self
._check
_create
_status
(ptr
)
332 _FieldClass
.__init
__(self
, ptr
)
335 def integer_field_class(self
):
336 ptr
= native_bt
.field_class_enumeration_get_container_type(self
._ptr
)
338 return _create_from_ptr(ptr
)
342 return self
.integer_field_class
.size
346 return self
.integer_field_class
.alignment
349 def alignment(self
, alignment
):
350 self
.integer_field_class
.alignment
= alignment
353 def byte_order(self
):
354 return self
.integer_field_class
.byte_order
357 def byte_order(self
, byte_order
):
358 self
.integer_field_class
.byte_order
= byte_order
362 return self
.integer_field_class
.is_signed
365 def is_signed(self
, is_signed
):
366 self
.integer_field_class
.is_signed
= is_signed
370 return self
.integer_field_class
.base
373 def base(self
, base
):
374 self
.integer_field_class
.base
= base
378 return self
.integer_field_class
.encoding
381 def encoding(self
, encoding
):
382 self
.integer_field_class
.encoding
= encoding
385 def mapped_clock_class(self
):
386 return self
.integer_field_class
.mapped_clock_class
388 @mapped_clock_class.setter
389 def mapped_clock_class(self
, mapped_clock_class
):
390 self
.integer_field_class
.mapped_clock_class
= mapped_clock_class
393 count
= native_bt
.field_class_enumeration_get_mapping_count(self
._ptr
)
397 def __getitem__(self
, index
):
398 utils
._check
_uint
64(index
)
400 if index
>= len(self
):
404 get_fn
= native_bt
.field_class_enumeration_get_mapping_signed
406 get_fn
= native_bt
.field_class_enumeration_get_mapping_unsigned
408 ret
, name
, lower
, upper
= get_fn(self
._ptr
, index
)
410 return _EnumerationFieldClassMapping(name
, lower
, upper
)
412 def _get_mapping_iter(self
, iter_ptr
):
413 return _EnumerationFieldClassMappingIterator(iter_ptr
, self
.is_signed
)
415 def mappings_by_name(self
, name
):
416 utils
._check
_str
(name
)
417 iter_ptr
= native_bt
.field_class_enumeration_find_mappings_by_name(self
._ptr
, name
)
418 print('iter_ptr', iter_ptr
)
419 return self
._get
_mapping
_iter
(iter_ptr
)
421 def mappings_by_value(self
, value
):
423 utils
._check
_int
64(value
)
424 iter_ptr
= native_bt
.field_class_enumeration_find_mappings_by_signed_value(self
._ptr
, value
)
426 utils
._check
_uint
64(value
)
427 iter_ptr
= native_bt
.field_class_enumeration_find_mappings_by_unsigned_value(self
._ptr
, value
)
429 return self
._get
_mapping
_iter
(iter_ptr
)
431 def add_mapping(self
, name
, lower
, upper
=None):
432 utils
._check
_str
(name
)
438 add_fn
= native_bt
.field_class_enumeration_add_mapping_signed
439 utils
._check
_int
64(lower
)
440 utils
._check
_int
64(upper
)
442 add_fn
= native_bt
.field_class_enumeration_add_mapping_unsigned
443 utils
._check
_uint
64(lower
)
444 utils
._check
_uint
64(upper
)
446 ret
= add_fn(self
._ptr
, name
, lower
, upper
)
447 utils
._handle
_ret
(ret
, "cannot add mapping to enumeration field class object")
449 def __iadd__(self
, mappings
):
450 for mapping
in mappings
:
451 self
.add_mapping(mapping
.name
, mapping
.lower
, mapping
.upper
)
456 class StringFieldClass(_FieldClass
):
459 def __init__(self
, encoding
=None):
460 ptr
= native_bt
.field_class_string_create()
461 self
._check
_create
_status
(ptr
)
462 super().__init
__(ptr
)
464 if encoding
is not None:
465 self
.encoding
= encoding
469 encoding
= native_bt
.field_class_string_get_encoding(self
._ptr
)
470 assert(encoding
>= 0)
474 def encoding(self
, encoding
):
475 utils
._check
_int
(encoding
)
476 ret
= native_bt
.field_class_string_set_encoding(self
._ptr
, encoding
)
477 utils
._handle
_ret
(ret
, "cannot set string field class object's encoding")
480 class _FieldContainer(collections
.abc
.Mapping
):
482 count
= self
._count
()
486 def __getitem__(self
, key
):
487 if not isinstance(key
, str):
488 raise TypeError("'{}' is not a 'str' object".format(key
.__class
__.__name
__))
490 ptr
= self
._get
_field
_by
_name
(key
)
495 return _create_from_ptr(ptr
)
498 return self
._ITER
_CLS
(self
)
500 def append_field(self
, name
, field_class
):
501 utils
._check
_str
(name
)
502 utils
._check
_type
(field_class
, _FieldClass
)
503 ret
= self
._add
_field
(name
, field_class
._ptr
)
504 utils
._handle
_ret
(ret
, "cannot add field to {} field class object".format(self
._NAME
.lower()))
506 def __iadd__(self
, fields
):
507 for name
, field_class
in fields
.items():
508 self
.append_field(name
, field_class
)
512 def at_index(self
, index
):
513 utils
._check
_uint
64(index
)
514 return self
._at
(index
)
517 class _StructureFieldClassFieldIterator(collections
.abc
.Iterator
):
518 def __init__(self
, struct_field_class
):
519 self
._struct
_field
_class
= struct_field_class
523 if self
._at
== len(self
._struct
_field
_class
):
526 get_fc_by_index
= native_bt
.field_class_structure_get_field_by_index
527 ret
, name
, field_class_ptr
= get_fc_by_index(self
._struct
_field
_class
._ptr
,
530 native_bt
.put(field_class_ptr
)
535 class _StructureFieldClass(_FieldClass
, _FieldContainer
, _AlignmentProp
):
537 _ITER_CLS
= _StructureFieldClassFieldIterator
539 def __init__(self
, min_alignment
=None):
540 ptr
= native_bt
.field_class_structure_create()
541 self
._check
_create
_status
(ptr
)
542 super().__init
__(ptr
)
544 if min_alignment
is not None:
545 self
.min_alignment
= min_alignment
548 return native_bt
.field_class_structure_get_field_count(self
._ptr
)
550 def _get_field_by_name(self
, key
):
551 return native_bt
.field_class_structure_get_field_class_by_name(self
._ptr
, key
)
553 def _add_field(self
, name
, ptr
):
554 return native_bt
.field_class_structure_append_member(self
._ptr
, name
, ptr
)
556 def _at(self
, index
):
557 if index
< 0 or index
>= len(self
):
560 ret
, name
, field_class_ptr
= native_bt
.field_class_structure_get_field_by_index(self
._ptr
, index
)
562 return _create_from_ptr(field_class_ptr
)
565 _StructureFieldClass
.min_alignment
= property(fset
=_StructureFieldClass
.alignment
.fset
)
566 _StructureFieldClass
.alignment
= property(fget
=_StructureFieldClass
.alignment
.fget
)
569 class _VariantFieldClassFieldIterator(collections
.abc
.Iterator
):
570 def __init__(self
, variant_field_class
):
571 self
._variant
_field
_class
= variant_field_class
575 if self
._at
== len(self
._variant
_field
_class
):
578 ret
, name
, field_class_ptr
= native_bt
.field_class_variant_get_field_by_index(self
._variant
_field
_class
._ptr
,
581 native_bt
.put(field_class_ptr
)
586 class VariantFieldClass(_FieldClass
, _FieldContainer
, _AlignmentProp
):
588 _ITER_CLS
= _VariantFieldClassFieldIterator
590 def __init__(self
, tag_name
, tag_field_class
=None):
591 utils
._check
_str
(tag_name
)
593 if tag_field_class
is None:
596 utils
._check
_type
(tag_field_class
, EnumerationFieldClass
)
597 tag_fc_ptr
= tag_field_class
._ptr
599 ptr
= native_bt
.field_class_variant_create(tag_fc_ptr
,
601 self
._check
_create
_status
(ptr
)
602 super().__init
__(ptr
)
606 tag_name
= native_bt
.field_class_variant_get_tag_name(self
._ptr
)
607 assert(tag_name
is not None)
611 def tag_name(self
, tag_name
):
612 utils
._check
_str
(tag_name
)
613 ret
= native_bt
.field_class_variant_set_tag_name(self
._ptr
, tag_name
)
614 utils
._handle
_ret
(ret
, "cannot set variant field class object's tag name")
617 def tag_field_class(self
):
618 fc_ptr
= native_bt
.field_class_variant_get_tag_type(self
._ptr
)
623 return _create_from_ptr(fc_ptr
)
626 return native_bt
.field_class_variant_get_field_count(self
._ptr
)
628 def _get_field_by_name(self
, key
):
629 return native_bt
.field_class_variant_get_field_class_by_name(self
._ptr
, key
)
631 def _add_field(self
, ptr
, name
):
632 return native_bt
.field_class_variant_add_field(self
._ptr
, ptr
, name
)
634 def _at(self
, index
):
635 if index
< 0 or index
>= len(self
):
638 ret
, name
, field_class_ptr
= native_bt
.field_class_variant_get_field_by_index(self
._ptr
, index
)
640 return _create_from_ptr(field_class_ptr
)
643 class ArrayFieldClass(_FieldClass
):
646 def __init__(self
, element_field_class
, length
):
647 utils
._check
_type
(element_field_class
, _FieldClass
)
648 utils
._check
_uint
64(length
)
649 ptr
= native_bt
.field_class_array_create(element_field_class
._ptr
, length
)
650 self
._check
_create
_status
(ptr
)
651 super().__init
__(ptr
)
655 length
= native_bt
.field_class_array_get_length(self
._ptr
)
660 def element_field_class(self
):
661 ptr
= native_bt
.field_class_array_get_element_type(self
._ptr
)
663 return _create_from_ptr(ptr
)
666 class SequenceFieldClass(_FieldClass
):
669 def __init__(self
, element_field_class
, length_name
):
670 utils
._check
_type
(element_field_class
, _FieldClass
)
671 utils
._check
_str
(length_name
)
672 ptr
= native_bt
.field_class_sequence_create(element_field_class
._ptr
,
674 self
._check
_create
_status
(ptr
)
675 super().__init
__(ptr
)
678 def length_name(self
):
679 length_name
= native_bt
.field_class_sequence_get_length_field_name(self
._ptr
)
680 assert(length_name
is not None)
684 def element_field_class(self
):
685 ptr
= native_bt
.field_class_sequence_get_element_type(self
._ptr
)
687 return _create_from_ptr(ptr
)
690 _FIELD_CLASS_TYPE_TO_OBJ
= {
691 native_bt
.FIELD_CLASS_TYPE_STRUCTURE
: _StructureFieldClass
,