1 /* 2 * This file has been copied from the zcbor library. 3 * Commit zcbor 0.8.1 4 */ 5 6 /* 7 * Copyright (c) 2020 Nordic Semiconductor ASA 8 * 9 * SPDX-License-Identifier: Apache-2.0 10 */ 11 12 #ifndef ZCBOR_ENCODE_H__ 13 #define ZCBOR_ENCODE_H__ 14 15 #include <stdint.h> 16 #include <stdbool.h> 17 #include <stddef.h> 18 #include "zcbor_common.h" 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 25 /** The zcbor_encode library provides functions for encoding CBOR data elements. 26 * 27 * See The README for an introduction to CBOR, including the meaning of pint, 28 * nint, bstr etc. 29 */ 30 31 32 /** See @ref zcbor_new_state() */ 33 void zcbor_new_encode_state(zcbor_state_t *state_array, size_t n_states, 34 uint8_t *payload, size_t payload_len, size_t elem_count); 35 36 /** Convenience macro for declaring and initializing an encoding state with backups. 37 * 38 * This gives you a state variable named @p name. The variable functions like 39 * a pointer. 40 * 41 * @param[in] name The name of the new state variable. 42 * @param[in] num_backups The number of backup slots to keep in the state. 43 * @param[in] payload The payload to work on. 44 * @param[in] payload_size The size (in bytes) of @p payload. 45 * @param[in] elem_count The starting elem_count (typically 1). 46 */ 47 #define ZCBOR_STATE_E(name, num_backups, payload, payload_size, elem_count) \ 48 zcbor_state_t name[((num_backups) + 2)]; \ 49 do { \ 50 zcbor_new_encode_state(name, ZCBOR_ARRAY_SIZE(name), payload, payload_size, elem_count); \ 51 } while(0) 52 53 54 /** The following applies to all _put and _encode functions listed directly below. 55 * 56 * The difference between _put and _encode is only in the argument type, 57 * but when a @ref zcbor_encoder_t is needed, such as for @ref zcbor_multi_encode, 58 * the _encode variant must be used. 59 * 60 * @param[inout] state The current state of the encoding. 61 * @param[in] input The value to encode. 62 * 63 * @retval true Everything is ok. 64 * @retval false If the payload is exhausted. Or an unexpected error happened. 65 * Use zcbor_peek_error() to see the error code. 66 */ 67 bool zcbor_int32_put(zcbor_state_t *state, int32_t input); /* pint/nint */ 68 bool zcbor_int64_put(zcbor_state_t *state, int64_t input); /* pint/nint */ 69 bool zcbor_uint32_put(zcbor_state_t *state, uint32_t input); /* pint */ 70 bool zcbor_uint64_put(zcbor_state_t *state, uint64_t input); /* pint */ 71 bool zcbor_size_put(zcbor_state_t *state, size_t input); /* pint */ 72 bool zcbor_tag_put(zcbor_state_t *state, uint32_t tag); /* CBOR tag */ 73 bool zcbor_simple_put(zcbor_state_t *state, uint8_t input); /* CBOR simple value */ 74 bool zcbor_bool_put(zcbor_state_t *state, bool input); /* boolean CBOR simple value */ 75 bool zcbor_nil_put(zcbor_state_t *state, const void *unused); /* 'nil' CBOR simple value */ 76 bool zcbor_undefined_put(zcbor_state_t *state, const void *unused); /* 'undefined' CBOR simple value */ 77 bool zcbor_float16_put(zcbor_state_t *state, float input); /* IEEE754 float16 */ 78 bool zcbor_float16_bytes_put(zcbor_state_t *state, uint16_t input); /* IEEE754 float16 raw bytes */ 79 bool zcbor_float32_put(zcbor_state_t *state, float input); /* IEEE754 float32 */ 80 bool zcbor_float64_put(zcbor_state_t *state, double input); /* IEEE754 float64 */ 81 82 bool zcbor_int32_encode(zcbor_state_t *state, const int32_t *input); /* pint/nint */ 83 bool zcbor_int64_encode(zcbor_state_t *state, const int64_t *input); /* pint/nint */ 84 bool zcbor_uint32_encode(zcbor_state_t *state, const uint32_t *input); /* pint */ 85 bool zcbor_uint64_encode(zcbor_state_t *state, const uint64_t *input); /* pint */ 86 bool zcbor_size_encode(zcbor_state_t *state, const size_t *input); /* pint */ 87 bool zcbor_int_encode(zcbor_state_t *state, const void *input_int, size_t int_size); 88 bool zcbor_uint_encode(zcbor_state_t *state, const void *input_uint, size_t uint_size); 89 bool zcbor_bstr_encode(zcbor_state_t *state, const struct zcbor_string *input); /* bstr */ 90 bool zcbor_tstr_encode(zcbor_state_t *state, const struct zcbor_string *input); /* tstr */ 91 bool zcbor_tag_encode(zcbor_state_t *state, uint32_t *tag); /* CBOR tag. Note that zcbor_tag_encode()'s argument was changed to be a pointer. See also zcbor_tag_put(). */ 92 bool zcbor_simple_encode(zcbor_state_t *state, uint8_t *input); /* CBOR simple value */ 93 bool zcbor_bool_encode(zcbor_state_t *state, const bool *input); /* boolean CBOR simple value */ 94 bool zcbor_float16_encode(zcbor_state_t *state, const float *input); /* IEEE754 float16 */ 95 bool zcbor_float16_bytes_encode(zcbor_state_t *state, const uint16_t *input); /* IEEE754 float16 raw bytes */ 96 bool zcbor_float32_encode(zcbor_state_t *state, const float *input); /* IEEE754 float32 */ 97 bool zcbor_float64_encode(zcbor_state_t *state, const double *input); /* IEEE754 float64 */ 98 99 /** Encode a list/map header. 100 * 101 * The contents of the list/map can be encoded via subsequent function calls. 102 * If ZCBOR_CANONICAL is defined, a state backup is created to keep track of the 103 * element count. 104 * When all members have been encoded, call @ref zcbor_list_end_encode / 105 * @ref zcbor_map_end_encode to close the list/map. 106 * 107 * @param[inout] state The current state of the encoding. 108 * @param[in] max_num The maximum number of members in the list/map. 109 * This serves as a size hint for the header. Must be 110 * equal to the max_num provided to the corresponding 111 * @ref zcbor_list_end_encode / @ref zcbor_map_end_encode 112 * call. 113 * Only used when ZCBOR_CANONICAL is defined. 114 */ 115 bool zcbor_list_start_encode(zcbor_state_t *state, size_t max_num); 116 bool zcbor_map_start_encode(zcbor_state_t *state, size_t max_num); 117 118 /** Encode the end of a list/map. Do some checks and deallocate backup. 119 * 120 * - Default: Adds a list terminator (0xFF) to mark the 121 * end of the list/map. 122 * - If ZCBOR_CANONICAL is defined: Instead encodes the number of members in 123 * the list/map header. If the header ends up a different size than expected, 124 * the list/map contents are moved using memmove(). 125 * 126 * Use @ref zcbor_list_map_end_force_encode to forcibly consume the backup if 127 * something has gone wrong. 128 * 129 * @param[inout] state The current state of the encoding. 130 * @param[in] max_num The maximum number of members in the list/map. Must be 131 * equal to the max_num provided to the corresponding 132 * @ref zcbor_list_start_encode call. 133 * Only used when ZCBOR_CANONICAL is defined. 134 */ 135 bool zcbor_list_end_encode(zcbor_state_t *state, size_t max_num); 136 bool zcbor_map_end_encode(zcbor_state_t *state, size_t max_num); 137 bool zcbor_list_map_end_force_encode(zcbor_state_t *state); 138 139 /** Encode 0 or more elements with the same type and constraints. 140 * 141 * The encoded values are taken from the @p input array. 142 * 143 * The following is an example of encoding a list containing 3 INTS followed by 144 * 0 to 2 bstrs: 145 * 146 * @code{c} 147 * uint32_t ints[3] = <initialize>; 148 * struct zcbor_string bstrs[2] = <initialize>; 149 * bool res; 150 * 151 * res = zcbor_list_start_encode(state, 5); 152 * res = res && zcbor_multi_encode(3, zcbor_uint32_encode, state, 153 * ints, sizeof(uint32_t)); 154 * res = res && zcbor_multi_encode(2, zcbor_bstr_encode, state, 155 * bstrs, sizeof(struct zcbor_string)); 156 * res = res && zcbor_list_end_encode(state, 5); 157 * // check res 158 * @endcode 159 * 160 * The @ref zcbor_encoder_t type is designed to be compatible with all single- 161 * value encoder functions in this library, e.g. @ref zcbor_uint32_encode, 162 * @ref zcbor_tstr_put, @ref zcbor_nil_put, etc. For _put() functions, 163 * @p input will be used as a value instead of an array/pointer, so 164 * @p input_len will determine how much the value changes for each call. 165 * To encode the same value multiple times, use a @p input_len of 0. 166 * This function can also be used with custom decoder functions, such as those 167 * generated by the zcbor.py script, which for example encodes larger chunks of 168 * the data at once. 169 * 170 * @param[in] num_encode The actual number of elements. 171 * @param[in] encoder The encoder function to call under the hood. This 172 * function will be called with the provided arguments 173 * repeatedly until the function fails (returns false) 174 * or until it has been called @p max_encode times. 175 * The input pointer is moved @p input_len bytes for 176 * each call to @p encoder, i.e. @p input refers to an 177 * array of input variables. 178 * @param[in] input Source of the encoded values. Must be an array of 179 * at least @p max_encode elements. 180 * @param[in] input_len The length of the input variables. Must be the 181 * length of the individual elements in input. 182 * 183 * @retval true If at least @p min_encode variables were correctly encoded. 184 * @retval false If @p encoder failed before having encoded @p min_encode 185 * values. 186 */ 187 bool zcbor_multi_encode(size_t num_encode, zcbor_encoder_t encoder, 188 zcbor_state_t *state, const void *input, size_t result_len); 189 190 /** Works like @ref zcbor_multi_encode 191 * 192 * But first checks that @p num_encode is between @p min_encode and @p max_encode. 193 */ 194 bool zcbor_multi_encode_minmax(size_t min_encode, size_t max_encode, 195 const size_t *num_encode, zcbor_encoder_t encoder, 196 zcbor_state_t *state, const void *input, size_t input_len); 197 198 199 /* Supplementary string (bstr/tstr) encoding functions: */ 200 201 /** Encode a char/uint8_t pointer as a bstr/tstr. 202 * 203 * @param[inout] state The current state of the encoding. 204 * @param[in] str The value to encode. A pointer to the string/array. 205 * _term() uses strnlen(), so @p str must be null-terminated. 206 * _lit() uses sizeof()-1, so @p str must be a (null-terminated) string literal. 207 * _arr() uses sizeof(), so @p str must be a uint8_t array (not null-terminated). 208 * @param[in] len (if present) The length of the string pointed to by @p str 209 * @param[in] maxlen (if present) The maximum length of the string pointed to by @p str. 210 * This value is passed to strnlen. 211 */ 212 bool zcbor_bstr_encode_ptr(zcbor_state_t *state, const char *str, size_t len); 213 bool zcbor_tstr_encode_ptr(zcbor_state_t *state, const char *str, size_t len); 214 bool zcbor_bstr_put_term(zcbor_state_t *state, char const *str, size_t maxlen); 215 bool zcbor_tstr_put_term(zcbor_state_t *state, char const *str, size_t maxlen); 216 #define zcbor_bstr_put_lit(state, str) zcbor_bstr_encode_ptr(state, str, sizeof(str) - 1) 217 #define zcbor_tstr_put_lit(state, str) zcbor_tstr_encode_ptr(state, str, sizeof(str) - 1) 218 #define zcbor_bstr_put_arr(state, str) zcbor_bstr_encode_ptr(state, str, sizeof(str)) 219 #define zcbor_tstr_put_arr(state, str) zcbor_tstr_encode_ptr(state, str, sizeof(str)) 220 221 /** Encode a bstr header. 222 * 223 * The rest of the string can be encoded as CBOR. 224 * A state backup is created to keep track of the element count. 225 * Call @ref zcbor_bstr_end_encode when done encoding the contents of the bstr. 226 * 227 * @param[inout] state The current state of the encoding. 228 * 229 * @retval true Header encoded correctly 230 * @retval false Header encoded incorrectly, or backup failed. 231 */ 232 bool zcbor_bstr_start_encode(zcbor_state_t *state); 233 234 /** Finalize encoding a CBOR-encoded bstr. 235 * 236 * This writes the final size of the bstr to the header. 237 * Restore element count from backup. 238 */ 239 bool zcbor_bstr_end_encode(zcbor_state_t *state, struct zcbor_string *result); 240 241 #ifdef __cplusplus 242 } 243 #endif 244 245 #endif /* ZCBOR_ENCODE_H__ */ 246