dmi_fields_decode_into

Synopsis

#include <opendmi/field.h>

bool dmi_fields_decode_into(
        dmi_decoder_t     *decoder,
        const dmi_field_t *fields,
        size_t             length,
        void              *info);

bool dmi_fields_encode_from(
        dmi_encoder_t     *encoder,
        const dmi_field_t *fields,
        size_t             length,
        const void        *info);

Description

The dmi_fields_decode_into function reads a part of a structure according to a list of fields, the way dmi_fields_decode reads a whole structure, for the decoding handlers which read the rest of the structure themselves: e.g. a record or a descriptor whose layout depends on a type the structure gives, whose length the structure gives too.

The fields, declared with DMI_FIELD and its kin, are read from the next length bytes of the structure, from the position of decoder, into info, a structure of the type the fields name. The decoder is then moved past the length bytes, whatever the fields have left unread, so that the bytes a part holds beyond the fields it is known to hold are stepped over.

The bytes of the part are the data the groups of the fields may end before, see DMI_FIELD_GROUP. A part which ends at the beginning of a group, or in the middle of it, leaves the fields it is too short for unset, along with the present members of their groups, and the structure is marked neither as partial nor as incomplete, since it is the part which is short rather than the structure. The fields before the first group are required.

The dmi_fields_encode_from function undoes it, for the encoding handlers which write the rest of the structure themselves, the way dmi_fields_encode writes a whole structure: the fields are written from info into the next length bytes of the structure, and the bytes of the part the fields do not describe are written the way the encoder writes the bytes the model does not hold, i.e. the ones of the source data in the preserve mode, and zeros in the canonical one. Writing stops at the first group the part does not hold, and, in the preserve mode, where the source data of the part ends.

Parameters

decoder

Decoder of the structure, see dmi_decoder_initialize, positioned at the part.

encoder

Encoder of the structure, see dmi_encoder_initialize, positioned at the part.

fields

Fields of the part, terminated by an empty field.

length

Number of the bytes of the part.

info

Structure the fields are read into, or written from.

Return value

dmi_fields_decode_into returns true if the part has been decoded, and false if the structure holds fewer than length bytes from the position of the decoder, if the part is too short for the required fields, or on the errors below.

dmi_fields_encode_from returns true if the part has been encoded, and false on the errors below.

Errors

DMI_ERROR_ARGUMENT_NULL

Decoder or encoder, fields or structure is nullptr.

DMI_ERROR_ARGUMENT_INVALID

A field declares a number wider than the widest one the engine reads and writes, which is eight bytes.

DMI_ERROR_STATE_INVALID

A field cannot be written, or the fields are longer than the part (dmi_fields_encode_from).

DMI_ERROR_OUT_OF_MEMORY

Elements of an array cannot be allocated, or buffers of the encoder cannot grow.

Example

The v2 descriptor of a USB network interface, whose length follows the device type and counts it along with itself:

static const dmi_field_t usb_v2_fields[] = {
    DMI_FIELD(dmi_mgmt_nhi_usb_v2_t, vendor_id,  dmi_word_t),
    DMI_FIELD(dmi_mgmt_nhi_usb_v2_t, product_id, dmi_word_t),
    DMI_FIELD_STRING(dmi_mgmt_nhi_usb_v2_t, serial_number),
    DMI_FIELD_BINARY(dmi_mgmt_nhi_usb_v2_t, mac_address, 6),

    // Device characteristics are present since DSP0270 1.3
    DMI_FIELD_GROUP(),
    DMI_FIELD(dmi_mgmt_nhi_usb_v2_t, characteristics,   dmi_word_t),
    DMI_FIELD(dmi_mgmt_nhi_usb_v2_t, credential_bootstrapping_handle, dmi_word_t),
    {}
};

dmi_byte_t length = 0;

if (dmi_decoder_get(decoder, dmi_byte_t, &length) and (length >= 2))
    dmi_fields_decode_into(decoder, usb_v2_fields, length - 2, &nhi->usb_v2);