blob: 64233a38099497df74b17c9acd6044787f98adee [file] [log] [blame]
/*
* Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef TLV_H
#define TLV_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* TLV provides a general purpose serialization for variable length
* objects, identified by a tag. A serialized TLV record has the following
* structure:
* | Tag | Length | Value |
* | (16-bits) | (16-bits) | (Length bytes) |
*
* No assumptions are made about the alignment of the start of a serialized record.
* Tag and Length fields are encoded in Big Endian byte order.
*/
#define TLV_TAG_WIDTH (2)
#define TLV_LENGTH_WIDTH (2)
#define TLV_HDR_LEN (TLV_TAG_WIDTH + TLV_LENGTH_WIDTH)
#define TLV_TAG_OFFSET (0)
#define TLV_LENGTH_OFFSET TLV_TAG_WIDTH
#define TLV_VALUE_OFFSET TLV_HDR_LEN
/*
* TLV record structure provides access to a serialized record.
*/
struct tlv_record
{
uint16_t tag;
uint16_t length;
const uint8_t *value;
};
/*
* Iterator state for interating over serialized tlv records when encoding.
*/
struct tlv_iterator
{
uint8_t *pos;
uint8_t *limit;
uint16_t prev_tag;
};
/*
* Iterator state for interating over serialized tlv records when decoding.
*/
struct tlv_const_iterator
{
const uint8_t *pos;
const uint8_t *limit;
};
/*
* Return the space required in bytes for a serialized record with the
* specified value length.
*/
size_t tlv_required_space(size_t length);
/*
* Initializes a TLV iterator to the start of a buffer. Used when writing
* records to a buffer when encoding.
*/
void tlv_iterator_begin(struct tlv_iterator *iter, uint8_t *buf, size_t bufsize);
/*
* Initializes a TLV const iterator to the start of a buffer. Used when reading
* records from a buffer when decoding.
*/
void tlv_const_iterator_begin(struct tlv_const_iterator *iter, const uint8_t *buf, size_t bufsize);
/*
* Encode a serialized record and advance the iterator, ready to encode the next
* record. Returns true if successful, false if insufficient room.
*/
bool tlv_encode(struct tlv_iterator *iter, const struct tlv_record *input);
/*
* Decode a serialized record and advance the iterator, ready to decode the next
* record (if there is one). Returns true if successful, false there is no serialized record
* or an incomplete one.
*/
bool tlv_decode(struct tlv_const_iterator *iter, struct tlv_record *output);
/*
* Advances the iterator until a record with the specified tag is found. If
* it's found, it's decoded and the iterator is advanced to the next position.
* This can be used when decoding an expected set of records, encoded in ascending
* tag order. Any unrecognised records are skipped over. This is the typical
* decoding pattern.
*/
bool tlv_find_decode(struct tlv_const_iterator *iter, uint16_t tag, struct tlv_record *output);
#ifdef __cplusplus
}
#endif
#endif /* TLV_H */