Extends Structure's functionality with support for bitfields such as: ('B:4,LowerHalf', 'B:4,UpperHalf') To this end, two lists are maintained: * self.__keys__ that contains compound fields, for example ('B,~LowerHalfUpperHalf'), and is used during packing/unpaking
| 1420 | |
| 1421 | |
| 1422 | class StructureWithBitfields(Structure): |
| 1423 | """ |
| 1424 | Extends Structure's functionality with support for bitfields such as: |
| 1425 | ('B:4,LowerHalf', 'B:4,UpperHalf') |
| 1426 | To this end, two lists are maintained: |
| 1427 | * self.__keys__ that contains compound fields, for example |
| 1428 | ('B,~LowerHalfUpperHalf'), and is used during packing/unpaking |
| 1429 | * self.__keys_ext__ containing a separate key for each field (ex., LowerHalf, |
| 1430 | UpperHalf) to simplify implementation of dump() |
| 1431 | This way the implementation of unpacking/packing and dump() from Structure can be |
| 1432 | reused. |
| 1433 | |
| 1434 | In addition, we create a dictionary: |
| 1435 | <comound_field_index_in_keys> --> |
| 1436 | (data type, [ (subfield name, length in bits)+ ] ) |
| 1437 | that facilitates bitfield paking and unpacking. |
| 1438 | |
| 1439 | With lru_cache() creating only once instance per format string, the memory |
| 1440 | overhead is negligible. |
| 1441 | """ |
| 1442 | |
| 1443 | BTF_NAME_IDX = 0 |
| 1444 | BTF_BITCNT_IDX = 1 |
| 1445 | CF_TYPE_IDX = 0 |
| 1446 | CF_SUBFLD_IDX = 1 |
| 1447 | |
| 1448 | def __init__(self, format, name=None, file_offset=None): |
| 1449 | ( |
| 1450 | self.__format__, |
| 1451 | self.__format_length__, |
| 1452 | self.__field_offsets__, |
| 1453 | self.__keys__, |
| 1454 | self.__keys_ext__, |
| 1455 | self.__compound_fields__, |
| 1456 | ) = set_bitfields_format(format) |
| 1457 | # create our own unpacked_data_elms to ensure they are not shared among |
| 1458 | # StructureWithBitfields instances with the same format string |
| 1459 | self.__unpacked_data_elms__ = [None for i in range(self.__format_length__)] |
| 1460 | self.__all_zeroes__ = False |
| 1461 | self.__file_offset__ = file_offset |
| 1462 | self.name = name if name != None else format[0] |
| 1463 | |
| 1464 | def __unpack__(self, data): |
| 1465 | # calling the original routine to deal with special cases/spurious data |
| 1466 | # structures |
| 1467 | super(StructureWithBitfields, self).__unpack__(data) |
| 1468 | self._unpack_bitfield_attributes() |
| 1469 | |
| 1470 | def __pack__(self): |
| 1471 | self._pack_bitfield_attributes() |
| 1472 | try: |
| 1473 | data = super(StructureWithBitfields, self).__pack__() |
| 1474 | finally: |
| 1475 | self._unpack_bitfield_attributes() |
| 1476 | return data |
| 1477 | |
| 1478 | def dump(self, indentation=0): |
| 1479 | tk = self.__keys__ |
no outgoing calls
no test coverage detected