PyPI License Python Status Binder

Logo

Welcome to the KonF‘00’ Documentation

KonFoo is a Python Package for creating byte stream mappers in a declarative way with as little code as necessary to help fighting the confusion with the foo of the all well-known memory dumps or hexadecimal views of binary data.

It comes with sensible defaults out of the box.

It aims to make the process of reading, de-serializing, viewing, serializing and writing binary data from and back to a byte stream provider as easy as possible.

KonFoo in points:

  • declarative way to describe the mapping of binary data to Python types
  • declarative classes to read, deserialize, view, serialize and write binary data from and back to a data source
  • easy adjustable byte stream provider bridge to any kind of data source
  • nesting of classes
  • adaptable classes on the fly while reading/de-serializing binary data
  • easy syntax for accessing nested fields
  • view the mapped binary data as a JSON string
  • list the mapped binary data as a flatten list or dictionary
  • write the mapped binary data to a .csv file
  • save the mapped binary data to an .ini file
  • load the mapped binary data from an .ini file
  • easy creatable nested metadata dictionaries of the members of a byte stream mapper
  • metadata converter to the flare.json format to visualise the mapper with d3js.

KonFoo runs on Python 3.5 or higher.

You can get the latest version of KonFoo directly from GitHub:

You can get the library directly from PyPI:

> pip install konfoo

Documentation Contents

This part of the documentation guides you through all of the library’s usage patterns.

Introduction

KonFoo is a Python package for de-serializing byte streams into a meaningful representation. KonFoo helps you to deserialize a byte stream retrievable through a byte stream provider to any kind of data source into a meaningful representation by just declaring how the parts of a byte stream should be represented, respectively mapped to fields.

You can store the representation into an .ini file to analyse the byte stream data.

The built-in deserialize hook deserialize(buffer=bytes(), index=Index(), **option) available for all container and field classes allows you to adapt even expand or declare the representation during the de-serialization process on the fly.

The built-in deserializer provided by the pointer class (called through the Pointer.read_from() method) is able to follow even nested absolute or relative pointers to retrieve the byte stream from the byte stream provider necessary for its referenced data object and to de-serialize (map) it.

After de-serializing the byte stream provided by the byte stream provider the built-in serializer provided also by the pointer class (called through the Pointer.write_to() method) is able to transfer the manipulated values of any container or field in the representation back to the byte stream provider to write it into its data source.

Concept

KonFoo is based on defining or declaring a byte stream mapper (representation) through classes. KonFoo has two abstract base classes the container class and the field class.

A container contains field and/or container classes and knows how to view, save and load the values of the field items within the container.

A field represents the value of a content area in a byte stream which the field maps and knows how to unpack and pack its value from and to a byte stream.

The mixin pointer class has both features of the two base classes and has an interface to a byte stream provider to read and write byte streams from and back to the byte stream provider for its referenced data object respectively its byte stream mapper.

The built-in deserializer and serializer unpacks and packs the byte stream sequential to and from each field in the declared byte stream mapper.

Mapper

A byte stream mapper consists of a collection of container and field members, whereby the container members describe the structure and the field members describe the content of one or more memory areas in a data source. The mix-in pointer field serves in combination with a byte stream provider as an entry point to a data source for the byte stream mapper to deserialize and serialize its byte stream.

Containers

The role of a Container is to describe the structure of one or more memory areas in a data source. A container always needs one or more fields to describe the content of the memory area.

View Field Attributes

A container can view the attributes of each field nested in the container by calling its method view_fields(). Default attribute is the field value.

>>> # Create an empty container.
>>> container = Container()
>>> # View the field values in the container.
>>> container.view_fields()

Note

The attributes of each field for containers nested in the container are viewed as well (chained method call).

View as a JSON String

A container can view the attributes of each field nested in the container as a JSON formatted string by calling its method to_json(). Default attribute is the field value.

>>> container.to_json()
'null'

Note

The attributes of each field for containers nested in the container are viewed as well (chained method call).

List Field Items

A container can list all its field items nested in the container as a flatten list in the form of ('field path', field item) tuples by calling its method field_items().

>>> # List the field items in the container.
>>> container.field_items()
[]

List Field Attributes

A container can list the attributes of each field item nested in the container as a flatten list in the form of ('field path', attribute) or ('field path', list(attributes)) tuples by calling its method to_list(). Default attribute is the field value.

>>> # List the field values in the container.
>>> container.to_list()
[]

A container can list the attributes of each field item nested in the container as a flatten ordered dictionary in the form of {'field path': attribute} or {'field path': list(attributes)} pairs by calling its method to_dict(). Default attribute is the field value.

>>> # List the field values in the container.
>>> container.to_dict()
OrderedDict([('Container', OrderedDict())])

A container can list the attributes of each field item nested in the container as a flatten list of dictionaries containing the field path and the selected field attributes by calling its method to_csv(). Default attribute is the field value.

>>> # List the field values in the container.
>>> container.to_csv()
[]

Note

The class name of the instance is used for the root name as long as no name is given.

Write Field Attributes

A container can write the attributes of each field item nested in the container to a .csv file by calling its method write_csv(). Default attribute is the field value.

>>> # Save the field values to an '.csv' file.
>>> container.write_csv("_static/container.csv")

The generated .csv file for the container looks like this:

id,value

Note

The class name of the instance is used for the root name as long as no name is given.

Save Field Attributes

A container can save the attributes of each field item nested in the container to an .ini file by calling its method save(). Default attribute is the field value.

>>> # Save the field values to an '.ini' file.
>>> container.save("_static/container.ini")

The generated .ini file for the container looks like this:

[Container]

Note

The class name of the instance is used for the section name as long as no section is given.

Load Field Values

A container can load the value of each field item nested in the container from an .ini file by calling its method load().

>>> # Load the field values from an '.ini' file.
>>> container.load("_static/container.ini")
[Container]

Note

The class name of the instance is used for the section name as long as no section is given.

Fields

The role of a Field is to map a specific content area of a byte stream. A field is always placed in a container except from a pointer field which is the entry point for a mapper to connect the attached data object via a byte stream provider to a data source to retrieve the required byte stream for the mapper.

>>> # Create a field.
>>> field = Field()
>>> # Display the field.
>>> field
Field(index=Index(byte=0, bit=0,
                  address=0, base_address=0,
                  update=False),
      alignment=Alignment(byte_size=0, bit_offset=0),
      bit_size=0,
      value=None)

Name

A field has a type name. The field name consists of the name of the field base class and its field size to describe the kind of the field.

>>> # Field name.
>>> field.name
'Field0'

Size

A field has a bit_size. The field size defines the size of the content area of a byte stream that the field map.

>>> # Field bit size.
>>> field.bit_size
0

Value

A field has a value. The field value represents the content area of a byte stream that the field map.

>>> # Field value.
>>> field.value

Index

A field has an index. The field index contains the location of the field in a byte stream and in the providing data source. The field index is automatically calculated by the built-in deserializer and serializer from the start point of the byte stream and the start address of the byte stream in the providing data source.

>>> # Field index.
>>> field.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> # Field index: byte offset of the field in the byte stream.
>>> field.index.byte
0
>>> # Field index: bit offset of the field relative to its byte offset.
>>> field.index.bit
0
>>> # Field index: memory address of the field in the data source.
>>> field.index.address
0
>>> # Field index: start address of the byte stream in the data source.
>>> field.index.base_address
0
>>> # Field index: update request for the byte stream.
>>> field.index.update
False

Alignment

A field has an alignment. The field alignment contains the location of the field within an aligned group of consecutive fields. The order how the consecutive fields are declared in a container defines the order how the consecutive fields are aligned to each other. The bit offset of the field alignment is automatically calculated by the built-in deserializer and serializer.

>>> # Field alignment.
>>> field.alignment
Alignment(byte_size=0, bit_offset=0)
>>> byte_size, bit_offset = field.alignment
>>> # Field alignment: byte size of the aligned field group.
>>> byte_size
0
>>> # Field alignment: bit offset of the field in its field group.
>>> bit_offset
0

A field can be aligned to a group of consecutive fields by using the align_to argument of the Field class to describe an atomic content part of a byte stream with more than one field.

>>> Decimal(15).alignment
Alignment(byte_size=2, bit_offset=0)
>>> Bool(1, align_to=2).alignment
Alignment(byte_size=2, bit_offset=0)

Note

A field aligns it self to the next matching byte size when the field size matches not full bytes and no field alignment is given.

For example to describe an atomic 16-bit value in a byte stream with more than one field can be achieved like this:

>>> # Create an empty structure for the atomic 16-bit value.
>>> atomic = Structure()
>>> # Add field for the first 15 bits of an atomic 16-bit value.
>>> atomic.size = Decimal(15, 2)
>>> # Add field for the last bit of an atomic 16-bit value.
>>> atomic.flag = Bool(1, 2)
>>> # Index the fields of the atomic 16-bit value.
>>> atomic.index_fields()
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> # Display alignment of the size field.
>>> atomic.size.alignment
Alignment(byte_size=2, bit_offset=0)
>>> # Display alignment of the flag field.
>>> atomic.flag.alignment
Alignment(byte_size=2, bit_offset=15)

Note

The field alignment works only for the Decimal field classes.

Byte order

A field defines its own decoding/encoding byte_order. The default field byte order is auto it means that the field use the byte order which the byte stream mapper defines to unpack and pack the required bytes and bits for its field value from and to the byte stream.

>>> # Field byte order.
>>> field.byte_order
Byteorder.auto = 'auto'
>>> # Field byte order value.
>>> field.byte_order.value
'auto'

Enumeration

The name instead of the value of an enumeration can be displayed with the Enum field class by assigning an Enumeration class to the Enum field.

For example to describe a 2-bit ambivalent enumeration by an Enum field can be achieved like this:

>>> # Define the enumeration class.
>>> class Validity(Enumeration):
...     error = 0
...     correct = 1
...     forced = 2
...     undefined = 3
>>> # Create an enum field and assign an enumeration to the field.
>>> ambivalent = Enum(2, enumeration=Validity)
>>> # Display the value of the field.
>>> ambivalent.value
'error'
>>> # Returns the field value as an integer.
>>> int(ambivalent)
0
>>> # Display the field.
>>> ambivalent
Enum(index=Index(byte=0, bit=0,
                 address=0, base_address=0,
                 update=False),
     alignment=Alignment(byte_size=1, bit_offset=0),
     bit_size=2,
     value='error')

Structure

KonFoo has a Structure class and many field classes to declare the mapping part of a byte stream mapper. The order how you declare the members in the structure defines the order how the members are deserialized and serialized by the built-in deserializer and serializer.

Member

A structure member can be any field or container class.

Define a Structure

You can define members of a structure by adding them in the constructor method of the Structure class.

>>> class Identifier(Structure):
...
...     def __init__(self):
...         super().__init__()        # <- NEVER forget to call it first!
...         self.version = Byte()     # 1st field
...         self.id = Unsigned8()     # 2nd field
...         self.length = Decimal8()  # 3rd field
...         self.module = Char()      # 4th field
...         self.index_fields()       # <- Indexes all fields (optional)
>>> # Create an instance of the structure.
>>> identifier = Identifier()
>>> # List the field values of the structure.
>>> identifier.to_list()
[('Identifier.version', '0x0'),
 ('Identifier.id', '0x0'),
 ('Identifier.length', 0),
 ('Identifier.module', '\x00')]
>>> # List the field values of the structure as a CSV list.
>>> identifier.to_csv()
[{'id': 'Identifier.version', 'value': '0x0'},
 {'id': 'Identifier.id', 'value': '0x0'},
 {'id': 'Identifier.length', 'value': 0},
 {'id': 'Identifier.module', 'value': '\x00'}]
>>> # View the structure field values as a JSON string.
>>> identifier.to_json()
'{"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"}'

Warning

A structure must always align to full bytes or an exception will be raised when an incomplete structure declaration is deserialized or serialized.

Align Fields in a Structure

You can align consecutive fields in a structure to each other by using the align_to parameter of the Field class.

>>> class Identifier(Structure):
...
...     def __init__(self):
...         super().__init__()
...         self.version = Byte(align_to=4)       # 1st field aligned to 4 bytes
...         self.id = Unsigned(8, align_to=4)     # 2nd field aligned to 4 bytes
...         self.length = Decimal(8, align_to=4)  # 3rd field aligned to 4 bytes
...         self.module = Char(align_to=4)        # 4th field aligned to 4 bytes
...         self.index_fields()
>>> # Create an instance of the structure.
>>> identifier = Identifier()
>>> # List the field alignments of the structure.
>>> identifier.to_list('alignment')
[('Identifier.version', Alignment(byte_size=4, bit_offset=0)),
 ('Identifier.id', Alignment(byte_size=4, bit_offset=8)),
 ('Identifier.length', Alignment(byte_size=4, bit_offset=16)),
 ('Identifier.module', Alignment(byte_size=4, bit_offset=24))]
>>> # List the field alignments of the structure as a CSV list.
>>> identifier.to_csv('alignment.byte_size', 'alignment.bit_offset')
[{'id': 'Identifier.version', 'alignment.byte_size': 4, 'alignment.bit_offset': 0},
 {'id': 'Identifier.id', 'alignment.byte_size': 4, 'alignment.bit_offset': 8},
 {'id': 'Identifier.length', 'alignment.byte_size': 4, 'alignment.bit_offset': 16},
 {'id': 'Identifier.module', 'alignment.byte_size': 4, 'alignment.bit_offset': 24}]
>>> # View the structure field alignments as a JSON string.
>>> identifier.to_json('alignment')
'{"version": [4, 0], "id": [4, 8], "length": [4, 16], "module": [4, 24]}'

Note

The field alignment works only for the Decimal field classes.

Nest Structures

You can nest a structure in another structure.

>>> # Define a new structure class with a nested structure.
>>> class Header(Structure):
...
...     def __init__(self):
...         super().__init__()
...         self.type = Identifier()  # nested structure
...         self.size = Decimal32()
...         self.index_fields()
>>> # Create an instance of the structure.
>>> header = Header()
>>> # List the field values of the structure.
>>> header.to_list()
[('Header.type.version', '0x0'),
 ('Header.type.id', '0x0'),
 ('Header.type.length', 0),
 ('Header.type.module', '\x00'),
 ('Header.size', 0)]
>>> # List the field values of the structure as a CSV list.
>>> header.to_csv()
[{'id': 'Header.type.version', 'value': '0x0'},
 {'id': 'Header.type.id', 'value': '0x0'},
 {'id': 'Header.type.length', 'value': 0},
 {'id': 'Header.type.module', 'value': '\x00'},
 {'id': 'Header.size', 'value': 0}]
>>> # View the structure field values as a JSON string.
>>> header.to_json()
'{"type": {"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"},
  "size": 0}'

Inherit from a Structure

You can inherit the members from a structure class to extend or change it.

>>> # Define a new structure class.
>>> class HeaderV1(Structure):
...
...     def __init__(self):
...         super().__init__()
...         self.type = Identifier()
...         self.index_fields()
>>> # Create an instance of the structure.
>>> header = HeaderV1()
>>> # List the field values of the structure.
>>> header.to_list()
[('HeaderV1.type.version', '0x0'),
 ('HeaderV1.type.id', '0x0'),
 ('HeaderV1.type.length', 0),
 ('HeaderV1.type.module', '\x00')]
>>> # List the field values of the structure as a CSV list.
>>> header.to_csv()
[{'id': 'HeaderV1.type.version', 'value': '0x0'},
 {'id': 'HeaderV1.type.id', 'value': '0x0'},
 {'id': 'HeaderV1.type.length', 'value': 0},
 {'id': 'HeaderV1.type.module', 'value': '\x00'}]
>>> # View the structure field values as a JSON string.
>>> header.to_json()
'{"type": {"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"}}'
>>> # Define a new structure class inherit from a structure the fields.
>>> class HeaderV2(HeaderV1):
...
...     def __init__(self):
...         super().__init__()
...         self.size = Decimal32()
...         self.index_fields()
>>> # Create an instance of the structure.
>>> header = HeaderV2()
>>> # List the field values of the structure.
>>> header.to_list()
[('HeaderV2.type.version', '0x0'),
 ('HeaderV2.type.id', '0x0'),
 ('HeaderV2.type.length', 0),
 ('HeaderV2.type.module', '\x00'),
 ('HeaderV2.size', 0)]
>>> # List the field values of the structure as a CSV list.
>>> header.to_csv()
[{'id': 'HeaderV2.type.version', 'value': '0x0'},
 {'id': 'HeaderV2.type.id', 'value': '0x0'},
 {'id': 'HeaderV2.type.length', 'value': 0},
 {'id': 'HeaderV2.type.module', 'value': '\x00'},
 {'id': 'HeaderV2.size', 'value': 0}]
>>> # View the structure field values as a JSON string.
>>> header.to_json()
'{"type": {"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"},
  "size": 0}'

Declare on the fly

You can declare a structure on the fly.

>>> # Create an empty structure.
>>> structure = Structure()
>>> # Add fields to the structure.
>>> structure.version = Byte()
>>> structure.id = Unsigned8()
>>> structure.length = Decimal8()
>>> structure.module = Char()
>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.version', '0x0'),
 ('Structure.id', '0x0'),
 ('Structure.length', 0),
 ('Structure.module', '\x00')]
>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.version', 'value': '0x0'},
 {'id': 'Structure.id', 'value': '0x0'},
 {'id': 'Structure.length', 'value': 0},
 {'id': 'Structure.module', 'value': '\x00'}]
>>> # View the structure field values as a JSON string.
>>> structure.to_json()
'{"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"}'

You can declare a structure with aligned fields on the fly.

>>> # Create an empty structure.
>>> structure = Structure()
>>> # Add aligned fields to the structure.
>>> structure.version = Byte(4)
>>> structure.id = Unsigned(8, 4)
>>> structure.length = Decimal(8, 4)
>>> structure.module = Char(4)
>>> # Index the fields in the structure.
>>> structure.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # List the field alignments of the structure.
>>> structure.to_list('alignment')
[('Structure.version', Alignment(byte_size=4, bit_offset=0)),
 ('Structure.id', Alignment(byte_size=4, bit_offset=8)),
 ('Structure.length', Alignment(byte_size=4, bit_offset=16)),
 ('Structure.module', Alignment(byte_size=4, bit_offset=24))]
>>> # List the field alignments of the structure as a CSV list.
>>> structure.to_csv('alignment.byte_size', 'alignment.bit_offset')
[{'id': 'Structure.version', 'alignment.byte_size': 4, 'alignment.bit_offset': 0},
 {'id': 'Structure.id', 'alignment.byte_size': 4, 'alignment.bit_offset': 8},
 {'id': 'Structure.length', 'alignment.byte_size': 4, 'alignment.bit_offset': 16},
 {'id': 'Structure.module', 'alignment.byte_size': 4, 'alignment.bit_offset': 24}]
>>> # View the structure field alignments as a JSON string.
>>> structure.to_json('alignment')
'{"version": [4, 0], "id": [4, 8], "length": [4, 16], "module": [4, 24]}'

You can declare a structure with keywords.

>>> # Create a structure with keywords.
>>> structure = Structure(
...     version=Byte(4),
...     id=Unsigned(8, 4),
...     length=Decimal(8, 4),
...     module=Char(4))
>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.version', '0x0'),
 ('Structure.id', '0x0'),
 ('Structure.length', 0),
 ('Structure.module', '\x00')]
>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.version', 'value': '0x0'},
 {'id': 'Structure.id', 'value': '0x0'},
 {'id': 'Structure.length', 'value': 0},
 {'id': 'Structure.module', 'value': '\x00'}]
>>> # View the structure field values as a JSON string.
>>> structure.to_json()
'{"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"}'

You can nest structure’s on the fly.

>>> # Create an empty structure.
>>> structure = Structure()
>>> # Add an empty nested structure to the structure.
>>> structure.type = Structure()
>>> # Add fields to the nested structure.
>>> structure.type.version = Byte(4)
>>> structure.type.id = Unsigned(8, 4)
>>> structure.type.length = Decimal(8, 4)
>>> structure.type.module = Char(4)
>>> # Add a field to the structure.
>>> structure.size = Decimal32()
>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.type.version', '0x0'),
 ('Structure.type.id', '0x0'),
 ('Structure.type.length', 0),
 ('Structure.type.module', '\x00'),
 ('Structure.size', 0)]
>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.type.version', 'value': '0x0'},
 {'id': 'Structure.type.id', 'value': '0x0'},
 {'id': 'Structure.type.length', 'value': 0},
 {'id': 'Structure.type.module', 'value': '\x00'},
 {'id': 'Structure.size', 'value': 0}]
>>> # View the structure field values as a JSON string.
>>> structure.to_json()
'{"type": {"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"},
  "size": 0}'

You can assign a structure to a member of another structure on the fly.

>>> # Create a structure to be nested.
>>> identifier = Structure(
...     version = Byte(4),
...     id = Unsigned(8, 4),
...     length = Decimal(8, 4),
...     module = Char(4))
>>> # Create an empty structure.
>>> structure = Structure()
>>> # Add a nested structure to the structure.
>>> structure.type = identifier
>>> # Add a field to the structure.
>>> structure.size = Decimal32()
>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.type.version', '0x0'),
 ('Structure.type.id', '0x0'),
 ('Structure.type.length', 0),
 ('Structure.type.module', '\x00'),
 ('Structure.size', 0)]
>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.type.version', 'value': '0x0'},
 {'id': 'Structure.type.id', 'value': '0x0'},
 {'id': 'Structure.type.length', 'value': 0},
 {'id': 'Structure.type.module', 'value': '\x00'},
 {'id': 'Structure.size', 'value': 0}]
>>> # View the structure field values as a JSON string.
>>> structure.to_json()
'{"type": {"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"},
  "size": 0}'

Initialize a Structure

You can initialize the fields in a structure by calling the method initialize_fields().

>>> # Create a structure.
>>> structure = Structure(
...     version=Byte(4),
...     id=Unsigned(8, 4),
...     length=Decimal(8, 4),
...     module=Char(4))
>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.version', '0x0'),
 ('Structure.id', '0x0'),
 ('Structure.length', 0),
 ('Structure.module', '\x00')]
>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.version', 'value': '0x0'},
 {'id': 'Structure.id', 'value': '0x0'},
 {'id': 'Structure.length', 'value': 0},
 {'id': 'Structure.module', 'value': '\x00'}]
>>> # View the structure field values as a JSON string.
>>> structure.to_json()
'{"version": "0x0", "id": "0x0", "length": 0, "module": "\\u0000"}'
>>> # Initialize the fields of the structure.
>>> structure.initialize_fields(
...     dict(version=1, id=2, length=9, module=0x46))
>>> # Initialize the fields in the structure.
>>> structure.initialize_fields({
...     "version": "0x1",
...     "id": "0x2",
...     "length": 9,
...     "module": "F"
... })
>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.version', '0x1'),
 ('Structure.id', '0x2'),
 ('Structure.length', 9),
 ('Structure.module', 'F')]
>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.version', 'value': '0x1'},
 {'id': 'Structure.id', 'value': '0x2'},
 {'id': 'Structure.length', 'value': 9},
 {'id': 'Structure.module', 'value': 'F'}]
>>> # View the structure field values as a JSON string.
>>> structure.to_json()
'{"version": "0x1", "id": "0x2", "length": 9, "module": "F"}'

Display a Structure

You can display the structure.

>>> # Create a structure.
>>> structure = Structure(
...     version=Byte(4),
...     id=Unsigned(8, 4),
...     length=Decimal(8, 4),
...     module=Char(4))
>>> # Index the fields in the structure.
>>> structure.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # Display the structure.
>>> structure
Structure([('version', Byte(index=Index(byte=0, bit=0,
                                        address=0, base_address=0,
                                        update=False),
                            alignment=Alignment(byte_size=4, bit_offset=0),
                            bit_size=8,
                            value='0x0')),
            ('id', Unsigned(index=Index(byte=0, bit=8,
                                        address=0, base_address=0,
                                        update=False),
                            alignment=Alignment(byte_size=4, bit_offset=8),
                            bit_size=8,
                            value='0x0')),
            ('length', Decimal(index=Index(byte=0, bit=16,
                                           address=0, base_address=0,
                                           update=False),
                               alignment=Alignment(byte_size=4, bit_offset=16),
                               bit_size=8,
                               value=0)),
            ('module', Char(index=Index(byte=0, bit=24,
                                        address=0, base_address=0,
                                        update=False),
                            alignment=Alignment(byte_size=4, bit_offset=24),
                            bit_size=8,
                            value='\x00'))])

Metadata of a Structure

You can get the metadata of the structure by calling the method describe().

>>> # Get the description of the structure.
>>> structure.describe()
OrderedDict([('class', 'Structure'),
             ('name', 'Structure'),
             ('size', 4),
             ('type', 'Structure'),
             ('member',
              [OrderedDict([('address', 0),
                            ('alignment', [4, 0]),
                            ('class', 'Byte'),
                            ('index', [0, 0]),
                            ('max', 255),
                            ('min', 0),
                            ('name', 'version'),
                            ('order', 'auto'),
                            ('signed', False),
                            ('size', 8),
                            ('type', 'Field'),
                            ('value', '0x0')]),
               OrderedDict([('address', 0),
                            ('alignment', [4, 8]),
                            ('class', 'Unsigned8'),
                            ('index', [0, 8]),
                            ('max', 255),
                            ('min', 0),
                            ('name', 'id'),
                            ('order', 'auto'),
                            ('signed', False),
                            ('size', 8),
                            ('type', 'Field'),
                            ('value', '0x0')]),
               OrderedDict([('address', 0),
                            ('alignment', [4, 16]),
                            ('class', 'Decimal8'),
                            ('index', [0, 16]),
                            ('max', 255),
                            ('min', 0),
                            ('name', 'length'),
                            ('order', 'auto'),
                            ('signed', False),
                            ('size', 8),
                            ('type', 'Field'),
                            ('value', 0)]),
               OrderedDict([('address', 0),
                            ('alignment', [4, 24]),
                            ('class', 'Char'),
                            ('index', [0, 24]),
                            ('max', 255),
                            ('min', 0),
                            ('name', 'module'),
                            ('order', 'auto'),
                            ('signed', False),
                            ('size', 8),
                            ('type', 'Field'),
                            ('value', '\x00')])])])
>>> json.dump(structure.describe(), sys.stdout, indent=2)
{
  "class": "Structure",
  "name": "Structure",
  "size": 4,
  "type": "Structure",
  "member": [
    {
      "address": 0,
      "alignment": [
        4,
        0
      ],
      "class": "Byte",
      "index": [
        0,
        0
      ],
      "max": 255,
      "min": 0,
      "name": "version",
      "order": "auto",
      "signed": false,
      "size": 8,
      "type": "Field",
      "value": "0x0"
    },
    {
      "address": 0,
      "alignment": [
        4,
        8
      ],
      "class": "Unsigned8",
      "index": [
        0,
        8
      ],
      "max": 255,
      "min": 0,
      "name": "id",
      "order": "auto",
      "signed": false,
      "size": 8,
      "type": "Field",
      "value": "0x0"
    },
    {
      "address": 0,
      "alignment": [
        4,
        16
      ],
      "class": "Decimal8",
      "index": [
        0,
        16
      ],
      "max": 255,
      "min": 0,
      "name": "length",
      "order": "auto",
      "signed": false,
      "size": 8,
      "type": "Field",
      "value": 0
    },
    {
      "address": 0,
      "alignment": [
        4,
        24
      ],
      "class": "Char",
      "index": [
        0,
        24
      ],
      "max": 255,
      "min": 0,
      "name": "module",
      "order": "auto",
      "signed": false,
      "size": 8,
      "type": "Field",
      "value": "\u0000"
    }
  ]
}

Size of a Structure

You can get the size of a structure as a tuple in the form of (number of bytes, number of remaining bits) by calling the method container_size().

>>> # Get the size of the structure.
>>> structure.container_size()
(4, 0)

Note

The number of remaining bits must be always zero or the structure declaration is incomplete.

Indexing

You can index all fields in a structure by calling the method index_fields(). The Index after the last field of the structure is returned.

>>> # Create a structure.
>>> structure = Structure(
...     version=Byte(),
...     id=Unsigned8(),
...     length=Decimal8(),
...     module=Char())
>>> # List the field indexes of the structure.
>>> structure.to_list('index')
[('Structure.version', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Structure.id', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Structure.length', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Structure.module', Index(byte=0, bit=0, address=0, base_address=0, update=False))]
>>> # List the field indexes of the structure as a CSV list.
>>> structure.to_csv('index.byte', 'index.address')
[{'id': 'Structure.version', 'index.byte': 0, 'index.address': 0},
 {'id': 'Structure.id', 'index.byte': 0, 'index.address': 0},
 {'id': 'Structure.length', 'index.byte': 0, 'index.address': 0},
 {'id': 'Structure.module', 'index.byte': 0, 'index.address': 0}]
>>> # View the structure field indexes as a JSON string.
>>> structure.to_json('index')
'{"version": [0, 0, 0, 0, false],
  "id":      [0, 0, 0, 0, false],
  "length":  [0, 0, 0, 0, false],
  "module":  [0, 0, 0, 0, false]}'
>>> # Index the fields in the structure.
>>> structure.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # Index the fields in the structure with a start index.
>>> structure.index_fields(index=Index())
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # List the field indexes of the structure.
>>> structure.to_list('index')
[('Structure.version', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Structure.id', Index(byte=1, bit=0, address=1, base_address=0, update=False)),
 ('Structure.length', Index(byte=2, bit=0, address=2, base_address=0, update=False)),
 ('Structure.module', Index(byte=3, bit=0, address=3, base_address=0, update=False))]
>>> # List the field indexes of the structure as a CSV list.
>>> structure.to_csv('index.byte', 'index.address')
[{'id': 'Structure.version', 'index.byte': 0, 'index.address': 0},
 {'id': 'Structure.id', 'index.byte': 1, 'index.address': 1},
 {'id': 'Structure.length', 'index.byte': 2, 'index.address': 2},
 {'id': 'Structure.module', 'index.byte': 3, 'index.address': 3}]
>>> # View the structure field indexes as a JSON string.
>>> structure.to_json('index')
'{"version": [0, 0, 0, 0, false],
  "id":      [1, 0, 1, 0, false],
  "length":  [2, 0, 2, 0, false],
  "module":  [3, 0, 3, 0, false]}'

De-Serializing

You can deserialize a byte stream with a structure by calling the method deserialize().

>>> # Create a structure.
>>> structure = Structure(
...     version=Byte(),
...     id=Unsigned8(),
...     length=Decimal8(),
...     module=Char())
>>> # Create a byte stream to be deserialized.
>>> bytestream = bytes.fromhex('01020946f00f00')
>>> # Deserialize the byte stream and map it to the structure.
>>> structure.deserialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.version', '0x1'),
 ('Structure.id', '0x2'),
 ('Structure.length', 9),
 ('Structure.module', 'F')]
>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.version', 'value': '0x1'},
 {'id': 'Structure.id', 'value': '0x2'},
 {'id': 'Structure.length', 'value': 9},
 {'id': 'Structure.module', 'value': 'F'}]
>>> # View the structure field values as a JSON string.
>>> structure.to_json()
'{"version": "0x1", "id": "0x2", "length": 9, "module": "F"}'

Serializing

You can serialize a byte stream with a structure by calling the method serialize().

>>> # Create an empty byte stream.
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> # Serialize the structure to the byte stream.
>>> structure.serialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # Display the byte stream.
>>> bytestream.hex()
'01020946'

or

>>> bytes(structure).hex()
'01020946'

Number of Members

You can get the number of structure members with the built-in function len().

>>> # Number of structure members.
>>> len(structure)
4

Access a Member

You can access a structure member with its name.

>>> # Access a structure member with its attribute name.
>>> structure.version
Byte(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
     alignment=Alignment(byte_size=1, bit_offset=0),
     bit_size=8,
     value='0x1')
>>> # Access a structure member with its key name.
>>> structure['version']
Byte(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
     alignment=Alignment(byte_size=1, bit_offset=0),
     bit_size=8,
     value='0x1')

Attributes of a Member Field

You can access the Field attributes of a field member in a structure with the attribute names:

>>> # Field name.
>>> structure.version.name
'Byte'
>>> # Field value.
>>> structure.version.value
'0x1'
>>> # Field bit size.
>>> structure.version.bit_size
8
>>> # Field alignment.
>>> structure.version.alignment
Alignment(byte_size=1, bit_offset=0)
>>> # Field alignment: byte size of the aligned field group.
>>> structure.version.alignment.byte_size
1
>>> # Field alignment: bit offset of the field in its field group.
>>> structure.version.alignment.bit_offset
0
>>> # Field byte order.
>>> structure.version.byte_order
Byteorder.auto = 'auto'
>>> # Field byte order value.
>>> structure.version.byte_order.value
'auto'
>>> # Field index.
>>> structure.version.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> # Field index: byte offset of the field in the byte stream.
>>> structure.version.index.byte
0
>>> # Field index: bit offset of the field relative to its byte offset.
>>> structure.version.index.bit
0
>>> # Field index: memory address of the field in the data source.
>>> structure.version.index.address
0
>>> # Field index: start address of the byte stream in the data source.
>>> structure.version.index.base_address
0
>>> # Field index: update request for the byte stream.
>>> structure.version.index.update
False

You can check if a structure member is a field.

>>> is_field(structure.version)
True

You can check what kind of field it is.

>>> # Field is a bit field.
>>> structure.version.is_bit()
False
>>> # Field is a boolean field.
>>> structure.version.is_bool()
False
>>> # Field is a decimal field.
>>> structure.version.is_decimal()
True
>>> # Field is a float field.
>>> structure.version.is_float()
False
>>> # Field is a pointer field.
>>> structure.version.is_pointer()
False
>>> # Field is a stream field.
>>> structure.version.is_stream()
False
>>> # Field is a string field.
>>> structure.version.is_string()
False

Iterate over Members

You can iterate over the structure member names.

>>> [name for name in structure.keys()]
['version', 'id', 'length', 'module']

You can iterate over all kind of member items of a structure.

>>> [(name, member.item_type) for name, member in structure.items()]
[('version', ItemClass.Byte = 42),
 ('id', ItemClass.Unsigned = 45),
 ('length', ItemClass.Decimal = 40),
 ('module', ItemClass.Char = 43)]

You can iterate over all kind of members of a structure.

>>> [member.item_type for member in structure.values()]
[ItemClass.Byte = 42,
 ItemClass.Unsigned = 45,
 ItemClass.Decimal = 40,
 ItemClass.Char = 43]

You can iterate over all field members of a structure.

>>> [member.name for member in structure.values() if is_field(member)]
['Byte', 'Unsigned8', 'Decimal8', 'Char']

View Field Attributes

You can view the attributes of each field of a structure as an ordered dictionary by calling the method view_fields(). Default attribute is the field value.

>>> # View the structure field values.
>>> structure.view_fields()
OrderedDict([('version', '0x1'),
             ('id', '0x2'),
             ('length', 9),
             ('module', 'F')])
>>> # View the structure field type names & field values.
>>> structure.view_fields('name', 'value')
OrderedDict([('version', {'name': 'Byte', 'value': '0x1'}),
             ('id', {'name': 'Unsigned8', 'value': '0x2'}),
             ('length', {'name': 'Decimal8', 'value': 9}),
             ('module', {'name': 'Char', 'value': 'F'})])
>>> # View the structure field indexes.
>>> structure.view_fields('index')
OrderedDict([('version',
              Index(byte=0, bit=0, address=0, base_address=0, update=False)),
             ('id',
              Index(byte=1, bit=0, address=1, base_address=0, update=False)),
             ('length',
              Index(byte=2, bit=0, address=2, base_address=0, update=False)),
             ('module',
              Index(byte=3, bit=0, address=3, base_address=0, update=False))])

Note

The attributes of each field for containers nested in the structure are viewed as well (chained method call).

View as a JSON string

You can view the attributes of each field of a structure as a JSON formatted string by calling the method to_json(). Default attribute is the field value.

>>> # View the structure field values as a JSON string.
>>> structure.to_json()
'{"version": "0x1", "id": "0x2", "length": 9, "module": "F"}'
>>> print(structure.to_json(indent=2))
{
  "version": "0x1",
  "id": "0x2",
  "length": 9,
  "module": "F"
}
>>> # View the structure field type names & field values as a JSON string.
>>> structure.to_json('name', 'value')
'{"version": {"name": "Byte", "value": "0x1"},
  "id": {"name": "Unsigned8", "value": "0x2"},
  "length": {"name": "Decimal8", "value": 9},
  "module": {"name": "Char", "value": "F"}}'
>>> # View the structure field indexes as a JSON string.
>>> structure.to_json('index')
'{"version": [0, 0, 0, 0, false],
  "id": [1, 0, 1, 0, false],
  "length": [2, 0, 2, 0, false],
  "module": [3, 0, 3, 0, false]}'

Note

The attributes of each field for containers nested in the structure are viewed as well (chained method call).

List Field Items

You can list all field items of a structure as a flatten list by calling the method field_items().

>>> # List the field items of the structure.
>>> structure.field_items()
[('version',
 Byte(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
      alignment=Alignment(byte_size=1, bit_offset=0),
      bit_size=8,
      value='0x1')),
('id',
 Unsigned8(index=Index(byte=1, bit=0, address=1, base_address=0, update=False),
           alignment=Alignment(byte_size=1, bit_offset=0),
           bit_size=8,
           value='0x2')),
('length',
 Decimal8(index=Index(byte=2, bit=0, address=2, base_address=0, update=False),
          alignment=Alignment(byte_size=1, bit_offset=0),
          bit_size=8,
          value=9)),
('module',
 Char(index=Index(byte=3, bit=0, address=3, base_address=0, update=False),
      alignment=Alignment(byte_size=1, bit_offset=0),
      bit_size=8,
      value='F'))]

List Field Attributes

You can list the attributes of each field of a structure as a flatten list by calling the method to_list(). Default attribute is the field value.

>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.version', '0x1'),
 ('Structure.id', '0x2'),
 ('Structure.length', 9),
 ('Structure.module', 'F')]
>>> # List the field type names & values of the structure.
>>> structure.to_list('name', 'value')
[('Structure.version', ('Byte', '0x1')),
 ('Structure.id', ('Unsigned8', '0x2')),
 ('Structure.length', ('Decimal8', 9)),
 ('Structure.module', ('Char', 'F'))]
>>> # List the field indexes of the structure.
>>> structure.to_list('index')
[('Structure.version', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Structure.id', Index(byte=1, bit=0, address=1, base_address=0, update=False)),
 ('Structure.length', Index(byte=2, bit=0, address=2, base_address=0, update=False)),
 ('Structure.module', Index(byte=3, bit=0, address=3, base_address=0, update=False))]

Note

The class name of the instance is used for the root name as long as no name is given.

You can list the attributes of each field of a structure as a flatten ordered dictionary by calling the method to_dict(). Default attribute is the field value.

>>> # List the field values of the structure.
>>> structure.to_dict()
OrderedDict([('Structure',
              OrderedDict([('version', '0x1'),
                           ('id', '0x2'),
                           ('length', 9),
                           ('module', 'F')]))])
>>> # List the field type names & values of the structure.
>>> structure.to_dict('name', 'value')
OrderedDict([('Structure',
              OrderedDict([('version', ('Byte', '0x1')),
                            ('id', ('Unsigned8', '0x2')),
                            ('length', ('Decimal8', 9)),
                            ('module', ('Char', 'F'))]))])
>>> # List the field indexes in the structure.
>>> structure.to_dict('index')
OrderedDict([('Structure',
              OrderedDict([('version', Index(byte=0, bit=0,
                                             address=0, base_address=0,
                                             update=False)),
                           ('id', Index(byte=1, bit=0,
                                        address=1, base_address=0,
                                        update=False)),
                           ('length', Index(byte=2, bit=0,
                                            address=2, base_address=0,
                                            update=False)),
                           ('module', Index(byte=3, bit=0,
                                            address=3, base_address=0,
                                            update=False))]))])

Note

The class name of the instance is used for the root name as long as no name is given.

You can list the attributes of each field of a structure as a flatten list of dictionaries containing the field path and the selected field attributes by calling the method to_csv(). Default attribute is the field value.

>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.version', 'value': '0x1'},
 {'id': 'Structure.id', 'value': '0x2'},
 {'id': 'Structure.length', 'value': 9},
 {'id': 'Structure.module', 'value': 'F'}]
>>> # List the field type names & values of the structure as a CSV list.
>>> structure.to_csv('name', 'value')
[{'id': 'Structure.version', 'name': 'Byte', 'value': '0x1'},
 {'id': 'Structure.id', 'name': 'Unsigned8', 'value': '0x2'},
 {'id': 'Structure.length', 'name': 'Decimal8', 'value': 9},
 {'id': 'Structure.module', 'name': 'Char', 'value': 'F'}]

Note

The class name of the instance is used for the root name as long as no name is given.

Write Field Attributes

You can write the attributes of each field of a structure to a .csv file by calling the method write_csv(). Default attribute is the field value.

>>> # List the field values of the structure as a CSV list.
>>> structure.to_csv()
[{'id': 'Structure.version', 'value': '0x1'},
 {'id': 'Structure.id', 'value': '0x2'},
 {'id': 'Structure.length', 'value': 9},
 {'id': 'Structure.module', 'value': 'F'}]
>>> # Save the structure field values to a '.csv' file.
>>> structure.write_csv("_static/structure.csv")

The generated .csv file for the structure looks like this:

id,value
Structure.version,0x1
Structure.id,0x2
Structure.length,9
Structure.module,F

Note

The class name of the instance is used for the root name as long as no name is given.

Save Field Attributes

You can save the attributes of each field of a structure to an .ini file by calling the method save(). Default attribute is the field value.

>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.version', '0x1'),
 ('Structure.id', '0x2'),
 ('Structure.length', 9),
 ('Structure.module', 'F')]
>>> # Save the structure field values to an '.ini' file.
>>> structure.save("_static/structure.ini")

The generated .ini file for the structure looks like this:

[Structure]
version = 0x1
id = 0x2
length = 9
module = F

Note

The class name of the instance is used for the section name as long as no section is given.

Load Field Values

You can load the value of each field of a structure from an .ini file by calling the method load().

>>> # Create a structure.
>>> structure = Structure(
...     version=Byte(),
...     id=Unsigned8(),
...     length=Decimal8(),
...     module=Char())
>>> # Load the structure field values from an '.ini' file.
>>> structure.load("_static/structure.ini")
[Structure]
Structure.version = 0x1
Structure.id = 0x2
Structure.length = 9
Structure.module = F
>>> # List the field values of the structure.
>>> structure.to_list()
[('Structure.version', '0x1'),
 ('Structure.id', '0x2'),
 ('Structure.length', 9),
 ('Structure.module', 'F')]

Note

The class name of the instance is used for the section name as long as no section is given.

Sequence

KonFoo has a Sequence class to map a consecutive area of a byte stream with different kind of members. The order how you append the members to the sequence defines the order how the members are deserialized and serialized by the built-in deserializer and serializer.

Member

A sequence member can be any field or container class.

Create a Sequence

You can create a sequence from a list of members.

>>> # Create a sequence.
>>> sequence = Sequence([
...     Byte(),
...     Unsigned8(),
...     Decimal8(),
...     Char()])
>>> # List the field values of the sequence.
>>> sequence.to_list()
[('Sequence[0]', '0x0'),
 ('Sequence[1]', '0x0'),
 ('Sequence[2]', 0),
 ('Sequence[3]', '\x00')]
>>> # List the field values of the sequence as a CSV list.
>>> sequence.to_csv()
[{'id': 'Sequence[0]', 'value': '0x0'},
 {'id': 'Sequence[1]', 'value': '0x0'},
 {'id': 'Sequence[2]', 'value': 0},
 {'id': 'Sequence[3]', 'value': '\x00'}]
>>> # View the sequence field values as a JSON string.
>>> sequence.to_json()
'["0x0", "0x0", 0, "\\u0000"]'

Append a Member

You can append a new member to the end of a sequence.

>>> # Create an empty sequence.
>>> sequence = Sequence()
>>> # Append a new member to the sequence.
>>> sequence.append(Unsigned8())
>>> # List the field values of the sequence.
>>> sequence.to_list()
[('Sequence[0]', '0x0')]
>>> # List the field values of the sequence as a CSV list.
>>> sequence.to_csv()
[{'id': 'Sequence[0]', 'value': '0x0'}]
>>> # View the sequence field values as a JSON string.
>>> sequence.to_json()
'["0x0"]'

Insert a Member

You can insert a new member at a given position in a sequence.

>>> # Insert a new member to the sequence.
>>> sequence.insert(0, Byte())
>>> # List the field values of the sequence.
>>> sequence.to_list()
[('Sequence[0]', '0x0'),
 ('Sequence[1]', '0x0')]
>>> # List the field values of the sequence as a CSV list.
>>> sequence.to_csv()
[{'id': 'Sequence[0]', 'value': '0x0'},
 {'id': 'Sequence[1]', 'value': '0x0'}]
>>> # View the sequence field values as a JSON string.
>>> sequence.to_json()
'["0x0", "0x0"]'

Extend a Sequence

You can extend a sequence with a list of new members.

>>> # Extend a sequence with a list of new members.
>>> sequence.extend([Decimal8(), Char()])
>>> # List the field values of the sequence.
>>> sequence.to_list()
[('Sequence[0]', '0x0'),
 ('Sequence[1]', '0x0'),
 ('Sequence[2]', 0),
 ('Sequence[3]', '\x00')]
>>> # List the field values of the sequence as a CSV list.
>>> sequence.to_csv()
[{'id': 'Sequence[0]', 'value': '0x0'},
 {'id': 'Sequence[1]', 'value': '0x0'},
 {'id': 'Sequence[2]', 'value': 0},
 {'id': 'Sequence[3]', 'value': '\x00'}]
>>> # View the sequence field values as a JSON string.
>>> sequence.to_json()
'["0x0", "0x0", 0, "\\u0000"]'

Initialize a Sequence

You can initialize the fields in a sequence by calling the method initialize_fields().

>>> # Create a sequence.
>>> sequence = Sequence([
...     Byte(),
...     Unsigned8(),
...     Decimal8(),
...     Char()])
>>> # List the field values of the sequence.
>>> sequence.to_list()
[('Sequence[0]', '0x0'),
 ('Sequence[1]', '0x0'),
 ('Sequence[2]', 0),
 ('Sequence[3]', '\x00')]
>>> # List the field values of the sequence as a CSV list.
>>> sequence.to_csv()
[{'id': 'Sequence[0]', 'value': '0x0'},
 {'id': 'Sequence[1]', 'value': '0x0'},
 {'id': 'Sequence[2]', 'value': 0},
 {'id': 'Sequence[3]', 'value': '\x00'}]
>>> # View the sequence field values as a JSON string.
>>> sequence.to_json()
'["0x0", "0x0", 0, "\\u0000"]'
>>> # Initialize the fields in the sequence.
>>> sequence.initialize_fields([1, 2, 9, 0x46])
>>> # List the field values of the sequence.
>>> sequence.to_list()
[('Sequence[0]', '0x1'),
 ('Sequence[1]', '0x2'),
 ('Sequence[2]', 9),
 ('Sequence[3]', 'F')]
>>> # List the field values of the sequence as a CSV list.
>>> sequence.to_csv()
[{'id': 'Sequence[0]', 'value': '0x1'},
 {'id': 'Sequence[1]', 'value': '0x2'},
 {'id': 'Sequence[2]', 'value': 9},
 {'id': 'Sequence[3]', 'value': 'F'}]
>>> # View the sequence field values as a JSON string.
>>> sequence.to_json()
'["0x1", "0x2", 9, "F"]'

Display a Sequence

You can display the sequence.

>>> # Create a sequence.
>>> sequence = Sequence([
...     Byte(),
...     Unsigned8(),
...     Decimal8(),
...     Char()])
>>> # Index the fields in the sequence.
>>> sequence.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # Display the sequence.
>>> sequence
[Byte(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
      alignment=Alignment(byte_size=1, bit_offset=0),
      bit_size=8,
      value='0x0'),
 Unsigned8(index=Index(byte=1, bit=0, address=1, base_address=0, update=False),
           alignment=Alignment(byte_size=1, bit_offset=0),
           bit_size=8,
           value='0x0'),
 Decimal8(index=Index(byte=2, bit=0, address=2, base_address=0, update=False),
          alignment=Alignment(byte_size=1, bit_offset=0),
          bit_size=8,
          value=0),
 Char(index=Index(byte=3, bit=0, address=3, base_address=0, update=False),
      alignment=Alignment(byte_size=1, bit_offset=0),
      bit_size=8,
      value='\x00')]

Metadata of a Sequence

You can get the metadata of the sequence by calling the method describe().

>>> # Get the description of the sequence.
>>> sequence.describe()
OrderedDict([('class', 'Sequence'),
             ('name', 'Sequence'),
             ('size', 4),
             ('type', 'Sequence'),
             ('member',
              [OrderedDict([('address', 0),
                            ('alignment', [1, 0]),
                            ('class', 'Byte'),
                            ('index', [0, 0]),
                            ('max', 255),
                            ('min', 0),
                            ('name', 'Sequence[0]'),
                            ('order', 'auto'),
                            ('signed', False),
                            ('size', 8),
                            ('type', 'Field'),
                            ('value', '0x0')]),
              OrderedDict([('address', 1),
                            ('alignment', [1, 0]),
                            ('class', 'Unsigned8'),
                            ('index', [1, 0]),
                            ('max', 255),
                            ('min', 0),
                            ('name', 'Sequence[1]'),
                            ('order', 'auto'),
                            ('signed', False),
                            ('size', 8),
                            ('type', 'Field'),
                            ('value', '0x0')]),
               OrderedDict([('address', 2),
                            ('alignment', [1, 0]),
                            ('class', 'Decimal8'),
                            ('index', [2, 0]),
                            ('max', 255),
                            ('min', 0),
                            ('name', 'Sequence[2]'),
                            ('order', 'auto'),
                            ('signed', False),
                            ('size', 8),
                            ('type', 'Field'),
                            ('value', 0)]),
               OrderedDict([('address', 3),
                            ('alignment', [1, 0]),
                            ('class', 'Char'),
                            ('index', [3, 0]),
                            ('max', 255),
                            ('min', 0),
                            ('name', 'Sequence[3]'),
                            ('order', 'auto'),
                            ('signed', False),
                            ('size', 8),
                            ('type', 'Field'),
                            ('value', '\x00')])])])
>>> json.dump(sequence.describe(), sys.stdout, indent=2)
{
  "class": "Sequence",
  "name": "Sequence",
  "size": 4,
  "type": "Sequence",
  "member": [
    {
      "address": 0,
      "alignment": [
        1,
        0
      ],
      "class": "Byte",
      "index": [
        0,
        0
      ],
      "max": 255,
      "min": 0,
      "name": "Sequence[0]",
      "order": "auto",
      "signed": false,
      "size": 8,
      "type": "Field",
      "value": "0x0"
    },
    {
      "address": 1,
      "alignment": [
        1,
        0
      ],
      "class": "Unsigned8",
      "index": [
        1,
        0
      ],
      "max": 255,
      "min": 0,
      "name": "Sequence[1]",
      "order": "auto",
      "signed": false,
      "size": 8,
      "type": "Field",
      "value": "0x0"
    },
    {
      "address": 2,
      "alignment": [
        1,
        0
      ],
      "class": "Decimal8",
      "index": [
        2,
        0
      ],
      "max": 255,
      "min": 0,
      "name": "Sequence[2]",
      "order": "auto",
      "signed": false,
      "size": 8,
      "type": "Field",
      "value": 0
    },
    {
      "address": 3,
      "alignment": [
        1,
        0
      ],
      "class": "Char",
      "index": [
        3,
        0
      ],
      "max": 255,
      "min": 0,
      "name": "Sequence[3]",
      "order": "auto",
      "signed": false,
      "size": 8,
      "type": "Field",
      "value": "\u0000"
    }
  ]
}

Size of a Sequence

You can get the size of a sequence as a tuple in the form of (number of bytes, number of remaining bits) by calling the method container_size().

>>> # Get the size of the sequence.
>>> sequence.container_size()
(4, 0)

Note

The number of remaining bits must be always zero or the sequence declaration is incomplete.

Indexing

You can index all fields in a sequence by calling the method index_fields(). The Index after the last field of the sequence is returned.

>>> # Create a sequence.
>>> sequence = Sequence([
...     Byte(),
...     Unsigned8(),
...     Decimal8(),
...     Char()])
>>> # List the field indexes of the sequence.
>>> sequence.to_list('index')
[('Sequence[0]', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Sequence[1]', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Sequence[2]', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Sequence[3]', Index(byte=0, bit=0, address=0, base_address=0, update=False))]
>>> # List the field indexes of the sequence as a CSV list.
>>> sequence.to_csv('index.byte', 'index.address')
[{'id': 'Sequence[0]', 'index.byte': 0, 'index.address': 0},
 {'id': 'Sequence[1]', 'index.byte': 0, 'index.address': 0},
 {'id': 'Sequence[2]', 'index.byte': 0, 'index.address': 0},
 {'id': 'Sequence[3]', 'index.byte': 0, 'index.address': 0}]
>>> # View the sequence field indexes as a JSON string.
>>> sequence.to_json('index')
'[[0, 0, 0, 0, false],
  [0, 0, 0, 0, false],
  [0, 0, 0, 0, false],
  [0, 0, 0, 0, false]]'
>>> # Index the fields in the sequence.
>>> sequence.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # Index the fields in the sequence with a start index.
>>> sequence.index_fields(index=Index())
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # List the field indexes of the sequence.
>>> sequence.to_list('index')
[('Sequence[0]', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Sequence[1]', Index(byte=1, bit=0, address=1, base_address=0, update=False)),
 ('Sequence[2]', Index(byte=2, bit=0, address=2, base_address=0, update=False)),
 ('Sequence[3]', Index(byte=3, bit=0, address=3, base_address=0, update=False))]
>>> # List the field indexes of the sequence as a CSV list.
>>> sequence.to_csv('index.byte', 'index.address')
[{'id': 'Sequence[0]', 'index.byte': 0, 'index.address': 0},
 {'id': 'Sequence[1]', 'index.byte': 1, 'index.address': 1},
 {'id': 'Sequence[2]', 'index.byte': 2, 'index.address': 2},
 {'id': 'Sequence[3]', 'index.byte': 3, 'index.address': 3}]
>>> # View the sequence field indexes as a JSON string.
>>> sequence.to_json('index')
'[[0, 0, 0, 0, false],
  [1, 0, 1, 0, false],
  [2, 0, 2, 0, false],
  [3, 0, 3, 0, false]]'

De-Serializing

You can deserialize a byte stream with a sequence by calling the method deserialize().

>>> # Create a sequence.
>>> sequence = Sequence([
...     Byte(),
...     Unsigned8(),
...     Decimal8(),
...     Char()])
>>> # Create a byte stream to be deserialized.
>>> bytestream = bytes.fromhex('01020946f00f00')
>>> # Deserialize the byte stream and map it to the sequence.
>>> sequence.deserialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # List the field values of the sequence.
>>> sequence.to_list()
[('Sequence[0]', '0x1'),
 ('Sequence[1]', '0x2'),
 ('Sequence[2]', 9),
 ('Sequence[3]', 'F')]
>>> # List the field values of the sequence as a CSV list.
>>> sequence.to_csv()
[{'id': 'Sequence[0]', 'value': '0x1'},
 {'id': 'Sequence[1]', 'value': '0x2'},
 {'id': 'Sequence[2]', 'value': 9},
 {'id': 'Sequence[3]', 'value': 'F'}]
>>> # View the sequence field values as a JSON string.
>>> sequence.to_json()
'["0x1", "0x2", 9, "F"]'

Serializing

You can serialize a byte stream with a sequence by calling the method serialize().

>>> # Create an empty byte stream.
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> # Serialize the sequence to the byte stream.
>>> sequence.serialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # View the byte stream.
>>> bytestream.hex()
'01020946'

or

>>> bytes(sequence).hex()
'01020946'

Number of Members

You can get the number of sequence members with the built-in function len().

>>> # Number of sequence members.
>>> len(sequence)
4

Access a Member

You can access a sequence member by its index.

>>> # Access a sequence member by its index.
>>> sequence[0]
Byte(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
     alignment=Alignment(byte_size=1, bit_offset=0),
     bit_size=8,
     value='0x1')

Attributes of a Member Field

You can access the Field attributes of a field member of a sequence with the attribute names:

>>> # Field name.
>>> sequence[0].name
'Byte'
>>> # Field value.
>>> sequence[0].value
'0x1'
>>> # Field bit size.
>>> sequence[0].bit_size
8
>>> # Field alignment.
>>> sequence[0].alignment
Alignment(byte_size=1, bit_offset=0)
>>> # Field alignment: byte size of the aligned field group.
>>> sequence[0].alignment.byte_size
1
>>> # Field alignment: bit offset of the field in its field group.
>>> sequence[0].alignment.bit_offset
0
>>> # Field byte order.
>>> sequence[0].byte_order
Byteorder.auto = 'auto'
>>> # Field byte order value.
>>> sequence[0].byte_order.value
'auto'
>>> # Field index.
>>> sequence[0].index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> # Field index: byte offset of the field in the byte stream.
>>> sequence[0].index.byte
0
>>> # Field index: bit offset of the field relative to its byte offset.
>>> sequence[0].index.bit
0
>>> # Field index: memory address of the field in the data source.
>>> sequence[0].index.address
0
>>> # Field index: start address of the byte stream in the data source.
>>> sequence[0].index.base_address
0
>>> # Field index: update request for the byte stream.
>>> sequence[0].index.update
False

You can check if a sequence member is a field.

>>> is_field(sequence[0])
True

You can check what kind of field it is.

>>> # Field is a bit field.
>>> sequence[0].is_bit()
False
>>> # Field is a boolean field.
>>> sequence[0].is_bool()
False
>>> # Field is a decimal field.
>>> sequence[0].is_decimal()
True
>>> # Field is a float field.
>>> sequence[0].is_float()
False
>>> # Field is a pointer field.
>>> sequence[0].is_pointer()
False
>>> # Field is a stream field.
>>> sequence[0].is_stream()
False
>>> # Field is a string field.
>>> sequence[0].is_string()
False

Iterate over Members

You can iterate over all kind of members of a sequence.

>>> [member.item_type for member in sequence]
[ItemClass.Byte = 42,
 ItemClass.Unsigned = 45,
 ItemClass.Decimal = 40,
 ItemClass.Char = 43]

You can iterate over all field members of a sequence.

>>> [member.name for member in sequence if is_field(member)]
['Byte', 'Unsigned8', 'Decimal8', 'Char']

View Field Attributes

You can view the attributes of each field of a sequence as a list by calling the method view_fields(). Default attribute is the field value.

>>> # View the sequence field values.
>>> sequence.view_fields()
['0x1', '0x2', 9, 'F']
>>> # View the sequence field type name & field values.
>>> sequence.view_fields('name', 'value')
[{'name': 'Byte', 'value': '0x1'},
 {'name': 'Unsigned8', 'value': '0x2'},
 {'name': 'Decimal8', 'value': 9},
 {'name': 'Char', 'value': 'F'}]
>>> # View the sequence field indexes.
>>> sequence.view_fields('index')
[Index(byte=0, bit=0, address=0, base_address=0, update=False),
 Index(byte=1, bit=0, address=1, base_address=0, update=False),
 Index(byte=2, bit=0, address=2, base_address=0, update=False),
 Index(byte=3, bit=0, address=3, base_address=0, update=False)]

Note

The attributes of each field for containers nested in the sequence are viewed as well (chained method call).

View as a JSON string

You can view the attributes of each field of a sequence as a JSON formatted string by calling the method to_json(). Default attribute is the field value.

>>> # View the sequence field values as a JSON string.
>>> sequence.to_json()
'["0x1", "0x2", 9, "F"]'
>>> print(sequence.to_json(indent=2))
[
  "0x1",
  "0x2",
  9,
  "F"
]
>>> # View the sequence field type names & field values as a JSON string.
>>> sequence.to_json('name', 'value')
'[{"name": "Byte", "value": "0x1"},
  {"name": "Unsigned8", "value": "0x2"},
  {"name": "Decimal8", "value": 9},
  {"name": "Char", "value": "F"}]'
>>> # View the sequence field indexes as a JSON string.
>>> sequence.to_json('index')
'[[0, 0, 0, 0, false],
  [1, 0, 1, 0, false],
  [2, 0, 2, 0, false],
  [3, 0, 3, 0, false]]'

Note

The attributes of each field for containers nested in the sequence are viewed as well (chained method call).

List Field Items

You can list all field items of a sequence as a flatten list by calling the method field_items().

>>> # List the field items of the sequence.
>>> sequence.field_items()
[('[0]', Byte(index=Index(byte=0, bit=0,
                          address=0, base_address=0,
                          update=False),
              alignment=Alignment(byte_size=1, bit_offset=0),
              bit_size=8,
              value='0x1')),
 ('[1]', Unsigned8(index=Index(byte=1, bit=0,
                               address=1, base_address=0,
                               update=False),
                   alignment=Alignment(byte_size=1, bit_offset=0),
                   bit_size=8,
                   value='0x2')),
 ('[2]', Decimal8(index=Index(byte=2, bit=0,
                              address=2, base_address=0,
                              update=False),
                  alignment=Alignment(byte_size=1, bit_offset=0),
                   bit_size=8,
                   value=9)),
 ('[3]', Char(index=Index(byte=3, bit=0,
                          address=3, base_address=0,
                          update=False),
              alignment=Alignment(byte_size=1, bit_offset=0),
              bit_size=8,
              value='F'))]

List Field Attributes

You can list the attributes of each field of a sequence as a flatten list by calling the method to_list(). Default attribute is the field value.

>>> # List the field values of the sequence.
>>> sequence.to_list()
[('Sequence[0]', '0x1'),
 ('Sequence[1]', '0x2'),
 ('Sequence[2]', 9),
 ('Sequence[3]', 'F')]
>>> # List the field type names & field values of the sequence.
>>> sequence.to_list('name', 'value')
[('Sequence[0]', ('Byte', '0x1')),
 ('Sequence[1]', ('Unsigned8', '0x2')),
 ('Sequence[2]', ('Decimal8', 9)),
 ('Sequence[3]', ('Char', 'F'))]
>>> # List the field indexes of the sequence.
>>> sequence.to_list('index')
[('Sequence[0]', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Sequence[1]', Index(byte=1, bit=0, address=1, base_address=0, update=False)),
 ('Sequence[2]', Index(byte=2, bit=0, address=2, base_address=0, update=False)),
 ('Sequence[3]', Index(byte=3, bit=0, address=3, base_address=0, update=False))]

Note

The class name of the instance is used for the root name as long as no name is given.

You can list the attributes of each field of a sequence as a flatten ordered dictionary by calling the method to_dict(). Default attribute is the field value.

>>> # List the field values of the sequence.
>>> sequence.to_dict()
OrderedDict([('Sequence',
              OrderedDict([('[0]', '0x1'),
                           ('[1]', '0x2'),
                           ('[2]', 9),
                           ('[3]', 'F')]))])
>>> # List the field type names & field values of the sequence.
>>> sequence.to_dict('name', 'value')
OrderedDict([('Sequence',
              OrderedDict([('[0]', ('Byte', '0x1')),
                           ('[1]', ('Unsigned8', '0x2')),
                           ('[2]', ('Decimal8', 9)),
                           ('[3]', ('Char', 'F'))]))])
>>> # List the field indexes of the sequence.
>>> sequence.to_dict('index')
OrderedDict([('Sequence',
              OrderedDict([('[0]', Index(byte=0, bit=0,
                                         address=0, base_address=0,
                                         update=False)),
                           ('[1]', Index(byte=1, bit=0,
                                         address=1, base_address=0,
                                         update=False)),
                           ('[2]', Index(byte=2, bit=0,
                                         address=2, base_address=0,
                                         update=False)),
                           ('[3]', Index(byte=3, bit=0,
                                         address=3, base_address=0,
                                         update=False))]))])

Note

The class name of the instance is used for the root name as long as no name is given.

You can list the attributes of each field of a sequence as a flatten list of dictionaries containing the field path and the selected field attributes by calling the method to_csv(). Default attribute is the field value.

>>> # List the field values of the sequence as a CSV list.
>>> sequence.to_csv()
[{'id': 'Sequence[0]', 'value': '0x1'},
 {'id': 'Sequence[1]', 'value': '0x2'},
 {'id': 'Sequence[2]', 'value': 9},
 {'id': 'Sequence[3]', 'value': 'F'}]
>>> # List the field type names & values of the sequence as a CSV list.
>>> sequence.to_csv('name', 'value')
[{'id': 'Sequence[0]', 'name': 'Byte', 'value': '0x1'},
 {'id': 'Sequence[1]', 'name': 'Unsigned8', 'value': '0x2'},
 {'id': 'Sequence[2]', 'name': 'Decimal8', 'value': 9},
 {'id': 'Sequence[3]', 'name': 'Char', 'value': 'F'}]

Note

The class name of the instance is used for the root name as long as no name is given.

Write Field Attributes

You can write the attributes of each field of a sequence to a .csv file by calling the method write_csv(). Default attribute is the field value.

>>> # List the field values of the sequence as a CSV list.
>>> sequence.to_csv()
[{'id': 'Sequence[0]', 'value': '0x1'},
 {'id': 'Sequence[1]', 'value': '0x2'},
 {'id': 'Sequence[2]', 'value': 9},
 {'id': 'Sequence[3]', 'value': 'F'}]
>>> # Save the structure field values to a '.csv' file.
>>> sequence.write_csv("_static/sequence.csv")

The generated .csv file for the structure looks like this:

id,value
Sequence[0],0x1
Sequence[1],0x2
Sequence[2],9
Sequence[3],F

Note

The class name of the instance is used for the root name as long as no name is given.

Save Field Attributes

You can save the attributes of each field of a sequence to an .ini file by calling the method save(). Default attribute is the field value.

>>> # List the field values of the sequence.
>>> sequence.to_list()
[('Sequence[0]', '0x1'),
 ('Sequence[1]', '0x2'),
 ('Sequence[2]', 9),
 ('Sequence[3]', 'F')]
>>> # Save the field values to an '.ini' file.
>>> sequence.save("_static/sequence.ini", nested=True)

The generated .ini file for the sequence looks like this:

[Sequence]
_[0] = 0x1
_[1] = 0x2
_[2] = 9
_[3] = F

Note

The class name of the instance is used for the section name as long as no section is given.

Load Field Values

You can load the value of each field of a sequence from an .ini file by calling the method load().

>>> # Create a sequence.
>>> sequence = Sequence([
...     Byte(),
...     Unsigned8(),
...     Decimal8(),
...     Char()])
>>> # Load the sequence field values from an '.ini' file.
>>> sequence.load("_static/sequence.ini")
[Sequence]
Sequence[0] = 0x1
Sequence[1] = 0x2
Sequence[2] = 9
Sequence[3] = F
>>> # List the field values of the sequence.
>>> sequence.to_list()
[('Sequence[0]', '0x1'),
 ('Sequence[1]', '0x2'),
 ('Sequence[2]', 9),
 ('Sequence[3]', 'F')]

Note

The class name of the instance is used for the section name as long as no section is given.

Array

KonFoo has an Array class to map a consecutive area of a byte stream with the same kind of array elements (member).

Array Element

An array element (member) can be any field or container class.

Define an Array

Define an array by using a class as the array element template.

>>> class ByteArray(Array):
...
...     def __init__(self, capacity=0):
...         # Array element class.
...         super().__init__(template=Byte, capacity=capacity)
>>> # Create an instance of the array.
>>> array = ByteArray(4)
>>> # List the field values of the array.
>>> array.to_list()
[('ByteArray[0]', '0x0'),
 ('ByteArray[1]', '0x0'),
 ('ByteArray[2]', '0x0'),
 ('ByteArray[3]', '0x0')]
>>> # List the field values of the array as a CSV list.
>>> array.to_csv()
[{'id': 'ByteArray[0]', 'value': '0x0'},
 {'id': 'ByteArray[1]', 'value': '0x0'},
 {'id': 'ByteArray[2]', 'value': '0x0'},
 {'id': 'ByteArray[3]', 'value': '0x0'}]
>>> # View the array field values as a JSON string.
>>> array.to_json()
'["0x0", "0x0", "0x0", "0x0"]'

Define an array by using an instance as the array element template.

>>> class ByteArray(Array):
...
...     def __init__(self, capacity=0):
...         # Array element instance.
...         super().__init__(template=Byte(), capacity=capacity)
>>> # Create an instance of the array.
>>> array = ByteArray(4)
>>> # List the field values of the array.
>>> array.to_list()
[('ByteArray[0]', '0x0'),
 ('ByteArray[1]', '0x0'),
 ('ByteArray[2]', '0x0'),
 ('ByteArray[3]', '0x0')]
>>> # List the field values of the array as a CSV list.
>>> array.to_csv()
[{'id': 'ByteArray[0]', 'value': '0x0'},
 {'id': 'ByteArray[1]', 'value': '0x0'},
 {'id': 'ByteArray[2]', 'value': '0x0'},
 {'id': 'ByteArray[3]', 'value': '0x0'}]
>>> # View the array field values as a JSON string.
>>> array.to_json()
'["0x0", "0x0", "0x0", "0x0"]'

Important

Only recommended for primitive field instances without nested members. For an array element instance with nested members the nested members will be assigned to all other array elements of the array.

Array of Data Object Pointers

Define an array of pointers by using a concrete data object pointer class for the the attached data object as the array element template.

>>> # Define an data object pointer class.
>>> class BytePointer(Pointer):
...     def __init__(self):
...         super().__init__(Byte())
>>> # Create an instance of the array.
>>> array = Array(BytePointer, 2)
>>> # List the field values of the array and nested pointers.
>>> array.to_list(nested=True)
[('Array[0]', '0x0'),
 ('Array[0].data', '0x0'),
 ('Array[1]', '0x0'),
 ('Array[1].data', '0x0')]
>>> # List the field values of the array and nested pointers as a CSV list.
>>> array.to_csv(nested=True)
[{'id': 'Array[0]', 'value': '0x0'},
 {'id': 'Array[0].data', 'value': '0x0'},
 {'id': 'Array[1]', 'value': '0x0'},
 {'id': 'Array[1].data', 'value': '0x0'}]
>>> # View the array and nested pointers field values as a JSON string.
>>> array.to_json(nested=True)
'[{"value": "0x0", "data": "0x0"},
  {"value": "0x0", "data": "0x0"}]'
>>> # Set field value of the pointer of the fist array element.
>>> array[0].value = 1
>>> # Set field value of the data object of the fist array element.
>>> array[0].data.value = 2
>>> # List the field values of the array and nested pointers.
>>> array.to_list(nested=True)
[('Array[0]', '0x1'),
 ('Array[0].data', '0x2'),
 ('Array[1]', '0x0'),
 ('Array[1].data', '0x0')]
>>> # List the field values of the array and nested pointers as a CSV list.
>>> array.to_csv(nested=True)
[{'id': 'Array[0]', 'value': '0x1'},
 {'id': 'Array[0].data', 'value': '0x2'},
 {'id': 'Array[1]', 'value': '0x0'},
 {'id': 'Array[1].data', 'value': '0x0'}]
>>> # View the array field values as a JSON string.
>>> array.to_json(nested=True)
'[{"value": "0x1", "data": "0x2"},
  {"value": "0x0", "data": "0x0"}]'

Array Element Factory

An array element factory is necessary whenever you use an array element which needs arguments and/or keywords to be instantiated and contains nested members, in this case you must assign an array element factory as the array element template to the array.

For primitive field instances without nested members, no factory is required, because the array is able to produce complete copies of a primitive field instance.

>>> # Define an array element factory.
>>> class FieldPointerFactory:
...     """ A factory class to produce a pointer array element to any field. """
...
...     def __init__(self, template):
...         # Data object: field template (instance or class).
...         self.template = template
...
...     def _create_data_object(self):
...         """ Produces the data object attached to the pointer. """
...         if is_field(self.template):
...             # Copy data object instance from instance template
...             return copy.copy(self.template)
...         elif callable(self.template):
...             # Create data object instance from class template
...             data_object = self.template()
...             if is_field(data_object):
...                 return data_object
...             else:
...                 raise FactoryTypeError(self, self.template, data_object)
...         else:
...             raise MemberTypeError(self, self.template)
...
...     def __call__(self):
...         """ Produces the array element. """
...         return Pointer(self._create_data_object())
>>> # Create an instance of the array.
>>> array = Array(FieldPointerFactory(Byte()), 2)
>>> # List the field values of the array and nested pointers.
>>> array.to_list(nested=True)
[('Array[0]', '0x0'),
 ('Array[0].data', '0x0'),
 ('Array[1]', '0x0'),
 ('Array[1].data', '0x0')]
>>> # List the field values of the array and nested pointers as a CSV list.
>>> array.to_csv(nested=True)
[{'id': 'Array[0]', 'value': '0x0'},
 {'id': 'Array[0].data', 'value': '0x0'},
 {'id': 'Array[1]', 'value': '0x0'},
 {'id': 'Array[1].data', 'value': '0x0'}]
>>> # View the array and nested pointers field values as a JSON string.
>>> array.to_json(nested=True)
'[{"value": "0x0", "data": "0x0"},
  {"value": "0x0", "data": "0x0"}]'
>>> # Set field value of the pointer of the fist array element.
>>> array[0].value = 1
>>> # Set field value of the data object of the fist array element.
>>> array[0].data.value = 2
>>> # List the field values of the array and nested pointers.
>>> array.to_list(nested=True)
[('Array[0]', '0x1'),
 ('Array[0].data', '0x2'),
 ('Array[1]', '0x0'),
 ('Array[1].data', '0x0')]
>>> # List the field values of the array and nested pointers as a CSV list.
>>> array.to_csv(nested=True)
[{'id': 'Array[0]', 'value': '0x1'},
 {'id': 'Array[0].data', 'value': '0x2'},
 {'id': 'Array[1]', 'value': '0x0'},
 {'id': 'Array[1].data', 'value': '0x0'}]
>>> # View the array and nested pointers field values as a JSON string.
>>> array.to_json(nested=True)
'[{"value": "0x1", "data": "0x2"},
  {"value": "0x0", "data": "0x0"}]'

Otherwise by creating an array using an instance with nested members as the array element template assigns the nested members of the array element template to all other array elements of the array.

>>> # Create an instance of the array with nested members and without a factory.
>>> array = Array(Pointer(Byte()), 2)
>>> # List the field values of the array and nested pointers.
>>> array.to_list(nested=True)
[('Array[0]', '0x0'),
 ('Array[0].data', '0x0'),
 ('Array[1]', '0x0'),
 ('Array[1].data', '0x0')]
>>> # List the field values of the array and nested pointers as a CSV list.
>>> array.to_csv(nested=True)
[{'id': 'Array[0]', 'value': '0x0'},
 {'id': 'Array[0].data', 'value': '0x0'},
 {'id': 'Array[1]', 'value': '0x0'},
 {'id': 'Array[1].data', 'value': '0x0'}]
>>> # View the array and nested pointers field values as a JSON string.
>>> array.to_json(nested=True)
'[{"value": "0x0", "data": "0x0"},
  {"value": "0x0", "data": "0x0"}]'
>>> # Set field value of the pointer of the fist array element.
>>> array[0].value = 1
>>> # Set field value of the data object of the fist array element.
>>> array[0].data.value = 2
>>> # List the field values of the array and nested pointers.
>>> array.to_list(nested=True)
[('Array[0]', '0x1'),
 ('Array[0].data', '0x2'),
 ('Array[1]', '0x0'),
 ('Array[1].data', '0x2')]
>>> # List the field values of the array and nested pointers as a CSV list.
>>> array.to_csv(nested=True)
[{'id': 'Array[0]', 'value': '0x1'},
 {'id': 'Array[0].data', 'value': '0x2'},
 {'id': 'Array[1]', 'value': '0x0'},
 {'id': 'Array[1].data', 'value': '0x2'}]
>>> # View the array and nested pointers field values as a JSON string.
>>> array.to_json(nested=True)
'[{"value": "0x1", "data": "0x2"},
  {"value": "0x0", "data": "0x2"}]'

Create an Array

You can create an array by assigning an array element class or array element factory to the array and the number of array elements the array holds.

>>> # Create an array with an array element class.
>>> array = Array(template=Byte, capacity=4)
>>> array = Array(Byte, 4)
>>> # List the field values of the array.
>>> array.to_list()
[('Array[0]', '0x0'),
 ('Array[1]', '0x0'),
 ('Array[2]', '0x0'),
 ('Array[3]', '0x0')]
>>> # List the field values of the array as a CSV list.
>>> array.to_csv()
[{'id': 'Array[0]', 'value': '0x0'},
 {'id': 'Array[1]', 'value': '0x0'},
 {'id': 'Array[2]', 'value': '0x0'},
 {'id': 'Array[3]', 'value': '0x0'}]
>>> # View the array field values as a JSON string.
>>> array.to_json()
'["0x0", "0x0", "0x0", "0x0"]'

Resize an Array

You can resize an array by calling resize().

>>> # Create an empty array.
>>> array = Array(Byte)
>>> # List the field values of the array.
>>> array.to_list()
[]
>>> # View the array field values as a JSON string.
>>> array.to_json()
'[]'
>>> # Resize the array.
>>> array.resize(4)
>>> # List the field values of the array.
>>> array.to_list()
[('Array[0]', '0x0'),
 ('Array[1]', '0x0'),
 ('Array[2]', '0x0'),
 ('Array[3]', '0x0')]
>>> # List the field values of the array as a CSV list.
>>> array.to_csv()
[{'id': 'Array[0]', 'value': '0x0'},
 {'id': 'Array[1]', 'value': '0x0'},
 {'id': 'Array[2]', 'value': '0x0'},
 {'id': 'Array[3]', 'value': '0x0'}]
>>> # View the array field values as a JSON string.
>>> array.to_json()
'["0x0", "0x0", "0x0", "0x0"]'

Initialize an Array

You can initialize the fields in an array by calling the method initialize_fields().

>>> # Create an array.
>>> array = Array(Byte, 4)
>>> # List the field values of the array.
>>> array.to_list()
[('Array[0]', '0x0'),
 ('Array[1]', '0x0'),
 ('Array[2]', '0x0'),
 ('Array[3]', '0x0')]
>>> # List the field values of the array as a CSV list.
>>> array.to_csv()
[{'id': 'Array[0]', 'value': '0x0'},
 {'id': 'Array[1]', 'value': '0x0'},
 {'id': 'Array[2]', 'value': '0x0'},
 {'id': 'Array[3]', 'value': '0x0'}]
>>> # View the array field values as a JSON string.
>>> array.to_json()
'["0x0", "0x0", "0x0", "0x0"]'
>>> # Initialize the fields of the array with a fill pattern.
>>> array.initialize_fields([1 ,2])
>>> # List the field values of the array.
>>> array.to_list()
[('Array[0]', '0x1'),
 ('Array[1]', '0x2'),
 ('Array[2]', '0x1'),
 ('Array[3]', '0x2')]
>>> # List the field values of the array as a CSV list.
>>> array.to_csv()
[{'id': 'Array[0]', 'value': '0x1'},
 {'id': 'Array[1]', 'value': '0x2'},
 {'id': 'Array[2]', 'value': '0x1'},
 {'id': 'Array[3]', 'value': '0x2'}]
>>> # View the array field values as a JSON string.
>>> array.to_json()
'["0x1", "0x2", "0x1", "0x2"]'

Display an Array

You can display the array.

>>> # Create an array.
>>> array = Array(Byte, 4)
>>> # Index the fields in the array.
>>> array.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # Display the array.
>>> array
[Byte(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
      alignment=Alignment(byte_size=1, bit_offset=0),
      bit_size=8,
      value='0x0'),
 Byte(index=Index(byte=1, bit=0, address=1, base_address=0, update=False),
      alignment=Alignment(byte_size=1, bit_offset=0),
      bit_size=8,
      value='0x0'),
 Byte(index=Index(byte=2, bit=0, address=2, base_address=0, update=False),
      alignment=Alignment(byte_size=1, bit_offset=0),
      bit_size=8,
      value='0x0'),
 Byte(index=Index(byte=3, bit=0, address=3, base_address=0, update=False),
      alignment=Alignment(byte_size=1, bit_offset=0),
      bit_size=8,
      value='0x0')]

Metadata of an Array

You can get the metadata of the array by calling the method describe().

>>> # Get the description of the array.
>>> array.describe()
OrderedDict([('class', 'Array'),
             ('name', 'Array'),
             ('size', 4),
             ('type', 'Array'),
             ('member',
              [OrderedDict([('address', 0),
                            ('alignment', [1, 0]),
                            ('class', 'Byte'),
                            ('index', [0, 0]),
                            ('max', 255),
                            ('min', 0),
                            ('name', 'Array[0]'),
                            ('order', 'auto'),
                            ('signed', False),
                            ('size', 8),
                            ('type', 'Field'),
                            ('value', '0x0')]),
              OrderedDict([('address', 1),
                            ('alignment', [1, 0]),
                            ('class', 'Byte'),
                            ('index', [1, 0]),
                            ('max', 255),
                            ('min', 0),
                            ('name', 'Array[1]'),
                            ('order', 'auto'),
                            ('signed', False),
                            ('size', 8),
                            ('type', 'Field'),
                            ('value', '0x0')]),
               OrderedDict([('address', 2),
                            ('alignment', [1, 0]),
                            ('class', 'Byte'),
                            ('index', [2, 0]),
                            ('max', 255),
                            ('min', 0),
                            ('name', 'Array[2]'),
                            ('order', 'auto'),
                            ('signed', False),
                            ('size', 8),
                            ('type', 'Field'),
                            ('value', '0x0')]),
               OrderedDict([('address', 3),
                            ('alignment', [1, 0]),
                            ('class', 'Byte'),
                            ('index', [3, 0]),
                            ('max', 255),
                            ('min', 0),
                            ('name', 'Array[3]'),
                            ('order', 'auto'),
                            ('signed', False),
                            ('size', 8),
                            ('type', 'Field'),
                            ('value', '0x0')])])])
>>> json.dump(array.describe(), sys.stdout, indent=2)
{
  "class": "Array",
  "name": "Array",
  "size": 4,
  "type": "Array",
  "member": [
    {
      "address": 0,
      "alignment": [
        1,
        0
      ],
      "class": "Byte",
      "index": [
        0,
        0
      ],
      "max": 255,
      "min": 0,
      "name": "Array[0]",
      "order": "auto",
      "signed": false,
      "size": 8,
      "type": "Field",
      "value": "0x0"
    },
    {
      "address": 1,
      "alignment": [
        1,
        0
      ],
      "class": "Byte",
      "index": [
        1,
        0
      ],
      "max": 255,
      "min": 0,
      "name": "Array[1]",
      "order": "auto",
      "signed": false,
      "size": 8,
      "type": "Field",
      "value": "0x0"
    },
    {
      "address": 2,
      "alignment": [
        1,
        0
      ],
      "class": "Byte",
      "index": [
        2,
        0
      ],
      "max": 255,
      "min": 0,
      "name": "Array[2]",
      "order": "auto",
      "signed": false,
      "size": 8,
      "type": "Field",
      "value": "0x0"
    },
    {
      "address": 3,
      "alignment": [
        1,
        0
      ],
      "class": "Byte",
      "index": [
        3,
        0
      ],
      "max": 255,
      "min": 0,
      "name": "Array[3]",
      "order": "auto",
      "signed": false,
      "size": 8,
      "type": "Field",
      "value": "0x0"
    }
  ]
}

Size of an Array

You can get the size of an array as a tuple in the form of (number of bytes, number of remaining bits) by calling the method container_size().

>>> # Get the size of the array.
>>> array.container_size()
(4, 0)

Note

The number of remaining bits must be always zero or the array declaration is incomplete.

Indexing

You can index all fields in an array by calling the method index_fields(). The Index after the last field of the array is returned.

>>> # Create an array.
>>> array = Array(Byte, 4)
>>> # List the field indexes of the array.
>>> array.to_list('index')
[('Array[0]', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Array[1]', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Array[2]', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Array[3]', Index(byte=0, bit=0, address=0, base_address=0, update=False))]
>>> # List the field indexes of the array as a CSV list.
>>> array.to_csv('index.byte', 'index.address')
[{'id': 'Array[0]', 'index.byte': 0, 'index.address': 0},
 {'id': 'Array[1]', 'index.byte': 0, 'index.address': 0},
 {'id': 'Array[2]', 'index.byte': 0, 'index.address': 0},
 {'id': 'Array[3]', 'index.byte': 0, 'index.address': 0}]
>>> # View the array field indexes as a JSON string.
>>> array.to_json('index')
'[[0, 0, 0, 0, false],
  [0, 0, 0, 0, false],
  [0, 0, 0, 0, false],
  [0, 0, 0, 0, false]]'
>>> # Index the fields in the array.
>>> array.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # Index the fields in the array with a start index.
>>> array.index_fields(index=Index())
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # List the field indexes of the array.
>>> array.to_list('index')
[('Array[0]', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Array[1]', Index(byte=1, bit=0, address=1, base_address=0, update=False)),
 ('Array[2]', Index(byte=2, bit=0, address=2, base_address=0, update=False)),
 ('Array[3]', Index(byte=3, bit=0, address=3, base_address=0, update=False))]
>>> # List the field indexes of the array as a CSV list.
>>> array.to_csv('index.byte', 'index.address')
[{'id': 'Array[0]', 'index.byte': 0, 'index.address': 0},
 {'id': 'Array[1]', 'index.byte': 1, 'index.address': 1},
 {'id': 'Array[2]', 'index.byte': 2, 'index.address': 2},
 {'id': 'Array[3]', 'index.byte': 3, 'index.address': 3}]
>>> # View the array field indexes as a JSON string.
>>> array.to_json('index')
'[[0, 0, 0, 0, false],
  [1, 0, 1, 0, false],
  [2, 0, 2, 0, false],
  [3, 0, 3, 0, false]]'

De-Serializing

You can deserialize a byte stream with an array by calling the method deserialize().

>>> # Create an array.
>>> array = Array(Byte, 4)
>>> # Create a byte stream to be deserialized.
>>> bytestream = bytes.fromhex('0102030405060708')
>>> # Deserialize the byte stream and map it to the array.
>>> array.deserialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # List the field values of the array.
>>> array.to_list()
[('Array[0]', '0x1'),
 ('Array[1]', '0x2'),
 ('Array[2]', '0x3'),
 ('Array[3]', '0x4')]
>>> # List the field values of the array as a CSV list.
>>> array.to_csv()
[{'id': 'Array[0]', 'value': '0x1'},
 {'id': 'Array[1]', 'value': '0x2'},
 {'id': 'Array[2]', 'value': '0x3'},
 {'id': 'Array[3]', 'value': '0x4'}]
>>> # View the array field values as a JSON string.
>>> array.to_json()
'["0x1", "0x2", "0x3", "0x4"]'

Serializing

You can serialize a byte stream with an array by calling the method serialize().

>>> # Create an empty byte stream.
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> # Serialize the array to the byte stream.
>>> array.serialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # View the byte stream.
>>> bytestream.hex()
'01020304'

or

>>> bytes(array).hex()
'01020304'

Number of Array Elements

You can get the number of array elements with the built-in function len().

>>> # Number of the array elements.
>>> len(array)
4

Access an Array Element

You can access an array element of an array by its index.

>>> # Access an array member by its index.
>>> array[0]
Byte(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
     alignment=Alignment(byte_size=1, bit_offset=0),
     bit_size=8,
     value='0x1')

Attributes of an Array Element Field

You can access the Field attributes of an field array element of an array with the attribute names:

>>> # Field name.
>>> array[0].name
'Byte'
>>> # Field value.
>>> array[0].value
'0x1'
>>> # Field bit size.
>>> array[0].bit_size
8
>>> # Field alignment.
>>> array[0].alignment
Alignment(byte_size=1, bit_offset=0)
>>> # Field alignment: byte size of the aligned field group.
>>> array[0].alignment.byte_size
1
>>> # Field alignment: bit offset of the field in its field group.
>>> array[0].alignment.bit_offset
0
>>> # Field byte order.
>>> array[0].byte_order
Byteorder.auto = 'auto'
>>> # Field byte order value.
>>> array[0].byte_order.value
'auto'
>>> # Field index.
>>> array[0].index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> # Field index: byte offset of the field in the byte stream.
>>> array[0].index.byte
0
>>> # Field index: bit offset of the field relative to its byte offset.
>>> array[0].index.bit
0
>>> # Field index: memory address of the field in the data source.
>>> array[0].index.address
0
>>> # Field index: start address of the byte stream in the data source.
>>> array[0].index.base_address
0
>>> # Field index: update request for the byte stream.
>>> array[0].index.update
False

You can check if an array element is a field.

>>> is_field(array[0])
True

You can check what kind of field it is.

>>> # Field is a bit field.
>>> array[0].is_bit()
False
>>> # Field is a boolean field.
>>> array[0].is_bool()
False
>>> # Field is a decimal field.
>>> array[0].is_decimal()
True
>>> # Field is a float field.
>>> array[0].is_float()
False
>>> # Field is a pointer field.
>>> array[0].is_pointer()
False
>>> # Field is a stream field.
>>> array[0].is_stream()
False
>>> # Field is a string field.
>>> array[0].is_string()
False

Iterate over Array Elements

You can iterate over the array elements of an array.

>>> [element.item_type for element in array]
[ItemClass.Byte = 42,
 ItemClass.Byte = 42,
 ItemClass.Byte = 42,
 ItemClass.Byte = 42]

View Field Attributes

You can view the attributes of each field of an array as a list by calling the method view_fields(). Default attribute is the field value.

>>> # View the array field values.
>>> array.view_fields()
['0x1', '0x2', '0x3', '0x4']
>>> # View the array field type names & field values.
>>> array.view_fields('name', 'value')
[{'name': 'Byte', 'value': '0x1'},
 {'name': 'Byte', 'value': '0x2'},
 {'name': 'Byte', 'value': '0x3'},
 {'name': 'Byte', 'value': '0x4'}]
>>> # View the array field indexes.
>>> array.view_fields('index')
[Index(byte=0, bit=0, address=0, base_address=0, update=False),
 Index(byte=1, bit=0, address=1, base_address=0, update=False),
 Index(byte=2, bit=0, address=2, base_address=0, update=False),
 Index(byte=3, bit=0, address=3, base_address=0, update=False)]

Note

The attributes of each field for containers nested in the array are viewed as well (chained method call).

View as a JSON string

You can view the attributes of each field of an array as a JSON formatted string by calling the method to_json(). Default attribute is the field value.

>>> # View the array field values as a JSON string.
>>> array.to_json()
'["0x1", "0x2", "0x3", "0x4"]'
>>> print(array.to_json(indent=2))
[
  "0x1",
  "0x2",
  "0x3",
  "0x4"
]
>>> # View the array field type names & field values as a JSON string.
>>> array.to_json('name', 'value')
'[{"name": "Byte", "value": "0x1"},
  {"name": "Byte", "value": "0x2"},
  {"name": "Byte", "value": "0x3"},
  {"name": "Byte", "value": "0x4"}]'
>>> # View the array field indexes as a JSON string.
>>> array.to_json('index')
'[[0, 0, 0, 0, false],
  [1, 0, 1, 0, false],
  [2, 0, 2, 0, false],
  [3, 0, 3, 0, false]]'

Note

The attributes of each field for containers nested in the array are viewed as well (chained method call).

List Field Items

You can list all field items of an array as a flatten list by calling the method field_items().

>>> # List the field items of the array.
>>> array.field_items()
[('[0]', Byte(index=Index(byte=0, bit=0,
                          address=0, base_address=0,
                          update=False),
              alignment=Alignment(byte_size=1, bit_offset=0),
              bit_size=8,
              value='0x1')),
 ('[1]', Byte(index=Index(byte=1, bit=0,
                          address=1, base_address=0,
                          update=False),
              alignment=Alignment(byte_size=1, bit_offset=0),
              bit_size=8,
              value='0x2')),
 ('[2]', Byte(index=Index(byte=2, bit=0,
                          address=2, base_address=0,
                          update=False),
              alignment=Alignment(byte_size=1, bit_offset=0),
              bit_size=8,
              value='0x3')),
 ('[3]', Byte(index=Index(byte=3, bit=0,
                          address=3, base_address=0,
                          update=False),
              alignment=Alignment(byte_size=1, bit_offset=0),
              bit_size=8,
              value='0x4'))]

List Field Attributes

You can list the attributes of each field of an array as a flatten list by calling the method to_list(). Default attribute is the field value.

>>> # List the field values of the array.
>>> array.to_list()
[('Array[0]', '0x1'),
 ('Array[1]', '0x2'),
 ('Array[2]', '0x3'),
 ('Array[3]', '0x4')]
>>> # List the field type names & field values of the array.
>>> array.to_list('name', 'value')
[('Array[0]', ('Byte', '0x1')),
 ('Array[1]', ('Byte', '0x2')),
 ('Array[2]', ('Byte', '0x3')),
 ('Array[3]', ('Byte', '0x4'))]
>>> # List the field indexes of the array.
>>> array.to_list('index')
[('Array[0]', Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Array[1]', Index(byte=1, bit=0, address=1, base_address=0, update=False)),
 ('Array[2]', Index(byte=2, bit=0, address=2, base_address=0, update=False)),
 ('Array[3]', Index(byte=3, bit=0, address=3, base_address=0, update=False))]

Note

The class name of the instance is used for the root name as long as no name is given.

You can list the attribute of each field of an array as a flatten ordered dictionary by calling the method to_dict(). Default attribute is the field value.

>>> # List the field values of the array.
>>> array.to_dict()
OrderedDict([('Array',
              OrderedDict([('[0]', '0x1'),
                           ('[1]', '0x2'),
                           ('[2]', '0x3'),
                           ('[3]', '0x4')]))])
>>> # List the field type names & field values of the array.
>>> array.to_dict('name', 'value')
OrderedDict([('Array',
              OrderedDict([('[0]', ('Byte', '0x1')),
                           ('[1]', ('Byte', '0x2')),
                           ('[2]', ('Byte', '0x3')),
                           ('[3]', ('Byte', '0x4'))]))])
>>> # List the field indexes of the array.
>>> array.to_dict('index')
OrderedDict([('Array',
              OrderedDict([('[0]', Index(byte=0, bit=0,
                                         address=0, base_address=0,
                                         update=False)),
                           ('[1]', Index(byte=1, bit=0,
                                         address=1, base_address=0,
                                         update=False)),
                           ('[2]', Index(byte=2, bit=0,
                                         address=2, base_address=0,
                                         update=False)),
                           ('[3]', Index(byte=3, bit=0,
                                         address=3, base_address=0,
                                         update=False))]))])

Note

The class name of the instance is used for the root name as long as no name is given.

You can list the attributes of each field of a array as a flatten list of dictionaries containing the field path and the selected field attributes by calling the method to_csv(). Default attribute is the field value.

>>> # List the field values of the array as a CSV list.
>>> array.to_csv()
[{'id': 'Array[0]', 'value': '0x1'},
 {'id': 'Array[1]', 'value': '0x2'},
 {'id': 'Array[2]', 'value': '0x3'},
 {'id': 'Array[3]', 'value': '0x4'}]
>>> # List the field values of the array as a CSV list.
>>> array.to_csv('name', 'value')
[{'id': 'Array[0]', 'name': 'Byte', 'value': '0x1'},
 {'id': 'Array[1]', 'name': 'Byte', 'value': '0x2'},
 {'id': 'Array[2]', 'name': 'Byte', 'value': '0x3'},
 {'id': 'Array[3]', 'name': 'Byte', 'value': '0x4'}]

Note

The class name of the instance is used for the root name as long as no name is given.

Write Field Attributes

You can write the attributes of each field of a array to a .csv file by calling the method write_csv(). Default attribute is the field value.

>>> # List the field values of the array as a CSV list.
>>> array.to_csv()
[{'id': 'Array[0]', 'value': '0x1'},
 {'id': 'Array[1]', 'value': '0x2'},
 {'id': 'Array[2]', 'value': '0x3'},
 {'id': 'Array[3]', 'value': '0x4'}]
>>> # Save the structure field values to a '.csv' file.
>>> array.write_csv("_static/array.csv")

The generated .csv file for the structure looks like this:

id,value
Array[0],0x1
Array[1],0x2
Array[2],0x3
Array[3],0x4

Note

The class name of the instance is used for the root name as long as no name is given.

Save Field Attributes

You can save the attributes of each field of an array to an .ini file by calling the method save(). Default attribute is the field value.

>>> # List the field values of the array.
>>> array.to_list()
[('Array[0]', '0x1'),
 ('Array[1]', '0x2'),
 ('Array[2]', '0x3'),
 ('Array[3]', '0x4')]
>>> # Save the array field values to an '.ini' file.
>>> array.save("_static/array.ini", nested=True)

The generated .ini file for the array looks like this:

[Array]
_[0] = 0x1
_[1] = 0x2
_[2] = 0x3
_[3] = 0x4

Note

The class name of the instance is used for the section name as long as no section is given.

Load Field Values

You can load the value of each field of an array from an .ini file by calling the method load().

>>> # Create an array.
>>> array = Array(Byte, 4)
>>> # Load the array field values from an '.ini' file.
>>> array.load("_static/array.ini")
[Array]
Array[0] = 0x1
Array[1] = 0x2
Array[2] = 0x3
Array[3] = 0x4
>>> # List the field values of the array.
>>> array.to_list()
[('Array[0]', '0x1'),
 ('Array[1]', '0x2'),
 ('Array[2]', '0x3'),
 ('Array[3]', '0x4')]

Note

The class name of the instance is used for the section name as long as no section is given.

Pointer

KonFoo has a Pointer class to reference a memory area in a data source to be mapped with its attached data object.

The Pointer class provides an interface to read the necessary amount of bytes for its attached data object through a byte stream provider from a data source.

The Pointer class provides an interface to write the field values of any container or field in its attached data object through a byte stream provider to the data source.

KonFoo provides the following specialized pointer fields

Relative Pointer

KonFoo has a RelativePointer class. The only difference between the a pointer field and a relative pointer field is that the data object is relative addressed by a relative pointer field instead of absolute addressed.

KonFoo provides the following specialized relative pointer fields

Data Object

A data object of a pointer field can be any field or container class.

Define a Data Object

Define a data object by defining an data object class.

>>> class DataObject(Structure):
...
...     def __init__(self):
...         super().__init__()
...         self.size = Decimal(16)
...         self.item = Pointer()
...         self.index_fields()
>>> # Create an instance of the data object.
>>> data_object = DataObject()
>>> # List the field values of the data object.
>>> data_object.to_list()
[('DataObject.size', 0),
 ('DataObject.item', '0x0')]
>>> # List the field values of the data object as a CSV list.
>>> data_object.to_csv()
[{'id': 'DataObject.size', 'value': 0},
 {'id': 'DataObject.item', 'value': '0x0'}]
>>> # View the data object field values as a JSON string.
>>> data_object.to_json()
'{"size": 0, "item": "0x0"}'
>>> # List the field values of the data object and nested pointers.
>>> data_object.to_list(nested=True)
[('DataObject.size', 0),
 ('DataObject.item', '0x0')]
>>> # List the field values of the data object and nested pointers as a CSV list.
>>> data_object.to_csv(nested=True)
[{'id': 'DataObject.size', 'value': 0},
 {'id': 'DataObject.item', 'value': '0x0'}]
>>> # View the data object and nested pointers field values as a JSON string.
>>> data_object.to_json(nested=True)
'{"size": 0,
  "item": {"value": "0x0",
           "data": null}}'

Define a Data Object Pointer

Define a data object pointer class for the data object attached to the pointer.

>>> class DataObjectPointer(Pointer):
...
...     def __init__(self, address=None, byte_order=BYTEORDER):
...         super().__init__(template=DataObject(),
...                          address=address,
...                          data_order=byte_order)
>>> # Create an instance of the pointer.
>>> pointer = DataObjectPointer()
>>> # List the field values of the pointer.
>>> pointer.to_list()
[('DataObjectPointer.field', '0x0'),
 ('DataObjectPointer.data.size', 0),
 ('DataObjectPointer.data.item', '0x0')]
>>> # List the field values of the pointer as a CSV list.
>>> pointer.to_csv()
[{'id': 'DataObjectPointer.field', 'value': '0x0'},
 {'id': 'DataObjectPointer.data.size', 'value': 0},
 {'id': 'DataObjectPointer.data.item', 'value': '0x0'}]
>>> # View the pointer field values as a JSON string.
>>> pointer.to_json()
'{"value": "0x0",
  "data": {"size": 0,
           "item": "0x0"}}'
>>> # List the field values of the pointer and nested pointers.
>>> pointer.to_list(nested=True)
[('DataObjectPointer.field', '0x0'),
 ('DataObjectPointer.data.size', 0),
 ('DataObjectPointer.data.item', '0x0')]
>>> # List the field values of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv(nested=True)
[{'id': 'DataObjectPointer.field', 'value': '0x0'},
 {'id': 'DataObjectPointer.data.size', 'value': 0},
 {'id': 'DataObjectPointer.data.item', 'value': '0x0'}]
>>> # View the pointer and nested pointers field values as a JSON string.
>>> pointer.to_json(nested=True)
'{"value": "0x0",
  "data": {"size": 0,
           "item": {"value": "0x0",
                    "data": null}}}'

Nest Pointers

You can nest pointer.

>>> # Create an nested pointer with no data object attached.
>>> pointer = Pointer(Pointer())
>>> # List the field values of the pointer.
>>> pointer.to_list()
[('Pointer.field', '0x0'),
 ('Pointer.data', '0x0')]
>>> # List the field values of the pointer as a CSV list.
>>> pointer.to_csv()
[{'id': 'Pointer.field', 'value': '0x0'},
 {'id': 'Pointer.data', 'value': '0x0'}]
>>> # View the pointer field values as a JSON string.
>>> pointer.to_json()
'{"value": "0x0",
  "data": "0x0"}'
>>> # List the field values of the pointer and nested pointers.
>>> pointer.to_list(nested=True)
[('Pointer.field', '0x0'),
 ('Pointer.data', '0x0')]
>>> # List the field values of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv(nested=True)
[{'id': 'Pointer.field', 'value': '0x0'},
 {'id': 'Pointer.data', 'value': '0x0'}]
>>> # View the pointer and nested pointers field values as a JSON string.
>>> pointer.to_json(nested=True)
'{"value": "0x0",
  "data": {"value": "0x0",
           "data": null}}'
>>> # Create an nested pointer with a data object attached.
>>> pointer = Pointer(Pointer(Byte()))
>>> # List the field values of the pointer.
>>> pointer.to_list()
[('Pointer.field', '0x0'),
 ('Pointer.data', '0x0')]
>>> # List the field values of the pointer as a CSV list.
>>> pointer.to_csv()
[{'id': 'Pointer.field', 'value': '0x0'},
 {'id': 'Pointer.data', 'value': '0x0'}]
>>> # View the pointer field values as a JSON string.
>>> pointer.to_json()
'{"value": "0x0",
  "data": "0x0"}'
>>> # List the field values of the pointer and nested pointers.
>>> pointer.to_list(nested=True)
[('Pointer.field', '0x0'),
 ('Pointer.data', '0x0'),
 ('Pointer.data.data', '0x0')]
>>> # List the field values of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv(nested=True)
[{'id': 'Pointer.field', 'value': '0x0'},
 {'id': 'Pointer.data', 'value': '0x0'},
 {'id': 'Pointer.data.data', 'value': '0x0'}]
>>> # View the pointer and nested pointers field values as a JSON string.
>>> pointer.to_json(nested=True)
'{"value": "0x0",
  "data": {"value": "0x0",
           "data": "0x0"}}'

Access the Data Object

You can access the data object attached to a pointer with the data attribute of a pointer field.

>>> # Create a nested pointer.
>>> pointer = Pointer(Pointer(Byte()))
>>> # Index the pointer field and the fields of the attached data object.
>>> pointer.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # Access the data object referenced the pointer field.
>>> pointer.data
Pointer(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
        alignment=Alignment(byte_size=4, bit_offset=0),
        bit_size=32,
        value='0x0')
>>> # Access the data object referenced a nested pointer field.
>>> pointer.data.data
Byte(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
     alignment=Alignment(byte_size=1, bit_offset=0),
     bit_size=8,
     value='0x0')

You can check if a data object is a field.

>>> is_field(pointer.data)
True

You can check what kind of field it is.

>>> # Field is a bit field.
>>> pointer.data.is_bit()
False
>>> # Field is a boolean field.
>>> pointer.data.is_bool()
False
>>> # Field is a decimal field.
>>> pointer.data.is_decimal()
True
>>> # Field is a float field.
>>> pointer.data.is_float()
False
>>> # Field is a pointer field.
>>> pointer.data.is_pointer()
True
>>> # Field is a stream field.
>>> pointer.data.is_stream()
False
>>> # Field is a string field.
>>> pointer.data.is_string()
False

Address of the Data Object

You can get the data source address of the data object attached to the pointer with the address attribute of a pointer field.

>>> # Data source address of the data object referenced by the pointer.
>>> pointer.address
0

Byte Order of the Data Object

You can get the byte order used by the pointer to deserialize or serialize its attached data object with the data_byte_order attribute of a pointer field.

>>> # Byte order to de-/serialize the data object attached to the pointer.
>>> pointer.data_byte_order
Byteorder.little = 'little'
>>> pointer.data_byte_order.value
'little'

Note

The default byte order for a data object is little endian.

You can set the byte order used by the pointer to deserialize or serialize its attached data object with the data_byte_order attribute of a pointer field.

>>> # Set byte order to de-/serialize the data objects referenced by the pointer.
>>> pointer.data_byte_order = 'big'
>>> # Byte order to de-/serialize the data objects referenced by the pointer.
>>> pointer.data_byte_order
Byteorder.big = 'big'

Byte Stream for the Data Object

You can get the internal byte stream used by the pointer to deserialize or serialize its attached data object with the bytestream attribute of a pointer field.

>>> # Get the internal byte stream of the pointer.
>>> pointer.bytestream
''

You can set the internal byte stream used by the pointer to deserialize or serialize its attached data object with the bytestream attribute of a pointer field.

>>> # Set the internal byte stream of the pointer.
>>> pointer.bytestream = '000000000000'
>>> pointer.bytestream
'000000000000'

Declare on the fly

You can declare a data object on the fly.

>>> # Create a data object.
>>> data_object = Structure(
...     size = Decimal(16),
...     item = Pointer(String()))
>>> # List the field values of the data object.
>>> data_object.to_list()
[('Structure.size', 0),
 ('Structure.item', '0x0')]
>>> # List the field values of the data object as a CSV list.
>>> data_object.to_csv()
[{'id': 'Structure.size', 'value': 0},
 {'id': 'Structure.item', 'value': '0x0'}]
>>> # View the data object field values as a JSON string.
>>> data_object.to_json()
'{"size": 0, "item": "0x0"}'
>>> # List the field values of the data object and nested pointers.
>>> data_object.to_list(nested=True)
[('Structure.size', 0),
 ('Structure.item', '0x0'),
 ('Structure.item.data', '')]
>>> # List the field values of the data object and nested pointers as a CSV list.
>>> data_object.to_csv(nested=True)
[{'id': 'Structure.size', 'value': 0},
 {'id': 'Structure.item', 'value': '0x0'},
 {'id': 'Structure.item.data', 'value': ''}]
>>> # View the data object and nested pointers field values as a JSON string.
>>> data_object.to_json(nested=True)
'{"size": 0,
  "item": {"value": "0x0",
           "data": ""}}'

You can declare a pointer on the fly.

>>> # Create a pointer for the data object.
>>> pointer = Pointer(data_object)
>>> # List the field values of the pointer.
>>> pointer.to_list()
[('Pointer.field', '0x0'),
 ('Pointer.data.size', 0),
 ('Pointer.data.item', '0x0')]
>>> # List the field values of the pointer as a CSV list.
>>> pointer.to_csv()
[{'id': 'Pointer.field', 'value': '0x0'},
 {'id': 'Pointer.data.size', 'value': 0},
 {'id': 'Pointer.data.item', 'value': '0x0'}]
>>> # View the pointer field values as a JSON string.
>>> pointer.to_json()
'{"value": "0x0",
  "data": {"size": 0,
           "item": "0x0"}}'
>>> # List all field values of the pointer and nested pointers.
>>> pointer.to_list(nested=True)
[('Pointer.field', '0x0'),
 ('Pointer.data.size', 0),
 ('Pointer.data.item', '0x0'),
 ('Pointer.data.item.data', '')]
>>> # List the field values of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv(nested=True)
[{'id': 'Pointer.field', 'value': '0x0'},
 {'id': 'Pointer.data.size', 'value': 0},
 {'id': 'Pointer.data.item', 'value': '0x0'},
 {'id': 'Pointer.data.item.data', 'value': ''}]
>>> # View the pointer and nested pointers field values as a JSON string.
>>> pointer.to_json(nested=True)
'{"value": "0x0",
  "data": {"size": 0,
           "item": {"value": "0x0",
                    "data": ""}}}'

Initialize a Pointer

You can initialize the fields in a pointer by calling the method initialize_fields().

>>> # Create a pointer with a nested pointer.
>>> pointer = Pointer(
...     Structure(
...         size=Decimal(16),
...         item=Pointer(String(14))))
>>> # List the field values of the pointer and nested pointers.
>>> pointer.to_list(nested=True)
[('Pointer.field', '0x0'),
 ('Pointer.data.size', 0),
 ('Pointer.data.item', '0x0'),
 ('Pointer.data.item.data', '')]
>>> # List the field values of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv(nested=True)
[{'id': 'Pointer.field', 'value': '0x0'},
 {'id': 'Pointer.data.size', 'value': 0},
 {'id': 'Pointer.data.item', 'value': '0x0'},
 {'id': 'Pointer.data.item.data', 'value': ''}]
>>> # View the pointer and nested pointers field values as a JSON string.
>>> pointer.to_json(nested=True)
'{"value": "0x0",
  "data": {"size": 0,
           "item": {"value": "0x0",
                    "data": ""}}}'
>>> # Initialize the fields values of the pointer and its attached data object.
>>> pointer.initialize_fields({
...     'value': 0x1,
...     'data': {
...         'size': 14,
...         'item': {
...             'value': 0x10,
...             'data': 'Konfoo is Fun'
...         }
...     }
... })
>>> # List the field values of the pointer and nested pointers.
>>> pointer.to_list(nested=True)
[('Pointer.field', '0x1'),
 ('Pointer.data.size', 14),
 ('Pointer.data.item', '0x10'),
 ('Pointer.data.item.data', 'Konfoo is Fun')]
>>> # List the field values of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv(nested=True)
[{'id': 'Pointer.field', 'value': '0x1'},
 {'id': 'Pointer.data.size', 'value': 14},
 {'id': 'Pointer.data.item', 'value': '0x10'},
 {'id': 'Pointer.data.item.data', 'value': 'Konfoo is Fun'}]
>>> # View the pointer and nested pointers field values as a JSON string.
>>> pointer.to_json(nested=True)
'{"value": "0x1",
  "data": {"size": 14,
           "item": {"value": "0x10",
                    "data": "Konfoo is Fun"}}}'

Display a Pointer

You can display a pointer field.

>>> # Create a pointer.
>>> pointer = Pointer(
...     Structure(
...         size=Decimal(16),
...         item=Pointer(String())))
>>> # Index the pointer field and its attached data object.
>>> pointer.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # Display the pointer field.
>>> pointer
Pointer(index=Index(byte=0, bit=0,
                    address=0, base_address=0,
                    update=False),
        alignment=Alignment(byte_size=4, bit_offset=0),
        bit_size=32,
        value='0x0')

Display the Data Object

You can display the data object of a pointer field.

>>> # Display the data object referenced by the pointer
>>> pointer.data
Structure([('size',
            Decimal(index=Index(byte=0, bit=0,
                                address=0, base_address=0,
                                update=False),
                    alignment=Alignment(byte_size=2, bit_offset=0),
                    bit_size=16,
                    value=0)),
           ('item',
            Pointer(index=Index(byte=2, bit=0,
                                address=2, base_address=0,
                                update=False),
                    alignment=Alignment(byte_size=4, bit_offset=0),
                    bit_size=32,
                    value='0x0'))])

Metadata of a Pointer

You can get the metadata of a pointer by calling the method describe().

>>> # Get the description of the pointer.
>>> pointer.describe()
OrderedDict([('address', 0),
             ('alignment', [4, 0]),
             ('class', 'Pointer'),
             ('index', [0, 0]),
             ('max', 4294967295),
             ('min', 0),
             ('name', 'Pointer'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 32),
             ('type', 'Pointer'),
             ('value', '0x0'),
             ('member',
              [OrderedDict([('class', 'Structure'),
                            ('name', 'data'),
                            ('size', 2),
                            ('type', 'Structure'),
                            ('member',
                             [OrderedDict([('address', 0),
                                           ('alignment', [2, 0]),
                                           ('class', 'Decimal16'),
                                           ('index', [0, 0]),
                                           ('max', 65535),
                                           ('min', 0),
                                           ('name', 'size'),
                                           ('order', 'auto'),
                                           ('signed', False),
                                           ('size', 16),
                                           ('type', 'Field'),
                                           ('value', 0)]),
                              OrderedDict([('address', 2),
                                           ('alignment', [4, 0]),
                                           ('class', 'Pointer'),
                                           ('index', [2, 0]),
                                           ('max', 4294967295),
                                           ('min', 0),
                                           ('name', 'item'),
                                           ('order', 'auto'),
                                           ('signed', False),
                                           ('size', 32),
                                           ('type', 'Pointer'),
                                           ('value', '0x0'),
                                           ('member',
                                            [OrderedDict([('address', 0),
                                                          ('alignment', [0, 0]),
                                                          ('class', 'String'),
                                                          ('index', [0, 0]),
                                                          ('name', 'data'),
                                                          ('order', 'auto'),
                                                          ('size', 0),
                                                          ('type', 'Field'),
                                                          ('value',
                                                           '')])])])])])])])
>>> json.dump(pointer.describe(), sys.stdout, indent=2)
{
  "address": 0,
  "alignment": [
    4,
    0
  ],
  "class": "Pointer",
  "index": [
    0,
    0
  ],
  "max": 4294967295,
  "min": 0,
  "name": "Pointer",
  "order": "auto",
  "signed": false,
  "size": 32,
  "type": "Pointer",
  "value": "0x0",
  "member": [
    {
      "class": "Structure",
      "name": "data",
      "size": 2,
      "type": "Structure",
      "member": [
        {
          "address": 0,
          "alignment": [
            2,
            0
          ],
          "class": "Decimal16",
          "index": [
            0,
            0
          ],
          "max": 65535,
          "min": 0,
          "name": "size",
          "order": "auto",
          "signed": false,
          "size": 16,
          "type": "Field",
          "value": 0
        },
        {
          "address": 2,
          "alignment": [
            4,
            0
          ],
          "class": "Pointer",
          "index": [
            2,
            0
          ],
          "max": 4294967295,
          "min": 0,
          "name": "item",
          "order": "auto",
          "signed": false,
          "size": 32,
          "type": "Pointer",
          "value": "0x0",
          "member": [
            {
              "address": 0,
              "alignment": [
                0,
                0
              ],
              "class": "String",
              "index": [
                0,
                0
              ],
              "name": "data",
              "order": "auto",
              "size": 0,
              "type": "Field",
              "value": ""
            }
          ]
        }
      ]
    }
  ]
}

Size of the Data Object

You can get the byte size of the data object attached to the pointer with the data_size attribute of a pointer field.

>>> # Byte size of the data object attached to the pointer.
>>> pointer.data_size
6

Indexing

You can index the pointer field and each field of the data object attached to the pointer field by calling the method index_fields(). The Index after the pointer field is returned.

>>> # Create a pointer with a nested pointer.
>>> pointer = Pointer(
...     Structure(
...         size=Decimal(16),
...         item=Pointer(String(14))))
>>> # Initialize the fields values.
>>> pointer.initialize_fields({
...     'value': 0x1,
...     'data': {
...         'size': 14,
...         'item': {
...             'value': 0x10,
...             'data': 'Konfoo is Fun'}}})
>>> # List the field indexes of the pointer and nested pointers.
>>> pointer.to_list('index', nested=True)
[('Pointer.field',
 Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Pointer.data.size',
 Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Pointer.data.item',
 Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Pointer.data.item.data',
 Index(byte=0, bit=0, address=0, base_address=0, update=False))]
>>> # List the field indexes of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv('index.byte', 'index.address', nested=True)
[{'id': 'Pointer.field', 'index.byte': 0, 'index.address': 0},
 {'id': 'Pointer.data.size', 'index.byte': 0, 'index.address': 0},
 {'id': 'Pointer.data.item', 'index.byte': 0, 'index.address': 0},
 {'id': 'Pointer.data.item.data', 'index.byte': 0, 'index.address': 0}]
>>> # View the pointer and nested pointers field indexes as a JSON string.
>>> pointer.to_json('index', nested=True)
'{"value": [0, 0, 0, 0, false],
  "data": {"size": [0, 0, 0, 0, false],
           "item": {"value": [0, 0, 0, 0, false],
                    "data": [0, 0, 0, 0, false]}}}'
>>> # Index the pointer field and the data object fields.
>>> pointer.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # Index the pointer field and the data object fields with a start index.
>>> pointer.index_fields(index=Index())
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # List the field indexes of the pointer and nested pointers.
>>> pointer.to_list('index', nested=True)
 [('Pointer.field',
  Index(byte=0, bit=0, address=0, base_address=0, update=False)),
  ('Pointer.data.size',
  Index(byte=0, bit=0, address=1, base_address=1, update=False)),
  ('Pointer.data.item',
  Index(byte=2, bit=0, address=3, base_address=1, update=False)),
  ('Pointer.data.item.data',
  Index(byte=0, bit=0, address=0, base_address=0, update=False))]
>>> # List the field indexes of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv('index.byte', 'index.address', nested=True)
[{'id': 'Pointer.field', 'index.byte': 0, 'index.address': 0},
 {'id': 'Pointer.data.size', 'index.byte': 0, 'index.address': 1},
 {'id': 'Pointer.data.item', 'index.byte': 2, 'index.address': 3},
 {'id': 'Pointer.data.item.data', 'index.byte': 0, 'index.address': 0}]
>>> # View the pointer and nested pointers field indexes as a JSON string.
>>> pointer.to_json('index', nested=True)
'{"value": [0, 0, 0, 0, false],
  "data": {"size": [0, 0, 1, 1, false],
           "item": {"value": [2, 0, 3, 1, false],
                    "data": [0, 0, 0, 0, false]}}}'
>>> # Index the pointer field and the fields of the data object and nested pointers.
>>> pointer.index_fields(nested=True)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # List the field indexes of the pointer and nested pointers.
>>> pointer.to_list('index', nested=True)
[('Pointer.field',
  Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Pointer.data.size',
  Index(byte=0, bit=0, address=1, base_address=1, update=False)),
 ('Pointer.data.item',
  Index(byte=2, bit=0, address=3, base_address=1, update=False)),
 ('Pointer.data.item.data',
  Index(byte=0, bit=0, address=16, base_address=16, update=False))]
>>> # List the field indexes of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv('index.byte', 'index.address', nested=True)
[{'id': 'Pointer.field', 'index.byte': 0, 'index.address': 0},
 {'id': 'Pointer.data.size', 'index.byte': 0, 'index.address': 1},
 {'id': 'Pointer.data.item', 'index.byte': 2, 'index.address': 3},
 {'id': 'Pointer.data.item.data', 'index.byte': 0, 'index.address': 16}]
>>> # View the pointer and nested pointers field indexes as a JSON string.
>>> pointer.to_json('index', nested=True)
'{"value": [0, 0, 0, 0, false],
  "data": {"size": [0, 0, 1, 1, false],
           "item": {"value": [2, 0, 3, 1, false],
                    "data": [0, 0, 16, 16, false]}}}'

Index the Pointer Field

You can index the pointer field by calling the method index_field(). The Index after the pointer field is returned.

>>> # Create a pointer.
>>> pointer = Pointer(
...     Structure(
...         size=Decimal(16),
...         item=Pointer(String(14))))
>>> # Initialize the fields values.
>>> pointer.initialize_fields({
...     'value': 0x1,
...     'data': {
...         'size': 14,
...         'item': {
...             'value': 0x10,
...             'data': 'Konfoo is Fun'}}})
>>> # List the field indexes of the pointer and nested pointers.
>>> pointer.to_list('index', nested=True)
[('Pointer.field',
 Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Pointer.data.size',
 Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Pointer.data.item',
 Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Pointer.data.item.data',
 Index(byte=0, bit=0, address=0, base_address=0, update=False))]
>>> # List the field indexes of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv('index.byte', 'index.address', nested=True)
[{'id': 'Pointer.field', 'index.byte': 0, 'index.address': 0},
 {'id': 'Pointer.data.size', 'index.byte': 0, 'index.address': 0},
 {'id': 'Pointer.data.item', 'index.byte': 0, 'index.address': 0},
 {'id': 'Pointer.data.item.data', 'index.byte': 0, 'index.address': 0}]
>>> # View the pointer and nested pointers field indexes as a JSON string.
>>> pointer.to_json('index', nested=True)
'{"value": [0, 0, 0, 0, false],
  "data": {"size": [0, 0, 0, 0, false],
           "item": {"value": [0, 0, 0, 0, false],
                    "data": [0, 0, 0, 0, false]}}}'
>>> # Index the pointer field.
>>> pointer.index_field()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # Index the pointer field with a start index.
>>> pointer.index_field(index=Index())
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # List the field indexes of the pointer and nested pointers.
>>> pointer.to_list('index', nested=True)
[('Pointer.field',
 Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Pointer.data.size',
 Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Pointer.data.item',
 Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Pointer.data.item.data',
 Index(byte=0, bit=0, address=0, base_address=0, update=False))]
>>> # List the field indexes of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv('index.byte', 'index.address', nested=True)
[{'id': 'Pointer.field', 'index.byte': 0, 'index.address': 0},
 {'id': 'Pointer.data.size', 'index.byte': 0, 'index.address': 0},
 {'id': 'Pointer.data.item', 'index.byte': 0, 'index.address': 0},
 {'id': 'Pointer.data.item.data', 'index.byte': 0, 'index.address': 0}]
>>> # View the pointer and nested pointers field indexes as a JSON string.
>>> pointer.to_json('index', nested=True)
'{"value": [0, 0, 0, 0, false],
  "data": {"size": [0, 0, 0, 0, false],
           "item": {"value": [0, 0, 0, 0, false],
                    "data": [0, 0, 0, 0, false]}}}'

Index the Data Object

You can index each field of the data object attached to the pointer field by calling the method index_data()

>>> # Create a pointer with a nested pointer.
>>> pointer = Pointer(
...     Structure(
...         size=Decimal(16),
...         item=Pointer(String(14))))
>>> # Initialize the fields values.
>>> pointer.initialize_fields({
...     'value': 0x1,
...     'data': {
...         'size': 14,
...         'item': {
...             'value': 0x10,
...             'data': 'Konfoo is Fun'}}})
>>> # List the field indexes of the pointer and nested pointers.
>>> pointer.to_list('index', nested=True)
[('Pointer.field',
  Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Pointer.data.size',
  Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Pointer.data.item',
  Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Pointer.data.item.data',
 Index(byte=0, bit=0, address=0, base_address=0, update=False))]
>>> # List the field indexes of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv('index.byte', 'index.address', nested=True)
[{'id': 'Pointer.field', 'index.byte': 0, 'index.address': 0},
 {'id': 'Pointer.data.size', 'index.byte': 0, 'index.address': 0},
 {'id': 'Pointer.data.item', 'index.byte': 0, 'index.address': 0},
 {'id': 'Pointer.data.item.data', 'index.byte': 0, 'index.address': 0}]
>>> # View the pointer and nested pointers field indexes as a JSON string.
>>> pointer.to_json('index', nested=True)
'{"value": [0, 0, 0, 0, false],
  "data": {"size": [0, 0, 0, 0, false],
           "item": {"value": [0, 0, 0, 0, false],
                    "data": [0, 0, 0, 0, false]}}}'
>>> # Index the data object and nested pointers of the pointer.
>>> pointer.index_data()
>>> # List the field indexes of the pointer and nested pointers.
>>> pointer.to_list('index', nested=True)
[('Pointer.field',
  Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Pointer.data.size',
  Index(byte=0, bit=0, address=1, base_address=1, update=False)),
 ('Pointer.data.item',
  Index(byte=2, bit=0, address=3, base_address=1, update=False)),
 ('Pointer.data.item.data',
 Index(byte=0, bit=0, address=16, base_address=16, update=False))]
>>> # List the field indexes of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv('index.byte', 'index.address', nested=True)
[{'id': 'Pointer.field', 'index.byte': 0, 'index.address': 0},
 {'id': 'Pointer.data.size', 'index.byte': 0, 'index.address': 1},
 {'id': 'Pointer.data.item', 'index.byte': 2, 'index.address': 3},
 {'id': 'Pointer.data.item.data', 'index.byte': 0, 'index.address': 16}]
>>> # View the pointer and nested pointers field indexes as a JSON string.
>>> pointer.to_json('index', nested=True)
'{"value": [0, 0, 0, 0, false],
  "data": {"size": [0, 0, 1, 1, false],
           "item": {"value": [2, 0, 3, 1, false],
                    "data": [0, 0, 16, 16, false]}}}'

Reading

You can read the byte stream used by the pointer to deserialize its attached data object from a data source through a byte stream provider by calling the method read_from() of a pointer field.

Note

Further information is provided by the reading chapter.

De-Serializing

You can deserialize the pointer field from a byte stream and the attached data object from the internal byte stream of a pointer by calling the method deserialize().

>>> # Create a pointer with a nested pointer.
>>> pointer = Pointer(
...     Structure(
...         size=Decimal(16),
...         item=Pointer(String(14))))
>>> # List the field values of the pointer and nested pointers
>>> pointer.to_list(nested=True)
[('Pointer.field', '0x0'),
 ('Pointer.data.size', 0),
 ('Pointer.data.item', '0x0'),
 ('Pointer.data.item.data', '')]
>>> # List the field values of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv(nested=True)
[{'id': 'Pointer.field', 'value': '0x0'},
 {'id': 'Pointer.data.size', 'value': 0},
 {'id': 'Pointer.data.item', 'value': '0x0'},
 {'id': 'Pointer.data.item.data', 'value': ''}]
>>> # View the pointer and nested pointers field values as a JSON string.
>>> pointer.to_json(nested=True)
'{"value": "0x0",
  "data": {"size": 0,
           "item": {"value": "0x0",
                    "data": ""}}}'
>>> # Internal byte stream of the pointer
>>> pointer.bytestream
''
>>> # Internal byte stream of the nested pointer
>>> pointer.data.item.bytestream
''
>>> # Deserialize the pointer field from the byte stream.
>>> pointer.deserialize(bytes.fromhex('01000000f00f00'))
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # List the field values of the pointer and nested pointers.
>>> pointer.to_list(nested=True)
[('Pointer.field', '0x1'),
 ('Pointer.data.size', 0),
 ('Pointer.data.item', '0x0'),
 ('Pointer.data.item.data', '')]
>>> # List the field values of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv(nested=True)
[{'id': 'Pointer.field', 'value': '0x1'},
 {'id': 'Pointer.data.size', 'value': 0},
 {'id': 'Pointer.data.item', 'value': '0x0'},
 {'id': 'Pointer.data.item.data', 'value': ''}]
>>> # View the pointer and nested pointers field values as a JSON string.
>>> pointer.to_json(nested=True)
'{"value": "0x1",
  "data": {"size": 0,
           "item": {"value": "0x0",
                    "data": ""}}}'
>>> # Set the internal byte stream of the pointer
>>> pointer.bytestream = '0e0010000000'
>>> # Set the internal byte stream of the nested pointer
>>> pointer.data.item.bytestream = '4b6f6e666f6f2069732046756e00f00f00'
>>> # Deserialize the pointer and nested pointers from the internal byte streams.
>>> pointer.deserialize(bytes.fromhex('01000000f00f00'), nested=True)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # List the field values of the pointer and nested pointers.
>>> pointer.to_list(nested=True)
[('Pointer.field', '0x1'),
 ('Pointer.data.size', 14),
 ('Pointer.data.item', '0x10'),
 ('Pointer.data.item.data', 'Konfoo is Fun')]
>>> # List the field values of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv(nested=True)
[{'id': 'Pointer.field', 'value': '0x1'},
 {'id': 'Pointer.data.size', 'value': 14},
 {'id': 'Pointer.data.item', 'value': '0x10'},
 {'id': 'Pointer.data.item.data', 'value': 'Konfoo is Fun'}]
>>> # View the pointer and nested pointers field values as a JSON string.
>>> pointer.to_json(nested=True)
'{"value": "0x1",
  "data": {"size": 14,
           "item": {"value": "0x10",
                    "data": "Konfoo is Fun"}}}'

Deserialize the Data Object

You can deserialize the data object attached to the pointer by calling the method deserialize_data() of a pointer field.

>>> # Create a pointer with a nested pointer.
>>> pointer = Pointer(
...     Structure(
...         size=Decimal(16),
...         item=Pointer(String(14))),
...     address=1)
>>> # List the field values of the pointer and nested pointers.
>>> pointer.to_list(nested=True)
[('Pointer.field', '0x1'),
 ('Pointer.data.size', 0),
 ('Pointer.data.item', '0x0'),
 ('Pointer.data.item.data', '')]
>>> # List the field values of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv(nested=True)
[{'id': 'Pointer.field', 'value': '0x1'},
 {'id': 'Pointer.data.size', 'value': 0},
 {'id': 'Pointer.data.item', 'value': '0x0'},
 {'id': 'Pointer.data.item.data', 'value': ''}]
>>> # View the pointer and nested pointers field values as a JSON string.
>>> pointer.to_json(nested=True)
'{"value": "0x1",
  "data": {"size": 0,
           "item": {"value": "0x0",
                    "data": ""}}}'
>>> # Internal byte stream of the pointer.
>>> pointer.bytestream
''
>>> # Set the internal byte stream of the nested pointer.
>>> pointer.data.item.bytestream = '4b6f6e666f6f2069732046756e00'
>>> # Deserialize the data object of the pointer from an external byte stream.
>>> pointer.deserialize_data(bytes.fromhex('0e0010000000'))
Index(byte=6, bit=0, address=7, base_address=1, update=False)
>>> # Internal byte stream of the pointer.
>>> pointer.bytestream
''
>>> # List the field values of the pointer and nested pointers.
>>> pointer.to_list(nested=True)
[('Pointer.field', '0x1'),
 ('Pointer.data.size', 14),
 ('Pointer.data.item', '0x10'),
 ('Pointer.data.item.data', '')]
>>> # List the field values of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv(nested=True)
[{'id': 'Pointer.field', 'value': '0x1'},
 {'id': 'Pointer.data.size', 'value': 14},
 {'id': 'Pointer.data.item', 'value': '0x10'},
 {'id': 'Pointer.data.item.data', 'value': ''}]
>>> # View the pointer and nested pointers field values as a JSON string.
>>> pointer.to_json(nested=True)
'{"value": "0x1",
  "data": {"size": 14,
           "item": {"value": "0x10",
                    "data": ""}}}'
>>> # Deserialize the data object of the nested pointer from the internal byte stream.
>>> pointer.data.item.deserialize_data()
Index(byte=14, bit=0, address=30, base_address=16, update=False)
>>> # List the field values of the pointer and nested pointers.
>>> pointer.to_list(nested=True)
[('Pointer.field', '0x1'),
 ('Pointer.data.size', 14),
 ('Pointer.data.item', '0x10'),
 ('Pointer.data.item.data', 'Konfoo is Fun')]
>>> # List the field values of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv(nested=True)
[{'id': 'Pointer.field', 'value': '0x1'},
 {'id': 'Pointer.data.size', 'value': 14},
 {'id': 'Pointer.data.item', 'value': '0x10'},
 {'id': 'Pointer.data.item.data', 'value': 'Konfoo is Fun'}]
>>> # View the pointer and nested pointers field values as a JSON string.
>>> pointer.to_json(nested=True)
'{"value": "0x1",
  "data": {"size": 14,
           "item": {"value": "0x10",
                    "data": "Konfoo is Fun"}}}'

Serializing

You can serialize the pointer field to a byte stream and the attached data object to the internal byte stream of a pointer by calling the method serialize().

>>> # Create a pointer with a nested pointer.
>>> pointer = Pointer(
...     Structure(
...         size=Decimal(16),
...         item=Pointer(String(14))))
>>> # Initialize the fields values.
>>> pointer.initialize_fields({
...     'value': 0x1,
...     'data': {
...         'size': 14,
...         'item': {
...             'value': 0x10,
...             'data': 'Konfoo is Fun'}}})
>>> # List the field values of the pointer and nested pointers.
>>> pointer.to_list(nested=True)
[('Pointer.field', '0x1'),
 ('Pointer.data.size', 14),
 ('Pointer.data.item', '0x10'),
 ('Pointer.data.item.data', 'Konfoo is Fun')]
>>> # List the field values of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv(nested=True)
[{'id': 'Pointer.field', 'value': '0x1'},
 {'id': 'Pointer.data.size', 'value': 14},
 {'id': 'Pointer.data.item', 'value': '0x10'},
 {'id': 'Pointer.data.item.data', 'value': 'Konfoo is Fun'}]
>>> # View the pointer and nested pointers field values as a JSON string.
>>> pointer.to_json(nested=True)
'{"value": "0x1",
  "data": {"size": 14,
           "item": {"value": "0x10",
                    "data": "Konfoo is Fun"}}}'
>>> # Internal byte stream of the pointer.
>>> pointer.bytestream
''
>>> # Internal byte stream of the nested pointer.
>>> pointer.data.item.bytestream
''
>>> # Byte stream for the serialized pointer field.
>>> bytestream = bytearray()
>>> # Serialize the pointer field to the byte stream
>>> pointer.serialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # Internal byte stream of the pointer.
>>> pointer.bytestream
''
>>> # Internal byte stream of the nested pointer.
>>> pointer.data.item.bytestream
''
>>> # Serialized pointer field
>>> bytestream.hex()
'01000000'
>>> # Serialized pointer field
>>> bytes(pointer).hex()
'01000000'
>>> # Byte stream for the serialized pointer field.
>>> bytestream = bytearray()
>>> # Serialize the pointer and nested pointers to the internal byte streams
>>> pointer.serialize(bytestream, nested=True)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> # Internal byte stream of the pointer.
>>> pointer.bytestream
'0e0010000000'
>>> # Internal byte stream of the nested pointer.
>>> pointer.data.item.bytestream
'4b6f6e666f6f2069732046756e00'
>>> # Serialized pointer field
>>> bytestream.hex()
'01000000'
>>> # Serialized pointer field
>>> bytes(pointer).hex()
'01000000'

Serialize the Data Object

You can serialize the data object attached to the pointer by calling the method serialize_data() of a pointer field.

>>> # Create a pointer with a nested pointer.
>>> pointer = Pointer(
...     Structure(
...         size=Decimal(16),
...         item=Pointer(String(14))))
>>> # Initialize the fields values.
>>> pointer.initialize_fields({
...     'value': 0x1,
...     'data': {
...         'size': 14,
...         'item': {
...             'value': 0x10,
...             'data': 'Konfoo is Fun'}}})
>>> # List the field values of the pointer and nested pointers.
>>> pointer.to_list(nested=True)
[('Pointer.field', '0x1'),
 ('Pointer.data.size', 14),
 ('Pointer.data.item', '0x10'),
 ('Pointer.data.item.data', 'Konfoo is Fun')]
>>> # List the field values of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv(nested=True)
[{'id': 'Pointer.field', 'value': '0x1'},
 {'id': 'Pointer.data.size', 'value': 14},
 {'id': 'Pointer.data.item', 'value': '0x10'},
 {'id': 'Pointer.data.item.data', 'value': 'Konfoo is Fun'}]
>>> # View the pointer and nested pointers field values as a JSON string.
>>> pointer.to_json(nested=True)
'{"value": "0x1",
  "data": {"size": 14,
           "item": {"value": "0x10",
                    "data": "Konfoo is Fun"}}}'
>>> # Internal byte stream of the pointer.
>>> pointer.bytestream
''
>>> # Internal byte stream of the nested pointer.
>>> pointer.data.item.bytestream
''
>>> # Serialize the data object of the pointer.
>>> pointer.serialize_data().hex()
'0e0010000000'
>>> # Internal byte stream of the pointer.
>>> pointer.bytestream
''
>>> # Serialize the data object of the nested pointer.
>>> pointer.data.item.serialize_data().hex()
'4b6f6e666f6f2069732046756e00'
>>> # Internal byte stream of the nested pointer.
>>> pointer.data.item.bytestream
''

Writing

You can write the field value of any field or the field values of any container of the data object attached to a pointer to a data source through a byte stream provider by calling method write_to() of a pointer field.

Note

Further information is provided by the writing chapter.

Attributes of a Pointer Field

You can access the field attributes of a pointer field with the following attribute names:

>>> # Field name.
>>> pointer.name
'Pointer32'
>>> # Field value.
>>> pointer.value
'0x1'
>>> # Field bit size.
>>> pointer.bit_size
32
>>> # Field alignment.
>>> pointer.alignment
Alignment(byte_size=4, bit_offset=0)
>>> # Field alignment: byte size of the aligned field group.
>>> pointer.alignment.byte_size
4
>>> # Field alignment: bit offset of the field in its field group.
>>> pointer.alignment.bit_offset
0
>>> # Field byte order.
>>> pointer.byte_order
Byteorder.auto = 'auto'
>>> # Field byte order value.
>>> pointer.byte_order.value
'auto'
>>> # Field index.
>>> pointer.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> # Field index: byte offset of the field in the byte stream.
>>> pointer.index.byte
0
>>> # Field index: bit offset of the field relative to its byte offset.
>>> pointer.index.bit
0
>>> # Field index: memory address of the field in the data source.
>>> pointer.index.address
0
>>> # Field index: start address of the byte stream in the data source.
>>> pointer.index.base_address
0
>>> # Field index: update request for the byte stream.
>>> pointer.index.update
False

You can check if a pointer is a Null-pointer.

>>> # Field points to zero.
>>> pointer.is_null()
False

View Field Attributes

You can view the attributes of a pointer field and of each field of the data object attached to the pointer field as an ordered dictionary by calling the method view_fields(). Default attribute is the field value.

>>> # View the pointer field values.
>>> pointer.view_fields()
OrderedDict([('value', '0x1'),
             ('data',
              OrderedDict([('size', 14),
                           ('item', '0x10')]))])
>>> # View the pointer and nested pointers field values.
>>> pointer.view_fields(nested=True)
OrderedDict([('value', '0x1'),
             ('data',
              OrderedDict([('size', 14),
                           ('item',
                            OrderedDict([('value', '0x10'),
                                         ('data', 'Konfoo is Fun')]))]))])
>>> # View the pointer field type names & field values.
>>> pointer.view_fields('name', 'value')
OrderedDict([('name', 'Pointer32'),
             ('value', '0x1'),
             ('data',
              OrderedDict([('size', {'name': 'Decimal16',
                                     'value': 14}),
                           ('item', {'name': 'Pointer32',
                                     'value': '0x10'})]))])
>>> # View the pointer field indexes.
>>> pointer.view_fields('index')
OrderedDict([('value',
              Index(byte=0, bit=0, address=0, base_address=0, update=False)),
             ('data',
              OrderedDict([('size',
                            Index(byte=0, bit=0, address=1, base_address=1, update=False)),
                           ('item',
                            Index(byte=2, bit=0, address=3, base_address=1, update=False))]))])

View as a JSON string

You can view the attributes of a pointer field and of each field of the data object attached to the pointer field as a JSON formatted string by calling the method to_json(). Default attribute is the field value.

>>> # View the pointer field values as a JSON string.
>>> pointer.to_json()
'{"value": "0x1",
  "data": {"size": 14,
           "item": "0x10"}}'
>>> print(pointer.to_json(indent=2))
{
  "value": "0x1",
  "data": {
    "size": 14,
    "item": "0x10"
  }
}
>>> # View the pointer and nested pointers field values as a JSON string.
>>> pointer.to_json(nested=True)
'{"value": "0x1",
  "data": {"size": 14,
           "item": {"value": "0x10",
                    "data": "Konfoo is Fun"}}}'
>>> # View the pointer field type names & field values as a JSON string.
>>> pointer.to_json('name', 'value')
'{"name": "Pointer32",
  "value": "0x1",
  "data": {"size": {"name": "Decimal16",
                    "value": 14},
           "item": {"name": "Pointer32",
                    "value": "0x10"}}}'
>>> # View the pointer field indexes as a JSON string.
>>> pointer.to_json('index')
'{"value": [0, 0, 0, 0, false],
  "data": {"size": [0, 0, 1, 1, false],
           "item": [2, 0, 3, 1, false]}}'

List Field Items

You can list all field items of a pointer as a flatten list by calling the method field_items().

>>> # List the field items of the pointer.
>>> pointer.field_items()
[('field',
  Pointer(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
          alignment=Alignment(byte_size=4, bit_offset=0),
          bit_size=32,
          value='0x1')),
 ('data.size',
  Decimal(index=Index(byte=0, bit=0, address=1, base_address=1, update=False),
          alignment=Alignment(byte_size=2, bit_offset=0),
          bit_size=16,
          value=14)),
 ('data.item',
  Pointer(index=Index(byte=2, bit=0, address=3, base_address=1, update=False),
          alignment=Alignment(byte_size=4, bit_offset=0),
          bit_size=32,
          value='0x10'))]
>>> # List the field items of the pointer and nested pointers.
>>> pointer.field_items(nested=True)
[('field',
  Pointer(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
          alignment=Alignment(byte_size=4, bit_offset=0),
          bit_size=32,
          value='0x1')),
 ('data.size',
  Decimal(index=Index(byte=0, bit=0, address=1, base_address=1, update=False),
          alignment=Alignment(byte_size=2, bit_offset=0),
          bit_size=16,
          value=14)),
 ('data.item',
  Pointer(index=Index(byte=2, bit=0, address=3, base_address=1, update=False),
          alignment=Alignment(byte_size=4, bit_offset=0),
          bit_size=32,
          value='0x10')),
 ('data.item.data',
  String(index=Index(byte=0, bit=0, address=16, base_address=16, update=False),
         alignment=Alignment(byte_size=14, bit_offset=0),
         bit_size=112,
         value='Konfoo is Fun'))]

List Field Attributes

You can list the attributes of each field of a pointer as a flatten list by calling the method to_list(). Default attribute is the field value.

>>> # List the field values of the pointer and its attached data object.
>>> pointer.to_list()
[('Pointer.field', '0x1'),
 ('Pointer.data.size', 14),
 ('Pointer.data.item', '0x10')]
>>> # List the field values of the pointer and nested pointers.
>>> pointer.to_list(nested=True)
[('Pointer.field', '0x1'),
 ('Pointer.data.size', 14),
 ('Pointer.data.item', '0x10'),
 ('Pointer.data.item.data', 'Konfoo is Fun')]
>>> # List the field type names & values of the pointer and its attached data object.
>>> pointer.to_list('name', 'value')
[('Pointer.field', ('Pointer32', '0x1')),
 ('Pointer.data.size', ('Decimal16', 14)),
 ('Pointer.data.item', ('Pointer32', '0x10'))]
>>> # List the field indexes of the pointer and its attached data object.
>>> pointer.to_list('index')
[('Pointer.field',
  Index(byte=0, bit=0, address=0, base_address=0, update=False)),
 ('Pointer.data.size',
  Index(byte=0, bit=0, address=1, base_address=1, update=False)),
 ('Pointer.data.item',
  Index(byte=2, bit=0, address=3, base_address=1, update=False))]

Note

The class name of the instance is used for the root name as long as no name is given.

You can list the attributes of each field of a pointer as a flatten ordered dictionary by calling the method to_dict(). Default attribute is the field value.

>>> # List the field values of the pointer and its attached data object.
>>> pointer.to_dict()
OrderedDict([('Pointer',
    OrderedDict([('field', '0x1'),
                 ('data.size', 14),
                 ('data.item', '0x10')]))])
>>> # List the field values of the pointer and nested pointers.
>>> pointer.to_dict(nested=True)
OrderedDict([('Pointer',
    OrderedDict([('field', '0x1'),
                 ('data.size', 14),
                 ('data.item', '0x10'),
                 ('data.item.data', 'Konfoo is Fun')]))])
>>> # List the field type names & values of the pointer and its attached data object.
>>> pointer.to_dict('name', 'value')
OrderedDict([('Pointer',
    OrderedDict([('field', ('Pointer32', '0x1')),
                 ('data.size', ('Decimal16', 14)),
                 ('data.item', ('Pointer32', '0x10'))]))])
>>> # List the field indexes of the pointer and its attached data object.
>>> pointer.to_dict('index')
OrderedDict([('Pointer',
    OrderedDict([('field',
                  Index(byte=0, bit=0, address=0, base_address=0, update=False)),
                 ('data.size',
                  Index(byte=0, bit=0, address=1, base_address=1, update=False)),
                 ('data.item',
                  Index(byte=2, bit=0, address=3, base_address=1, update=False))]))])

Note

The class name of the instance is used for the root name as long as no name is given.

You can list the attributes of each field of a pointer as a flatten list of dictionaries containing the field path and the selected field attributes by calling the method to_csv(). Default attribute is the field value.

>>> # List the field values of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv(nested=True)
[{'id': 'Pointer.field', 'value': '0x1'},
 {'id': 'Pointer.data.size', 'value': 14},
 {'id': 'Pointer.data.item', 'value': '0x10'},
 {'id': 'Pointer.data.item.data', 'value': 'Konfoo is Fun'}]
>>> # List the field type names & values of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv('name', 'value', nested=True)
[{'id': 'Pointer.field', 'name': 'Pointer32', 'value': '0x1'},
 {'id': 'Pointer.data.size', 'name': 'Decimal16', 'value': 14},
 {'id': 'Pointer.data.item', 'name': 'Pointer32', 'value': '0x10'},
 {'id': 'Pointer.data.item.data', 'name': 'String14', 'value': 'Konfoo is Fun'}]

Note

The class name of the instance is used for the root name as long as no name is given.

Write Field Attributes

You can write the attributes of each field of a pointer to a .csv file by calling the method write_csv(). Default attribute is the field value.

>>> # List the field values of the pointer and nested pointers as a CSV list.
>>> pointer.to_csv(nested=True)
[{'id': 'Pointer.field', 'value': '0x1'},
 {'id': 'Pointer.data.size', 'value': 14},
 {'id': 'Pointer.data.item', 'value': '0x10'},
 {'id': 'Pointer.data.item.data', 'value': 'Konfoo is Fun'}]
>>> # Save the structure field values to a '.csv' file.
>>> pointer.write_csv("_static/pointer.csv", nested=True)

The generated .csv file for the structure looks like this:

id,value
Pointer.field,0x1
Pointer.data.size,14
Pointer.data.item,0x10
Pointer.data.item.data,Konfoo is Fun

Note

The class name of the instance is used for the root name as long as no name is given.

Save Field Attributes

You can save the attributes of each field of a pointer to an .ini file by calling the method save(). Default attribute is the field value.

>>> # List the field values of the pointer and nested pointers.
>>> pointer.to_list(nested=True)
[('Pointer.field', '0x1'),
 ('Pointer.data.size', 14),
 ('Pointer.data.item', '0x10'),
 ('Pointer.data.item.data', 'Konfoo is Fun')]
>>> # Save the pointer and nested pointers field values to an '.ini' file.
>>> pointer.save("_static/pointer.ini", nested=True)

The generated .ini file for the pointer looks like this:

[Pointer]
field = 0x1
data.size = 14
data.item = 0x10
data.item.data = Konfoo is Fun

Note

The class name of the instance is used for the section name as long as no section is given.

Load Field Values

You can load the values of each field of a pointer from an .ini file by calling the method load().

>>> # Load the pointer and nested pointers field values from an '.ini' file.
>>> pointer.load("_static/pointer.ini", nested=True)
[Pointer]
Pointer.field = 0x1
Pointer.data.size = 14
Pointer.data.item = 0x10
Pointer.data.item.data = Konfoo is Fun
>>> # List the field values of the pointer and nested pointers.
>>> pointer.to_list(nested=True)
[('Pointer.field', '0x1'),
 ('Pointer.data.size', 14),
 ('Pointer.data.item', '0x10'),
 ('Pointer.data.item.data', 'Konfoo is Fun')]

Note

The class name of the instance is used for the section name as long as no section is given.

Provider

KonFoo has an abstract Provider class with an abstract interface to read a byte stream from a data source and to write a byte stream to a data source.

Read Interface

A Provider class has the abstract method Provider.read() which must be implemented by a derived class to read at the given start address the given number of bytes from the data source and returns the bytes.

Write Interface

A Provider class has the abstract method Provider.write() which must be implemented by a derived class to write the given number of bytes at the given start address to the data source.

Define a Provider

You define a provider by creating a class derived from the abstract Provider class and implement the two abstract methods read() and write() for your kind of data source like shown below:

from konfoo import Provider
from pathlib import Path

class MyProvider(Provider):

    def __init__(self, file):
        #: File path.
        self.path = Path(file).absolute()
        #: Byte cache.
        self.cache = bytearray(self.path.read_bytes())

    def read(self, address=0, count=0):
        """ Returns a *number* of bytes read from the :attr:`cache` beginning
        at the start *address*.

        :param int address: start address.
        :param int count: number of bytes to read from the cache.
        """
        return self.cache[address:address + count]

    def write(self, buffer=bytes(), address=0, count=0):
        """ Writes the content of the *buffer* to the :attr:`cache` beginning
        at the start *address*.

        :param bytes buffer: content to write.
        :param int address: start address.
        :param int count: number of bytes to write to the cache.
        """
        view = memoryview(self.cache)
        view[address:address + count] = buffer

Reading

The procedure to read from a data source the required byte stream and deserialize it with a byte stream mapper includes four steps.

Create the Byte Stream Provider

First, create the byte stream provider to access the data source.

>>> # Create the byte stream provider for the data source.
>>> provider = FileProvider('./_static/reading.bin')
>>> provider.cache
bytearray(b"\x0f\x00KonFoo is \'Fun\'")
>>> provider.cache.hex()
'0f004b6f6e466f6f206973202746756e27'

Note

We use here a FileProvider but you can write your own provider class to access any kind of data source.

Create the Byte Stream Mapper

Second, create the byte stream mapper for the binary data to be mapped in the data source.

>>> class FileMapper(Structure):
...
...     def __init__(self):
...         super().__init__()
...         self.length = Decimal16()
...         self.content = String(15)
...         self.index_fields()

or

>>> # Create the byte stream mapper.
>>> mapper = Structure(length = Decimal16(), content = String(15))
>>> # Index the fields of the mapper.
>>> mapper.index_fields()
Index(byte=17, bit=0, address=17, base_address=0, update=False)
>>> # List the field values of the mapper.
>>> mapper.to_list()
[('Structure.length', 0),
 ('Structure.content', '')]
>>> # List the field values of the mapper as a CSV list.
>>> mapper.to_csv()
[{'id': 'Structure.length', 'value': 0},
 {'id': 'Structure.content', 'value': ''}]
>>> # View the mapper field values as a JSON string.
>>> mapper.to_json()
'{"length": 0, "content": ""}'

Create the Byte Stream Reader

Third, create a reader for the byte stream mapper to the data source by attaching the byte stream mapper to the data object of a pointer field.

>>> class FileReader(Pointer):
...
...     def __init__(self, address=None, byte_order=BYTEORDER):
...         super().__init__(FileMapper(), address, byte_order)

or

>>> # Create the byte stream reader.
>>> reader = Pointer(mapper, address=0, data_order='little')
>>> # List the field values of the pointer and data object.
>>> reader.to_list()
[('Pointer.field', '0x0'),
 ('Pointer.data.length', 0),
 ('Pointer.data.content', '')]
>>> # List the field values of the pointer and data object as a CSV list.
>>> reader.to_csv()
[{'id': 'Pointer.field', 'value': '0x0'},
 {'id': 'Pointer.data.length', 'value': 0},
 {'id': 'Pointer.data.content', 'value': ''}]
>>> # View the pointer and data object field values as a JSON string.
>>> reader.to_json()
'{"value": "0x0",
  "data": {"length": 0, "content": ""}}'

Read from the Data Source

Fourth, read the required byte stream for the data object attached to the pointer field with the byte stream provider from the data source by calling the method read_from() of the pointer field.

>>> # Start address to read the byte stream for the data object from the data source.
>>> reader.address
0
>>> # Reader points to zero (Null).
>>> reader.is_null()
True
>>> # Internal byte stream of the reader for the data object.
>>> reader.bytestream
''
>>> # Read from the provider the byte stream and deserialize the byte stream.
>>> reader.read_from(provider, null_allowed=True)
>>> # Internal byte stream of the reader for the data object.
>>> reader.bytestream
'0f004b6f6e466f6f206973202746756e27'
>>> bytes.fromhex(reader.bytestream)
b"\x0f\x00KonFoo is 'Fun'"
>>> # List the field values of the data object.
>>> reader.data.to_list()
[('Structure.length', 15),
 ('Structure.content', "KonFoo is 'Fun'")]
>>> # List the field values of the data object as a CSV list.
>>> reader.data.to_csv()
[{'id': 'Structure.length', 'value': 15},
 {'id': 'Structure.content', 'value': "KonFoo is 'Fun'"}]
>>> # View the data object field values as a JSON string.
>>> reader.data.to_json()
'{"length": 15, "content": "KonFoo is \'Fun\'"}'

Writing

Create the Byte Stream Provider

First, create the byte stream provider to access the data source.

>>> # Create the byte stream provider for the data source.
>>> provider = FileProvider('./_static/writing.bin')
>>> provider.cache
bytearray(b"\x0f\x00KonFoo is \'Fun\'")

Note

We use here a FileProvider but you can write your own provider class to access any kind of data source.

Create the Byte Stream Mapper

Second, create the byte stream mapper for the binary data to be mapped in the data source.

>>> # Create the byte stream mapper.
>>> mapper = Structure(length = Decimal16(), content = String(15))

Create the Byte Stream Writer

Third, create a writer for the byte stream mapper to the data source by attaching the byte stream mapper to the data object of a pointer field.

>>> # Create the byte stream writer.
>>> writer = Pointer(mapper)
>>> # List the field values of the pointer and data object.
>>> writer.to_list()
[('Pointer.field', '0x0'),
 ('Pointer.data.length', 0),
 ('Pointer.data.content', '')]
>>> # List the field values of the pointer and data object as a CSV list.
>>> writer.to_csv()
[{'id': 'Pointer.field', 'value': '0x0'},
 {'id': 'Pointer.data.length', 'value': 0},
 {'id': 'Pointer.data.content', 'value': ''}]
>>> # View the pointer and data object field values as a JSON string.
>>> writer.to_json()
'{"value": "0x0",
  "data": {"length": 0, "content": ""}}'

Read from the Data Source

Fourth, read the required byte stream for the data object attached to the pointer field with the byte stream provider from the data source by calling the method read_from() of the pointer field.

>>> # Read from the provider the byte stream
>>> writer.read_from(provider, null_allowed=True)
>>> bytes.fromhex(writer.bytestream)
b"\x0f\x00KonFoo is 'Fun'"
>>> # List the field values of the data object.
>>> writer.data.to_list()
[('Structure.length', 15),
 ('Structure.content', "KonFoo is 'Fun'")]
>>> # List the field values of the data object as a CSV list.
>>> writer.data.to_csv()
[{'id': 'Structure.length', 'value': 15},
 {'id': 'Structure.content', 'value': "KonFoo is 'Fun'"}]
>>> # View the data object field values as a JSON string.
>>> writer.data.to_json()
'{"length": 15, "content": "KonFoo is \'Fun\'"}'

Write to the Data Source

Fifth, write the field value of any field of the data object attached to a pointer to a data source with the byte stream provider by calling method write_to().

>>> writer.data.length.value = 0x0f00
>>> # Write to the provider the bytes represented by the field.
>>> writer.write_to(provider, writer.data.length)
>>> provider.cache
bytearray(b"\x00\x0fKonFoo is \'Fun\'")
>>> bytes.fromhex(writer.bytestream)
b"\x0f\x00KonFoo is 'Fun'"

or write the field values of any container of the data object attached to a pointer to a data source with the byte stream provider by calling method write_to().

>>> writer.data.length.value = 14
>>> writer.data.content.value = 'Konfoo is Fun'
>>> # Write to the provider the bytes represented by the container.
>>> writer.write_to(provider, writer.data)
>>> provider.cache
bytearray(b'\x0e\x00Konfoo is Fun\x00\x00')
>>> bytes.fromhex(writer.bytestream)
b"\x0f\x00KonFoo is 'Fun'"

De-Serializing

The de-serialization of a byte stream by a byte stream mapper is not considered independent from the reading of the byte stream.

Therefore the deserialize() method of the byte stream mapper is not called directly during the de-serialization process. The deserialize() method is called by the pointer during the reading of the byte stream where the byte stream mapper is attached to.

De-Serializing Hook

The deserialize() method which every field and container has allows to hook in the reading/de-serialization process at a certain point of the byte stream to adapt the byte stream mapper and to control the reading of the byte stream by the providing pointer.

>>> class OPCString(Structure):
...
...     def __init__(self):
...         super().__init__()
...         # Length of the string
...         self.length = Decimal16()
...         # Content of the string
...         self.content = String()
...         self.index_fields()
...
...     def deserialize(self, buffer=bytes(), index=Index(), **options):
...         # Deserialize length field first.
...         index = self.length.deserialize(buffer, index, **options)
...         # Check if content field size is incorrect.
...         if int(self.length) != len(self.content):
...             # Re-size content field on the fly.
...             self.content.resize(int(self.length))
...             # Deserialize content field with new size.
...             index = self.content.deserialize(buffer, index, **options)
...             # Request a buffer update from the providing pointer on the fly.
...             # note: Starts the deserialization for the byte stream mapper again.
...             return index._replace(update=True)
...         else:
...             # Deserialize content field with correct size.
...             return self.content.deserialize(buffer, index, **options)
>>> # Create an instance of the empty OPC string
>>> string = OPCString()
>>> # List the field values of the OPC string.
>>> string.to_list()
[('OPCString.length', 0),
 ('OPCString.content', '')]
>>> # List the field values of the OPC string as a CSV list.
>>> string.to_csv()
[{'id': 'OPCString.length', 'value': 0},
 {'id': 'OPCString.content', 'value': ''}]
>>> # View the OPC string field values as a JSON string.
>>> string.to_json()
'{"length": 0, "content": ""}'
>>> # Size of the OPC string.
>>> string.container_size()
(2, 0)
>>> # Deserialize the empty OPC string
>>> string.deserialize(bytes.fromhex('0f004b6f6e466f6f206973202746756e27'))
Index(byte=17, bit=0, address=17, base_address=0, update=True)
>>> # Size of the OPC string.
>>> string.container_size()
(17, 0)
>>> # Deserialize the filled OPC string
>>> string.deserialize(bytes.fromhex('0f004b6f6e466f6f206973202746756e27'))
Index(byte=17, bit=0, address=17, base_address=0, update=False)
>>> # Size of the OPC string.
>>> string.container_size()
(17, 0)
>>> # List the field values of the OPC string.
>>> string.to_list()
[('OPCString.length', 15),
 ('OPCString.content', "KonFoo is 'Fun'")]
>>> # List the field values of the OPC string as a CSV list.
>>> string.to_csv()
[{'id': 'OPCString.length', 'value': 15},
 {'id': 'OPCString.content', 'value': "KonFoo is 'Fun'"}]
>>> # View the OPC string field values as a JSON string.
>>> string.to_json()
'{"length": 15, "content": "KonFoo is \'Fun\'"}'

API Reference

If you are looking for information on a specific function, class or method, this part of the documentation is for you.

API

This part of the documentation lists the full API reference of all public classes and functions.

Provider

class konfoo.Provider[source]

A Provider class provides access for the Pointer class to read and write byte streams from and back to a data source. The Provider class servers as a meta class. A derived class must implement the two methods read() and write() for reading and writing byte streams from and back to the data source.

read(address=0, count=0)[source]

Returns a number of bytes read from a data source beginning at the start address.

Parameters:
  • address (int) – start address.
  • count (int) – number of bytes to read from a data source.

Note

This abstract method must be implemented by a derived class.

write(buffer=b'', address=0, count=0)[source]

Writes the content of the buffer to a data source beginning at the start address.

Parameters:
  • buffer (bytes) – content to write.
  • address (int) – start address.
  • count (int) – number of bytes to write to a data source.

Note

This abstract method must be implemented by a derived class.

FileProvider
class konfoo.FileProvider(file)[source]

A FileProvider is a byte stream Provider for binary files. The file content is internal stored in a cache. The read() and write() methods only operate on the internal cache.

Call flush() to store the updated file content to the same or a new file.

Parameters:file (Path, str) – name and location of the file to read.
path = None

File path.

cache

Returns the internal byte stream cache of the Provider (read-only).

read(address=0, count=0)[source]

Returns a number of bytes read from the cache beginning at the start address.

Parameters:
  • address (int) – start address.
  • count (int) – number of bytes to read from the cache.
write(buffer=b'', address=0, count=0)[source]

Writes the content of the buffer to the cache beginning at the start address.

Parameters:
  • buffer (bytes) – content to write.
  • address (int) – start address.
  • count (int) – number of bytes to write to the cache.
flush(file='')[source]

Flushes the updated file content to the given file.

Note

Overwrites an existing file.

Parameters:file (str) – name and location of the file. Default is the original file.

Container

class konfoo.Container[source]

The Container class is an abstract interface for all classes which can contain Field items. Container classes are Structures, Sequences, Arrays and Pointers.

The Container class provides core features to view, save and load the attributes of the Field items in the Container.

view_fields(*attributes, **options)[source]

Returns a container with the selected field attribute or with the dictionary of the selected field attributes for each Field nested in the Container.

The attributes of each Field for containers nested in the Container are viewed as well (chained method call).

Parameters:
  • attributes (str) – selected Field attributes. Fallback is the field value.
  • fieldnames (tuple) – sequence of dictionary keys for the selected field attributes. Defaults to (*attributes).
  • nested (bool) – if True all Pointer fields in the Container views their referenced data object field attributes as well (chained method call).

Note

This abstract method must be implemented by a derived class.

to_json(*attributes, **options)[source]

Returns the selected field attributes for each Field nested in the Container as a JSON formatted string.

The attributes of each Field for containers nested in the Container are viewed as well (chained method call).

Parameters:
  • attributes (str) – selected Field attributes. Fallback is the field value.
  • fieldnames (tuple) – sequence of dictionary keys for the selected field attributes. Defaults to (*attributes).
  • nested (bool) – if True all Pointer fields in the Container views their referenced data object field attributes as well (chained method call).
field_items(path='', **options)[source]

Returns a flatten list of ('field path', field item) tuples for each Field nested in the Container.

Parameters:
  • path (str) – item path.
  • nested (bool) – if True all Pointer fields in the data objects of all Pointer fields in the Container list their referenced data object field items as well (chained method call).

Note

This abstract method must be implemented by a derived class.

to_list(*attributes, **options)[source]

Returns a flatten list of ('field path', attribute) or ('field path', tuple(attributes)) tuples for each Field nested in the Container.

Parameters:
  • attributes (str) – selected Field attributes. Fallback is the field value.
  • name (str) – name of the Container. Default is the class name of the instance.
  • chain (bool) – if True the field attributes are chained to its field path. Defaults to False.
  • nested (bool) – if True all Pointer fields in the Container lists their referenced data object field attributes as well (chained method call).
to_dict(*attributes, **options)[source]

Returns a flatten ordered dictionary of {'field path': attribute} or {'field path': tuple(attributes)} pairs for each Field nested in the Container.

Parameters:
  • attributes (str) – selected Field attributes. Fallback is the field value.
  • name (str) – name of the Container. Default is the class name of the instance.
  • nested (bool) – if True all Pointer fields in the Container lists their referenced data object field attributes as well (chained method call).
to_csv(*attributes, **options)[source]

Returns a flatten list of dictionaries containing the field path and the selected field attributes for each Field nested in the Container.

Parameters:
  • attributes (str) – selected Field attributes. Fallback is the field value.
  • name (str) – name of the Container. Default is the class name of the instance.
  • fieldnames (tuple) – sequence of dictionary keys for the field path and the selected field attributes. Defaults to ('id', *attributes).
  • nested (bool) – if True all Pointer fields in the Container lists their referenced data object field attributes as well (chained method call).
write_csv(file, *attributes, **options)[source]

Writes the field path and the selected field attributes for each Field nested in the Container to a .csv file.

Parameters:
  • file (str) – name and location of the .csv file.
  • attributes (str) – selected Field attributes. Fallback is the field value.
  • name (str) – name of the Container. Default is the class name of the instance.
  • fieldnames (tuple) – sequence of dictionary keys for the field path and the selected field attributes. Defaults to ('id', *attributes).
  • nested (bool) – if True all Pointer fields in the Container lists their referenced data object field attributes as well (chained method call).
save(file, *attributes, **options)[source]

Saves the selected field attributes for each Field nested in the Container to an .ini file.

Parameters:
  • file (str) – name and location of the .ini file.
  • attributes (str) – selected Field attributes. Fallback is the field value.
  • section (str) – section in the .ini file to look for the Field values of the Container. If no section is specified the class name of the instance is used.
  • nested (bool) – if True all Pointer fields in the Container saves their referenced data object field attributes as well (chained method call).

Example:

>>> class Foo(Structure):
...     def __init__(self):
...         super().__init__()
...         self.stream = Stream()
...         self.float = Float()
...         self.structure = Structure()
...         self.structure.decimal = Decimal(8)
...         self.array = Array(Byte, 3)
...         self.pointer = Pointer()
>>> foo = Foo()
>>> foo.to_list(nested=True)
[('Foo.stream', ''),
 ('Foo.float', 0.0),
 ('Foo.structure.decimal', 0),
 ('Foo.array[0]', '0x0'),
 ('Foo.array[1]', '0x0'),
 ('Foo.array[2]', '0x0'),
 ('Foo.pointer', '0x0')]
>>> foo.to_json(nested=True)
'{"stream": "",
  "float": 0.0,
  "structure": {"decimal": 0},
  "array": ["0x0", "0x0", "0x0"],
  "pointer": {"value": "0x0",
              "data": null}}'
>>> foo.save('foo.ini')

File foo.ini:

[Foo]
stream =
float = 0.0
structure.decimal = 0
array[0] = 0x0
array[1] = 0x0
array[2] = 0x0
pointer = 0x0
load(file, **options)[source]

Loads the field value for each Field nested in the Container from an .ini file.

Parameters:
  • file (str) – name and location of the .ini file.
  • section (str) – section in the .ini file to lookup the value for each Field in the Container. If no section is specified the class name of the instance is used.
  • nested (bool) – if True all Pointer fields in the Container load their referenced data object field valus as well (chained method call).
  • verbose (bool) – if True the loading is executed in verbose mode.

File foo.ini:

[Foo]
stream =
float = 0.0
structure.decimal = 0
array[0] = 0x0
array[1] = 0x0
array[2] = 0x0
pointer = 0x0

Example:

>>> class Foo(Structure):
...     def __init__(self):
...         super().__init__()
...         self.stream = Stream()
...         self.float = Float()
...         self.structure = Structure()
...         self.structure.decimal = Decimal(8)
...         self.array = Array(Byte, 3)
...         self.pointer = Pointer()
>>> foo = Foo()
>>> foo.load('foo.ini')
[Foo]
Foo.stream =
Foo.float = 0.0
Foo.structure.decimal = 0
Foo.array[0] = 0x0
Foo.array[1] = 0x0
Foo.array[2] = 0x0
Foo.pointer = 0x0
>>> foo.to_list(nested=True)
[('Foo.stream', ''),
 ('Foo.float', 0.0),
 ('Foo.structure.decimal', 0),
 ('Foo.array[0]', '0x0'),
 ('Foo.array[1]', '0x0'),
 ('Foo.array[2]', '0x0'),
 ('Foo.pointer', '0x0')]
>>> foo.to_json(nested=True)
'{"stream": "",
  "float": 0.0,
  "structure": {"decimal": 0},
  "array": ["0x0", "0x0", "0x0"],
  "pointer": {"value": "0x0",
              "data": null}}'
Structure
class konfoo.Structure(*args, **kwargs)[source]

A Structure is an ordered dictionary whereby the dictionary key describes the name of a member of the Structure and the value of the dictionary key describes the type of the member. Allowed members are Structure, Sequence, Array or Field instances.

The Structure class extends the ordered dictionary with the Container interface and attribute getter and setter for the {'key': value} pairs to access and to assign the members of the Structure easier, but this comes with the trade-off that the dictionary keys must be valid Python attribute names.

A Structure has additional methods to read, deserialize, serialize and view binary data:

read_from(provider, **options)[source]

All Pointer fields in the Structure read the necessary number of bytes from the data Provider for their referenced data object. Null pointer are ignored.

Parameters:
deserialize(buffer=b'', index=Index(byte=0, bit=0, address=0, base_address=0, update=False), **options)[source]

De-serializes the Structure from the byte buffer starting at the begin of the buffer or with the given index by mapping the bytes to the value for each Field in the Structure in accordance with the decoding byte order for the de-serialization and the decoding byte_order of each Field in the Structure.

A specific decoding byte_order of a Field overrules the decoding byte order for the de-serialization.

Returns the Index of the buffer after the last de-serialized Field in the Structure.

Optional the de-serialization of the referenced data objects of all Pointer fields in the Structure can be enabled.

Parameters:
  • buffer (bytes) – byte stream.
  • index (Index) – current read Index within the buffer.
  • byte_order (Byteorder, str) – decoding byte order for the de-serialization.
  • nested (bool) – if True all Pointer fields of a Structure de-serialize their referenced data object as well (chained method call). Each Pointer field uses for the de-serialization of its referenced data object its own bytestream.
serialize(buffer=bytearray(b''), index=Index(byte=0, bit=0, address=0, base_address=0, update=False), **options)[source]

Serializes the Structure to the byte buffer starting at begin of the buffer or with the given index by mapping the value for each Field in the Structure to the byte buffer in accordance with the encoding byte order for the serialization and the encoding byte_order of each Field in the Structure.

A specific encoding byte_order of a Field overrules the encoding byte order for the serialization.

Returns the Index of the buffer after the last serialized Field in the Structure.

Optional the serialization of the referenced data objects of all Pointer fields in the Structure can be enabled.

Parameters:
  • buffer (bytearray) – byte stream.
  • index (Index) – current write Index within the buffer.
  • byte_order (Byteorder, str) – encoding byte order for the serialization.
  • nested (bool) – if True all Pointer fields of a Structure serialize their referenced data object as well (chained method call). Each Pointer field uses for the serialization of its referenced data object its own bytestream.
index_fields(index=Index(byte=0, bit=0, address=0, base_address=0, update=False), **options)[source]

Indexes all fields in the Structure starting with the given index and returns the Index after the last Field in the Structure.

Parameters:
  • index (Index) – start Index for the first Field in the Structure.
  • nested (bool) – if True all Pointer fields of the Structure indexes their referenced data object fields as well (chained method call).
container_size()[source]

Returns the accumulated bit size of all fields in the Structure as a tuple in the form of (number of bytes, remaining number of bits).

first_field()[source]

Returns the first Field in the Structure or None for an empty Structure.

initialize_fields(content)[source]

Initializes the Field members in the Structure with the values in the content dictionary.

Parameters:content (dict) – a dictionary contains the Field values for each member in the Structure.
view_fields(*attributes, **options)[source]

Returns an ordered dictionary which contains the {'member name': field attribute} or the {'member name': dict(field attributes)} pairs for each Field nested in the Structure.

The attributes of each Field for containers nested in the Structure are viewed as well (chained method call).

Parameters:
  • attributes (str) – selected Field attributes. Fallback is the field value.
  • fieldnames (tuple) – sequence of dictionary keys for the selected field attributes. Defaults to (*attributes).
  • nested (bool) – if True all Pointer fields nested in the Structure views their referenced data object field attributes as well (chained method call).
field_items(path='', **options)[source]

Returns a flatten list of ('field path', field item) tuples for each Field nested in the Structure.

Parameters:
  • path (str) – field path of the Structure.
  • nested (bool) – if True all Pointer fields in the data objects of all Pointer fields in the Structure list their referenced data object field items as well (chained method call).
describe(name='', **options)[source]

Returns the metadata of the Structure as an ordered dictionary.

metadata = {
    'class': self.__class__.__name__,
    'name': name if name else self.__class__.__name__,
    'size': len(self),
    'type': Structure.item_type.name
    'member': [
        item.describe(member) for member, item in self.items()
    ]
}
Parameters:
  • name (str) – optional name for the Structure. Fallback is the class name.
  • nested (bool) – if True all Pointer fields of the Structure lists their referenced data object fields as well (chained method call). Default is True.
Sequence
class konfoo.Sequence(iterable=None)[source]

A Sequence is a mutable sequence containing heterogeneous items and is extended with the Container interface. Allowed items are Structure, Sequence, Array or Field instances.

A Sequence is:

  • containable: item in self returns True if item is in the Sequence.
  • sized: len(self) returns the number of items in the Sequence.
  • indexable self[index] returns the item at the index of the Sequence.
  • iterable iter(self) iterates over the items in the Sequence

A Sequence supports the usual methods for sequences:

  • Append an item to the Sequence via append().
  • Insert an item before the index into the Sequence via insert().
  • Extend the Sequence with items via extend().
  • Clear the Sequence via clear().
  • Pop an item with the index from the Sequence via pop().
  • Remove the first occurrence of an item from the Sequence via remove().
  • Reverse all items in the Sequence via reverse().

A Sequence has additional methods to read, deserialize, serialize and view binary data:

Parameters:iterable – any iterable that contains items of Structure, Sequence, Array or Field instances. If the iterable is one of these instances itself then the iterable itself is appended to the Sequence.
append(item)[source]

Appends the item to the end of the Sequence.

Parameters:item – any Structure, Sequence, Array or Field instance.
insert(index, item)[source]

Inserts the item before the index into the Sequence.

Parameters:
pop(index=-1)[source]

Removes and returns the item at the index from the Sequence.

Parameters:index (int) – Sequence index.
clear()[source]

Remove all items from the Sequence.

remove(item)[source]

Removes the first occurrence of an item from the Sequence.

Parameters:item – any Structure, Sequence, Array or Field instance.
reverse()[source]

In place reversing of the Sequence items.

extend(iterable)[source]

Extends the Sequence by appending items from the iterable.

Parameters:iterable – any iterable that contains items of Structure, Sequence, Array or Field instances. If the iterable is one of these instances itself then the iterable itself is appended to the Sequence.
read_from(provider, **options)[source]

All Pointer fields in the Sequence read the necessary number of bytes from the data Provider for their referenced data object. Null pointer are ignored.

Parameters:
deserialize(buffer=b'', index=Index(byte=0, bit=0, address=0, base_address=0, update=False), **options)[source]

De-serializes the Sequence from the byte buffer starting at the begin of the buffer or with the given index by mapping the bytes to the value for each Field in the Sequence in accordance with the decoding byte order for the de-serialization and the decoding byte_order of each Field in the Sequence.

A specific decoding byte_order of a Field overrules the decoding byte order for the de-serialization.

Returns the Index of the buffer after the last de-serialized Field in the Sequence.

Optional the de-serialization of the referenced data objects of all Pointer fields in the Sequence can be enabled.

Parameters:
  • buffer (bytes) – byte stream.
  • index (Index) – current read Index within the buffer.
  • byte_order (Byteorder, str) – decoding byte order for the de-serialization.
  • nested (bool) – if True all Pointer fields of a Sequence de-serialize their referenced data object as well (chained method call). Each Pointer field uses for the de-serialization of its referenced data object its own bytestream.
serialize(buffer=bytearray(b''), index=Index(byte=0, bit=0, address=0, base_address=0, update=False), **options)[source]

Serializes the Sequence to the byte buffer starting at begin of the buffer or with the given index by mapping the value for each Field in the Sequence to the byte buffer in accordance with the encoding byte order for the serialization and the encoding byte_order of each Field in the Sequence.

A specific encoding byte_order of a Field overrules the encoding byte order for the serialization.

Returns the Index of the buffer after the last serialized Field in the Sequence.

Optional the serialization of the referenced data objects of all Pointer fields in the Sequence can be enabled.

Parameters:
  • buffer (bytearray) – byte stream.
  • index (Index) – current write Index within the buffer.
  • byte_order (Byteorder, str) – encoding byte order for the serialization.
  • nested (bool) – if True all Pointer fields of a Sequence serialize their referenced data object as well (chained method call). Each Pointer field uses for the serialization of its referenced data object its own bytestream.
index_fields(index=Index(byte=0, bit=0, address=0, base_address=0, update=False), **options)[source]

Indexes all fields in the Sequence starting with the given index and returns the Index after the last Field in the Sequence.

Parameters:
  • index (Index) – start Index for the first Field in the Sequence.
  • nested (bool) – if True all Pointer fields in the Sequence indexes their referenced data object fields as well (chained method call).
container_size()[source]

Returns the accumulated bit size of all fields in the Sequence as a tuple in the form of (number of bytes, remaining number of bits).

first_field()[source]

Returns the first Field in the Sequence or None for an empty Sequence.

initialize_fields(content)[source]

Initializes the Field items in the Sequence with the values in the content list.

Parameters:content (list) – a list contains the Field values for each item in the Sequence.
view_fields(*attributes, **options)[source]

Returns a list with the selected field attribute or a list with the dictionaries of the selected field attributes for each Field nested in the Sequence.

The attributes of each Field for containers nested in the Sequence are viewed as well (chained method call).

Parameters:
  • attributes (str) – selected Field attributes. Fallback is the field value.
  • fieldnames (tuple) – sequence of dictionary keys for the selected field attributes. Defaults to (*attributes).
  • nested (bool) – if True all Pointer fields nested in the Sequence views their referenced data object field attributes as well (chained method call).
field_items(path='', **options)[source]

Returns a flatten list of ('field path', field item) tuples for each Field nested in the Sequence.

Parameters:
  • path (str) – field path of the Sequence.
  • nested (bool) – if True all Pointer fields in the data objects of all Pointer fields in the Sequence list their referenced data object field items as well (chained method call).
describe(name='', **options)[source]

Returns the metadata of the Sequence as an ordered dictionary.

metadata = {
    'class': self.__class__.__name__,
    'name': name if name else self.__class__.__name__,
    'size': len(self),
    'type': Sequence.item_type.name
    'member': [
        item.describe('name[idx]') for idx, item in enumerate(self)
    ]
}
Parameters:
  • name (str) – optional name for the Sequence. Fallback is the class name.
  • nested (bool) – if True all Pointer fields in the Sequence lists their referenced data object fields as well (chained method call). Default is True.
Array
class konfoo.Array(template, capacity=0)[source]

An Array is a Sequence which contains elements of one type. The template for the array element can be any Field instance or a callable (factory) which returns a Structure, Sequence, Array or any Field instance.

A callable template (factory) is necessary to ensure that the internal constructor for the array element produces complete copies for each array element including the nested objects in the template for the array element.

An Array of Pointer fields should use a callable instead of assigning a Pointer field instance directly as the array element template to ensure that the referenced data object of a Pointer field is also complete copied for each array element.

An Array adapts and extends a Sequence with the following features:

  • Append a new array element to the Array via append().
  • Insert a new array element before the index into the Array via insert().
  • Re-size the Array via resize().

An Array replaces the 'type' key of the metadata of a Sequence with its own item type.

Parameters:
  • template – template for the array element. The template can be any Field instance or any callable that returns a Structure, Sequence, Array or any Field instance.
  • capacity (int) – capacity of the Array in number of array elements.
append()[source]

Appends a new array element to the Array.

insert(index)[source]

Inserts a new array element before the index of the Array.

Parameters:index (int) – Array index.
resize(capacity)[source]

Re-sizes the Array by appending new array elements or removing array elements from the end.

Parameters:capacity (int) – new capacity of the Array in number of array elements.
initialize_fields(content)[source]

Initializes the Field elements in the Array with the values in the content list.

If the content list is shorter than the Array then the content list is used as a rotating fill pattern for the Field elements in the Array.

Parameters:content (list) – a list contains the Field values for each element in the Array or one Field value for all elements in the Array.

Fields

class konfoo.Field(bit_size=0, align_to=0, byte_order='auto')[source]

The Field class is the abstract class for all field classes.

A Field has a specific name, bit size, byte order and can be aligned to other fields.

A Field has methods to unpack, pack, deserialize and serialize its field value from and to a byte stream and stores its location within the byte stream and the providing data source in its field index.

Parameters:
  • bit_size (int) – is the size of a Field in bits.
  • align_to (int) – aligns the Field to the number of bytes, can be between 1 and 8.
  • byte_order (Byteorder, str) – byte order used to unpack and pack the value of the Field. Default is auto.
alignment

Returns the Alignment of the Field (read-only).

bit_size

Returns the size of the Field in bits (read-only).

byte_order

Byteorder used to decode and encode the value of the Field.

index

Index of the Field.

name

Returns the type name of the Field (read-only).

value

Field value.

static is_bit()[source]

Returns False.

static is_bool()[source]

Returns False.

static is_decimal()[source]

Returns False.

static is_float()[source]

Returns False.

static is_pointer()[source]

Returns False.

static is_stream()[source]

Returns False.

static is_string()[source]

Returns False.

unpack(buffer=b'', index=Index(byte=0, bit=0, address=0, base_address=0, update=False), **options)[source]

Unpacks the field value from the buffer at the given index in accordance with the decoding byte order for the de-serialization and the byte_order and alignment of the Field.

The specific decoding byte_order of the Field overrules the decoding byte order for the de-serialization.

Returns the deserialized field value.

Parameters:
  • buffer (bytes) – byte stream.
  • index (Index) – current read Index within the buffer.
  • byte_order (Byteorder, str) – decoding byte order for the de-serialization.

Note

This abstract method must be implemented by a derived class.

pack(buffer=bytearray(b''), **options)[source]

Packs the field value to the buffer at the given index in accordance with the encoding byte order for the serialization and the byte_order and alignment of the Field.

The specific encoding byte_order of the Field overrules the encoding byte order for the serialization.

Returns the bytes for the serialized field value.

Parameters:
  • buffer (bytearray) – byte stream.
  • byte_order (Byteorder, str) – encoding byte order for the serialization.

Note

This abstract method must be implemented by a derived class.

deserialize(buffer=b'', index=Index(byte=0, bit=0, address=0, base_address=0, update=False), **options)[source]

De-serializes the Field from the byte buffer starting at the begin of the buffer or with the given index by unpacking the bytes to the value of the Field in accordance with the decoding byte order for the de-serialization and the decoding byte_order of the Field.

The specific decoding byte_order of the Field overrules the decoding byte order for the de-serialization.

Returns the Index of the buffer after the Field.

Optional the de-serialization of the referenced data object of a Pointer field can be enabled.

Parameters:
  • buffer (bytes) – byte stream.
  • index (Index) – current read Index within the buffer.
  • byte_order (Byteorder, str) – decoding byte order for the de-serialization.
  • nested (bool) – if True a Pointer field de-serialize its referenced data object as well (chained method call). Each Pointer field uses for the de-serialization of its referenced data object its own bytestream.
serialize(buffer=bytearray(b''), index=Index(byte=0, bit=0, address=0, base_address=0, update=False), **options)[source]

Serializes the Field to the byte buffer starting at the begin of the buffer or with the given index by packing the value of the Field to the byte buffer in accordance with the encoding byte order for the serialization and the encoding byte_order of the Field.

The specific encoding byte_order of the Field overrules the encoding byte order for the serialization.

Returns the Index of the buffer after the Field.

Optional the serialization of the referenced data object of a Pointer field can be enabled.

Parameters:
  • buffer (bytearray) – byte stream.
  • index (Index) – current write Index of the buffer.
  • byte_order (Byteorder, str) – encoding byte order for the serialization.
  • nested (bool) – if True a Pointer field serializes its referenced data object as well (chained method call). Each Pointer field uses for the encoding of its referenced data object its own bytestream.
index_field(index=Index(byte=0, bit=0, address=0, base_address=0, update=False))[source]

Indexes the Field with the given index und returns the Index after the Field.

Parameters:index (Index) – start Index for the Field.
describe(name='', **options)[source]

Returns the metadata of a Field as an ordered dictionary.

metadata = {
    'address': self.index.address,
    'alignment': [self.alignment.byte_size, self.alignment.bit_offset],
    'class': self.name,
    'index': [self.index.byte, self.index.bit],
    'name': name if name else self.name,
    'order': self.byte_order.value,
    'size': self.bit_size,
    'type': Field.item_type.name,
    'value': self.value
}
Parameters:
  • name (str) – optional name for the Field. Fallback is the class name.
  • nested (bool) – if True a Pointer field lists its referenced data object fields as well (chained method call). Default is True.
Stream
class konfoo.Stream(size=0)[source]

A Stream field is a Field with a variable size and returns its field value as a hexadecimal string.

Internally a Stream field uses a bytes class to store the data of its field value.

A Stream field is:

  • containable: item in self returns True if item is part of the Stream field.
  • sized: len(self) returns the length of the Stream field.
  • indexable self[index] returns the byte at the index of the Stream field.
  • iterable iter(self) iterates over the bytes of the Stream field.
Parameters:size (int) – is the size of the Stream field in bytes.

Example:

>>> stream = Stream()
>>> stream.is_stream()
True
>>> stream.name
'Stream'
>>> stream.alignment
Alignment(byte_size=0, bit_offset=0)
>>> stream.byte_order
Byteorder.auto = 'auto'
>>> stream.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> stream.index_field()
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> stream.bit_size
0
>>> len(stream)
0
>>> bool(stream)
False
>>> stream.value
''
>>> bytes(stream)
b''
>>> stream.hex()
''
>>> stream.resize(10)
>>> stream.name
'Stream10'
>>> stream.alignment
Alignment(byte_size=10, bit_offset=0)
>>> stream.bit_size
80
>>> stream.index_field()
Index(byte=10, bit=0, address=10, base_address=0, update=False)
>>> stream.value
'00000000000000000000'
>>> stream.value = '0102030405'
>>> stream.value
'01020304050000000000'
>>> stream.resize(15)
>>> stream.value
'010203040500000000000000000000'
>>> stream.resize(10)
>>> stream.value = '0102030405060708090a0b0c'
>>> stream.value
'0102030405060708090a'
>>> stream.hex()
'0102030405060708090a'
>>> len(stream)
10
>>> [byte for byte in stream]  # converts to int
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> [hex(byte) for byte in stream]
['0x1', '0x2', '0x3', '0x4', '0x5', '0x6', '0x7', '0x8', '0x9', '0xa']
>>> stream[5]  # converts to int
6
>>> 7 in stream
True
>>> 0x0 in stream
False
>>> hexlify(stream[5:])  # converts to bytes
b'060708090a'
>>> stream.describe()
OrderedDict([('address', 0),
             ('alignment', [10, 0]),
             ('class', 'Stream10'),
             ('index', [0, 0]),
             ('name', 'Stream10'),
             ('order', 'auto'),
             ('size', 80),
             ('type', 'Field'),
             ('value', '0102030405060708090a')])
name

Returns the type name of the Stream field (read-only).

value

Field value as a lowercase hexadecimal encoded string.

hex()[source]

Returns a string containing two hexadecimal digits for each byte in the value of the Stream field.

static is_stream()[source]

Returns True.

unpack(buffer=b'', index=Index(byte=0, bit=0, address=0, base_address=0, update=False), **options)[source]

Unpacks the field value from the buffer at the given index in accordance with the decoding byte order for the de-serialization and the byte_order and alignment of the Field.

The specific decoding byte_order of the Field overrules the decoding byte order for the de-serialization.

Returns the deserialized field value.

Parameters:
  • buffer (bytes) – byte stream.
  • index (Index) – current read Index within the buffer.
  • byte_order (Byteorder, str) – decoding byte order for the de-serialization.

Note

This abstract method must be implemented by a derived class.

pack(buffer=bytearray(b''), **options)[source]

Packs the field value to the buffer at the given index in accordance with the encoding byte order for the serialization and the byte_order and alignment of the Field.

The specific encoding byte_order of the Field overrules the encoding byte order for the serialization.

Returns the bytes for the serialized field value.

Parameters:
  • buffer (bytearray) – byte stream.
  • byte_order (Byteorder, str) – encoding byte order for the serialization.

Note

This abstract method must be implemented by a derived class.

resize(size)[source]

Re-sizes the Stream field by appending zero bytes or removing bytes from the end.

Parameters:size (int) – Stream size in number of bytes.
String
class konfoo.String(size=0)[source]

A String field is a Stream field with a variable size and returns its field value as a zero-terminated ASCII string.

A String field is:

  • containable: item in self returns True if item is part of the String field.
  • sized: len(self) returns the length of the String field.
  • indexable self[index] returns the byte at the index of the String field.
  • iterable iter(self) iterates over the bytes of the String field.
Parameters:size (int) – is the size of the String field in bytes.

Example:

>>> string = String()
>>> string.is_stream()
True
>>> string.is_string()
True
>>> string.is_terminated()
False
>>> string.name
'String'
>>> string.alignment
Alignment(byte_size=0, bit_offset=0)
>>> string.byte_order
Byteorder.auto = 'auto'
>>> string.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> string.index_field()
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> string.bit_size
0
>>> len(string)
0
>>> bool(string)
False
>>> string.value
''
>>> bytes(string)
b''
>>> string.hex()
''
>>> string.resize(10)
>>> string.name
'String10'
>>> string.alignment
Alignment(byte_size=10, bit_offset=0)
>>> string.bit_size
80
>>> string.index_field()
Index(byte=10, bit=0, address=10, base_address=0, update=False)
>>> string.value
''
>>> string.value = 'KonFoo'
>>> string.value
'KonFoo'
>>> string.resize(3)
>>> string.value
'Kon'
>>> string.resize(10)
>>> string.value
'Kon'
>>> string.value = 'KonFoo is Fun'
>>> string.value
'KonFoo is '
>>> string.hex()
'4b6f6e466f6f20697320'
>>> len(string)
10
>>> [byte for byte in string]  # converts to int
[75, 111, 110, 70, 111, 111, 32, 105, 115, 32]
>>> [chr(byte) for byte in string]  # converts to int
['K', 'o', 'n', 'F', 'o', 'o', ' ', 'i', 's', ' ']
>>> chr(string[5])  # converts to int -> chr
'o'
>>> ord(' ') in string
True
>>> 0x0 in string
False
>>> string[:6]  # converts to bytes
b'KonFoo'
>>> string[3:6]  # converts to bytes
b'Foo'
>>> string.describe()
OrderedDict([('address', 0),
             ('alignment', [10, 0]),
             ('class', 'String10'),
             ('index', [0, 0]),
             ('name', 'String10'),
             ('order', 'auto'),
             ('size', 80),
             ('type', 'Field'),
             ('value', 'KonFoo is ')])
value

Field value as an ascii encoded string.

static is_string()[source]

Returns True.

is_terminated()[source]

Returns True if the String field is zero-terminated.

Float
class konfoo.Float(byte_order='auto')[source]

A Float field is a Field with a fix size of four bytes and returns its field value as a single precision float.

Internally a Float field uses a float class to store the data of its field value.

A Float field extends the metadata of a Field with a 'max' and 'min' key for its maximum and minimum possible field value.

Parameters:byte_order (Byteorder, str) – byte order used to unpack and pack the value of the Float field.

Example:

>>> real = Float()
>>> real.is_float()
True
>>> real.name
'Float32'
>>> real.alignment
Alignment(byte_size=4, bit_offset=0)
>>> real.byte_order
Byteorder.auto = 'auto'
>>> real.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> real.index_field()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> real.bit_size
32
>>> real.min()
-3.4028234663852886e+38
>>> real.max()
3.4028234663852886e+38
>>> real.smallest()
1.1754943508222875e-38
>>> real.epsilon()
5.960464477539063e-08
>>> real.value
0.0
>>> bytes(real)
b'\x00\x00\x00\x00'
>>> int(real)
0
>>> float(real)
0.0
>>> bool(real)
False
>>> real.value = 0x10
>>> real.value
16.0
>>> real.value = -3.4028234663852887e+38
>>> real.value
-3.4028234663852886e+38
>>> real.value = 3.4028234663852887e+38
>>> real.value
3.4028234663852886e+38
>>> real.describe()
OrderedDict([('address', 0),
             ('alignment', [4, 0]),
             ('class', 'Float32'),
             ('index', [0, 0]),
             ('max', 3.4028234663852886e+38),
             ('min', -3.4028234663852886e+38),
             ('name', 'Float32'),
             ('order', 'auto'),
             ('size', 32),
             ('type', 'Field'),
             ('value', 3.4028234663852886e+38)])
value

Field value as a single precision floating point number.

static is_float()[source]

Returns True.

static smallest()[source]

Returns the smallest normalized field value of the Float field.

static max()[source]

Returns the maximal possible field value of the Float field.

static min()[source]

Returns the minimal possible field value of the Float field.

unpack(buffer=b'', index=Index(byte=0, bit=0, address=0, base_address=0, update=False), **options)[source]

Unpacks the field value from the buffer at the given index in accordance with the decoding byte order for the de-serialization and the byte_order and alignment of the Field.

The specific decoding byte_order of the Field overrules the decoding byte order for the de-serialization.

Returns the deserialized field value.

Parameters:
  • buffer (bytes) – byte stream.
  • index (Index) – current read Index within the buffer.
  • byte_order (Byteorder, str) – decoding byte order for the de-serialization.

Note

This abstract method must be implemented by a derived class.

pack(buffer=bytearray(b''), **options)[source]

Packs the field value to the buffer at the given index in accordance with the encoding byte order for the serialization and the byte_order and alignment of the Field.

The specific encoding byte_order of the Field overrules the encoding byte order for the serialization.

Returns the bytes for the serialized field value.

Parameters:
  • buffer (bytearray) – byte stream.
  • byte_order (Byteorder, str) – encoding byte order for the serialization.

Note

This abstract method must be implemented by a derived class.

describe(name='', **options)[source]

Returns the metadata of a Field as an ordered dictionary.

metadata = {
    'address': self.index.address,
    'alignment': [self.alignment.byte_size, self.alignment.bit_offset],
    'class': self.name,
    'index': [self.index.byte, self.index.bit],
    'name': name if name else self.name,
    'order': self.byte_order.value,
    'size': self.bit_size,
    'type': Field.item_type.name,
    'value': self.value
}
Parameters:
  • name (str) – optional name for the Field. Fallback is the class name.
  • nested (bool) – if True a Pointer field lists its referenced data object fields as well (chained method call). Default is True.
Double
class konfoo.Double(byte_order='auto')[source]

A Double field is a Field with a fix size of eight bytes and returns its field value as a double precision float.

Internally a Double field uses a float class to store the data of its field value.

A Double field extends the metadata of a Field with a 'max' and 'min' key for its maximum and minimum possible field value.

Parameters:byte_order (Byteorder, str) – byte order used to unpack and pack the value of the Double field.

Example:

>>> double = Double()
>>> double.is_float()
True
>>> double.name
'Double64'
>>> double.alignment
Alignment(byte_size=8, bit_offset=0)
>>> double.byte_order
Byteorder.auto = 'auto'
>>> double.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> double.index_field()
Index(byte=8, bit=0, address=8, base_address=0, update=False)
>>> double.bit_size
64
>>> double.min()
-1.7976931348623157e+308
>>> double.max()
1.7976931348623157e+308
>>> double.smallest()
2.2250738585072014e-308
>>> double.epsilon()
1.1102230246251565e-16
>>> double.value
0.0
>>> bytes(double)
b'\x00\x00\x00\x00\x00\x00\x00\x00'
>>> int(double)
0
>>> float(double)
0.0
>>> bool(double)
False
>>> double.value = 0x10
>>> double.value
16.0
>>> double.value = -1.7976931348623158e+308
>>> double.value
-1.7976931348623157e+308
>>> double.value = 1.7976931348623158e+308
>>> double.value
1.7976931348623157e+308
>>> double.describe()
OrderedDict([('address', 0),
             ('alignment', [8, 0]),
             ('class', 'Double64'),
             ('index', [0, 0]),
             ('max', 1.7976931348623157e+308),
             ('min', -1.7976931348623157e+308),
             ('name', 'Double64'),
             ('order', 'auto'),
             ('size', 64),
             ('type', 'Field'),
             ('value', 1.7976931348623157e+308)])
value

Field value as a double precision floating point number.

static is_float()[source]

Returns True.

static smallest()[source]

Returns the smallest normalized field value of the Double field.

static max()[source]

Returns the maximal possible field value of the Double field.

static min()[source]

Returns the minimal possible field value of the Double field.

unpack(buffer=b'', index=Index(byte=0, bit=0, address=0, base_address=0, update=False), **options)[source]

Unpacks the field value from the buffer at the given index in accordance with the decoding byte order for the de-serialization and the byte_order and alignment of the Field.

The specific decoding byte_order of the Field overrules the decoding byte order for the de-serialization.

Returns the deserialized field value.

Parameters:
  • buffer (bytes) – byte stream.
  • index (Index) – current read Index within the buffer.
  • byte_order (Byteorder, str) – decoding byte order for the de-serialization.

Note

This abstract method must be implemented by a derived class.

pack(buffer=bytearray(b''), **options)[source]

Packs the field value to the buffer at the given index in accordance with the encoding byte order for the serialization and the byte_order and alignment of the Field.

The specific encoding byte_order of the Field overrules the encoding byte order for the serialization.

Returns the bytes for the serialized field value.

Parameters:
  • buffer (bytearray) – byte stream.
  • byte_order (Byteorder, str) – encoding byte order for the serialization.

Note

This abstract method must be implemented by a derived class.

describe(name='', **options)[source]

Returns the metadata of a Field as an ordered dictionary.

metadata = {
    'address': self.index.address,
    'alignment': [self.alignment.byte_size, self.alignment.bit_offset],
    'class': self.name,
    'index': [self.index.byte, self.index.bit],
    'name': name if name else self.name,
    'order': self.byte_order.value,
    'size': self.bit_size,
    'type': Field.item_type.name,
    'value': self.value
}
Parameters:
  • name (str) – optional name for the Field. Fallback is the class name.
  • nested (bool) – if True a Pointer field lists its referenced data object fields as well (chained method call). Default is True.
Decimal
class konfoo.Decimal(bit_size, align_to=None, signed=False, byte_order='auto')[source]

A Decimal field is a Field with a variable size and returns its field value as a decimal number.

Internally a Decimal field uses an int class to store the data of its field value.

A Decimal field extends the metadata of a Field with a 'max' and 'min' key for its maximum and minimum possible field value and a 'signed' key to mark the decimal number as signed or unsigned.

Parameters:
  • bit_size (int) – is the size of the Decimal field in bits, can be between 1 and 64.
  • align_to (int) – aligns the Decimal field to the number of bytes, can be between 1 and 8. If no field alignment is set the Decimal field aligns itself to the next matching byte size according to the size of the Decimal field.
  • signed (bool) – if True the Decimal field is signed otherwise unsigned.
  • byte_order (Byteorder, str) – byte order used to unpack and pack the value of the Decimal field.

Example:

>>> unsigned = Decimal(16)
>>> unsigned.is_decimal()
True
>>> unsigned.name
'Decimal16'
>>> unsigned.alignment
Alignment(byte_size=2, bit_offset=0)
>>> unsigned.byte_order
Byteorder.auto = 'auto'
>>> unsigned.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> unsigned.index_field()
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> unsigned.bit_size
16
>>> unsigned.signed
False
>>> unsigned.min()
0
>>> unsigned.max()
65535
>>> unsigned.value
0
>>> bytes(unsigned)
b'\x00\x00'
>>> int(unsigned)
0
>>> float(unsigned)
0.0
>>> hex(unsigned)
'0x0'
>>> bin(unsigned)
'0b0'
>>> oct(unsigned)
'0o0'
>>> bool(unsigned)
False
>>> unsigned.as_signed()
0
>>> unsigned.as_unsigned()
0
>>> unsigned.deserialize(bytes.fromhex('0080'))
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> unsigned.value
32768
>>> unsigned.value = 0x4000
>>> unsigned.value
16384
>>> unsigned.value = -1
>>> unsigned.value
0
>>> unsigned.value = 65536
>>> unsigned.value
65535
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> unsigned.serialize(bytestream)
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> hexlify(bytestream)
b'ffff'
>>> unsigned.describe()
OrderedDict([('address', 0),
             ('alignment', [2, 0]),
             ('class', 'Decimal16'),
             ('index', [0, 0]),
             ('max', 65535),
             ('min', 0),
             ('name', 'Decimal16'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 16),
             ('type', 'Field'),
             ('value', 65535)])

Example:

>>> signed = Decimal(16, signed=True)
>>> signed.is_decimal()
True
>>> signed.name
'Decimal16'
>>> signed.alignment
Alignment(byte_size=2, bit_offset=0)
>>> signed.byte_order
Byteorder.auto = 'auto'
>>> signed.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> signed.index_field()
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> signed.bit_size
16
>>> signed.signed
True
>>> signed.min()
-32768
>>> signed.max()
32767
>>> signed.value
0
>>> bytes(signed)
b'\x00\x00'
>>> int(signed)
0
>>> float(signed)
0.0
>>> hex(signed)
'0x0'
>>> bin(signed)
'0b0'
>>> oct(signed)
'0o0'
>>> bool(signed)
False
>>> signed.deserialize(bytes.fromhex('00c0'))
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> signed.value
-16384
>>> signed.value = -0x4000
>>> signed.value
-16384
>>> signed.value = -32769
>>> signed.value
-32768
>>> signed.value = 32768
>>> signed.value
32767
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> signed.serialize(bytestream)
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> hexlify(bytestream)
b'ff7f'
>>> signed.describe()
OrderedDict([('address', 0),
             ('alignment', [2, 0]),
             ('class', 'Decimal16'),
             ('index', [0, 0]),
             ('max', 32767),
             ('min', -32768),
             ('name', 'Decimal16'),
             ('order', 'auto'),
             ('signed', True),
             ('size', 16),
             ('type', 'Field'),
             ('value', 32767)])
value

Field value as a decimal number.

signed

Returns True if the Decimal field is signed.

static is_decimal()[source]

Returns True.

max()[source]

Returns the maximal possible field value of the Decimal field.

min()[source]

Returns the minimal possible field value of the Decimal field.

as_unsigned()[source]

Returns the field value of the Decimal field as an unsigned integer.

as_signed()[source]

Returns the field value of the Decimal field as a signed integer.

unpack(buffer=b'', index=Index(byte=0, bit=0, address=0, base_address=0, update=False), **options)[source]

Unpacks the field value from the buffer at the given index in accordance with the decoding byte order for the de-serialization and the byte_order and alignment of the Field.

The specific decoding byte_order of the Field overrules the decoding byte order for the de-serialization.

Returns the deserialized field value.

Parameters:
  • buffer (bytes) – byte stream.
  • index (Index) – current read Index within the buffer.
  • byte_order (Byteorder, str) – decoding byte order for the de-serialization.

Note

This abstract method must be implemented by a derived class.

pack(buffer=bytearray(b''), **options)[source]

Packs the field value to the buffer at the given index in accordance with the encoding byte order for the serialization and the byte_order and alignment of the Field.

The specific encoding byte_order of the Field overrules the encoding byte order for the serialization.

Returns the bytes for the serialized field value.

Parameters:
  • buffer (bytearray) – byte stream.
  • byte_order (Byteorder, str) – encoding byte order for the serialization.

Note

This abstract method must be implemented by a derived class.

describe(name=None, **options)[source]

Returns the metadata of a Field as an ordered dictionary.

metadata = {
    'address': self.index.address,
    'alignment': [self.alignment.byte_size, self.alignment.bit_offset],
    'class': self.name,
    'index': [self.index.byte, self.index.bit],
    'name': name if name else self.name,
    'order': self.byte_order.value,
    'size': self.bit_size,
    'type': Field.item_type.name,
    'value': self.value
}
Parameters:
  • name (str) – optional name for the Field. Fallback is the class name.
  • nested (bool) – if True a Pointer field lists its referenced data object fields as well (chained method call). Default is True.
class konfoo.Decimal8(signed=False, byte_order='auto')[source]

A Decimal8 field is a Decimal field with a size of one byte and is by default unsigned.

class konfoo.Decimal16(signed=False, byte_order='auto')[source]

A Decimal16 field is a Decimal field with a size of two bytes and is by default unsigned.

class konfoo.Decimal24(signed=False, byte_order='auto')[source]

A Decimal24 field is a Decimal field with a size of three bytes and is by default unsigned.

class konfoo.Decimal32(signed=False, byte_order='auto')[source]

A Decimal32 field is a Decimal field with a size of four bytes and is by default unsigned.

class konfoo.Decimal64(signed=False, byte_order='auto')[source]

A Decimal64 field is a Decimal field with a size of eight bytes and is by default unsigned.

Bit
class konfoo.Bit(number, align_to=None)[source]

A Bit field is an unsigned Decimal with a size of one bit and returns its field value as an unsigned integer number.

Parameters:
  • number (int) – is the bit offset of the Bit field within the aligned bytes, can be between 0 and 63.
  • align_to (int) – aligns the Bit field to the number of bytes, can be between 1 and 8.

Example:

>>> bit = Bit(0)
>>> bit.is_decimal()
True
>>> bit.is_bit()
True
>>> bit.name
'Bit'
>>> bit.alignment
Alignment(byte_size=1, bit_offset=0)
>>> bit.byte_order
Byteorder.auto = 'auto'
>>> bit.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> bit.index_field()
Index(byte=0, bit=1, address=0, base_address=0, update=False)
>>> bit.bit_size
1
>>> bit.signed
False
>>> bit.min()
0
>>> bit.max()
1
>>> bit.value
0
>>> bit.signed
False
>>> bit.value
0
>>> bytes(bit)
b'\x00'
>>> int(bit)
0
>>> float(bit)
0.0
>>> hex(bit)
'0x0'
>>> bin(bit)
'0b0'
>>> oct(bit)
'0o0'
>>> bool(bit)
False
>>> bit.as_signed()
0
>>> bit.as_unsigned()
0
>>> bit.deserialize(bytes.fromhex('01'))
Index(byte=0, bit=1, address=0, base_address=0, update=False)
>>> bit.value
1
>>> bit.value = 0
>>> bit.value
0
>>> bit.value = False
>>> bit.value
0
>>> bit.value = True
>>> bit.value
1
>>> bit.value = -1
>>> bit.value
0
>>> bit.value = 2
>>> bit.value
1
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> bit.serialize(bytestream)
Index(byte=0, bit=1, address=0, base_address=0, update=False)
>>> hexlify(bytestream)
b'01'
>>> bit.describe()
OrderedDict([('address', 0),
             ('alignment', [1, 0]),
             ('class', 'Bit'),
             ('index', [0, 0]),
             ('max', 1),
             ('min', 0),
             ('name', 'Bit'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 1),
             ('type', 'Field'),
             ('value', 1)])
name

Returns the type name of the Bit field (read-only).

static is_bit()[source]

Returns True.

Byte
class konfoo.Byte(align_to=None)[source]

A Byte field is an unsigned Decimal field with a size of one byte and returns its field value as a lowercase hexadecimal string prefixed with 0x.

Parameters:align_to (int) – aligns the Byte field to the number of bytes, can be between 1 and 8. If no field alignment is set the Byte field aligns itself to the next matching byte size according to the size of the Byte field.

Example:

>>> byte = Byte()
>>> byte.is_decimal()
True
>>> byte.name
'Byte'
>>> byte.alignment
Alignment(byte_size=1, bit_offset=0)
>>> byte.byte_order
Byteorder.auto = 'auto'
>>> byte.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> byte.index_field()
Index(byte=1, bit=0, address=1, base_address=0, update=False)
>>> byte.bit_size
8
>>> byte.signed
False
>>> byte.min()
0
>>> byte.max()
255
>>> byte.value
'0x0'
>>> bytes(byte)
b'\x00'
>>> int(byte)
0
>>> float(byte)
0.0
>>> hex(byte)
'0x0'
>>> bin(byte)
'0b0'
>>> oct(byte)
'0o0'
>>> bool(byte)
False
>>> byte.as_signed()
0
>>> byte.as_unsigned()
0
>>> byte.deserialize(bytes.fromhex('20'))
Index(byte=1, bit=0, address=1, base_address=0, update=False)
>>> byte.value
'0x20'
>>> byte.value = 16
>>> byte.value
'0x10'
>>> byte.value = -1
>>> byte.value
'0x0'
>>> byte.value = 256
>>> byte.value
'0xff'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> byte.serialize(bytestream)
Index(byte=1, bit=0, address=1, base_address=0, update=False)
>>> hexlify(bytestream)
b'ff'
>>> byte.describe()
OrderedDict([('address', 0),
             ('alignment', [1, 0]),
             ('class', 'Byte'),
             ('index', [0, 0]),
             ('max', 255),
             ('min', 0),
             ('name', 'Byte'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 8),
             ('type', 'Field'),
             ('value', '0xff')])
name

Returns the type name of the Byte field (read-only).

value

Field value as a lowercase hexadecimal string prefixed with 0x.

Char
class konfoo.Char(align_to=None)[source]

A Char field is an unsigned Decimal field with a size of one byte and returns its field value as an unicode string character.

Parameters:align_to (int) – aligns the Char field to the number of bytes, can be between 1 and 8. If no field alignment is set the Char field aligns itself to the next matching byte size according to the size of the Char field.

Example:

>>> char = Char()
>>> char.is_decimal()
True
>>> char.name
'Char'
>>> char.alignment
Alignment(byte_size=1, bit_offset=0)
>>> char.byte_order
Byteorder.auto = 'auto'
>>> char.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> char.index_field()
Index(byte=1, bit=0, address=1, base_address=0, update=False)
>>> char.bit_size
8
>>> char.signed
False
>>> char.min()
0
>>> char.max()
255
>>> char.value
'\x00'
>>> bytes(char)
b'\x00'
>>> ord(char.value)
0
>>> int(char)
0
>>> float(char)
0.0
>>> hex(char)
'0x0'
>>> bin(char)
'0b0'
>>> oct(char)
'0o0'
>>> bool(char)
False
>>> char.as_signed()
0
>>> char.as_unsigned()
0
>>> char.deserialize(bytes.fromhex('41'))
Index(byte=1, bit=0, address=1, base_address=0, update=False)
>>> char.value
'A'
>>> char.value = 66
>>> char.value
'B'
>>> char.value = 0x41
>>> char.value
'A'
>>> char.value = 'F'
>>> char.value
'F'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> char.serialize(bytestream)
Index(byte=1, bit=0, address=1, base_address=0, update=False)
>>> hexlify(bytestream)
b'46'
>>> char.describe()
OrderedDict([('address', 0),
             ('alignment', [1, 0]),
             ('class', 'Char'),
             ('index', [0, 0]),
             ('max', 255),
             ('min', 0),
             ('name', 'Char'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 8),
             ('type', 'Field'),
             ('value', 'F')])
name

Returns the type name of the Char field (read-only).

value

Field value as an unicode string character.

Signed
class konfoo.Signed(bit_size, align_to=None, byte_order='auto')[source]

A Signed field is a signed Decimal field with a variable size and returns its field value as a signed integer number.

Parameters:
  • bit_size (int) – is the size of the Signed field in bits, can be between 1 and 64.
  • align_to (int) – aligns the Signed field to the number of bytes, can be between 1 and 8. If no field alignment is set the Signed field aligns itself to the next matching byte size according to the size of the Signed field.
  • byte_order (Byteorder, str) – byte order used to unpack and pack the value of the Signed field.

Example:

>>> signed = Signed(16)
>>> signed.is_decimal()
True
>>> signed.name
'Signed16'
>>> signed.alignment
Alignment(byte_size=2, bit_offset=0)
>>> signed.byte_order
Byteorder.auto = 'auto'
>>> signed.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> signed.index_field()
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> signed.bit_size
16
>>> signed.signed
True
>>> signed.min()
-32768
>>> signed.max()
32767
>>> signed.value
0
>>> bytes(signed)
b'\x00\x00'
>>> int(signed)
0
>>> float(signed)
0.0
>>> hex(signed)
'0x0'
>>> bin(signed)
'0b0'
>>> oct(signed)
'0o0'
>>> bool(signed)
False
>>> signed.as_signed()
0
>>> signed.as_unsigned()
0
>>> signed.deserialize(bytes.fromhex('00c0'))
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> signed.value
-16384
>>> signed.value = -0x4000
>>> signed.value
-16384
>>> signed.value = -32769
>>> signed.value
-32768
>>> signed.value = 32768
>>> signed.value
32767
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> signed.serialize(bytestream)
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> hexlify(bytestream)
b'ff7f'
>>> signed.describe()
OrderedDict([('address', 0),
             ('alignment', [2, 0]),
             ('class', 'Signed16'),
             ('index', [0, 0]),
             ('max', 32767),
             ('min', -32768),
             ('name', 'Signed16'),
             ('order', 'auto'),
             ('signed', True),
             ('size', 16),
             ('type', 'Field'),
             ('value', 32767)])
class konfoo.Signed8(byte_order='auto')[source]

A Signed8 field is a Signed field with a size of one byte.

class konfoo.Signed16(byte_order='auto')[source]

A Signed16 field is a Signed field with a size of two bytes.

class konfoo.Signed24(byte_order='auto')[source]

A Signed24 field is a Signed field with a size of three bytes.

class konfoo.Signed32(byte_order='auto')[source]

A Signed32 field is a Signed field with a size of four bytes.

class konfoo.Signed64(byte_order='auto')[source]

A Signed64 field is a Signed field with a size of eight bytes.

Unsigned
class konfoo.Unsigned(bit_size, align_to=None, byte_order='auto')[source]

A Unsigned field is an unsigned Decimal field with a variable size and returns its field value as a lowercase hexadecimal string prefixed with 0x.

Parameters:
  • bit_size (int) – is the size of the Unsigned field in bits, can be between 1 and 64.
  • align_to (int) – aligns the Unsigned field to the number of bytes, can be between 1 and 8. If no field alignment is set the Unsigned field aligns itself to the next matching byte size according to the size of the Unsigned field.
  • byte_order (Byteorder, str) – byte order used to unpack and pack the value of the Unsigned field.

Example:

>>> unsigned = Unsigned(16)
>>> unsigned.is_decimal()
True
>>> unsigned.name
'Unsigned16'
>>> unsigned.alignment
Alignment(byte_size=2, bit_offset=0)
>>> unsigned.byte_order
Byteorder.auto = 'auto'
>>> unsigned.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> unsigned.index_field()
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> unsigned.bit_size
16
>>> unsigned.signed
False
>>> unsigned.min()
0
>>> unsigned.max()
65535
>>> unsigned.value
'0x0'
>>> bytes(unsigned)
b'\x00\x00'
>>> int(unsigned)
0
>>> float(unsigned)
0.0
>>> hex(unsigned)
'0x0'
>>> bin(unsigned)
'0b0'
>>> oct(unsigned)
'0o0'
>>> bool(unsigned)
False
>>> unsigned.as_signed()
0
>>> unsigned.as_unsigned()
0
>>> unsigned.deserialize(bytes.fromhex('00c0'))
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> unsigned.value
'0xc000'
>>> unsigned.value = 0x4000
>>> unsigned.value
'0x4000'
>>> unsigned.value = -0x1
>>> unsigned.value
'0x0'
>>> unsigned.value = 0x10000
>>> unsigned.value
'0xffff'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> unsigned.serialize(bytestream)
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> hexlify(bytestream)
b'ffff'
>>> unsigned.describe()
OrderedDict([('address', 0),
             ('alignment', [2, 0]),
             ('class', 'Unsigned16'),
             ('index', [0, 0]),
             ('max', 65535),
             ('min', 0),
             ('name', 'Unsigned16'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 16),
             ('type', 'Field'),
             ('value', '0xffff')])
value

Field value as a lowercase hexadecimal string prefixed with 0x.

class konfoo.Unsigned8(byte_order='auto')[source]

A Unsigned8 field is an Unsigned field with a size of one byte.

class konfoo.Unsigned16(byte_order='auto')[source]

A Unsigned16 field is an Unsigned field with a size of two bytes.

class konfoo.Unsigned24(byte_order='auto')[source]

A Unsigned24 field is an Unsigned field with a size of three bytes.

class konfoo.Unsigned32(byte_order='auto')[source]

A Unsigned32 field is an Unsigned field with a size of four bytes.

class konfoo.Unsigned64(byte_order='auto')[source]

A Unsigned64 field is an Unsigned field with a size of eight bytes.

Bitset
class konfoo.Bitset(bit_size, align_to=None, byte_order='auto')[source]

A Bitset field is an unsigned Decimal field with a variable size and returns its field value as a binary string prefixed with 0b.

Parameters:
  • bit_size (int) – is the size of the Bitset field in bits, can be between 1 and 64.
  • align_to (int) – aligns the Bitset field to the number of bytes, can be between 1 and 8. If no field alignment is set the Bitset field aligns itself to the next matching byte size according to the size of the Bitset field.
  • byte_order (Byteorder, str) – byte order used to unpack and pack the value of the Bitset field.

Example:

>>> bitset = Bitset(16)
>>> bitset.is_decimal()
True
>>> bitset.name
'Bitset16'
>>> bitset.alignment
Alignment(byte_size=2, bit_offset=0)
>>> bitset.byte_order
Byteorder.auto = 'auto'
>>> bitset.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> bitset.index_field()
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> bitset.bit_size
16
>>> bitset.signed
False
>>> bitset.min()
0
>>> bitset.max()
65535
>>> bitset.value
'0b0000000000000000'
>>> bytes(bitset)
b'\x00\x00'
>>> int(bitset)
0
>>> float(bitset)
0.0
>>> hex(bitset)
'0x0'
>>> bin(bitset)
'0b0'
>>> oct(bitset)
'0o0'
>>> bool(bitset)
False
>>> bitset.as_signed()
0
>>> bitset.as_unsigned()
0
>>> bitset.deserialize(bytes.fromhex('f00f'))
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> bitset.value
'0b0000111111110000'
>>> bitset.value = 0b1111
>>> bitset.value
'0b0000000000001111'
>>> bitset.value = -1
>>> bitset.value
'0b0000000000000000'
>>> bitset.value = 0x10000
>>> bitset.value
'0b1111111111111111'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> bitset.serialize(bytestream)
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> hexlify(bytestream)
b'ffff'
>>> bitset.describe()
OrderedDict([('address', 0),
             ('alignment', [2, 0]),
             ('class', 'Bitset16'),
             ('index', [0, 0]),
             ('max', 65535),
             ('min', 0),
             ('name', 'Bitset16'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 16),
             ('type', 'Field'),
             ('value', '0b1111111111111111')])
value

Field value as a binary string prefixed with 0b.

class konfoo.Bitset8(byte_order='auto')[source]

A Bitset8 field is a Bitset field with a size of one byte.

class konfoo.Bitset16(byte_order='auto')[source]

A Bitset16 field is a Bitset field with a size of two bytes.

class konfoo.Bitset24(byte_order='auto')[source]

A Bitset24 field is a Bitset field with a size of three bytes.

class konfoo.Bitset32(byte_order='auto')[source]

A Bitset32 field is a Bitset field with a size of four bytes.

class konfoo.Bitset64(byte_order='auto')[source]

A Bitset64 field is a Bitset field with a size of eight bytes.

Bool
class konfoo.Bool(bit_size, align_to=None, byte_order='auto')[source]

A Bool field is an unsigned Decimal field with a variable size and returns its field value as a boolean value.

Parameters:
  • bit_size (int) – is the size of the Bool field in bits, can be between 1 and 64.
  • align_to (int) – aligns the Bool field to the number of bytes, can be between 1 and 8. If no field alignment is set the Bool field aligns itself to the next matching byte size according to the size of the Bool field.
  • byte_order (Byteorder, str) – byte order used to unpack and pack the value of the Bool field.

Example:

>>> boolean = Bool(16)
>>> boolean.is_decimal()
True
>>> boolean.is_bool()
True
>>> boolean.name
'Bool16'
>>> boolean.alignment
Alignment(byte_size=2, bit_offset=0)
>>> boolean.byte_order
Byteorder.auto = 'auto'
>>> boolean.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> boolean.index_field()
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> boolean.bit_size
16
>>> boolean.signed
False
>>> boolean.min()
0
>>> boolean.max()
65535
>>> boolean.value
False
>>> bytes(boolean)
b'\x00\x00'
>>> int(boolean)
0
>>> float(boolean)
0.0
>>> hex(boolean)
'0x0'
>>> bin(boolean)
'0b0'
>>> oct(boolean)
'0o0'
>>> bool(boolean)
False
>>> boolean.as_signed()
0
>>> boolean.as_unsigned()
0
>>> boolean.deserialize(bytes.fromhex('0f00'))
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> boolean.value
True
>>> boolean.value = False
>>> boolean.value
False
>>> boolean.value = -1
>>> boolean.value
False
>>> boolean.value = 0x10000
>>> boolean.value
True
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> boolean.serialize(bytestream)
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> hexlify(bytestream)
b'ffff'
>>> boolean.describe()
OrderedDict([('address', 0),
             ('alignment', [2, 0]),
             ('class', 'Bool16'),
             ('index', [0, 0]),
             ('max', 65535),
             ('min', 0),
             ('name', 'Bool16'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 16),
             ('type', 'Field'),
             ('value', True)])
value

Field value as a boolean value, True or False.

static is_bool()[source]

Returns True.

class konfoo.Bool8(byte_order='auto')[source]

A Bool8 field is a Bool field with a size of one byte.

class konfoo.Bool16(byte_order='auto')[source]

A Bool16 field is a Bool field with a size of two bytes.

class konfoo.Bool24(byte_order='auto')[source]

A Bool24 field is a Bool field with a size of three bytes.

class konfoo.Bool32(byte_order='auto')[source]

A Bool32 field is a Bool field with a size of four bytes.

class konfoo.Bool64(byte_order='auto')[source]

A Bool64 field is a Bool field with a size of eight bytes.

Enum
class konfoo.Enum(bit_size, align_to=None, enumeration=None, byte_order='auto')[source]

A Enum field is an unsigned Decimal field with a variable size and returns its field value as an unsigned integer number.

If an Enumeration is available and a member matches the integer number then the member name string is returned otherwise the integer number is returned.

Parameters:
  • bit_size (int) – is the size of the Enum field in bits, can be between 1 and 64.
  • align_to (int) – aligns the Enum field to the number of bytes, can be between 1 and 8. If no field alignment is set the Enum field aligns itself to the next matching byte size according to the size of the Enum field.
  • enumerationEnumeration definition of the Enum field.
  • byte_order (Byteorder, str) – byte order used to unpack and pack the value of the Enum field.

Example:

>>> enum = Enum(16, enumeration=ItemClass)
>>> enum.is_decimal()
True
>>> enum.name
'Enum16'
>>> enum.alignment
Alignment(byte_size=2, bit_offset=0)
>>> enum.byte_order
Byteorder.auto = 'auto'
>>> enum.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> enum.index_field()
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> enum.bit_size
16
>>> enum.signed
False
>>> bytes(enum)
b'\x00\x00'
>>> enum.min()
0
>>> enum.max()
65535
>>> enum.value
0
>>> int(enum)
0
>>> float(enum)
0.0
>>> hex(enum)
'0x0'
>>> bin(enum)
'0b0'
>>> oct(enum)
'0o0'
>>> bool(enum)
False
>>> enum.as_signed()
0
>>> enum.as_unsigned()
0
>>> enum.deserialize(bytes.fromhex('2800'))
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> enum.value
'Decimal'
>>> enum.value = 48
>>> enum.value
'Enum'
>>> enum.value = 'Enum'
>>> enum.value
'Enum'
>>> enum.value = 40
>>> enum.value
'Decimal'
>>> enum.value = -1
>>> enum.value
0
>>> enum.value = 65536
>>> enum.value
65535
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> enum.serialize(bytestream)
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> hexlify(bytestream)
b'ffff'
>>> enum.describe()
OrderedDict([('address', 0),
             ('alignment', [2, 0]),
             ('class', 'Enum16'),
             ('index', [0, 0]),
             ('max', 65535),
             ('min', 0),
             ('name', 'Enum16'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 16),
             ('type', 'Field'),
             ('value', 65535)])
value

Field value as an enum name string. Fall back is an unsigned integer number.

class konfoo.Antivalent(align_to=None, byte_order='auto')[source]

An Antivalent field is an Enum field with a size of two bits and a fix assigned enumeration.

class Validity[source]

An enumeration.

class konfoo.Enum4(align_to=None, enumeration=None, byte_order='auto')[source]

An Enum4 field is an Enum field with a size of four bits.

class konfoo.Enum8(enumeration=None, byte_order='auto')[source]

An Enum8 field is an Enum field with a size of one byte.

class konfoo.Enum16(enumeration=None, byte_order='auto')[source]

An Enum16 field is an Enum field with a size of two bytes.

class konfoo.Enum24(enumeration=None, byte_order='auto')[source]

An Enum24 field is an Enum field with a size of three bytes.

class konfoo.Enum32(enumeration=None, byte_order='auto')[source]

An Enum32 field is an Enum field with a size of four bytes.

class konfoo.Enum64(enumeration=None, byte_order='auto')[source]

An Enum64 field is an Enum field with a size of eight bytes.

Scaled
class konfoo.Scaled(scale, bit_size, align_to=None, byte_order='auto')[source]

A Scaled field is a signed Decimal field with a variable size and returns its scaled field value as a floating point number.

The scaled field value is:

(unscaled field value / scaling base) * scaling factor

The unscaled field value is:

(scaled field value / scaling factor) * scaling base

The scaling base is:

2 ** (field size - 1) / 2

A Scaled field extends the metadata of a Decimal with a 'scale' key for its scaling factor.

Parameters:
  • scale (float) – scaling factor of the Scaled field.
  • bit_size (int) – is the size of the Scaled field in bits, can be between 1 and 64.
  • align_to (int) – aligns the Scaled field to the number of bytes, can be between 1 and 8. If no field alignment is set the Scaled field aligns itself to the next matching byte size according to the size of the Scaled field.
  • byte_order (Byteorder, str) – byte order used to unpack and pack the value of the Scaled field.

Example:

>>> scaled = Scaled(100, 16)
>>> scaled.is_decimal()
True
>>> scaled.name
'Scaled16'
>>> scaled.alignment
Alignment(byte_size=2, bit_offset=0)
>>> scaled.byte_order
Byteorder.auto = 'auto'
>>> scaled.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> scaled.index_field()
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> scaled.scale
100.0
>>> scaled.scaling_base()
16384.0
>>> scaled.bit_size
16
>>> scaled.signed
True
>>> scaled.min()
-32768
>>> scaled.max()
32767
>>> scaled.value
0.0
>>> bytes(scaled)
b'\x00\x00'
>>> int(scaled)
0
>>> float(scaled)
0.0
>>> hex(scaled)
'0x0'
>>> bin(scaled)
'0b0'
>>> oct(scaled)
'0o0'
>>> bool(scaled)
False
>>> scaled.as_signed()
0
>>> scaled.as_unsigned()
0
>>> scaled.deserialize(bytes.fromhex('0040'))
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> scaled.value
100.0
>>> scaled.value = -100
>>> scaled.value
-100.0
>>> scaled.value = -200.001
>>> scaled.value
-200.0
>>> scaled.value = 200
>>> scaled.value
199.993896484375
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> scaled.serialize(bytestream)
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> hexlify(bytestream)
b'ff7f'
>>> scaled.describe()
OrderedDict([('address', 0),
             ('alignment', [2, 0]),
             ('class', 'Scaled16'),
             ('index', [0, 0]),
             ('max', 32767),
             ('min', -32768),
             ('name', 'Scaled16'),
             ('order', 'auto'),
             ('scale', 100.0),
             ('signed', True),
             ('size', 16),
             ('type', 'Field'),
             ('value', 199.993896484375)])
value

Field value as a floating point number.

scale

Scaling factor of the Scaled field.

scaling_base()[source]

Returns the scaling base of the Scaled field.

describe(name=None, **options)[source]

Returns the metadata of a Field as an ordered dictionary.

metadata = {
    'address': self.index.address,
    'alignment': [self.alignment.byte_size, self.alignment.bit_offset],
    'class': self.name,
    'index': [self.index.byte, self.index.bit],
    'name': name if name else self.name,
    'order': self.byte_order.value,
    'size': self.bit_size,
    'type': Field.item_type.name,
    'value': self.value
}
Parameters:
  • name (str) – optional name for the Field. Fallback is the class name.
  • nested (bool) – if True a Pointer field lists its referenced data object fields as well (chained method call). Default is True.
class konfoo.Scaled8(scale, byte_order='auto')[source]

A Scaled8 field is a Scaled field with a size of one byte.

class konfoo.Scaled16(scale, byte_order='auto')[source]

A Scaled16 field is a Scaled field with a size of two bytes.

class konfoo.Scaled24(scale, byte_order='auto')[source]

A Scaled24 field is a Scaled field with a size of three bytes.

class konfoo.Scaled32(scale, byte_order='auto')[source]

A Scaled32 field is a Scaled field with a size of four bytes.

class konfoo.Scaled64(scale, byte_order='auto')[source]

A Scaled64 field is a Scaled field with a size of eight bytes.

Fraction
class konfoo.Fraction(bits_integer, bit_size, align_to=None, signed=False, byte_order='auto')[source]

A Fraction field is an unsigned Decimal field with a variable size and returns its fractional field value as a floating point number.

A fractional number is bitwise encoded and has up to three bit parts for this task.

The first part are the bits for the fraction part of a fractional number. The number of bits for the fraction part is derived from the bit size of the field and the required bits for the other two parts. The fraction part is always smaller than one.

fraction part = (2**bits - 1) / (2**bits)

The second part are the bits for the integer part of a fractional number.

integer part = (2**bits - 1)

The third part is the bit for the sign of a signed fractional number. Only a signed fractional number posses this bit.

sign part = {'0': '+', '1': '-'}

A fractional number is multiplied by hundred.

Parameters:
  • bits_integer (int) – number of bits for the integer part of the fraction number, can be between 1 and the size of the Fraction field.
  • bit_size (int) – is the size of the Fraction field in bits, can be between 1 and 64.
  • align_to (int) – aligns the Fraction field to the number of bytes, can be between 1 and 8. If no field alignment is set the Fraction field aligns itself to the next matching byte size according to the size of the Fraction field.
  • signed (bool) – if True the Fraction field is signed otherwise unsigned.
  • byte_order (Byteorder, str) – byte order used to unpack and pack the value of the Fraction field

Example:

>>> unipolar = Fraction(2, 16)
>>> unipolar.is_decimal()
True
>>> unipolar.name
'Fraction2.16'
>>> unipolar.alignment
Alignment(byte_size=2, bit_offset=0)
>>> unipolar.byte_order
Byteorder.auto = 'auto'
>>> unipolar.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> unipolar.index_field()
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> unipolar.bit_size
16
>>> unipolar.signed
False
>>> unipolar.min()
0
>>> unipolar.max()
65535
>>> unipolar.value
0.0
>>> bytes(unipolar)
b'\x00\x00'
>>> int(unipolar)
0
>>> float(unipolar)
0.0
>>> hex(unipolar)
'0x0'
>>> bin(unipolar)
'0b0'
>>> oct(unipolar)
'0o0'
>>> bool(unipolar)
False
>>> unipolar.as_signed()
0
>>> unipolar.as_unsigned()
0
>>> unipolar.deserialize(bytes.fromhex('0080'))
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> unipolar.value
200.0
>>> unipolar.value = 100
>>> unipolar.value
100.0
>>> unipolar.as_float(0x4000)
100.0
>>> unipolar.value = -1
>>> unipolar.value
0.0
>>> unipolar.value = 400
>>> unipolar.value
399.993896484375
>>> unipolar.as_float(0xffff)
399.993896484375
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> unipolar.serialize(bytestream)
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> hexlify(bytestream)
b'ffff'
>>> unipolar.describe()
OrderedDict([('address', 0),
             ('alignment', [2, 0]),
             ('class', 'Fraction2.16'),
             ('index', [0, 0]),
             ('max', 65535),
             ('min', 0),
             ('name', 'Fraction2.16'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 16),
             ('type', 'Field'),
             ('value', 399.993896484375)])

Example:

>>> bipolar = Fraction(2, 16, 2, True)
>>> bipolar.is_decimal()
True
>>> bipolar.name
'Fraction2.16'
>>> bipolar.alignment
Alignment(byte_size=2, bit_offset=0)
>>> bipolar.byte_order
Byteorder.auto = 'auto'
>>> bipolar.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> bipolar.index_field()
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> bipolar.bit_size
16
>>> bipolar.signed
False
>>> bipolar.min()
0
>>> bipolar.max()
65535
>>> bipolar.value
0.0
>>> bytes(bipolar)
b'\x00\x00'
>>> int(bipolar)
0
>>> float(bipolar)
0.0
>>> hex(bipolar)
'0x0'
>>> bin(bipolar)
'0b0'
>>> oct(bipolar)
'0o0'
>>> bool(bipolar)
False
>>> bipolar.as_signed()
0
>>> bipolar.as_unsigned()
0
>>> bipolar.deserialize(bytes.fromhex('0040'))
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> bipolar.value
100.0
>>> bipolar.value = -100
>>> bipolar.value
-100.0
>>> bipolar.as_float(0xc000)
-100.0
>>> bipolar.as_float(0x8000)
-0.0
>>> bipolar.value = -200
>>> bipolar.value
-199.993896484375
>>> bipolar.as_float(0xffff)
-199.993896484375
>>> bipolar.value = 200
>>> bipolar.value
199.993896484375
>>> bipolar.as_float(0x7fff)
199.993896484375
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> bipolar.serialize(bytestream)
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> hexlify(bytestream)
b'ff7f'
>>> bipolar.describe()
OrderedDict([('address', 0),
             ('alignment', [2, 0]),
             ('class', 'Fraction2.16'),
             ('index', [0, 0]),
             ('max', 65535),
             ('min', 0),
             ('name', 'Fraction2.16'),
             ('order', 'auto'),
             ('signed', True),
             ('size', 16),
             ('type', 'Field'),
             ('value', 199.993896484375)])
name

Returns the type name of the Fraction field (read-only).

value

Field value as a floating point number.

describe(name=None, **options)[source]

Returns the metadata of a Field as an ordered dictionary.

metadata = {
    'address': self.index.address,
    'alignment': [self.alignment.byte_size, self.alignment.bit_offset],
    'class': self.name,
    'index': [self.index.byte, self.index.bit],
    'name': name if name else self.name,
    'order': self.byte_order.value,
    'size': self.bit_size,
    'type': Field.item_type.name,
    'value': self.value
}
Parameters:
  • name (str) – optional name for the Field. Fallback is the class name.
  • nested (bool) – if True a Pointer field lists its referenced data object fields as well (chained method call). Default is True.
Bipolar
class konfoo.Bipolar(bits_integer, bit_size, align_to=None, byte_order='auto')[source]

A Bipolar field is a signed Fraction field with a variable size and returns its fractional field value as a floating point number.

Parameters:
  • bits_integer (int) – number of bits for the integer part of the fraction number, can be between 1 and the size of the Bipolar field.
  • bit_size (int) – is the size of the Bipolar field in bits, can be between 1 and 64.
  • align_to (int) – aligns the Bipolar field to the number of bytes, can be between 1 and 8. If no field alignment is set the Bipolar field aligns itself to the next matching byte size according to the size of the Bipolar field.
  • byte_order (Byteorder, str) – byte order used to unpack and pack the value of the Bipolar field.

Example:

>>> bipolar = Bipolar(2, 16)
>>> bipolar.is_decimal()
True
>>> bipolar.name
'Bipolar2.16'
>>> bipolar.alignment
Alignment(byte_size=2, bit_offset=0)
>>> bipolar.byte_order
Byteorder.auto = 'auto'
>>> bipolar.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> bipolar.index_field()
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> bipolar.bit_size
16
>>> bipolar.signed
False
>>> bipolar.min()
0
>>> bipolar.max()
65535
>>> bipolar.value
0.0
>>> bytes(bipolar)
b'\x00\x00'
>>> int(bipolar)
0
>>> float(bipolar)
0.0
>>> hex(bipolar)
'0x0'
>>> bin(bipolar)
'0b0'
>>> oct(bipolar)
'0o0'
>>> bool(bipolar)
False
>>> bipolar.as_signed()
0
>>> bipolar.as_unsigned()
0
>>> bipolar.value = -100
>>> bipolar.value
-100.0
>>> bipolar.as_float(0xc000)
-100.0
>>> bipolar.as_float(0x8000)
-0.0
>>> bipolar.value = -200
>>> bipolar.value
-199.993896484375
>>> bipolar.as_float(0xffff)
-199.993896484375
>>> bipolar.value = 200
>>> bipolar.value
199.993896484375
>>> bipolar.as_float(0x7fff)
199.993896484375
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> bipolar.serialize(bytestream)
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> hexlify(bytestream)
b'ff7f'
>>> bipolar.describe()
OrderedDict([('address', 0),
             ('alignment', [2, 0]),
             ('class', 'Bipolar2.16'),
             ('index', [0, 0]),
             ('max', 65535),
             ('min', 0),
             ('name', 'Bipolar2.16'),
             ('order', 'auto'),
             ('signed', True),
             ('size', 16),
             ('type', 'Field'),
             ('value', 199.993896484375)])
class konfoo.Bipolar2(byte_order='auto')[source]

A Bipolar2 field is a Bipolar field with a size of two bytes and an integer part of two bits.

class konfoo.Bipolar4(byte_order='auto')[source]

A Bipolar4 field is a Bipolar field with a size of two bytes and an integer part of four bits.

Unipolar
class konfoo.Unipolar(bits_integer, bit_size, align_to=None, byte_order='auto')[source]

An Unipolar field is an unsigned Fraction field with a variable size and returns its fractional field value as a floating point number.

Parameters:
  • bits_integer (int) – number of bits for the integer part of the fraction number, can be between 1 and the size of the Unipolar field.
  • bit_size (int) – is the size of the Unipolar field in bits, can be between 1 and 64.
  • align_to (int) – aligns the Unipolar field to the number of bytes, can be between 1 and 8. If no field alignment is set the Unipolar field aligns itself to the next matching byte size according to the size of the Unipolar field.
  • byte_order (Byteorder, str) – byte order used to unpack and pack the value of the Unipolar field.

Example:

>>> unipolar = Unipolar(2, 16)
>>> unipolar.is_decimal()
True
>>> unipolar.name
'Unipolar2.16'
>>> unipolar.alignment
Alignment(byte_size=2, bit_offset=0)
>>> unipolar.byte_order
Byteorder.auto = 'auto'
>>> unipolar.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> unipolar.index_field()
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> unipolar.bit_size
16
>>> unipolar.signed
False
>>> unipolar.min()
0
>>> unipolar.max()
65535
>>> unipolar.value
0.0
>>> bytes(unipolar)
b'\x00\x00'
>>> int(unipolar)
0
>>> float(unipolar)
0.0
>>> hex(unipolar)
'0x0'
>>> bin(unipolar)
'0b0'
>>> oct(unipolar)
'0o0'
>>> bool(unipolar)
False
>>> unipolar.as_signed()
0
>>> unipolar.as_unsigned()
0
>>> unipolar.deserialize(bytes.fromhex('0080'))
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> unipolar.value
200.0
>>> unipolar.value = 100
>>> unipolar.value
100.0
>>> unipolar.as_float(0x4000)
100.0
>>> unipolar.value = -1
>>> unipolar.value
0.0
>>> unipolar.value = 400
>>> unipolar.value
399.993896484375
>>> unipolar.as_float(0xffff)
399.993896484375
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> unipolar.serialize(bytestream)
Index(byte=2, bit=0, address=2, base_address=0, update=False)
>>> hexlify(bytestream)
b'ffff'
>>> unipolar.describe()
OrderedDict([('address', 0),
             ('alignment', [2, 0]),
             ('class', 'Unipolar2.16'),
             ('index', [0, 0]),
             ('max', 65535),
             ('min', 0),
             ('name', 'Unipolar2.16'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 16),
             ('type', 'Field'),
             ('value', 399.993896484375)])
class konfoo.Unipolar2(byte_order='auto')[source]

An Unipolar2 field is an Unipolar field with a size of two bytes and an integer part of two bits.

Datetime
class konfoo.Datetime(byte_order='auto')[source]

A Datetime field is an unsigned Decimal field with a fix size of four bytes and returns its field value as an UTC datetime string in the ISO format YYYY-mm-dd HH:MM:SS.

Parameters:byte_order (Byteorder, str) – byte order used to unpack and pack the value of the Datetime field.

Example:

>>> datetime = Datetime()
>>> datetime.is_decimal()
True
>>> datetime.name
'Datetime32'
>>> datetime.alignment
Alignment(byte_size=4, bit_offset=0)
>>> datetime.byte_order
Byteorder.auto = 'auto'
>>> datetime.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> datetime.index_field()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> datetime.bit_size
32
>>> datetime.signed
False
>>> datetime.min()
0
>>> datetime.max()
4294967295
>>> datetime.value
'1970-01-01 00:00:00'
>>> bytes(datetime)
b'\x00\x00\x00\x00'
>>> int(datetime)
0
>>> float(datetime)
0.0
>>> hex(datetime)
'0x0'
>>> bin(datetime)
'0b0'
>>> oct(datetime)
'0o0'
>>> bool(datetime)
False
>>> datetime.as_signed()
0
>>> datetime.as_unsigned()
0
>>> datetime.deserialize(bytes.fromhex('ffffffff'))
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> datetime.value
'2106-02-07 06:28:15'
>>> datetime.value = '1969-12-31 23:59:59'
>>> datetime.value
'1970-01-01 00:00:00'
>>> datetime.value = '2106-02-07 06:28:16'
>>> datetime.value
'2106-02-07 06:28:15'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> datetime.serialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> hexlify(bytestream)
b'ffffffff'
>>> datetime.describe()
OrderedDict([('address', 0),
             ('alignment', [4, 0]),
             ('class', 'Datetime32'),
             ('index', [0, 0]),
             ('max', 4294967295),
             ('min', 0),
             ('name', 'Datetime32'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 32),
             ('type', 'Field'),
             ('value', '2106-02-07 06:28:15')])
value

Field value as an UTC datetime string in the ISO format YYYY-mm-dd HH:MM:SS

IPv4Address
class konfoo.IPv4Address(byte_order='auto')[source]

An IPv4Address field is an unsigned Decimal field with a fix size of four bytes and returns its field value as an IPv4 address formatted string.

Parameters:byte_order (Byteorder, str) – byte order used to unpack and pack the value of the IPv4Address field.

Example:

>>> ipv4 = IPv4Address()
>>> ipv4.is_decimal()
True
>>> ipv4.name
'Ipaddress32'
>>> ipv4.alignment
Alignment(byte_size=4, bit_offset=0)
>>> ipv4.byte_order
Byteorder.auto = 'auto'
>>> ipv4.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> ipv4.index_field()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> ipv4.bit_size
32
>>> ipv4.signed
False
>>> ipv4.min()
0
>>> ipv4.max()
4294967295
>>> ipv4.value
'0.0.0.0'
>>> bytes(ipv4)
b'\x00\x00\x00\x00'
>>> int(ipv4)
0
>>> float(ipv4)
0.0
>>> hex(ipv4)
'0x0'
>>> bin(ipv4)
'0b0'
>>> oct(ipv4)
'0o0'
>>> bool(ipv4)
False
>>> ipv4.as_signed()
0
>>> ipv4.as_unsigned()
0
>>> ipv4.deserialize(bytes.fromhex('ffffffff'))
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> ipv4.value
'255.255.255.255'
>>> ipv4.value = '192.168.0.0'
>>> ipv4.value
'192.168.0.0'
>>> ipv4.value = '255.255.255.255'
>>> ipv4.value
'255.255.255.255'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> ipv4.serialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> hexlify(bytestream)
b'ffffffff'
>>> ipv4.describe()
OrderedDict([('address', 0),
             ('alignment', [4, 0]),
             ('class', 'Ipaddress32'),
             ('index', [0, 0]),
             ('max', 4294967295),
             ('min', 0),
             ('name', 'Ipaddress32'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 32),
             ('type', 'Field'),
             ('value', '255.255.255.255')])
value

Field value as an IPv4 address formatted string.

Pointer

class konfoo.Pointer(template=None, address=None, data_order=Byteorder.little = 'little', bit_size=32, align_to=None, field_order='auto')[source]

A Pointer field is an unsigned Decimal field with a size of four bytes and returns its field value as a hexadecimal string.

A Pointer field refers absolutely to a data object of a data Provider.

The Pointer class extends the Decimal field with the Container interface for its referenced data object.

A Pointer field has additional features to read, write, deserialize, serialize and view binary data:

  • Deserialize the value for each Field in the data object referenced by the Pointer field from a byte stream via deserialize_data().
  • Serialize the value for each Field in the data object referenced by the Pointer field to a byte stream via serialize_data().
  • Indexes each Field in the data object referenced by the Pointer field via index_data().
  • Read from a Provider the necessary bytes for the data object referenced by the Pointer field via read_from().
  • Write to a Provider the necessary bytes for the data object referenced by the Pointer field via write_to().
  • Get the accumulated size of all fields in the data object referenced by the Pointer field via data_size.
  • Indexes the Pointer field and each Field in the data object referenced by the Pointer field via index_fields().
  • View the selected attributes of the Pointer field and for each Field in the data object referenced by the Pointer field via view_fields().
  • List the path to the field and the field item for the Pointer field and for each Field in the data object referenced by the Pointer field as a flatten list via field_items().
  • Get the metadata of the Pointer field via describe().
Parameters:
  • template – template for the data object referenced by the Pointer field.
  • address (int) – absolute address of the data object referenced by the Pointer field.
  • data_order (Byteorder, str) – byte order used to unpack and pack the data object referenced by the Pointer field.
  • bit_size (int) – is the size of the Pointer field in bits, can be between 1 and 64.
  • align_to (int) – aligns the Pointer field to the number of bytes, can be between 1 and 8. If no field alignment is set the Pointer field aligns itself to the next matching byte size according to the size of the Pointer field.
  • field_order (Byteorder, str) – byte order used to unpack and pack the value of the Pointer field.

Example:

>>> pointer = Pointer()
>>> pointer.is_decimal()
True
>>> pointer.is_pointer()
True
>>> pointer.name
'Pointer32'
>>> pointer.alignment
Alignment(byte_size=4, bit_offset=0)
>>> pointer.byte_order
Byteorder.auto = 'auto'
>>> pointer.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> pointer.index_field()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.bit_size
32
>>> pointer.signed
False
>>> pointer.min()
0
>>> pointer.max()
4294967295
>>> pointer.base_address
0
>>> pointer.address
0
>>> pointer.is_null()
True
>>> pointer.data
>>> pointer.data_size
0
>>> pointer.data_byte_order
Byteorder.little = 'little'
>>> pointer.bytestream
''
>>> pointer.value
'0x0'
>>> bytes(pointer)
b'\x00\x00\x00\x00'
>>> int(pointer)
0
>>> float(pointer)
0.0
>>> hex(pointer)
'0x0'
>>> bin(pointer)
'0b0'
>>> oct(pointer)
'0o0'
>>> bool(pointer)
False
>>> pointer.as_signed()
0
>>> pointer.as_unsigned()
0
>>> pointer.deserialize(bytes.fromhex('00c0'))
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.value
'0xc000'
>>> pointer.value = 0x4000
>>> pointer.value
'0x4000'
>>> pointer.initialize_fields({'value': 0x8000})
>>> pointer.value
'0x8000'
>>> pointer.value = -0x1
>>> pointer.value
'0x0'
>>> pointer.value = 0x100000000
>>> pointer.value
'0xffffffff'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> pointer.serialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> hexlify(bytestream)
b'ffffffff'
>>> pointer.bytestream = b'KonFoo is Fun'
>>> pointer.bytestream
'4b6f6e466f6f2069732046756e'
>>> pointer.serialize_data()
b''
>>> pointer.deserialize_data()
Index(byte=0, bit=0, address=4294967295, base_address=4294967295, update=False)
>>> pointer.serialize_data()
b''
>>> pointer.describe()
OrderedDict([('address', 0),
             ('alignment', [4, 0]),
             ('class', 'Pointer'),
             ('index', [0, 0]),
             ('max', 4294967295),
             ('min', 0),
             ('name', 'Pointer'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 32),
             ('type', 'Pointer'),
             ('value', '0xffffffff')])
>>> pointer.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.view_fields()
OrderedDict([('value', '0xffffffff'), ('data', None)])
>>> pointer.to_json()
'{"value": "0xffffffff", "data": null}'
>>> pointer.field_items()
[('field',
  Pointer(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
          alignment=Alignment(byte_size=4, bit_offset=0),
          bit_size=32,
          value='0xffffffff'))]
>>> pointer.to_list()
[('Pointer.field', '0xffffffff')]
>>> pointer.to_dict()
OrderedDict([('Pointer', OrderedDict([('field', '0xffffffff')]))])
address

Returns the data source address of the data object referenced by the Pointer field (read-only).

base_address

Returns the data source base address of the data object referenced by the Pointer field (read-only).

bytestream

Byte stream of the Pointer field for the referenced data object. Returned as a lowercase hexadecimal encoded string.

data

Data object referenced by the Pointer field.

data_byte_order

Byteorder used to deserialize and serialize the data object referenced by the Pointer field.

data_size

Returns the size of the data object in bytes (read-only).

value

Field value as a lowercase hexadecimal string prefixed with 0x.

static is_pointer()[source]

Returns True.

is_null()[source]

Returns True if the Pointer field points to zero.

deserialize_data(buffer=b'', byte_order=None)[source]

De-serializes the data object referenced by the Pointer field from the byte buffer by mapping the bytes to the value for each Field in the data object in accordance with the decoding byte order for the de-serialization and the decoding byte_order of each Field in the data object.

A specific decoding byte_order of a Field in the data object overrules the decoding byte order for the de-serialization.

Returns the Index of the buffer after the last de-serialized Field in the data object.

Parameters:
  • buffer (bytes) – byte stream. Default is the internal bytestream of the Pointer field.
  • byte_order (Byteorder, str) – decoding byte order for the de-serialization. Default is the data_byte_order of the Pointer field.
serialize_data(byte_order=None)[source]

Serializes the data object referenced by the Pointer field to bytes by mapping the value for each Field in the data object to a number of bytes in accordance with the encoding byte order for the serialization and the encoding byte_order of each Field in the data object.

A specific encoding byte_order of a Field in the data object overrules the encoding byte order for the serialization.

Returns a number of bytes for the serialized data object referenced by the Pointer field.

Parameters:byte_order (Byteorder, str) – encoding byte order for the serialization. Default is the data_byte_order of the Pointer field.
index_data()[source]

Indexes each Field in the data object referenced by the Pointer field.

read_from(provider, null_allowed=False, **options)[source]

Reads from the data Provider the necessary number of bytes for the data object referenced by the Pointer field.

A Pointer field stores the binary data read from the data Provider in its bytestream.

Parameters:
  • provider (Provider) – data Provider.
  • null_allowed (bool) – if True read access of address zero (Null) is allowed.
  • nested (bool) – if True all Pointer fields in the data object of the Pointer field reads their referenced data object fields as well (chained method call). Each Pointer field stores the bytes for its referenced data object in its bytestream.
patch(item, byte_order=Byteorder.little = 'little')[source]

Returns a memory Patch for the given item that shall be patched in the data source.

Parameters:
write_to(provider, item, byte_order=Byteorder.little = 'little')[source]

Writes via a data Provider the Field values of the given item to the data source.

Parameters:
deserialize(buffer=b'', index=Index(byte=0, bit=0, address=0, base_address=0, update=False), **options)[source]

De-serializes the Pointer field from the byte buffer starting at the begin of the buffer or with the given index by mapping the bytes to the value of the Pointer field in accordance with the decoding byte order for the de-serialization and the decoding byte_order of the Pointer field.

The specific decoding byte_order of the Pointer field overrules the decoding byte order for the de-serialization.

Returns the Index of the buffer after the Pointer field.

Optional the de-serialization of the referenced data object of the Pointer field can be enabled.

Parameters:
  • buffer (bytes) – byte stream.
  • index (Index) – current read Index within the buffer.
  • byte_order (Byteorder, str) – decoding byte order for the de-serialization.
  • nested (bool) – if True a Pointer field de-serialize its referenced data object as well (chained method call). Each Pointer field uses for the de-serialization of its referenced data object its own bytestream.
serialize(buffer=bytearray(b''), index=Index(byte=0, bit=0, address=0, base_address=0, update=False), **options)[source]

Serializes the Pointer field to the byte buffer starting at the begin of the buffer or with the given index by mapping the value of the Pointer field to the byte buffer in accordance with the encoding byte order for the serialization and the encoding byte_order of the Pointer field.

The specific encoding byte_order of the Poiner field overrules the encoding byte order for the serialization.

Returns the Index of the buffer after the Pointer field.

Optional the serialization of the referenced data object of the Pointer field can be enabled.

Parameters:
  • buffer (bytearray) – byte stream.
  • index (Index) – current write Index within the buffer.
  • byte_order (Byteorder, str) – encoding byte order for the serialization.
  • nested (bool) – if True a Pointer field serializes its referenced data object as well (chained method call). Each Pointer field uses for the serialization of its referenced data object its own bytestream.
initialize_fields(content)[source]

Initializes the Pointer field itself and the Field items in the data object referenced by the Pointer field with the values in the content dictionary.

The ['value'] key in the content dictionary refers to the Pointer field itself and the ['data'] key refers to the data object referenced by the Pointer field.

Parameters:content (dict) – a dictionary contains the value for the Pointer field and the value for each Field in the data object referenced by the Pointer field.
index_fields(index=Index(byte=0, bit=0, address=0, base_address=0, update=False), **options)[source]

Indexes the Pointer field and the data object referenced by the Pointer field starting with the given index and returns the Index after the Pointer field.

Parameters:
  • index (Index) – Index for the Pointer field.
  • nested (bool) – if True all Pointer fields in the data object referenced by the Pointer field indexes their referenced data object fields as well (chained method call).
view_fields(*attributes, **options)[source]

Returns an ordered dictionary which contains the selected field attributes of the Pointer field itself extended with a ['data'] key which contains the selected field attribute or the dictionaries of the selected field attributes for each Field nested in the data object referenced by the Pointer field.

The attributes of each Field for containers nested in the data object referenced by the Pointer field are viewed as well (chained method call).

Parameters:
  • attributes (str) – selected Field attributes. Fallback is the field value.
  • fieldnames (tuple) – sequence of dictionary keys for the selected field attributes. Defaults to (*attributes).
  • nested (bool) – if True all Pointer fields in the data object referenced by the Pointer field views their referenced data object field attributes as well (chained method call).
field_items(path='', **options)[source]

Returns a flatten list of ('field path', field item) tuples for the Pointer field itself and for each Field nested in the data object referenced by the Pointer field.

Parameters:
  • path (str) – path of the Pointer field.
  • nested (bool) – if True all Pointer fields in the data object referenced by the Pointer field lists their referenced data object field items as well (chained method call).
describe(name='', **options)[source]

Returns the metadata of a Pointer as an ordered dictionary.

metadata = {
    'address': self.index.address,
    'alignment': [self.alignment.byte_size, self.alignment.bit_offset],
    'class': self.__class__.__name__,
    'index': [self.index.byte, self.index.bit],
    'max': self.max(),
    'min': self.min(),
    'name': name if name else self.__class__.__name__,
    'order': self.byte_order.value,
    'size': self.bit_size,
    'type': Pointer.item_type.name,
    'value': self.value,
    'member': [self.data.describe()]
}
Parameters:
  • name (str) – optional name for the Pointer field. Fallback is the class name.
  • nested (bool) – if True a Pointer field lists its referenced data object fields as well (chained method call). Default is True.
class konfoo.Pointer8(template=None, address=None, data_order=Byteorder.little = 'little')[source]

A Pointer8 field is a Pointer field with a Field size of one byte.

class konfoo.Pointer16(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A Pointer16 field is a Pointer field with a Field size of two bytes.

class konfoo.Pointer24(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A Pointer24 field is a Pointer field with a Field size of three bytes.

class konfoo.Pointer32(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A Pointer32 field is a Pointer field with a Field size of four bytes.

class konfoo.Pointer48(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A Pointer48 field is a Pointer field with a Field size of six bytes.

class konfoo.Pointer64(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A Pointer64 field is a Pointer field with a Field size of eight bytes.

Structure Pointer
class konfoo.StructurePointer(template=None, address=None, data_order=Byteorder.little = 'little', bit_size=32, align_to=None, field_order='auto')[source]

A StructurePointer field is a Pointer which refers to a Structure.

Parameters:
  • template – template for the data object referenced by the Pointer field. The template must be a Structure instance.
  • address (int) – absolute address of the data object referenced by the Pointer field.
  • data_order (Byteorder, str) – byte order used to unpack and pack the data object referenced by the Pointer field.
  • bit_size (int) – is the size of the Pointer field in bits, can be between 1 and 64.
  • align_to (int) – aligns the Pointer field to the number of bytes, can be between 1 and 8. If no field alignment is set the Pointer field aligns itself to the next matching byte size according to the size of the Pointer field.
  • field_order (Byteorder, str) – byte order used to unpack and pack the value of the Pointer field.

Example:

>>> pointer = StructurePointer()
>>> pointer.is_decimal()
True
>>> pointer.is_pointer()
True
>>> pointer.name
'Pointer32'
>>> pointer.alignment
Alignment(byte_size=4, bit_offset=0)
>>> pointer.byte_order
Byteorder.auto = 'auto'
>>> pointer.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> pointer.index_field()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.bit_size
32
>>> pointer.signed
False
>>> pointer.min()
0
>>> pointer.max()
4294967295
>>> pointer.base_address
0
>>> pointer.address
0
>>> pointer.is_null()
True
>>> pointer.data
Structure()
>>> pointer.data_size
0
>>> pointer.data_byte_order
Byteorder.little = 'little'
>>> pointer.bytestream
''
>>> pointer.value
'0x0'
>>> bytes(pointer)
b'\x00\x00\x00\x00'
>>> int(pointer)
0
>>> float(pointer)
0.0
>>> hex(pointer)
'0x0'
>>> bin(pointer)
'0b0'
>>> oct(pointer)
'0o0'
>>> bool(pointer)
False
>>> pointer.as_signed()
0
>>> pointer.as_unsigned()
0
>>> pointer.deserialize(bytes.fromhex('00c0'))
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.value
'0xc000'
>>> pointer.value = 0x4000
>>> pointer.value
'0x4000'
>>> pointer.value = -0x1
>>> pointer.value
'0x0'
>>> pointer.value = 0x100000000
>>> pointer.value
'0xffffffff'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> len(pointer)
0
>>> [name for name in pointer.keys()]
[]
>>> [member.value for member in pointer.values()]
[]
>>> [(name, member.value) for name, member in pointer.items()]
[]
>>> pointer.describe()
OrderedDict([('address', 0),
             ('alignment', [4, 0]),
             ('class', 'StructurePointer'),
             ('index', [0, 0]),
             ('max', 4294967295),
             ('min', 0),
             ('name', 'StructurePointer'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 32),
             ('type', 'Pointer'),
             ('value', '0xffffffff'),
             ('member',
              [OrderedDict([('class', 'Structure'),
                            ('name', 'data'),
                            ('size', 0),
                            ('type', 'Structure'),
                            ('member', [])])])])
>>> pointer.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.view_fields()
OrderedDict([('value', '0xffffffff'), ('data', OrderedDict())])
>>> pointer.to_json()
'{"value": "0xffffffff", "data": {}}'
>>> pointer.field_items()
[('field',
  StructurePointer(index=Index(byte=0, bit=0,
                               address=0, base_address=0,
                               update=False),
                   alignment=Alignment(byte_size=4, bit_offset=0),
                   bit_size=32,
                   value='0xffffffff'))]
>>> pointer.to_list(nested=True)
[('StructurePointer.field', '0xffffffff')]
>>> pointer.to_dict(nested=True)
OrderedDict([('StructurePointer', OrderedDict([('field', '0xffffffff')]))])
class konfoo.StructurePointer8(template=None, address=None, data_order=Byteorder.little = 'little')[source]

A StructurePointer8 field is a StructurePointer field with a Field size of one byte.

class konfoo.StructurePointer16(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A StructurePointer16 field is a StructurePointer field with a Field size of two bytes.

class konfoo.StructurePointer24(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A StructurePointer24 field is a StructurePointer field with a Field size of three bytes.

class konfoo.StructurePointer32(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A StructurePointer32 field is a StructurePointer field with a Field size of four bytes.

class konfoo.StructurePointer48(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A StructurePointer48 field is a StructurePointer field with a Field size of six bytes.

class konfoo.StructurePointer64(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A StructurePointer64 field is a StructurePointer field with a Field size of eight bytes.

Sequence Pointer
class konfoo.SequencePointer(iterable=None, address=None, data_order=Byteorder.little = 'little', bit_size=32, align_to=None, field_order='auto')[source]

A SequencePointer field is a Pointer field which refers to a Sequence.

A SequencePointer field is:

  • containable: item in self returns True if item is part of the referenced Sequence.
  • sized: len(self) returns the number of items in the referenced Sequence.
  • indexable self[index] returns the item at the index of the referenced Sequence.
  • iterable iter(self) iterates over the items of the referenced Sequence

A SequencePointer field supports the usual methods for sequences:

Parameters:
  • iterable – any iterable that contains items of Structure, Sequence, Array or Field instances. If the iterable is one of these instances itself then the iterable itself is appended to the Sequence.
  • address (int) – absolute address of the data object referenced by the Pointer field.
  • data_order (Byteorder, str) – byte order used to unpack and pack the data object referenced by the Pointer field.
  • bit_size (int) – is the size of the Pointer field in bits, can be between 1 and 64.
  • align_to (int) – aligns the Pointer field to the number of bytes, can be between 1 and 8. If no field alignment is set the Pointer field aligns itself to the next matching byte size according to the size of the Pointer field.
  • field_order (Byteorder, str) – byte order used to unpack and pack the value of the Pointer field.

Example:

>>> pointer = SequencePointer()
>>> pointer.is_decimal()
True
>>> pointer.is_pointer()
True
>>> pointer.name
'Pointer32'
>>> pointer.alignment
Alignment(byte_size=4, bit_offset=0)
>>> pointer.byte_order
Byteorder.auto = 'auto'
>>> pointer.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> pointer.index_field()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.bit_size
32
>>> pointer.signed
False
>>> pointer.min()
0
>>> pointer.max()
4294967295
>>> pointer.base_address
0
>>> pointer.address
0
>>> pointer.is_null()
True
>>> pointer.data
[]
>>> pointer.data_size
0
>>> pointer.data_byte_order
Byteorder.little = 'little'
>>> pointer.bytestream
''
>>> pointer.value
'0x0'
>>> hexlify(bytes(pointer))
b'00000000'
>>> bytes(pointer)
b'\x00\x00\x00\x00'
>>> int(pointer)
0
>>> float(pointer)
0.0
>>> hex(pointer)
'0x0'
>>> bin(pointer)
'0b0'
>>> oct(pointer)
'0o0'
>>> bool(pointer)
False
>>> pointer.as_signed()
0
>>> pointer.as_unsigned()
0
>>> pointer.deserialize(bytes.fromhex('00c0'))
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.value
'0xc000'
>>> pointer.value = 0x4000
>>> pointer.value
'0x4000'
>>> pointer.value = -0x1
>>> pointer.value
'0x0'
>>> pointer.value = 0x100000000
>>> pointer.value
'0xffffffff'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> len(pointer)
0
>>> [item for item in pointer]
[]
>>> pointer[:]
[]
>>> pointer.append(Field())
>>> pointer[0]
Field(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
      alignment=Alignment(byte_size=0, bit_offset=0),
      bit_size=0,
      value=None)
>>> len(pointer)
1
>>> pointer.pop()
Field(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
      alignment=Alignment(byte_size=0, bit_offset=0),
      bit_size=0,
      value=None)
>>> pointer.insert(0, Field())
>>> pointer.data
[Field(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
       alignment=Alignment(byte_size=0, bit_offset=0),
       bit_size=0,
       value=None)]
>>> pointer.remove(pointer[0])
>>> pointer.data
[]
>>> pointer.clear()
>>> pointer.describe()
OrderedDict([('address', 0),
             ('alignment', [4, 0]),
             ('class', 'SequencePointer'),
             ('index', [0, 0]),
             ('max', 4294967295),
             ('min', 0),
             ('name', 'SequencePointer'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 32),
             ('type', 'Pointer'),
             ('value', '0xffffffff'),
             ('member',
              [OrderedDict([('class', 'Sequence'),
                            ('name', 'data'),
                            ('size', 0),
                            ('type', 'Sequence'),
                            ('member', [])])])])
>>> pointer.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.view_fields()
OrderedDict([('value', '0xffffffff'), ('data', [])])
>>> pointer.to_json()
'{"value": "0xffffffff", "data": []}'
>>> pointer.field_items()
[('field',
  SequencePointer(index=Index(byte=0, bit=0,
                              address=0, base_address=0,
                              update=False),
                  alignment=Alignment(byte_size=4, bit_offset=0),
                  bit_size=32,
                  value='0xffffffff'))]
>>> pointer.to_list(nested=True)
[('SequencePointer.field', '0xffffffff')]
>>> pointer.to_dict(nested=True)
OrderedDict([('SequencePointer', OrderedDict([('field', '0xffffffff')]))])
append(item)[source]

Appends the item to the end of the Sequence.

Parameters:item – any Structure, Sequence, Array or Field instance.
insert(index, item)[source]

Inserts the item before the index into the Sequence.

Parameters:
pop(index=-1)[source]

Removes and returns the item at the index from the Sequence.

Parameters:index (int) – Sequence index.
clear()[source]

Remove all items from the Sequence.

remove(item)[source]

Removes the first occurrence of an item from the Sequence.

Parameters:item – any Structure, Sequence, Array or Field instance.
reverse()[source]

In place reversing of the Sequence items.

extend(iterable)[source]

Extends the Sequence by appending items from the iterable.

Parameters:iterable – any iterable that contains items of Structure, Sequence, Array or Field instances. If the iterable is one of these instances itself then the iterable itself is appended to the Sequence.
Array Pointer
class konfoo.ArrayPointer(template, size=0, address=None, data_order=Byteorder.little = 'little', bit_size=32, align_to=None, field_order='auto')[source]

An ArrayPointer field is a SequencePointer field which refers to a Array.

An ArrayPointer field adapts and extends a SequencePointer field with the following features:

Parameters:
  • template – template for the Array element. The template can be any Field instance or any callable that returns a Structure, Sequence, Array or any Field instance.
  • size (int) – is the size of the Array in number of Array elements.
  • address (int) – absolute address of the data object referenced by the Pointer field.
  • data_order (Byteorder, str) – byte order used to unpack and pack the data object referenced by the Pointer field.
  • bit_size (int) – is the size of the Pointer field in bits, can be between 1 and 64.
  • align_to (int) – aligns the Pointer field to the number of bytes, can be between 1 and 8. If no field alignment is set the Pointer field aligns itself to the next matching byte size according to the size of the Pointer field.
  • field_order (Byteorder, str) – byte order used to unpack and pack the value of the Pointer field.

Example:

>>> pointer = ArrayPointer(Byte)
>>> pointer.is_decimal()
True
>>> pointer.is_pointer()
True
>>> pointer.name
'Pointer32'
>>> pointer.alignment
Alignment(byte_size=4, bit_offset=0)
>>> pointer.byte_order
Byteorder.auto = 'auto'
>>> pointer.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> pointer.index_field()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.bit_size
32
>>> pointer.signed
False
>>> pointer.min()
0
>>> pointer.max()
4294967295
>>> pointer.base_address
0
>>> pointer.address
0
>>> pointer.is_null()
True
>>> pointer.data
[]
>>> pointer.data_size
0
>>> pointer.data_byte_order
Byteorder.little = 'little'
>>> pointer.bytestream
''
>>> pointer.value
'0x0'
>>> bytes(pointer)
b'\x00\x00\x00\x00'
>>> int(pointer)
0
>>> float(pointer)
0.0
>>> hex(pointer)
'0x0'
>>> bin(pointer)
'0b0'
>>> oct(pointer)
'0o0'
>>> bool(pointer)
False
>>> pointer.as_signed()
0
>>> pointer.as_unsigned()
0
>>> pointer.deserialize(bytes.fromhex('00c0'))
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.value
'0xc000'
>>> pointer.value = 0x4000
>>> pointer.value
'0x4000'
>>> pointer.value = -0x1
>>> pointer.value
'0x0'
>>> pointer.value = 0x100000000
>>> pointer.value
'0xffffffff'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> len(pointer)
0
>>> [item for item in pointer]
[]
>>> pointer[:]
[]
>>> pointer.append()
>>> pointer[0]
Byte(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
     alignment=Alignment(byte_size=1, bit_offset=0),
     bit_size=8,
     value='0x0')
>>> len(pointer)
1
>>> pointer.pop()
Byte(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
     alignment=Alignment(byte_size=1, bit_offset=0),
     bit_size=8,
     value='0x0')
>>> pointer.insert(0)
>>> pointer.data
[Byte(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
      alignment=Alignment(byte_size=1, bit_offset=0),
      bit_size=8,
      value='0x0')]
>>> pointer.remove(pointer[0])
>>> pointer.data
[]
>>> pointer.resize(10)
>>> len(pointer)
10
>>> pointer.clear()
>>> pointer.describe()
OrderedDict([('address', 0),
             ('alignment', [4, 0]),
             ('class', 'ArrayPointer'),
             ('index', [0, 0]),
             ('max', 4294967295),
             ('min', 0),
             ('name', 'ArrayPointer'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 32),
             ('type', 'Pointer'),
             ('value', '0xffffffff'),
             ('member',
              [OrderedDict([('class', 'Array'),
                            ('name', 'data'),
                            ('size', 0),
                            ('type', 'Array'),
                            ('member', [])])])])
>>> pointer.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.view_fields()
OrderedDict([('value', '0xffffffff'), ('data', [])])
>>> pointer.to_json()
'{"value": "0xffffffff", "data": []}'
>>> pointer.field_items()
[('field',
  ArrayPointer(index=Index(byte=0, bit=0,
                           address=0, base_address=0,
                           update=False),
               alignment=Alignment(byte_size=4, bit_offset=0),
               bit_size=32,
               value='0xffffffff'))]
>>> pointer.to_list(nested=True)
[('ArrayPointer.field', '0xffffffff')]
>>> pointer.to_dict(nested=True)
OrderedDict([('ArrayPointer', OrderedDict([('field', '0xffffffff')]))])
append()[source]

Appends a new Array element to the Array.

insert(index)[source]

Inserts a new Array element before the index of the Array.

Parameters:index (int) – Array index.
resize(size)[source]

Re-sizes the Array by appending new Array elements or removing Array elements from the end.

Parameters:size (int) – new size of the Array in number of Array elements.
class konfoo.ArrayPointer8(template, address=None, data_order=Byteorder.little = 'little')[source]

An ArrayPointer8 field is an ArrayPointer field with a Field size of one byte.

class konfoo.ArrayPointer16(template, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

An ArrayPointer16 field is an ArrayPointer field with a Field size of two bytes.

class konfoo.ArrayPointer24(template, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

An ArrayPointer24 field is an ArrayPointer field with a Field size of three bytes.

class konfoo.ArrayPointer32(template, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

An ArrayPointer32 field is an ArrayPointer field with a Field size of four bytes.

class konfoo.ArrayPointer48(template, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

An ArrayPointer48 field is an ArrayPointer field with a Field size of six bytes.

class konfoo.ArrayPointer64(template, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

An ArrayPointer64 field is an ArrayPointer field with a Field size of eight bytes.

Stream Pointer
class konfoo.StreamPointer(size=0, address=None, bit_size=32, align_to=None, field_order='auto')[source]

A StreamPointer field is a Pointer field which refers to a Stream field.

A StreamPointer field is:

  • containable: item in self returns True if item is part of the referenced Stream field.
  • sized: len(self) returns the length of the referenced Stream field.
  • indexable self[index] returns the byte at the index of the referenced Stream field.
  • iterable iter(self) iterates over the bytes of the referenced Stream field.
Parameters:
  • size (int) – is the size of the Stream field in bytes.
  • address (int) – absolute address of the data object referenced by the Pointer field.
  • bit_size (int) – is the size of the Pointer field in bits, can be between 1 and 64.
  • align_to (int) – aligns the Pointer field to the number of bytes, can be between 1 and 8. If no field alignment is set the Pointer field aligns itself to the next matching byte size according to the size of the Pointer field.
  • field_order (Byteorder, str) – byte order used to unpack and pack the value of the Pointer field.

Example:

>>> pointer = StreamPointer()
>>> pointer.is_decimal()
True
>>> pointer.is_pointer()
True
>>> pointer.name
'Pointer32'
>>> pointer.alignment
Alignment(byte_size=4, bit_offset=0)
>>> pointer.byte_order
Byteorder.auto = 'auto'
>>> pointer.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> pointer.index_field()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.bit_size
32
>>> pointer.signed
False
>>> pointer.min()
0
>>> pointer.max()
4294967295
>>> pointer.base_address
0
>>> pointer.address
0
>>> pointer.is_null()
True
>>> pointer.data
Stream(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
       alignment=Alignment(byte_size=0, bit_offset=0),
       bit_size=0,
       value='')
>>> pointer.data_size
0
>>> len(pointer)
0
>>> pointer.data_byte_order
Byteorder.little = 'little'
>>> pointer.bytestream
''
>>> pointer.value
'0x0'
>>> bytes(pointer)
b'\x00\x00\x00\x00'
>>> int(pointer)
0
>>> float(pointer)
0.0
>>> hex(pointer)
'0x0'
>>> bin(pointer)
'0b0'
>>> oct(pointer)
'0o0'
>>> bool(pointer)
False
>>> pointer.as_signed()
0
>>> pointer.as_unsigned()
0
>>> pointer.deserialize(bytes.fromhex('00c0'))
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.value
'0xc000'
>>> pointer.value = 0x4000
>>> pointer.value
'0x4000'
>>> pointer.value = -0x1
>>> pointer.value
'0x0'
>>> pointer.value = 0x100000000
>>> pointer.value
'0xffffffff'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> pointer.serialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> hexlify(bytestream)
b'ffffffff'
>>> pointer.resize(10)
>>> pointer.data_size
10
>>> len(pointer)
10
>>> pointer.bytestream = b'KonFoo is Fun'
>>> pointer.bytestream
'4b6f6e466f6f2069732046756e'
>>> hexlify(pointer.serialize_data())
b'00000000000000000000'
>>> pointer.deserialize_data()
Index(byte=10, bit=0, address=4294967305, base_address=4294967295, update=False)
>>> pointer.serialize_data()
b'KonFoo is '
>>> [byte for byte in pointer]  # converts to int
[75, 111, 110, 70, 111, 111, 32, 105, 115, 32]
>>> [hex(byte) for byte in pointer]
['0x4b', '0x6f', '0x6e', '0x46', '0x6f', '0x6f', '0x20', '0x69', '0x73', '0x20']
>>> pointer[5]  # converts to int
111
>>> 111 in pointer
True
>>> 0x0 in pointer
False
>>> pointer[:6]  # converts to bytes
b'KonFoo'
>>> pointer[3:6]  # converts to bytes
b'Foo'
>>> pointer.describe()
OrderedDict([('address', 0),
             ('alignment', [4, 0]),
             ('class', 'StreamPointer'),
             ('index', [0, 0]),
             ('max', 4294967295),
             ('min', 0),
             ('name', 'StreamPointer'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 32),
             ('type', 'Pointer'),
             ('value', '0xffffffff'),
             ('member',
              [OrderedDict([('address', 4294967295),
                            ('alignment', [10, 0]),
                            ('class', 'Stream10'),
                            ('index', [0, 0]),
                            ('name', 'data'),
                            ('order', 'auto'),
                            ('size', 80),
                            ('type', 'Field'),
                            ('value', '4b6f6e466f6f20697320')])])])
>>> pointer.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.view_fields()
OrderedDict([('value', '0xffffffff'), ('data', '4b6f6e466f6f20697320')])
>>> pointer.to_json()
'{"value": "0xffffffff", "data": "4b6f6e466f6f20697320"}'
>>> pointer.field_items()
[('field',
  StreamPointer(index=Index(byte=0, bit=0,
                            address=0, base_address=0,
                            update=False),
                alignment=Alignment(byte_size=4, bit_offset=0),
                bit_size=32,
                value='0xffffffff')),
 ('data',
  Stream(index=Index(byte=0, bit=0,
                     address=4294967295, base_address=4294967295,
                     update=False),
         alignment=Alignment(byte_size=10, bit_offset=0),
         bit_size=80,
         value='4b6f6e466f6f20697320'))]
>>> pointer.to_list()
[('StreamPointer.field', '0xffffffff'),
 ('StreamPointer.data', '4b6f6e466f6f20697320')]
>>> pointer.to_dict()
OrderedDict([('StreamPointer',
              OrderedDict([('field', '0xffffffff'),
                           ('data', '4b6f6e466f6f20697320')]))])
resize(size)[source]

Re-sizes the Stream field by appending zero bytes or removing bytes from the end.

Parameters:size (int) – Stream size in number of bytes.
class konfoo.StreamPointer8(size=0, address=None)[source]

A StreamPointer8 field is a StreamPointer field with a Field size of one byte.

class konfoo.StreamPointer16(size=0, address=None, field_order='auto')[source]

A StreamPointer16 field is a StreamPointer field with a Field size of two bytes.

class konfoo.StreamPointer24(size=0, address=None, field_order='auto')[source]

A StreamPointer24 field is a StreamPointer field with a Field size of three bytes.

class konfoo.StreamPointer32(size=0, address=None, field_order='auto')[source]

A StreamPointer32 field is a StreamPointer field with a Field size of four bytes.

class konfoo.StreamPointer48(size=0, address=None, field_order='auto')[source]

A StreamPointer48 field is a StreamPointer field with a Field size of six bytes.

class konfoo.StreamPointer64(size=0, address=None, field_order='auto')[source]

A StreamPointer64 field is a StreamPointer field with a Field size of eight bytes.

String Pointer
class konfoo.StringPointer(size=0, address=None, bit_size=32, align_to=None, field_order='auto')[source]

A StringPointer field is a StreamPointer field which refers to a String field.

Parameters:
  • size (int) – is the size of the String field in bytes.
  • address (int) – absolute address of the data object referenced by the Pointer field.
  • bit_size (int) – is the size of the Pointer field in bits, can be between 1 and 64.
  • align_to (int) – aligns the Pointer field to the number of bytes, can be between 1 and 8. If no field alignment is set the Pointer field aligns itself to the next matching byte size according to the size of the Pointer field.
  • field_order (Byteorder, str) – byte order used to unpack and pack the value of the Pointer field.

Example:

>>> pointer = StringPointer()
>>> pointer.is_decimal()
True
>>> pointer.is_pointer()
True
>>> pointer.name
'Pointer32'
>>> pointer.alignment
Alignment(byte_size=4, bit_offset=0)
>>> pointer.byte_order
Byteorder.auto = 'auto'
>>> pointer.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> pointer.index_field()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.bit_size
32
>>> pointer.signed
False
>>> pointer.min()
0
>>> pointer.max()
4294967295
>>> pointer.base_address
0
>>> pointer.address
0
>>> pointer.is_null()
True
>>> pointer.data
String(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
       alignment=Alignment(byte_size=0, bit_offset=0),
       bit_size=0,
       value='')
>>> pointer.data_size
0
>>> len(pointer)
0
>>> pointer.data_byte_order
Byteorder.little = 'little'
>>> pointer.bytestream
''
>>> pointer.value
'0x0'
>>> bytes(pointer)
b'\x00\x00\x00\x00'
>>> int(pointer)
0
>>> float(pointer)
0.0
>>> hex(pointer)
'0x0'
>>> bin(pointer)
'0b0'
>>> oct(pointer)
'0o0'
>>> bool(pointer)
False
>>> pointer.as_signed()
0
>>> pointer.as_unsigned()
0
>>> pointer.deserialize(bytes.fromhex('00c0'))
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.value
'0xc000'
>>> pointer.value = 0x4000
>>> pointer.value
'0x4000'
>>> pointer.value = -0x1
>>> pointer.value
'0x0'
>>> pointer.value = 0x100000000
>>> pointer.value
'0xffffffff'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> pointer.serialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> hexlify(bytestream)
b'ffffffff'
>>> pointer.resize(10)
>>> pointer.data_size
10
>>> len(pointer)
10
>>> pointer.bytestream = b'KonFoo is Fun'
>>> pointer.bytestream
'4b6f6e466f6f2069732046756e'
>>> hexlify(pointer.serialize_data())
b'00000000000000000000'
>>> pointer.deserialize_data()
Index(byte=10, bit=0, address=4294967305, base_address=4294967295, update=False)
>>> pointer.serialize_data()
b'KonFoo is '
>>> [byte for byte in pointer]  # converts to int
[75, 111, 110, 70, 111, 111, 32, 105, 115, 32]
>>> [chr(byte) for byte in pointer]  # converts to int
['K', 'o', 'n', 'F', 'o', 'o', ' ', 'i', 's', ' ']
>>> chr(pointer[5])  # converts to int -> chr
'o'
>>> ord(' ') in pointer
True
>>> 0x0 in pointer
False
>>> pointer[:6]  # converts to bytes
b'KonFoo'
>>> pointer[3:6]  # converts to bytes
b'Foo'
>>> pointer.describe()
OrderedDict([('address', 0),
             ('alignment', [4, 0]),
             ('class', 'StringPointer'),
             ('index', [0, 0]),
             ('max', 4294967295),
             ('min', 0),
             ('name', 'StringPointer'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 32),
             ('type', 'Pointer'),
             ('value', '0xffffffff'),
             ('member',
              [OrderedDict([('address', 4294967295),
                            ('alignment', [10, 0]),
                            ('class', 'String10'),
                            ('index', [0, 0]),
                            ('name', 'data'),
                            ('order', 'auto'),
                            ('size', 80),
                            ('type', 'Field'),
                            ('value', 'KonFoo is ')])])])
>>> pointer.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.view_fields()
OrderedDict([('value', '0xffffffff'), ('data', 'KonFoo is ')])
>>> pointer.to_json()
'{"value": "0xffffffff", "data": "KonFoo is "}'
>>> pointer.field_items()
[('field',
  StringPointer(index=Index(byte=0, bit=0,
                            address=0, base_address=0,
                            update=False),
                alignment=Alignment(byte_size=4, bit_offset=0),
                bit_size=32,
                value='0xffffffff')),
 ('data',
  String(index=Index(byte=0, bit=0,
                     address=4294967295, base_address=4294967295,
                     update=False),
         alignment=Alignment(byte_size=10, bit_offset=0),
         bit_size=80,
         value='KonFoo is '))]
>>> pointer.to_list()
[('StringPointer.field', '0xffffffff'), ('StringPointer.data', 'KonFoo is ')]
>>> pointer.to_dict()
OrderedDict([('StringPointer',
              OrderedDict([('field', '0xffffffff'), ('data', 'KonFoo is ')]))])
class konfoo.StringPointer8(size=0, address=None)[source]

A StringPointer8 field is a StringPointer field with a Field size of one byte.

class konfoo.StringPointer16(size=0, address=None, field_order='auto')[source]

A StringPointer16 field is a StringPointer field with a Field size of two bytes.

class konfoo.StringPointer24(size=0, address=None, field_order='auto')[source]

A StringPointer24 field is a StringPointer field with a Field size of three bytes.

class konfoo.StringPointer32(size=0, address=None, field_order='auto')[source]

A StringPointer32 field is a StringPointer field with a Field size of four bytes.

class konfoo.StringPointer48(size=0, address=None, field_order='auto')[source]

A StringPointer48 field is a StringPointer field with a Field size of six bytes.

class konfoo.StringPointer64(size=0, address=None, field_order='auto')[source]

A StringPointer64 field is a StringPointer field with a Field size of eight bytes.

Auto String Pointer
class konfoo.AutoStringPointer(address=None, bit_size=32, align_to=None, field_order='auto')[source]

An AutoStringPointer field is a StringPointer field which refers to an auto-sized String field.

Parameters:
  • address (int) – absolute address of the data object referenced by the Pointer field.
  • bit_size (int) – is the size of the Pointer field in bits, can be between 1 and 64.
  • align_to (int) – aligns the Pointer field to the number of bytes, can be between 1 and 8. If no field alignment is set the Pointer field aligns itself to the next matching byte size according to the size of the Pointer field.
  • field_order (Byteorder, str) – byte order used to unpack and pack the value of the Pointer field.

Example:

>>> pointer = AutoStringPointer()
>>> pointer.is_decimal()
True
>>> pointer.is_pointer()
True
>>> pointer.name
'Pointer32'
>>> pointer.alignment
Alignment(byte_size=4, bit_offset=0)
>>> pointer.byte_order
Byteorder.auto = 'auto'
>>> pointer.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> pointer.index_field()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.bit_size
32
>>> pointer.signed
False
>>> pointer.min()
0
>>> pointer.max()
4294967295
>>> pointer.base_address
0
>>> pointer.address
0
>>> pointer.is_null()
True
>>> pointer.data
String(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
       alignment=Alignment(byte_size=64, bit_offset=0),
       bit_size=512,
       value='')
>>> pointer.data_size
64
>>> len(pointer)
64
>>> pointer.data_byte_order
Byteorder.little = 'little'
>>> pointer.bytestream
''
>>> pointer.value
'0x0'
>>> bytes(pointer)
b'\x00\x00\x00\x00'
>>> int(pointer)
0
>>> float(pointer)
0.0
>>> hex(pointer)
'0x0'
>>> bin(pointer)
'0b0'
>>> oct(pointer)
'0o0'
>>> bool(pointer)
False
>>> pointer.as_signed()
0
>>> pointer.as_unsigned()
0
>>> pointer.deserialize(bytes.fromhex('00c0'))
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.value
'0xc000'
>>> pointer.value = 0x4000
>>> pointer.value
'0x4000'
>>> pointer.value = -0x1
>>> pointer.value
'0x0'
>>> pointer.value = 0x100000000
>>> pointer.value
'0xffffffff'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> pointer.serialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> hexlify(bytestream)
b'ffffffff'
>>> pointer.resize(10)
>>> pointer.data_size
10
>>> len(pointer)
10
>>> pointer.bytestream = b'KonFoo is Fun'
>>> pointer.bytestream
'4b6f6e466f6f2069732046756e'
>>> hexlify(pointer.serialize_data())
b'00000000000000000000'
>>> pointer.deserialize_data()
Index(byte=10, bit=0, address=4294967305, base_address=4294967295, update=False)
>>> pointer.serialize_data()
b'KonFoo is '
>>> [byte for byte in pointer]  # converts to int
[75, 111, 110, 70, 111, 111, 32, 105, 115, 32]
>>> [chr(byte) for byte in pointer]  # converts to int
['K', 'o', 'n', 'F', 'o', 'o', ' ', 'i', 's', ' ']
>>> chr(pointer[5])  # converts to int -> chr
'o'
>>> ord(' ') in pointer
True
>>> 0x0 in pointer
False
>>> pointer[:6]  # converts to bytes
b'KonFoo'
>>> pointer[3:6]  # converts to bytes
b'Foo'
>>> pointer.describe()
OrderedDict([('address', 0),
             ('alignment', [4, 0]),
             ('class', 'AutoStringPointer'),
             ('index', [0, 0]),
             ('max', 4294967295),
             ('min', 0),
             ('name', 'AutoStringPointer'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 32),
             ('type', 'Pointer'),
             ('value', '0xffffffff'),
             ('member',
              [OrderedDict([('address', 4294967295),
                            ('alignment', [10, 0]),
                            ('class', 'String10'),
                            ('index', [0, 0]),
                            ('name', 'data'),
                            ('order', 'auto'),
                            ('size', 80),
                            ('type', 'Field'),
                            ('value', 'KonFoo is ')])])])
>>> pointer.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.view_fields()
OrderedDict([('value', '0xffffffff'), ('data', 'KonFoo is ')])
>>> pointer.to_json()
'{"value": "0xffffffff", "data": "KonFoo is "}'
>>> pointer.field_items()
[('field',
  AutoStringPointer(index=Index(byte=0, bit=0,
                            address=0, base_address=0,
                            update=False),
                    alignment=Alignment(byte_size=4, bit_offset=0),
                    bit_size=32,
                    value='0xffffffff')),
 ('data',
  String(index=Index(byte=0, bit=0,
                     address=4294967295, base_address=4294967295,
                     update=False),
         alignment=Alignment(byte_size=10, bit_offset=0),
         bit_size=80,
         value='KonFoo is '))]
>>> pointer.to_list()
[('AutoStringPointer.field', '0xffffffff'),
 ('AutoStringPointer.data', 'KonFoo is ')]
>>> pointer.to_dict()
OrderedDict([('AutoStringPointer',
              OrderedDict([('field', '0xffffffff'), ('data', 'KonFoo is ')]))])
BLOCK_SIZE = 64

Block size in bytes to read for the String field.

MAX_ADDRESS = 4294967295

Maximal allowed address of the String field.

read_from(provider, null_allowed=False, **options)[source]

Reads from the data Provider the necessary number of bytes for the data object referenced by the Pointer field.

A Pointer field stores the binary data read from the data Provider in its bytestream.

Parameters:
  • provider (Provider) – data Provider.
  • null_allowed (bool) – if True read access of address zero (Null) is allowed.
  • nested (bool) – if True all Pointer fields in the data object of the Pointer field reads their referenced data object fields as well (chained method call). Each Pointer field stores the bytes for its referenced data object in its bytestream.

Relative Pointer

class konfoo.RelativePointer(template=None, address=None, data_order=Byteorder.little = 'little', bit_size=32, align_to=None, field_order='auto')[source]

A RelativePointer field is a Pointer field which references its data object relative to a base address in the data source.

Important

The base_address of a RelativePointer is defined by the field index of the RelativePointer field.

Parameters:
  • template – template for the data object referenced by the RelativePointer field.
  • address (int) – relative address of the data object referenced by the RelativePointer field.
  • data_order (Byteorder, str) – byte order used to unpack and pack the data object referenced by the RelativePointer field.
  • bit_size (int) – is the size of the RelativePointer field in bits, can be between 1 and 64.
  • align_to (int) – aligns the RelativePointer field to the number of bytes, can be between 1 and 8. If no field alignment is set the RelativePointer field aligns itself to the next matching byte size according to the size of the RelativePointer field.
  • field_order (Byteorder, str) – byte order used to unpack and pack the value of the RelativePointer field.

Example:

>>> pointer = RelativePointer()
>>> pointer.is_decimal()
True
>>> pointer.is_pointer()
True
>>> pointer.name
'Pointer32'
>>> pointer.alignment
Alignment(byte_size=4, bit_offset=0)
>>> pointer.byte_order
Byteorder.auto = 'auto'
>>> pointer.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> pointer.index_field()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.bit_size
32
>>> pointer.signed
False
>>> pointer.min()
0
>>> pointer.max()
4294967295
>>> pointer.base_address
0
>>> pointer.address
0
>>> pointer.is_null()
True
>>> pointer.data
>>> pointer.data_size
0
>>> pointer.data_byte_order
Byteorder.little = 'little'
>>> pointer.bytestream
''
>>> pointer.value
'0x0'
>>> bytes(pointer)
b'\x00\x00\x00\x00'
>>> int(pointer)
0
>>> float(pointer)
0.0
>>> hex(pointer)
'0x0'
>>> bin(pointer)
'0b0'
>>> oct(pointer)
'0o0'
>>> bool(pointer)
False
>>> pointer.as_signed()
0
>>> pointer.as_unsigned()
0
>>> pointer.deserialize(bytes.fromhex('00c0'))
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.value
'0xc000'
>>> pointer.value = 0x4000
>>> pointer.value
'0x4000'
>>> pointer.value = -0x1
>>> pointer.value
'0x0'
>>> pointer.value = 0x100000000
>>> pointer.value
'0xffffffff'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> pointer.serialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> hexlify(bytestream)
b'ffffffff'
>>> pointer.bytestream = b'KonFoo is Fun'
>>> pointer.bytestream
'4b6f6e466f6f2069732046756e'
>>> pointer.serialize_data()
b''
>>> pointer.deserialize_data()
Index(byte=0, bit=0, address=4294967295, base_address=0, update=False)
>>> pointer.serialize_data()
b''
>>> pointer.describe()
OrderedDict([('address', 0),
             ('alignment', [4, 0]),
             ('class', 'RelativePointer'),
             ('index', [0, 0]),
             ('max', 4294967295),
             ('min', 0),
             ('name', 'RelativePointer'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 32),
             ('type', 'Pointer'),
             ('value', '0xffffffff')])
>>> pointer.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.view_fields()
OrderedDict([('value', '0xffffffff'), ('data', None)])
>>> pointer.to_json()
'{"value": "0xffffffff", "data": null}'
>>> pointer.field_items()
[('field',
  RelativePointer(index=Index(byte=0, bit=0,
                              address=0, base_address=0,
                              update=False),
                  alignment=Alignment(byte_size=4, bit_offset=0),
                  bit_size=32,
                  value='0xffffffff'))]
>>> pointer.to_list()
[('RelativePointer.field', '0xffffffff')]
>>> pointer.to_dict()
OrderedDict([('RelativePointer', OrderedDict([('field', '0xffffffff')]))])
address

Returns the data source address of the data object referenced by the RelativePointer field (read-only).

base_address

Returns the data source base address of the data object relative referenced by the RelativePointer field (read-only).

class konfoo.RelativePointer8(template=None, address=None, data_order=Byteorder.little = 'little')[source]

A RelativePointer8 field is a RelativePointer field with a Field size of one byte.

class konfoo.RelativePointer16(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A RelativePointer16 field is a RelativePointer field with a Field size of two bytes.

class konfoo.RelativePointer24(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A RelativePointer24 field is a RelativePointer field with a Field size of three bytes.

class konfoo.RelativePointer32(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A RelativePointer32 field is a RelativePointer field with a Field size of four bytes.

class konfoo.RelativePointer48(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A RelativePointer48 field is a RelativePointer field with a Field size of six bytes.

class konfoo.RelativePointer64(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A RelativePointer64 field is a RelativePointer field with a Field size of eight bytes.

Structure Relative Pointer
class konfoo.StructureRelativePointer(template=None, address=None, data_order=Byteorder.little = 'little', bit_size=32, align_to=None, field_order='auto')[source]

A StructureRelativePointer field is a RelativePointer which refers to a Structure.

Parameters:
  • template – template for the data object referenced by the RelativePointer field. The template must be a Structure instance.
  • address (int) – relative address of the data object referenced by the RelativePointer field.
  • data_order (Byteorder, str) – byte order used to unpack and pack the data object referenced by the RelativePointer field.
  • bit_size (int) – is the size of the RelativePointer field in bits, can be between 1 and 64.
  • align_to (int) – aligns the RelativePointer field to the number of bytes, can be between 1 and 8. If no field alignment is set the RelativePointer field aligns itself to the next matching byte size according to the size of the RelativePointer field.
  • field_order (Byteorder, str) – byte order used to unpack and pack the value of the RelativePointer field.

Example:

>>> pointer = StructureRelativePointer()
>>> pointer.is_decimal()
True
>>> pointer.is_pointer()
True
>>> pointer.name
'Pointer32'
>>> pointer.alignment
Alignment(byte_size=4, bit_offset=0)
>>> pointer.byte_order
Byteorder.auto = 'auto'
>>> pointer.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> pointer.index_field()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.bit_size
32
>>> pointer.signed
False
>>> pointer.min()
0
>>> pointer.max()
4294967295
>>> pointer.base_address
0
>>> pointer.address
0
>>> pointer.is_null()
True
>>> pointer.data
Structure()
>>> pointer.data_size
0
>>> pointer.data_byte_order
Byteorder.little = 'little'
>>> pointer.bytestream
''
>>> pointer.value
'0x0'
>>> bytes(pointer)
b'\x00\x00\x00\x00'
>>> int(pointer)
0
>>> float(pointer)
0.0
>>> hex(pointer)
'0x0'
>>> bin(pointer)
'0b0'
>>> oct(pointer)
'0o0'
>>> bool(pointer)
False
>>> pointer.as_signed()
0
>>> pointer.as_unsigned()
0
>>> pointer.deserialize(bytes.fromhex('00c0'))
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.value
'0xc000'
>>> pointer.value = 0x4000
>>> pointer.value
'0x4000'
>>> pointer.value = -0x1
>>> pointer.value
'0x0'
>>> pointer.value = 0x100000000
>>> pointer.value
'0xffffffff'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> len(pointer)
0
>>> [name for name in pointer.keys()]
[]
>>> [member.value for member in pointer.values()]
[]
>>> [(name, member.value) for name, member in pointer.items()]
[]
>>> pointer.describe()
OrderedDict([('address', 0),
             ('alignment', [4, 0]),
             ('class', 'StructureRelativePointer'),
             ('index', [0, 0]),
             ('max', 4294967295),
             ('min', 0),
             ('name', 'StructureRelativePointer'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 32),
             ('type', 'Pointer'),
             ('value', '0xffffffff'),
             ('member',
              [OrderedDict([('class', 'Structure'),
                            ('name', 'data'),
                            ('size', 0),
                            ('type', 'Structure'),
                            ('member', [])])])])
>>> pointer.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.view_fields()
OrderedDict([('value', '0xffffffff'), ('data', OrderedDict())])
>>> pointer.to_json()
'{"value": "0xffffffff", "data": {}}'
>>> pointer.field_items()
[('field',
  StructureRelativePointer(index=Index(byte=0, bit=0,
                                       address=0, base_address=0,
                                       update=False),
                           alignment=Alignment(byte_size=4, bit_offset=0),
                           bit_size=32,
                           value='0xffffffff'))]
>>> pointer.to_list(nested=True)
[('StructureRelativePointer.field', '0xffffffff')]
>>> pointer.to_dict(nested=True)
OrderedDict([('StructureRelativePointer',
              OrderedDict([('field', '0xffffffff')]))])
class konfoo.StructureRelativePointer8(template=None, address=None, data_order=Byteorder.little = 'little')[source]

A StructureRelativePointer8 field is a StructureRelativePointer field with a Field size of one byte.

class konfoo.StructureRelativePointer16(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A StructureRelativePointer16 field is a StructureRelativePointer field with a Field size of two bytes.

class konfoo.StructureRelativePointer24(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A StructureRelativePointer24 field is a StructureRelativePointer field with a Field size of three bytes.

Members:
class konfoo.StructureRelativePointer32(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A StructureRelativePointer32 field is a StructureRelativePointer field with a Field size of four bytes.

class konfoo.StructureRelativePointer48(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A StructureRelativePointer48 field is a StructureRelativePointer field with a Field size of six bytes.

class konfoo.StructureRelativePointer64(template=None, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

A StructureRelativePointer64 field is a StructureRelativePointer field with a Field size of eight bytes.

Sequence Relative Pointer
class konfoo.SequenceRelativePointer(iterable=None, address=None, data_order=Byteorder.little = 'little', bit_size=32, align_to=None, field_order='auto')[source]

A SequenceRelativePointer field is a RelativePointer which refers to a Sequence.

A SequenceRelativePointer is:

  • containable: item in self returns True if item is part of the referenced Sequence.
  • sized: len(self) returns the number of items in the referenced Sequence.
  • indexable self[index] returns the item at the index of the referenced Sequence.
  • iterable iter(self) iterates over the items of the referenced Sequence

A SequenceRelativePointer supports the usual methods:

Parameters:
  • iterable – any iterable that contains items of Structure, Sequence, Array or Field instances. If the iterable is one of these instances itself then the iterable itself is appended to the Sequence.
  • address (int) – relative address of the data object referenced by the RelativePointer field.
  • data_order (Byteorder, str) – byte order used to unpack and pack the data object referenced by the RelativePointer field.
  • bit_size (int) – is the size of the RelativePointer field in bits, can be between 1 and 64.
  • align_to (int) – aligns the RelativePointer field to the number of bytes, can be between 1 and 8. If no field alignment is set the RelativePointer field aligns itself to the next matching byte size according to the size of the RelativePointer field.
  • field_order (Byteorder, str) – byte order used to unpack and pack the value of the RelativePointer field.

Example:

>>> pointer = SequenceRelativePointer()
>>> pointer.is_decimal()
True
>>> pointer.is_pointer()
True
>>> pointer.name
'Pointer32'
>>> pointer.alignment
Alignment(byte_size=4, bit_offset=0)
>>> pointer.byte_order
Byteorder.auto = 'auto'
>>> pointer.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> pointer.index_field()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.bit_size
32
>>> pointer.signed
False
>>> pointer.min()
0
>>> pointer.max()
4294967295
>>> pointer.base_address
0
>>> pointer.address
0
>>> pointer.is_null()
True
>>> pointer.data
[]
>>> pointer.data_size
0
>>> pointer.data_byte_order
Byteorder.little = 'little'
>>> pointer.bytestream
''
>>> pointer.value
'0x0'
>>> bytes(pointer)
b'\x00\x00\x00\x00'
>>> int(pointer)
0
>>> float(pointer)
0.0
>>> hex(pointer)
'0x0'
>>> bin(pointer)
'0b0'
>>> oct(pointer)
'0o0'
>>> bool(pointer)
False
>>> pointer.as_signed()
0
>>> pointer.as_unsigned()
0
>>> pointer.deserialize(bytes.fromhex('00c0'))
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.value
'0xc000'
>>> pointer.value = 0x4000
>>> pointer.value
'0x4000'
>>> pointer.value = -0x1
>>> pointer.value
'0x0'
>>> pointer.value = 0x100000000
>>> pointer.value
'0xffffffff'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> len(pointer)
0
>>> [item for item in pointer]
[]
>>> pointer[:]
[]
>>> pointer.append(Field())
>>> pointer[0]
Field(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
      alignment=Alignment(byte_size=0, bit_offset=0),
      bit_size=0,
      value=None)
>>> len(pointer)
1
>>> pointer.pop()
Field(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
      alignment=Alignment(byte_size=0, bit_offset=0),
      bit_size=0,
      value=None)
>>> pointer.insert(0, Field())
>>> pointer.data
[Field(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
       alignment=Alignment(byte_size=0, bit_offset=0),
       bit_size=0,
       value=None)]
>>> pointer.remove(pointer[0])
>>> pointer.data
[]
>>> pointer.clear()
>>> pointer.describe()
OrderedDict([('address', 0),
             ('alignment', [4, 0]),
             ('class', 'SequenceRelativePointer'),
             ('index', [0, 0]),
             ('max', 4294967295),
             ('min', 0),
             ('name', 'SequenceRelativePointer'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 32),
             ('type', 'Pointer'),
             ('value', '0xffffffff'),
             ('member',
              [OrderedDict([('class', 'Sequence'),
                            ('name', 'data'),
                            ('size', 0),
                            ('type', 'Sequence'),
                            ('member', [])])])])
>>> pointer.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.view_fields()
OrderedDict([('value', '0xffffffff'), ('data', [])])
>>> pointer.to_json()
'{"value": "0xffffffff", "data": []}'
>>> pointer.field_items()
[('field',
  SequenceRelativePointer(index=Index(byte=0, bit=0,
                                      address=0, base_address=0,
                                      update=False),
                          alignment=Alignment(byte_size=4, bit_offset=0),
                          bit_size=32,
                          value='0xffffffff'))]
>>> pointer.to_list(nested=True)
[('SequenceRelativePointer.field', '0xffffffff')]
>>> pointer.to_dict(nested=True)
OrderedDict([('SequenceRelativePointer',
              OrderedDict([('field', '0xffffffff')]))])
append(item)[source]

Appends the item to the end of the Sequence.

Parameters:item – any Structure, Sequence, Array or Field instance.
insert(index, item)[source]

Inserts the item before the index into the Sequence.

Parameters:
pop(index=-1)[source]

Removes and returns the item at the index from the Sequence.

Parameters:index (int) – Sequence index
clear()[source]

Remove all items from the Sequence.

remove(item)[source]

Removes the first occurrence of an item from the Sequence.

Parameters:item – any Structure, Sequence, Array or Field instance.
reverse()[source]

In place reversing of the Sequence items.

extend(iterable)[source]

Extends the Sequence by appending items from the iterable.

Parameters:iterable – any iterable that contains items of Structure, Sequence, Array or Field instances. If the iterable is one of these instances itself then the iterable itself is appended to the Sequence.
Array Relative Pointer
class konfoo.ArrayRelativePointer(template, size=0, address=None, data_order=Byteorder.little = 'little', bit_size=32, align_to=None, field_order='auto')[source]

An ArrayRelativePointer field is a SequenceRelativePointer which refers to a Array.

An ArrayRelativePointer adapts and extends a SequenceRelativePointer with the following features:

Parameters:
  • template – template for the Array element. The template can be any Field instance or any callable that returns a Structure, Sequence, Array or any Field instance.
  • size (int) – is the size of the Array in number of Array elements.
  • address (int) – relative address of the data object referenced by the RelativePointer field.
  • data_order (Byteorder, str) – byte order used to unpack and pack the data object referenced by the RelativePointer field.
  • bit_size (int) – is the size of the RelativePointer field in bits, can be between 1 and 64.
  • align_to (int) – aligns the RelativePointer field to the number of bytes, can be between 1 and 8. If no field alignment is set the RelativePointer field aligns itself to the next matching byte size according to the size of the RelativePointer field.
  • field_order (Byteorder, str) – byte order used to unpack and pack the value of the RelativePointer field.

Example:

>>> pointer = ArrayRelativePointer(Byte)
>>> pointer.is_decimal()
True
>>> pointer.is_pointer()
True
>>> pointer.name
'Pointer32'
>>> pointer.alignment
Alignment(byte_size=4, bit_offset=0)
>>> pointer.byte_order
Byteorder.auto = 'auto'
>>> pointer.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> pointer.index_field()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.bit_size
32
>>> pointer.signed
False
>>> pointer.min()
0
>>> pointer.max()
4294967295
>>> pointer.base_address
0
>>> pointer.address
0
>>> pointer.is_null()
True
>>> pointer.data
[]
>>> pointer.data_size
0
>>> pointer.data_byte_order
Byteorder.little = 'little'
>>> pointer.bytestream
''
>>> pointer.value
'0x0'
>>> bytes(pointer)
b'\x00\x00\x00\x00'
>>> int(pointer)
0
>>> float(pointer)
0.0
>>> hex(pointer)
'0x0'
>>> bin(pointer)
'0b0'
>>> oct(pointer)
'0o0'
>>> bool(pointer)
False
>>> pointer.as_signed()
0
>>> pointer.as_unsigned()
0
>>> pointer.deserialize(bytes.fromhex('00c0'))
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.value
'0xc000'
>>> pointer.value = 0x4000
>>> pointer.value
'0x4000'
>>> pointer.value = -0x1
>>> pointer.value
'0x0'
>>> pointer.value = 0x100000000
>>> pointer.value
'0xffffffff'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> len(pointer)
0
>>> [item for item in pointer]
[]
>>> pointer[:]
[]
>>> pointer.append()
>>> pointer[0]
Byte(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
     alignment=Alignment(byte_size=1, bit_offset=0),
     bit_size=8,
     value='0x0')
>>> len(pointer)
1
>>> pointer.pop()
Byte(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
     alignment=Alignment(byte_size=1, bit_offset=0),
     bit_size=8,
     value='0x0')
>>> pointer.insert(0)
>>> pointer.data
[Byte(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
      alignment=Alignment(byte_size=1, bit_offset=0),
      bit_size=8,
      value='0x0')]
>>> pointer.remove(pointer[0])
>>> pointer.data
[]
>>> pointer.resize(10)
>>> len(pointer)
10
>>> pointer.clear()
>>> pointer.describe()
OrderedDict([('address', 0),
             ('alignment', [4, 0]),
             ('class', 'ArrayRelativePointer'),
             ('index', [0, 0]),
             ('max', 4294967295),
             ('min', 0),
             ('name', 'ArrayRelativePointer'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 32),
             ('type', 'Pointer'),
             ('value', '0xffffffff'),
             ('member',
              [OrderedDict([('class', 'Array'),
                            ('name', 'data'),
                            ('size', 0),
                            ('type', 'Array'),
                            ('member', [])])])])
>>> pointer.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.view_fields()
OrderedDict([('value', '0xffffffff'), ('data', [])])
>>> pointer.to_json()
'{"value": "0xffffffff", "data": []}'
>>> pointer.field_items()
[('field',
  ArrayRelativePointer(index=Index(byte=0, bit=0,
                                   address=0, base_address=0,
                                   update=False),
                       alignment=Alignment(byte_size=4, bit_offset=0),
                       bit_size=32,
                       value='0xffffffff'))]
>>> pointer.to_list(nested=True)
[('ArrayRelativePointer.field', '0xffffffff')]
>>> pointer.to_dict(nested=True)
OrderedDict([('ArrayRelativePointer', OrderedDict([('field', '0xffffffff')]))])
append()[source]

Appends a new Array element to the Array.

insert(index)[source]

Inserts a new Array element before the index of the Array.

Parameters:index (int) – Array index.
resize(size)[source]

Re-sizes the Array by appending new Array elements or removing Array elements from the end.

Parameters:size (int) – new size of the Array in number of Array elements.
class konfoo.ArrayRelativePointer8(template, address=None, data_order=Byteorder.little = 'little')[source]

An ArrayRelativePointer8 field is an ArrayRelativePointer field with a Field size of one byte.

class konfoo.ArrayRelativePointer16(template, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

An ArrayRelativePointer16 field is an ArrayRelativePointer field with a Field size of two bytes.

class konfoo.ArrayRelativePointer24(template, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

An ArrayRelativePointer24 field is an ArrayRelativePointer field with a Field size of three bytes.

class konfoo.ArrayRelativePointer32(template, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

An ArrayRelativePointer32 field is an ArrayRelativePointer field with a Field size of four bytes.

class konfoo.ArrayRelativePointer48(template, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

An ArrayRelativePointer48 field is an ArrayRelativePointer field with a Field size of six bytes.

class konfoo.ArrayRelativePointer64(template, address=None, data_order=Byteorder.little = 'little', field_order='auto')[source]

An ArrayRelativePointer64 field is an ArrayRelativePointer field with a Field size of eight bytes.

Stream Relative Pointer
class konfoo.StreamRelativePointer(size=0, address=None, bit_size=32, align_to=None, field_order='auto')[source]

A StreamRelativePointer field is a RelativePointer field which refers to a Stream field.

A StreamRelativePointer field is:

  • containable: item in self returns True if item is part of the referenced Stream field.
  • sized: len(self) returns the length of the referenced Stream field.
  • indexable self[index] returns the byte at the index of the referenced Stream field.
  • iterable iter(self) iterates over the bytes of the referenced Stream field.
Parameters:
  • size (int) – is the size of the Stream field in bytes.
  • address (int) – relative address of the data object referenced by the RelativePointer field.
  • bit_size (int) – is the size of the RelativePointer field in bits, can be between 1 and 64.
  • align_to (int) – aligns the RelativePointer field to the number of bytes, can be between 1 and 8. If no field alignment is set the RelativePointer field aligns itself to the next matching byte size according to the size of the RelativePointer field.
  • field_order (Byteorder, str) – byte order used to unpack and pack the value of the RelativePointer field.

Example:

>>> pointer = StreamRelativePointer()
>>> pointer.is_decimal()
True
>>> pointer.is_pointer()
True
>>> pointer.name
'Pointer32'
>>> pointer.alignment
Alignment(byte_size=4, bit_offset=0)
>>> pointer.byte_order
Byteorder.auto = 'auto'
>>> pointer.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> pointer.index_field()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.bit_size
32
>>> pointer.signed
False
>>> pointer.min()
0
>>> pointer.max()
4294967295
>>> pointer.base_address
0
>>> pointer.address
0
>>> pointer.is_null()
True
>>> pointer.data
Stream(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
       alignment=Alignment(byte_size=0, bit_offset=0),
       bit_size=0,
       value='')
>>> pointer.data_size
0
>>> len(pointer)
0
>>> pointer.data_byte_order
Byteorder.little = 'little'
>>> pointer.bytestream
''
>>> pointer.value
'0x0'
>>> bytes(pointer)
b'\x00\x00\x00\x00'
>>> int(pointer)
0
>>> float(pointer)
0.0
>>> hex(pointer)
'0x0'
>>> bin(pointer)
'0b0'
>>> oct(pointer)
'0o0'
>>> bool(pointer)
False
>>> pointer.as_signed()
0
>>> pointer.as_unsigned()
0
>>> pointer.deserialize(bytes.fromhex('00c0'))
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.value
'0xc000'
>>> pointer.value = 0x4000
>>> pointer.value
'0x4000'
>>> pointer.value = -0x1
>>> pointer.value
'0x0'
>>> pointer.value = 0x100000000
>>> pointer.value
'0xffffffff'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> pointer.serialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> hexlify(bytestream)
b'ffffffff'
>>> pointer.resize(10)
>>> pointer.data_size
10
>>> len(pointer)
10
>>> pointer.bytestream = b'KonFoo is Fun'
>>> pointer.bytestream
'4b6f6e466f6f2069732046756e'
>>> hexlify(pointer.serialize_data())
b'00000000000000000000'
>>> pointer.deserialize_data()
Index(byte=10, bit=0, address=4294967305, base_address=0, update=False)
>>> pointer.serialize_data()
b'KonFoo is '
>>> [byte for byte in pointer]  # converts to int
[75, 111, 110, 70, 111, 111, 32, 105, 115, 32]
>>> [hex(byte) for byte in pointer]
['0x4b', '0x6f', '0x6e', '0x46', '0x6f', '0x6f', '0x20', '0x69', '0x73', '0x20']
>>> pointer[5]  # converts to int
111
>>> 111 in pointer
True
>>> 0x0 in pointer
False
>>> pointer[:6]  # converts to bytes
b'KonFoo'
>>> pointer[3:6]  # converts to bytes
b'Foo'
>>> pointer.describe()
OrderedDict([('address', 0),
             ('alignment', [4, 0]),
             ('class', 'StreamRelativePointer'),
             ('index', [0, 0]),
             ('max', 4294967295),
             ('min', 0),
             ('name', 'StreamRelativePointer'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 32),
             ('type', 'Pointer'),
             ('value', '0xffffffff'),
             ('member',
              [OrderedDict([('address', 4294967295),
                            ('alignment', [10, 0]),
                            ('class', 'Stream10'),
                            ('index', [0, 0]),
                            ('name', 'data'),
                            ('order', 'auto'),
                            ('size', 80),
                            ('type', 'Field'),
                            ('value', '4b6f6e466f6f20697320')])])])
>>> pointer.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.view_fields()
OrderedDict([('value', '0xffffffff'), ('data', '4b6f6e466f6f20697320')])
>>> pointer.to_json()
'{"value": "0xffffffff", "data": "4b6f6e466f6f20697320"}'
>>> pointer.field_items()
[('field',
  StreamRelativePointer(index=Index(byte=0, bit=0,
                                    address=0, base_address=0,
                                    update=False),
                        alignment=Alignment(byte_size=4, bit_offset=0),
                        bit_size=32,
                        value='0xffffffff')),
 ('data',
  Stream(index=Index(byte=0, bit=0,
                     address=4294967295, base_address=0,
                     update=False),
         alignment=Alignment(byte_size=10, bit_offset=0),
         bit_size=80,
         value='4b6f6e466f6f20697320'))]
>>> pointer.to_list()
[('StreamRelativePointer.field', '0xffffffff'),
 ('StreamRelativePointer.data', '4b6f6e466f6f20697320')]
>>> pointer.to_dict()
OrderedDict([('StreamRelativePointer',
              OrderedDict([('field', '0xffffffff'),
                           ('data', '4b6f6e466f6f20697320')]))])
resize(size)[source]

Re-sizes the Stream field by appending zero bytes or removing bytes from the end.

Parameters:size (int) – Stream size in number of bytes.
class konfoo.StreamRelativePointer8(size=0, address=None)[source]

A StreamRelativePointer8 field is a StreamRelativePointer field with a Field size of one byte.

class konfoo.StreamRelativePointer16(size=0, address=None, field_order='auto')[source]

A StreamRelativePointer16 field is a StreamRelativePointer field with a Field size of two bytes.

class konfoo.StreamRelativePointer24(size=0, address=None, field_order='auto')[source]

A StreamRelativePointer24 field is a StreamRelativePointer field with a Field size of three bytes.

class konfoo.StreamRelativePointer32(size=0, address=None, field_order='auto')[source]

A StreamRelativePointer32 field is a StreamRelativePointer field with a Field size of four bytes.

class konfoo.StreamRelativePointer48(size=0, address=None, field_order='auto')[source]

A StreamRelativePointer48 field is a StreamRelativePointer field with a Field size of six bytes.

class konfoo.StreamRelativePointer64(size=0, address=None, field_order='auto')[source]

A StreamRelativePointer64 field is a StreamRelativePointer field with a Field size of eight bytes.

String Relative Pointer
class konfoo.StringRelativePointer(size=0, address=None, bit_size=32, align_to=None, field_order='auto')[source]

A StringRelativePointer field is a StreamRelativePointer which refers to a String field.

Parameters:
  • size (int) – is the size of the String field in bytes.
  • address (int) – relative address of the data object referenced by the RelativePointer field.
  • bit_size (int) – is the size of the RelativePointer field in bits, can be between 1 and 64.
  • align_to (int) – aligns the RelativePointer field to the number of bytes, can be between 1 and 8. If no field alignment is set the RelativePointer field aligns itself to the next matching byte size according to the size of the RelativePointer field.
  • field_order (Byteorder, str) – byte order used to unpack and pack the value of the RelativePointer field.

Example:

>>> pointer = StringRelativePointer()
>>> pointer.is_decimal()
True
>>> pointer.is_pointer()
True
>>> pointer.name
'Pointer32'
>>> pointer.alignment
Alignment(byte_size=4, bit_offset=0)
>>> pointer.byte_order
Byteorder.auto = 'auto'
>>> pointer.index
Index(byte=0, bit=0, address=0, base_address=0, update=False)
>>> pointer.index_field()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.bit_size
32
>>> pointer.signed
False
>>> pointer.min()
0
>>> pointer.max()
4294967295
>>> pointer.base_address
0
>>> pointer.address
0
>>> pointer.is_null()
True
>>> pointer.as_signed()
0
>>> pointer.as_unsigned()
0
>>> pointer.data
String(index=Index(byte=0, bit=0, address=0, base_address=0, update=False),
       alignment=Alignment(byte_size=0, bit_offset=0),
       bit_size=0,
       value='')
>>> pointer.data_size
0
>>> len(pointer)
0
>>> pointer.data_byte_order
Byteorder.little = 'little'
>>> pointer.bytestream
''
>>> pointer.value
'0x0'
>>> bytes(pointer)
b'\x00\x00\x00\x00'
>>> int(pointer)
0
>>> float(pointer)
0.0
>>> hex(pointer)
'0x0'
>>> bin(pointer)
'0b0'
>>> oct(pointer)
'0o0'
>>> bool(pointer)
False
>>> pointer.deserialize(bytes.fromhex('00c0'))
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.value
'0xc000'
>>> pointer.value = 0x4000
>>> pointer.value
'0x4000'
>>> pointer.value = -0x1
>>> pointer.value
'0x0'
>>> pointer.value = 0x100000000
>>> pointer.value
'0xffffffff'
>>> bytestream = bytearray()
>>> bytestream
bytearray(b'')
>>> pointer.serialize(bytestream)
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> hexlify(bytestream)
b'ffffffff'
>>> pointer.resize(10)
>>> pointer.data_size
10
>>> len(pointer)
10
>>> pointer.bytestream = b'KonFoo is Fun'
>>> pointer.bytestream
'4b6f6e466f6f2069732046756e'
>>> hexlify(pointer.serialize_data())
b'00000000000000000000'
>>> pointer.deserialize_data()
Index(byte=10, bit=0, address=4294967305, base_address=0, update=False)
>>> pointer.serialize_data()
b'KonFoo is '
>>> [byte for byte in pointer]  # converts to int
[75, 111, 110, 70, 111, 111, 32, 105, 115, 32]
>>> [chr(byte) for byte in pointer]  # converts to int
['K', 'o', 'n', 'F', 'o', 'o', ' ', 'i', 's', ' ']
>>> chr(pointer[5])  # converts to int -> chr
'o'
>>> ord(' ') in pointer
True
>>> 0x0 in pointer
False
>>> pointer[:6]  # converts to bytes
b'KonFoo'
>>> pointer[3:6]  # converts to bytes
b'Foo'
>>> pointer.describe()
OrderedDict([('address', 0),
             ('alignment', [4, 0]),
             ('class', 'StringRelativePointer'),
             ('index', [0, 0]),
             ('max', 4294967295),
             ('min', 0),
             ('name', 'StringRelativePointer'),
             ('order', 'auto'),
             ('signed', False),
             ('size', 32),
             ('type', 'Pointer'),
             ('value', '0xffffffff'),
             ('member',
              [OrderedDict([('address', 4294967295),
                            ('alignment', [10, 0]),
                            ('class', 'String10'),
                            ('index', [0, 0]),
                            ('name', 'data'),
                            ('order', 'auto'),
                            ('size', 80),
                            ('type', 'Field'),
                            ('value', 'KonFoo is ')])])])
>>> pointer.index_fields()
Index(byte=4, bit=0, address=4, base_address=0, update=False)
>>> pointer.view_fields()
OrderedDict([('value', '0xffffffff'), ('data', 'KonFoo is ')])
>>> pointer.to_json()
'{"value": "0xffffffff", "data": "KonFoo is "}'
>>> pointer.field_items()
[('field',
  StringRelativePointer(index=Index(byte=0, bit=0,
                                    address=0, base_address=0,
                                    update=False),
                        alignment=Alignment(byte_size=4, bit_offset=0),
                        bit_size=32,
                        value='0xffffffff')),
 ('data',
  String(index=Index(byte=0, bit=0,
                     address=4294967295, base_address=0,
                     update=False),
         alignment=Alignment(byte_size=10, bit_offset=0),
         bit_size=80,
         value='KonFoo is '))]
>>> pointer.to_list()
[('StringRelativePointer.field', '0xffffffff'),
 ('StringRelativePointer.data', 'KonFoo is ')]
>>> pointer.to_dict()
OrderedDict([('StringRelativePointer',
              OrderedDict([('field', '0xffffffff'), ('data', 'KonFoo is ')]))])
class konfoo.StringRelativePointer8(size=0, address=None)[source]

A StringRelativePointer8 field is a StringRelativePointer field with a Field size of one byte.

class konfoo.StringRelativePointer16(size=0, address=None, field_order='auto')[source]

A StringRelativePointer16 field is a StringRelativePointer field with a Field size of two bytes.

class konfoo.StringRelativePointer24(size=0, address=None, field_order='auto')[source]

A StringRelativePointer24 field is a StringRelativePointer field with a Field size of three bytes.

class konfoo.StringRelativePointer32(size=0, address=None, field_order='auto')[source]

A StringRelativePointer32 field is a StringRelativePointer field with a Field size of four bytes.

class konfoo.StringRelativePointer48(size=0, address=None, field_order='auto')[source]

A StringRelativePointer48 field is a StringRelativePointer field with a Field size of six bytes.

class konfoo.StringRelativePointer64(size=0, address=None, field_order='auto')[source]

A StringRelativePointer64 field is a StringRelativePointer field with a Field size of eight bytes.

Byteorder

class konfoo.Byteorder[source]

Byte order categories.

auto = 'auto'
little = 'little'
big = 'big'

Field Index

class konfoo.Index(byte, bit, address, base_address, update)

The Index class contains the relevant information of the location of a Field in a byte stream and in a data source. The byte stream is normally provided by a Pointer field. The data source is normally accessed via a data Provider by a Pointer field.

Parameters:
  • byte (int) – byte offset of the Field in the byte stream.
  • bit (int) – bit offset of the Field relative to its byte offset.
  • address (int) – address of the Field in the data source.
  • base_address (int) – start address of the byte stream in the data source.
  • update (bool) – if True the byte stream needs to be updated.

Field Alignment

class konfoo.Alignment(byte_size, bit_offset)

The Alignment class contains the location of the Field within an aligned group of consecutive fields.

Parameters:
  • byte_size (int) – size of the field group in bytes which the Field is aligned to.
  • bit_offset (int) – bit offset of the Field within its aligned field group.

Memory Patch

class konfoo.Patch(buffer, address, byteorder, bit_size, bit_offset, inject)

The Patch class contains the relevant information to patch a memory area of a data source accessed via a data Provider by a Pointer field.

Parameters:
  • buffer (bytes) – byte stream for the memory area to patch in the data source. The byte stream contains the data of the patch item.
  • address (int) – address of the memory area to patch in the data source.
  • byteorderByteorder of the memory area to patch in the data source.
  • bit_size (int) – bit size of the patch item.
  • bit_offset (int) – bit offset of the patch item within the memory area.
  • inject (bool) – if True the patch item must be injected into the memory area of the data source.

Enumerations

class konfoo.Enumeration[source]

The Enumeration class is a subclass from the IntEnum class provided by the Python standard module enum and extends its base class with methods

  • to describe a specific Enumeration member by its name, value pair
  • to list the member names of an Enumeration
  • to list the member values of an Enumeration
  • to get the value of the Enumeration member with the matching name
  • to get the name of the Enumeration member with the matching value
  • to get the member of the Enumeration with the matching value

Example:

>>> class Color(Enumeration):
...     black = 0x000000
...     maroon = 0x080000
...     white = 0xffffff
>>> Color
<enum 'Color'>
>>> type(Color.maroon)
<enum 'Color'>
>>> isinstance(Color, Enumeration)
False
>>> issubclass(Color, Enumeration)
True
>>> isinstance(Color.maroon, Color)
True
>>> print(Color.maroon)
(maroon, 524288)
>>> str(Color.maroon)
'(maroon, 524288)'
>>> Color.maroon
Color.maroon = 524288
>>> repr(Color.maroon)
'Color.maroon = 524288'
>>> list(Color)
[Color.black = 0, Color.maroon = 524288, Color.white = 16777215]
>>> [color for color in Color]
[Color.black = 0, Color.maroon = 524288, Color.white = 16777215]
>>> Color.maroon.name
'maroon'
>>> Color.maroon.value
524288
>>> Color.maroon.describe()
('maroon', 524288)
>>> [color.name for color in Color]
['black', 'maroon', 'white']
>>> Color.names()
['black', 'maroon', 'white']
>>> [color.value for color in Color]
[0, 524288, 16777215]
>>> Color.values()
[0, 524288, 16777215]
>>> Color['maroon'].value
524288
>>> Color.get_value('maroon')
524288
>>> Color(0).name
'black'
>>> Color.get_name(0)
'black'
>>> Color.get_member(0)
Color.black = 0
>>> int(Color.black)
0
>>> 0 in Color.values()
True
>>> 'black' in Color.names()
True
describe()[source]

Returns the name, value pair to describe a specific Enumeration member.

Example:

>>> class Color(Enumeration):
...     black = 0x000000
...     maroon = 0x080000
...     white = 0xffffff
>>> Color.maroon.describe()
('maroon', 524288)

Categories

class konfoo.Category[source]

The Category class is a is a subclass of the Enum class provided by the Python standard module enum and extends its base class with methods

  • to describe a specific Category member by its name, value pair
  • to list the member names of a Category
  • to list the member values of a Category
  • to get the value of the Category member with the matching name
  • to get the name of the Category member with the matching value
  • to get the member of the Category with the matching value

Example:

>>> class Format(Category):
...     hour = 'hh'
...     minute = 'mm'
...     second = 'ss'
>>> Format
<enum 'Format'>
>>> type(Format.hour)
<enum 'Format'>
>>> isinstance(Format, Category)
False
>>> issubclass(Format, Category)
True
>>> isinstance(Format.hour, Format)
True
>>> print(Format.hour)
(hour, hh)
>>> str(Format.hour)
'(hour, hh)'
>>> Format.hour
Format.hour = 'hh'
>>> repr(Format.hour)
"Format.hour = 'hh'"
>>> list(Format)
[Format.hour = 'hh', Format.minute = 'mm', Format.second = 'ss']
>>> [format for format in Format]
[Format.hour = 'hh', Format.minute = 'mm', Format.second = 'ss']
>>> Format.hour.name
'hour'
>>> Format.hour.value
'hh'
>>> Format.hour.describe()
('hour', 'hh')
>>> [format.name for format in Format]
['hour', 'minute', 'second']
>>> Format.names()
['hour', 'minute', 'second']
>>> [format.value for format in Format]
['hh', 'mm', 'ss']
>>> Format.values()
['hh', 'mm', 'ss']
>>> Format['hour'].value
'hh'
>>> Format.get_value('hour')
'hh'
>>> Format('hh').name
'hour'
>>> Format.get_name('hh')
'hour'
>>> Format.get_member('hh')
Format.hour = 'hh'
>>> 'hh' in Format.values()
True
>>> 'hour' in Format.names()
True
describe()[source]

Returns the name, value pair to describe a specific Category member.

Example:

>>> class Format(Category):
...     hour = 'hh'
...     minute = 'mm'
...     second = 'ss'
>>> Format.hour.describe()
('hour', 'hh')

Exceptions

exception konfoo.ByteOrderTypeError(field, byte_order)[source]

Raised if an inappropriate byte order type is assigned to a field class.

exception konfoo.EnumTypeError(field, enumeration)[source]

Raised if an inappropriate enum type is assigned to a field class.

exception konfoo.FactoryTypeError(field, factory, item, member=None, index=None)[source]

Raised if an inappropriate member type is produced by a factory class.

exception konfoo.MemberTypeError(field, item, member=None, index=None)[source]

Raised if an inappropriate member type is assigned to any container class.

exception konfoo.ProviderTypeError(field, provider)[source]

Raised if an inappropriate data provider type is assigned to a pointer class.

exception konfoo.ContainerLengthError(field, length)[source]

Raised if a container class has an inappropriate field length.

exception konfoo.FieldAddressError(field, index, address)[source]

Raised if an inappropriate address is assigned to a field class.

exception konfoo.FieldAlignmentError(field, index, alignment)[source]

Raised if an inappropriate alignment value is assigned to a field class.

exception konfoo.FieldByteOrderError(field, index, byte_order)[source]

Raised if an inappropriate byte order value is assigned to a field class.

exception konfoo.FieldIndexError(field, index)[source]

Raised if an inappropriate index value is assigned to a field class.

exception konfoo.FieldSizeError(field, index, size)[source]

Raised if an inappropriate bit size value is assigned to a field class.

exception konfoo.FieldTypeError(field, index, value)[source]

Raised if an inappropriate argument type is assigned to a field class.

exception konfoo.FieldValueError(field, index, value)[source]

Raised if an inappropriate argument value is assigned to a field class.

exception konfoo.FieldValueEncodingError(field, index, encoding)[source]

Raised if an inappropriate value encoding is assigned to a field class.

exception konfoo.FieldGroupByteOrderError(field, index, byte_order)[source]

Raised if the byte order of a field contradicts its aligned field group.

exception konfoo.FieldGroupOffsetError(field, index, alignment)[source]

Raised if the alignment offset of a field does not match with its field group.

exception konfoo.FieldGroupSizeError(field, index, alignment)[source]

Raised if the alignment size of a field does not match with its field group.

Utilities

Metadata Converter
konfoo.d3flare_json(metadata, file=None, **options)[source]

Converts the metadata dictionary of a container or field into a flare.json formatted string or formatted stream written to the file

The flare.json format is defined by the d3.js graphic library.

The flare.json format looks like this:

{
    "class": "class of the field or container",
    "name":  "name of the field or container",
    "size":  "bit size of the field",
    "value": "value of the field",
    "children": []
}
Parameters:
Hexadecimal Viewer
class konfoo.HexViewer(columns=16)[source]

A HexViewer writes or prints a source file or a byte stream as a hexadecimal dump to a output file or the console.

Parameters:columns (int) – number of output columns. Allowed values are 8, 16 or 32.

Example:

>>> viewer = HexViewer()
>>> viewer.dump(b'KonF`00` is Fun.')
         | 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 |
---------+-------------------------------------------------+-----------------
00000000 | 4B 6F 6E 46 60 30 30 60 20 69 73 20 46 75 6E 2E | KonF`00` is Fun.
columns

Number of output columns.

file_dump(source, index=0, count=0, output='')[source]

Dumps the content of the source file to the console or to the optional given output file.

Parameters:
  • source (str) – location and name of the source file.
  • index (int) – optional start index of the viewing area in bytes. Default is from the begin of the file.
  • count (int) – optional number of bytes to view. Default is to the end of the file.
  • output (str) – location and name for the optional output file.
dump(stream, index=0, count=0, output='')[source]

Dumps the content of the byte stream to the console or to the optional given output file.

Parameters:
  • stream (bytes) – byte stream to view.
  • index (int) – optional start index of the viewing area in bytes. Default is the begin of the stream.
  • count (int) – optional number of bytes to view. Default is to the end of the stream.
  • output (str) – location and name for the optional output file.

Changelog

Here you can see the full list of changes between each KonFoo release.

Version 1.1 (Released 2019-10-27)

Enhancements
Bug Fixes
  • Fixed syntax warnings to support Python 3.8 correctly.
  • Fixed Structure to raise the correct AttributeError exception instead of a KeyError exception when an unknown attribute is accessed.
  • Fixed the Structure class that the built-in help() function works correctly on an instance of Structure.

Version 1.0 (Released 2019-01-02)

  • First release.

License

KonFoo is licensed under a three-clause BSD License. It basically means: do whatever you want with it as long as the copyright in KonFoo sticks around, the conditions are not modified and the disclaimer is present. Furthermore, you must not use the names of the authors to promote derivatives of the software without written consent.

License Text

Copyright (c) 2015-2019 by Jochen Gerhaeusser. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  • Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Index