blob: 64233a38099497df74b17c9acd6044787f98adee [file] [log] [blame]
julhal01734dbad2020-12-21 10:27:41 +00001/*
2 * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef TLV_H
8#define TLV_H
9
10#include <stddef.h>
11#include <stdint.h>
12#include <stdbool.h>
13
14#ifdef __cplusplus
15extern "C" {
16#endif
17
18/*
19 * TLV provides a general purpose serialization for variable length
20 * objects, identified by a tag. A serialized TLV record has the following
21 * structure:
22 * | Tag | Length | Value |
23 * | (16-bits) | (16-bits) | (Length bytes) |
24 *
25 * No assumptions are made about the alignment of the start of a serialized record.
26 * Tag and Length fields are encoded in Big Endian byte order.
27 */
28#define TLV_TAG_WIDTH (2)
29#define TLV_LENGTH_WIDTH (2)
30#define TLV_HDR_LEN (TLV_TAG_WIDTH + TLV_LENGTH_WIDTH)
31#define TLV_TAG_OFFSET (0)
32#define TLV_LENGTH_OFFSET TLV_TAG_WIDTH
33#define TLV_VALUE_OFFSET TLV_HDR_LEN
34
35/*
36 * TLV record structure provides access to a serialized record.
37 */
38struct tlv_record
39{
40 uint16_t tag;
41 uint16_t length;
42 const uint8_t *value;
43};
44
45/*
46 * Iterator state for interating over serialized tlv records when encoding.
47 */
48struct tlv_iterator
49{
50 uint8_t *pos;
51 uint8_t *limit;
52 uint16_t prev_tag;
53};
54
55/*
56 * Iterator state for interating over serialized tlv records when decoding.
57 */
58struct tlv_const_iterator
59{
60 const uint8_t *pos;
61 const uint8_t *limit;
62};
63
64/*
65 * Return the space required in bytes for a serialized record with the
66 * specified value length.
67 */
68size_t tlv_required_space(size_t length);
69
70/*
71 * Initializes a TLV iterator to the start of a buffer. Used when writing
72 * records to a buffer when encoding.
73 */
74void tlv_iterator_begin(struct tlv_iterator *iter, uint8_t *buf, size_t bufsize);
75
76/*
77 * Initializes a TLV const iterator to the start of a buffer. Used when reading
78 * records from a buffer when decoding.
79 */
80void tlv_const_iterator_begin(struct tlv_const_iterator *iter, const uint8_t *buf, size_t bufsize);
81
82/*
83 * Encode a serialized record and advance the iterator, ready to encode the next
84 * record. Returns true if successful, false if insufficient room.
85 */
86bool tlv_encode(struct tlv_iterator *iter, const struct tlv_record *input);
87
88/*
89 * Decode a serialized record and advance the iterator, ready to decode the next
90 * record (if there is one). Returns true if successful, false there is no serialized record
91 * or an incomplete one.
92 */
93bool tlv_decode(struct tlv_const_iterator *iter, struct tlv_record *output);
94
95/*
96 * Advances the iterator until a record with the specified tag is found. If
97 * it's found, it's decoded and the iterator is advanced to the next position.
98 * This can be used when decoding an expected set of records, encoded in ascending
99 * tag order. Any unrecognised records are skipped over. This is the typical
100 * decoding pattern.
101 */
102bool tlv_find_decode(struct tlv_const_iterator *iter, uint16_t tag, struct tlv_record *output);
103
104#ifdef __cplusplus
105}
106#endif
107
108#endif /* TLV_H */