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
25 from bt2
import field_path
as bt2_field_path
26 from bt2
import integer_range_set
as bt2_integer_range_set
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 IntegerDisplayBase
:
36 BINARY
= native_bt
.FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_BINARY
37 OCTAL
= native_bt
.FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_OCTAL
38 DECIMAL
= native_bt
.FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_DECIMAL
39 HEXADECIMAL
= native_bt
.FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
42 class _FieldClass(object._SharedObject
):
43 _get_ref
= staticmethod(native_bt
.field_class_get_ref
)
44 _put_ref
= staticmethod(native_bt
.field_class_put_ref
)
46 def _check_create_status(self
, ptr
):
48 raise bt2
._MemoryError(
49 'cannot create {} field class object'.format(self
._NAME
.lower())
53 class _BoolFieldClass(_FieldClass
):
57 class _BitArrayFieldClass(_FieldClass
):
62 length
= native_bt
.field_class_bit_array_get_length(self
._ptr
)
67 class _IntegerFieldClass(_FieldClass
):
69 def field_value_range(self
):
70 size
= native_bt
.field_class_integer_get_field_value_range(self
._ptr
)
74 def _field_value_range(self
, size
):
75 if size
< 1 or size
> 64:
76 raise ValueError("Value is outside valid range [1, 64] ({})".format(size
))
77 native_bt
.field_class_integer_set_field_value_range(self
._ptr
, size
)
79 _field_value_range
= property(fset
=_field_value_range
)
82 def preferred_display_base(self
):
83 base
= native_bt
.field_class_integer_get_preferred_display_base(self
._ptr
)
87 def _preferred_display_base(self
, base
):
88 utils
._check
_uint
64(base
)
91 IntegerDisplayBase
.BINARY
,
92 IntegerDisplayBase
.OCTAL
,
93 IntegerDisplayBase
.DECIMAL
,
94 IntegerDisplayBase
.HEXADECIMAL
,
96 raise ValueError("Display base is not a valid IntegerDisplayBase value")
98 native_bt
.field_class_integer_set_preferred_display_base(self
._ptr
, base
)
100 _preferred_display_base
= property(fset
=_preferred_display_base
)
103 class _UnsignedIntegerFieldClass(_IntegerFieldClass
):
104 _NAME
= 'Unsigned integer'
107 class _SignedIntegerFieldClass(_IntegerFieldClass
):
108 _NAME
= 'Signed integer'
111 class _RealFieldClass(_FieldClass
):
115 def is_single_precision(self
):
116 return native_bt
.field_class_real_is_single_precision(self
._ptr
)
118 def _is_single_precision(self
, is_single_precision
):
119 utils
._check
_bool
(is_single_precision
)
120 native_bt
.field_class_real_set_is_single_precision(
121 self
._ptr
, is_single_precision
124 _is_single_precision
= property(fset
=_is_single_precision
)
127 # an enumeration field class mapping does not have a reference count, so
128 # we copy the properties here to avoid eventual memory access errors.
129 class _EnumerationFieldClassMapping
:
130 def __init__(self
, mapping_ptr
):
131 base_mapping_ptr
= self
._as
_enumeration
_field
_class
_mapping
_ptr
(mapping_ptr
)
132 self
._label
= native_bt
.field_class_enumeration_mapping_get_label(
135 assert self
._label
is not None
136 ranges_ptr
= self
._mapping
_borrow
_ranges
_ptr
(mapping_ptr
)
137 assert ranges_ptr
is not None
138 self
._ranges
= self
._ranges
_type
._create
_from
_ptr
_and
_get
_ref
(ranges_ptr
)
149 class _UnsignedEnumerationFieldClassMapping(_EnumerationFieldClassMapping
):
150 _ranges_type
= bt2_integer_range_set
.UnsignedIntegerRangeSet
151 _as_enumeration_field_class_mapping_ptr
= staticmethod(
152 native_bt
.field_class_enumeration_unsigned_mapping_as_mapping_const
154 _mapping_borrow_ranges_ptr
= staticmethod(
155 native_bt
.field_class_enumeration_unsigned_mapping_borrow_ranges_const
159 class _SignedEnumerationFieldClassMapping(_EnumerationFieldClassMapping
):
160 _ranges_type
= bt2_integer_range_set
.SignedIntegerRangeSet
161 _as_enumeration_field_class_mapping_ptr
= staticmethod(
162 native_bt
.field_class_enumeration_signed_mapping_as_mapping_const
164 _mapping_borrow_ranges_ptr
= staticmethod(
165 native_bt
.field_class_enumeration_signed_mapping_borrow_ranges_const
169 class _EnumerationFieldClass(_IntegerFieldClass
, collections
.abc
.Mapping
):
171 count
= native_bt
.field_class_enumeration_get_mapping_count(self
._ptr
)
175 def add_mapping(self
, label
, ranges
):
176 utils
._check
_str
(label
)
177 utils
._check
_type
(ranges
, self
._range
_set
_type
)
180 raise ValueError("duplicate mapping label '{}'".format(label
))
182 status
= self
._add
_mapping
(self
._ptr
, label
, ranges
._ptr
)
183 utils
._handle
_func
_status
(
184 status
, 'cannot add mapping to enumeration field class object'
187 def mappings_for_value(self
, value
):
188 status
, labels
= self
._get
_mapping
_labels
_for
_value
(self
._ptr
, value
)
189 utils
._handle
_func
_status
(
190 status
, 'cannot get mapping labels for value {}'.format(value
)
192 return [self
[label
] for label
in labels
]
195 for idx
in range(len(self
)):
196 mapping
= self
._get
_mapping
_by
_index
(self
._ptr
, idx
)
199 def __getitem__(self
, label
):
200 utils
._check
_str
(label
)
201 mapping
= self
._get
_mapping
_by
_label
(self
._ptr
, label
)
204 raise KeyError(label
)
208 def __iadd__(self
, mappings
):
209 for label
, ranges
in mappings
:
210 self
.add_mapping(label
, ranges
)
215 class _UnsignedEnumerationFieldClass(
216 _EnumerationFieldClass
, _UnsignedIntegerFieldClass
218 _NAME
= 'Unsigned enumeration'
219 _range_set_type
= bt2_integer_range_set
.UnsignedIntegerRangeSet
220 _add_mapping
= staticmethod(native_bt
.field_class_enumeration_unsigned_add_mapping
)
223 def _get_mapping_by_index(enum_ptr
, index
):
224 mapping_ptr
= native_bt
.field_class_enumeration_unsigned_borrow_mapping_by_index_const(
227 assert mapping_ptr
is not None
228 return _UnsignedEnumerationFieldClassMapping(mapping_ptr
)
231 def _get_mapping_by_label(enum_ptr
, label
):
232 mapping_ptr
= native_bt
.field_class_enumeration_unsigned_borrow_mapping_by_label_const(
236 if mapping_ptr
is None:
239 return _UnsignedEnumerationFieldClassMapping(mapping_ptr
)
242 def _get_mapping_labels_for_value(enum_ptr
, value
):
243 utils
._check
_uint
64(value
)
244 return native_bt
.field_class_enumeration_unsigned_get_mapping_labels_for_value(
249 class _SignedEnumerationFieldClass(_EnumerationFieldClass
, _SignedIntegerFieldClass
):
250 _NAME
= 'Signed enumeration'
251 _range_set_type
= bt2_integer_range_set
.SignedIntegerRangeSet
252 _add_mapping
= staticmethod(native_bt
.field_class_enumeration_signed_add_mapping
)
255 def _get_mapping_by_index(enum_ptr
, index
):
256 mapping_ptr
= native_bt
.field_class_enumeration_signed_borrow_mapping_by_index_const(
259 assert mapping_ptr
is not None
260 return _SignedEnumerationFieldClassMapping(mapping_ptr
)
263 def _get_mapping_by_label(enum_ptr
, label
):
264 mapping_ptr
= native_bt
.field_class_enumeration_signed_borrow_mapping_by_label_const(
268 if mapping_ptr
is None:
271 return _SignedEnumerationFieldClassMapping(mapping_ptr
)
274 def _get_mapping_labels_for_value(enum_ptr
, value
):
275 utils
._check
_int
64(value
)
276 return native_bt
.field_class_enumeration_signed_get_mapping_labels_for_value(
281 class _StringFieldClass(_FieldClass
):
285 class _StructureFieldClassMember
:
286 def __init__(self
, name
, field_class
):
288 self
._field
_class
= field_class
295 def field_class(self
):
296 return self
._field
_class
299 class _StructureFieldClass(_FieldClass
, collections
.abc
.Mapping
):
302 def append_member(self
, name
, field_class
):
303 utils
._check
_str
(name
)
304 utils
._check
_type
(field_class
, _FieldClass
)
307 raise ValueError("duplicate member name '{}'".format(name
))
309 status
= native_bt
.field_class_structure_append_member(
310 self
._ptr
, name
, field_class
._ptr
312 utils
._handle
_func
_status
(
313 status
, 'cannot append member to structure field class object'
317 count
= native_bt
.field_class_structure_get_member_count(self
._ptr
)
322 def _create_member_from_ptr(member_ptr
):
323 name
= native_bt
.field_class_structure_member_get_name(member_ptr
)
324 assert name
is not None
325 fc_ptr
= native_bt
.field_class_structure_member_borrow_field_class_const(
328 assert fc_ptr
is not None
329 fc
= _create_field_class_from_ptr_and_get_ref(fc_ptr
)
330 return _StructureFieldClassMember(name
, fc
)
332 def __getitem__(self
, key
):
333 if not isinstance(key
, str):
335 "key must be a 'str' object, got '{}'".format(key
.__class
__.__name
__)
338 member_ptr
= native_bt
.field_class_structure_borrow_member_by_name_const(
342 if member_ptr
is None:
345 return self
._create
_member
_from
_ptr
(member_ptr
)
348 for idx
in range(len(self
)):
349 member_ptr
= native_bt
.field_class_structure_borrow_member_by_index_const(
352 assert member_ptr
is not None
353 yield native_bt
.field_class_structure_member_get_name(member_ptr
)
355 def __iadd__(self
, members
):
356 for name
, field_class
in members
:
357 self
.append_member(name
, field_class
)
361 def member_at_index(self
, index
):
362 utils
._check
_uint
64(index
)
364 if index
>= len(self
):
367 member_ptr
= native_bt
.field_class_structure_borrow_member_by_index_const(
370 assert member_ptr
is not None
371 return self
._create
_member
_from
_ptr
(member_ptr
)
374 class _OptionFieldClass(_FieldClass
):
376 def field_class(self
):
377 elem_fc_ptr
= native_bt
.field_class_option_borrow_field_class_const(self
._ptr
)
378 return _create_field_class_from_ptr_and_get_ref(elem_fc_ptr
)
381 def selector_field_path(self
):
382 ptr
= native_bt
.field_class_option_borrow_selector_field_path_const(self
._ptr
)
386 return bt2_field_path
._FieldPath
._create
_from
_ptr
_and
_get
_ref
(ptr
)
389 class _VariantFieldClassOption
:
390 def __init__(self
, name
, field_class
):
392 self
._field
_class
= field_class
399 def field_class(self
):
400 return self
._field
_class
403 class _VariantFieldClassWithSelectorOption(_VariantFieldClassOption
):
404 def __init__(self
, name
, field_class
, ranges
):
405 super().__init
__(name
, field_class
)
406 self
._ranges
= ranges
413 class _VariantFieldClass(_FieldClass
, collections
.abc
.Mapping
):
415 _borrow_option_by_name_ptr
= staticmethod(
416 native_bt
.field_class_variant_borrow_option_by_name_const
418 _borrow_member_by_index_ptr
= staticmethod(
419 native_bt
.field_class_variant_borrow_option_by_index_const
423 def _as_option_ptr(opt_ptr
):
426 def _create_option_from_ptr(self
, opt_ptr
):
427 name
= native_bt
.field_class_variant_option_get_name(opt_ptr
)
428 assert name
is not None
429 fc_ptr
= native_bt
.field_class_variant_option_borrow_field_class_const(opt_ptr
)
430 assert fc_ptr
is not None
431 fc
= _create_field_class_from_ptr_and_get_ref(fc_ptr
)
432 return _VariantFieldClassOption(name
, fc
)
435 count
= native_bt
.field_class_variant_get_option_count(self
._ptr
)
439 def __getitem__(self
, key
):
440 if not isinstance(key
, str):
442 "key must be a 'str' object, got '{}'".format(key
.__class
__.__name
__)
445 opt_ptr
= self
._borrow
_option
_by
_name
_ptr
(self
._ptr
, key
)
450 return self
._create
_option
_from
_ptr
(opt_ptr
)
453 for idx
in range(len(self
)):
454 opt_ptr
= self
._borrow
_member
_by
_index
_ptr
(self
._ptr
, idx
)
455 assert opt_ptr
is not None
456 base_opt_ptr
= self
._as
_option
_ptr
(opt_ptr
)
457 yield native_bt
.field_class_variant_option_get_name(base_opt_ptr
)
459 def option_at_index(self
, index
):
460 utils
._check
_uint
64(index
)
462 if index
>= len(self
):
465 opt_ptr
= self
._borrow
_member
_by
_index
_ptr
(self
._ptr
, index
)
466 assert opt_ptr
is not None
467 return self
._create
_option
_from
_ptr
(opt_ptr
)
470 class _VariantFieldClassWithoutSelector(_VariantFieldClass
):
471 _NAME
= 'Variant (without selector)'
473 def append_option(self
, name
, field_class
):
474 utils
._check
_str
(name
)
475 utils
._check
_type
(field_class
, _FieldClass
)
478 raise ValueError("duplicate option name '{}'".format(name
))
480 status
= native_bt
.field_class_variant_without_selector_append_option(
481 self
._ptr
, name
, field_class
._ptr
483 utils
._handle
_func
_status
(
484 status
, 'cannot append option to variant field class object'
487 def __iadd__(self
, options
):
488 for name
, field_class
in options
:
489 self
.append_option(name
, field_class
)
494 class _VariantFieldClassWithSelector(_VariantFieldClass
):
495 _NAME
= 'Variant (with selector)'
497 def _create_option_from_ptr(self
, opt_ptr
):
498 base_opt_ptr
= self
._as
_option
_ptr
(opt_ptr
)
499 name
= native_bt
.field_class_variant_option_get_name(base_opt_ptr
)
500 assert name
is not None
501 fc_ptr
= native_bt
.field_class_variant_option_borrow_field_class_const(
504 assert fc_ptr
is not None
505 fc
= _create_field_class_from_ptr_and_get_ref(fc_ptr
)
506 range_set_ptr
= self
._option
_borrow
_ranges
_ptr
(opt_ptr
)
507 assert range_set_ptr
is not None
508 range_set
= self
._range
_set
_type
._create
_from
_ptr
_and
_get
_ref
(range_set_ptr
)
509 return _VariantFieldClassWithSelectorOption(name
, fc
, range_set
)
512 def selector_field_path(self
):
513 ptr
= native_bt
.field_class_variant_with_selector_borrow_selector_field_path_const(
520 return bt2_field_path
._FieldPath
._create
_from
_ptr
_and
_get
_ref
(ptr
)
522 def append_option(self
, name
, field_class
, ranges
):
523 utils
._check
_str
(name
)
524 utils
._check
_type
(field_class
, _FieldClass
)
525 utils
._check
_type
(ranges
, self
._range
_set
_type
)
528 raise ValueError("duplicate option name '{}'".format(name
))
531 raise ValueError('range set is empty')
533 # TODO: check overlaps (precondition of self._append_option())
535 status
= self
._append
_option
(self
._ptr
, name
, field_class
._ptr
, ranges
._ptr
)
536 utils
._handle
_func
_status
(
537 status
, 'cannot append option to variant field class object'
540 def __iadd__(self
, options
):
541 for name
, field_class
, ranges
in options
:
542 self
.append_option(name
, field_class
, ranges
)
547 class _VariantFieldClassWithUnsignedSelector(_VariantFieldClassWithSelector
):
548 _NAME
= 'Variant (with unsigned selector)'
549 _borrow_option_by_name_ptr
= staticmethod(
550 native_bt
.field_class_variant_with_selector_unsigned_borrow_option_by_name_const
552 _borrow_member_by_index_ptr
= staticmethod(
553 native_bt
.field_class_variant_with_selector_unsigned_borrow_option_by_index_const
555 _as_option_ptr
= staticmethod(
556 native_bt
.field_class_variant_with_selector_unsigned_option_as_option_const
558 _append_option
= staticmethod(
559 native_bt
.field_class_variant_with_selector_unsigned_append_option
561 _option_borrow_ranges_ptr
= staticmethod(
562 native_bt
.field_class_variant_with_selector_unsigned_option_borrow_ranges_const
564 _range_set_type
= bt2_integer_range_set
.UnsignedIntegerRangeSet
567 class _VariantFieldClassWithSignedSelector(_VariantFieldClassWithSelector
):
568 _NAME
= 'Variant (with signed selector)'
569 _borrow_option_by_name_ptr
= staticmethod(
570 native_bt
.field_class_variant_with_selector_signed_borrow_option_by_name_const
572 _borrow_member_by_index_ptr
= staticmethod(
573 native_bt
.field_class_variant_with_selector_signed_borrow_option_by_index_const
575 _as_option_ptr
= staticmethod(
576 native_bt
.field_class_variant_with_selector_signed_option_as_option_const
578 _append_option
= staticmethod(
579 native_bt
.field_class_variant_with_selector_signed_append_option
581 _option_borrow_ranges_ptr
= staticmethod(
582 native_bt
.field_class_variant_with_selector_signed_option_borrow_ranges_const
584 _range_set_type
= bt2_integer_range_set
.SignedIntegerRangeSet
587 class _ArrayFieldClass(_FieldClass
):
589 def element_field_class(self
):
590 elem_fc_ptr
= native_bt
.field_class_array_borrow_element_field_class_const(
593 return _create_field_class_from_ptr_and_get_ref(elem_fc_ptr
)
596 class _StaticArrayFieldClass(_ArrayFieldClass
):
599 return native_bt
.field_class_array_static_get_length(self
._ptr
)
602 class _DynamicArrayFieldClass(_ArrayFieldClass
):
604 def length_field_path(self
):
605 ptr
= native_bt
.field_class_array_dynamic_borrow_length_field_path_const(
611 return bt2_field_path
._FieldPath
._create
_from
_ptr
_and
_get
_ref
(ptr
)
614 _FIELD_CLASS_TYPE_TO_OBJ
= {
615 native_bt
.FIELD_CLASS_TYPE_BOOL
: _BoolFieldClass
,
616 native_bt
.FIELD_CLASS_TYPE_BIT_ARRAY
: _BitArrayFieldClass
,
617 native_bt
.FIELD_CLASS_TYPE_UNSIGNED_INTEGER
: _UnsignedIntegerFieldClass
,
618 native_bt
.FIELD_CLASS_TYPE_SIGNED_INTEGER
: _SignedIntegerFieldClass
,
619 native_bt
.FIELD_CLASS_TYPE_REAL
: _RealFieldClass
,
620 native_bt
.FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION
: _UnsignedEnumerationFieldClass
,
621 native_bt
.FIELD_CLASS_TYPE_SIGNED_ENUMERATION
: _SignedEnumerationFieldClass
,
622 native_bt
.FIELD_CLASS_TYPE_STRING
: _StringFieldClass
,
623 native_bt
.FIELD_CLASS_TYPE_STRUCTURE
: _StructureFieldClass
,
624 native_bt
.FIELD_CLASS_TYPE_STATIC_ARRAY
: _StaticArrayFieldClass
,
625 native_bt
.FIELD_CLASS_TYPE_DYNAMIC_ARRAY
: _DynamicArrayFieldClass
,
626 native_bt
.FIELD_CLASS_TYPE_OPTION
: _OptionFieldClass
,
627 native_bt
.FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR
: _VariantFieldClassWithoutSelector
,
628 native_bt
.FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR
: _VariantFieldClassWithUnsignedSelector
,
629 native_bt
.FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR
: _VariantFieldClassWithSignedSelector
,