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