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