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