Add user dynamic array field support
This patch adds support for user dynamic array fields.
The element field type of a user dynamic array field type can be any of
the following:
* Bit array field type.
* String field type.
* Static array field type.
Note that it _cannot_ be another dynamic array field type.
The new `barectf.DynamicArrayFieldType` represents a dynamic array field
type. Its constructor accepts a length field type. As of this version,
this length field type must be within the same immediate structure field
type and before it.
The YAML ways to specify a dynamic array field type are:
barectf 2 configuration:
class: array
length: dynamic
element-type:
...
barectf 3 configuration:
class: dynamic-array
element-field-type:
...
Note that in YAML, you don't specify the length field type: the parser
automatically creates a 32-bit, byte-aligned unsigned integer field type
before which, for a dynamic array field type named `a`, has the name
`__a_len`. This also becomes part of the corresponding tracing function
parameter's name.
In the future, I can add a `length-field-type` property to a barectf 3
YAML dynamic array field type to point to an anterior unsigned integer
field type using some kind of reference, for example:
class: structure
members:
- my_length: uint16
- my_array:
field-type:
class: dynamic-array
length-field-type-name: my_length
element-field-type:
...
This would make it possible for more than one dynamic array fields
to use the same length field, for example:
class: structure
members:
- my_length: uint16
- my_uint_array:
field-type:
class: dynamic-array
length-field-type-name: my_length
element-field-type: uint8
- my_string_array:
field-type:
class: dynamic-array
length-field-type-name: my_length
element-field-type: string
The constructor of `barectf.StructureFieldType` calls
_set_dyn_array_ft_length_ft_member_names() which, for each member having
a dynamic array field type:
* Sets its `_length_ft_member_name` attribute to the name of the
structure field type member having its length field type.
* Sets its length field type's `_is_len` attribute to `True`.
I consider those as hacks, but considering the current constraints, it
makes parts of the (barectf) code easier to implement and maintain.
The C code generation approach is similar to the static array field
case. The `*-write-static-array-statements.j2` templates are renamed to
`*-write-array-statements.j2` and use the `length_src` variable as the
loop's length's value. `*-write-static-array-statements.j2` and the new
`*-write-dynamic-array-statements.j2` set `length_src` before including
`*-write-array-statements.j2`.
To make things easier, barectf now systematically generates alignment
statements if the alignment is greater than one. This could be optimized
again in the future, considering arrays this time. The
`_WriteOp.offset_in_byte` optimization still exists, although as soon as
it's not statically known, it's now `None` and
`serialize-write-bit-array-statements.j2` uses the safe, dynamic
`ctx->at % 8` expression. try_create_align_op() does this, more or less:
If `self._offset_in_byte` is not currently known and the requested
alignment is 8:
Set `self._offset_in_byte` to 0.
Else:
If we're currently within an array operation:
Reset `self._offset_in_byte`.
Else:
If `self._offset_in_byte` is currently known:
Align `self._offset_in_byte` with the requested alignment.
This ensures that each array field's element is aligned before being
written.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
19 files changed:
This page took 0.026612 seconds and 4 git commands to generate.