blob: 31fda52253dea86ad84a39a628fa1ce30f0e8073 [file] [log] [blame]
Michael Eckel5c531332020-03-02 01:35:30 +01001/*==============================================================================
2 Copyright (c) 2016-2018, The Linux Foundation.
3 Copyright (c) 2018-2020, Laurence Lundblade.
4 All rights reserved.
5
6Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =============================================================================*/
32
33
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#ifndef qcbor_encode_h
35#define qcbor_encode_h
Michael Eckel5c531332020-03-02 01:35:30 +010036
37
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080038#include "qcbor/qcbor_common.h"
39#include "qcbor/qcbor_private.h"
Michael Eckel5c531332020-03-02 01:35:30 +010040#include <stdbool.h>
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080041
Michael Eckel5c531332020-03-02 01:35:30 +010042
43#ifdef __cplusplus
44extern "C" {
Dave Thaler12b23752020-03-27 01:23:08 -070045#if 0
Michael Eckel5c531332020-03-02 01:35:30 +010046} // Keep editor indention formatting happy
47#endif
48#endif
49
Michael Eckel5c531332020-03-02 01:35:30 +010050
51/**
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080052 @file qcbor_encode.h
Michael Eckel5c531332020-03-02 01:35:30 +010053
54 Q C B O R E n c o d e / D e c o d e
55
56 This implements CBOR -- Concise Binary Object Representation as
57 defined in [RFC 7049] (https://tools.ietf.org/html/rfc7049). More
58 info is at http://cbor.io. This is a near-complete implementation of
59 the specification. Limitations are listed further down.
60
61 CBOR is intentionally designed to be translatable to JSON, but not
62 all CBOR can convert to JSON. See RFC 7049 for more info on how to
63 construct CBOR that is the most JSON friendly.
64
65 The memory model for encoding and decoding is that encoded CBOR must
66 be in a contiguous buffer in memory. During encoding the caller must
67 supply an output buffer and if the encoding would go off the end of
68 the buffer an error is returned. During decoding the caller supplies
69 the encoded CBOR in a contiguous buffer and the decoder returns
70 pointers and lengths into that buffer for strings.
71
72 This implementation does not require malloc. All data structures
73 passed in/out of the APIs can fit on the stack.
74
75 Decoding of indefinite-length strings is a special case that requires
76 a "string allocator" to allocate memory into which the segments of
77 the string are coalesced. Without this, decoding will error out if an
78 indefinite-length string is encountered (indefinite-length maps and
79 arrays do not require the string allocator). A simple string
80 allocator called MemPool is built-in and will work if supplied with a
81 block of memory to allocate. The string allocator can optionally use
82 malloc() or some other custom scheme.
83
84 Here are some terms and definitions:
85
86 - "Item", "Data Item": An integer or string or such. The basic "thing" that
87 CBOR is about. An array is an item itself that contains some items.
88
89 - "Array": An ordered sequence of items, the same as JSON.
90
91 - "Map": A collection of label/value pairs. Each pair is a data
92 item. A JSON "object" is the same as a CBOR "map".
93
94 - "Label": The data item in a pair in a map that names or identifies
95 the pair, not the value. This implementation refers to it as a
96 "label". JSON refers to it as the "name". The CBOR RFC refers to it
97 this as a "key". This implementation chooses label instead because
98 key is too easily confused with a cryptographic key. The COSE
99 standard, which uses CBOR, has also chosen to use the term "label"
100 rather than "key" for this same reason.
101
102 - "Key": See "Label" above.
103
104 - "Tag": Optional integer that can be added before each data item
105 usually to indicate it is new or more specific data type. For
106 example, a tag can indicate an integer is a date, or that a map is to
107 be considered a type (analogous to a typedef in C).
108
109 - "Initial Byte": The first byte of an encoded item. Encoding and
110 decoding of this byte is taken care of by the implementation.
111
112 - "Additional Info": In addition to the major type, all data items
113 have some other info. This is usually the length of the data but can
114 be several other things. Encoding and decoding of this is taken care
115 of by the implementation.
116
117 CBOR has two mechanisms for tagging and labeling the data values like
118 integers and strings. For example, an integer that represents
119 someone's birthday in epoch seconds since Jan 1, 1970 could be
120 encoded like this:
121
122 - First it is CBOR_MAJOR_TYPE_POSITIVE_INT (@ref QCBOR_TYPE_INT64),
123 the primitive positive integer.
124
125 - Next it has a "tag" @ref CBOR_TAG_DATE_EPOCH indicating the integer
126 represents a date in the form of the number of seconds since Jan 1,
127 1970.
128
129 - Last it has a string "label" like "BirthDate" indicating the
130 meaning of the data.
131
132 The encoded binary looks like this:
133
134 a1 # Map of 1 item
135 69 # Indicates text string of 9 bytes
136 426972746844617465 # The text "BirthDate"
137 c1 # Tags next integer as epoch date
138 1a # Indicates a 4-byte integer
139 580d4172 # unsigned integer date 1477263730
140
141 Implementors using this API will primarily work with
142 labels. Generally, tags are only needed for making up new data
143 types. This implementation covers most of the data types defined in
144 the RFC using tags. It also, allows for the use of custom tags if
145 necessary.
146
147 This implementation explicitly supports labels that are text strings
148 and integers. Text strings translate nicely into JSON objects and are
149 very readable. Integer labels are much less readable but can be very
150 compact. If they are in the range of 0 to 23, they take up only one
151 byte.
152
153 CBOR allows a label to be any type of data including an array or a
154 map. It is possible to use this API to construct and parse such
155 labels, but it is not explicitly supported.
156
157 A common encoding usage mode is to invoke the encoding twice. First
158 with no output buffer to compute the length of the needed output
159 buffer. Then the correct sized output buffer is allocated. Last the
160 encoder is invoked again, this time with the output buffer.
161
162 The double invocation is not required if the maximum output buffer
163 size can be predicted. This is usually possible for simple CBOR
164 structures. If the double invocation is implemented, it can be in a
165 loop or function as in the example code so that the code doesn't have
166 to actually be written twice, saving code size.
167
168 If a buffer too small to hold the encoded output is given, the error
169 @ref QCBOR_ERR_BUFFER_TOO_SMALL will be returned. Data will never be
170 written off the end of the output buffer no matter which functions
171 here are called or what parameters are passed to them.
172
173 The encoding error handling is simple. The only possible errors are
174 trying to encode structures that are too large or too complex. There
175 are no internal malloc calls so there will be no failures for out of
176 memory. The error state is tracked internally, so there is no need
177 to check for errors when encoding. Only the return code from
178 QCBOREncode_Finish() need be checked as once an error happens, the
179 encoder goes into an error state and calls to it to add more data
180 will do nothing. An error check is not needed after every data item
181 is added.
182
183 Encoding generally proceeds by calling QCBOREncode_Init(), calling
184 lots of @c QCBOREncode_AddXxx() functions and calling
185 QCBOREncode_Finish(). There are many @c QCBOREncode_AddXxx()
186 functions for various data types. The input buffers need only to be
187 valid during the @c QCBOREncode_AddXxx() calls as the data is copied
188 into the output buffer.
189
190 There are three `Add` functions for each data type. The first / main
191 one for the type is for adding the data item to an array. The second
192 one's name ends in `ToMap`, is used for adding data items to maps and
193 takes a string argument that is its label in the map. The third one
194 ends in `ToMapN`, is also used for adding data items to maps, and
195 takes an integer argument that is its label in the map.
196
197 The simplest aggregate type is an array, which is a simple ordered
198 set of items without labels the same as JSON arrays. Call
199 QCBOREncode_OpenArray() to open a new array, then various @c
200 QCBOREncode_AddXxx() functions to put items in the array and then
201 QCBOREncode_CloseArray(). Nesting to the limit @ref
202 QCBOR_MAX_ARRAY_NESTING is allowed. All opens must be matched by
203 closes or an encoding error will be returned.
204
205 The other aggregate type is a map which does use labels. The `Add`
206 functions that end in `ToMap` and `ToMapN` are convenient ways to add
207 labeled data items to a map. You can also call any type of `Add`
208 function once to add a label of any time and then call any type of
209 `Add` again to add its value.
210
211 Note that when you nest arrays or maps in a map, the nested array or
212 map has a label.
213
214 @anchor Tags-Overview
215 Any CBOR data item can be tagged to add semantics, define a new data
216 type or such. Some tags are fully standardized and some are just
217 registered. Others are not registered and used in a proprietary way.
218
219 Encoding and decoding of many of the registered tags is fully
220 implemented by QCBOR. It is also possible to encode and decode tags
221 that are not directly supported. For many use cases the built-in tag
222 support should be adequate.
223
224 For example, the registered epoch date tag is supported in encoding
225 by QCBOREncode_AddDateEpoch() and in decoding by @ref
226 QCBOR_TYPE_DATE_EPOCH and the @c epochDate member of @ref
227 QCBORItem. This is typical of the built-in tag support. There is an
228 API to encode data for it and a @c QCBOR_TYPE_XXX when it is decoded.
229
230 Tags are registered in the [IANA CBOR Tags Registry]
231 (https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml). There
232 are roughly three options to create a new tag. First, a public
233 specification can be created and the new tag registered with IANA.
234 This is the most formal. Second, the new tag can be registered with
235 IANA with just a short description rather than a full specification.
236 These tags must be greater than 256. Third, a tag can be used without
237 any IANA registration, though the registry should be checked to see
238 that the new value doesn't collide with one that is registered. The
239 value of these tags must be 256 or larger.
240
241 The encoding side of tags not built-in is handled by
242 QCBOREncode_AddTag() and is relatively simple. Tag decoding is more
243 complex and mainly handled by QCBORDecode_GetNext(). Decoding of the
244 structure of tagged data not built-in (if there is any) has to be
245 implemented by the caller.
246
247 Summary Limits of this implementation:
248 - The entire encoded CBOR must fit into contiguous memory.
249 - Max size of encoded / decoded CBOR data is @c UINT32_MAX (4GB).
250 - Max array / map nesting level when encoding / decoding is
251 @ref QCBOR_MAX_ARRAY_NESTING (this is typically 15).
252 - Max items in an array or map when encoding / decoding is
253 @ref QCBOR_MAX_ITEMS_IN_ARRAY (typically 65,536).
254 - Does not directly support labels in maps other than text strings & integers.
255 - Does not directly support integer labels greater than @c INT64_MAX.
256 - Epoch dates limited to @c INT64_MAX (+/- 292 billion years).
257 - Exponents for bigfloats and decimal integers are limited to @c INT64_MAX.
258 - Tags on labels are ignored during decoding.
259 - There is no duplicate detection of map labels (but duplicates are passed on).
260 - Works only on 32- and 64-bit CPUs (modifications could make it work
261 on 16-bit CPUs).
262
263 The public interface uses @c size_t for all lengths. Internally the
264 implementation uses 32-bit lengths by design to use less memory and
265 fit structures on the stack. This limits the encoded CBOR it can work
266 with to size @c UINT32_MAX (4GB) which should be enough.
267
268 This implementation assumes two's compliment integer machines. @c
269 <stdint.h> also requires this. It is possible to modify this
270 implementation for another integer representation, but all modern
271 machines seem to be two's compliment.
272
273 */
274
275
Michael Eckel5c531332020-03-02 01:35:30 +0100276/*
277 The size of the buffer to be passed to QCBOREncode_EncodeHead(). It is one
278 byte larger than sizeof(uint64_t) + 1, the actual maximum size of the
279 head of a CBOR data item. because QCBOREncode_EncodeHead() needs
280 one extra byte to work.
281 */
282#define QCBOR_HEAD_BUFFER_SIZE (sizeof(uint64_t) + 2)
283
Michael Eckel5c531332020-03-02 01:35:30 +0100284
285
286/**
287 QCBOREncodeContext is the data type that holds context for all the
288 encoding functions. It is less than 200 bytes, so it can go on the
289 stack. The contents are opaque, and the caller should not access
290 internal members. A context may be re used serially as long as it is
291 re initialized.
292 */
293typedef struct _QCBOREncodeContext QCBOREncodeContext;
294
295
296/**
297 Initialize the encoder to prepare to encode some CBOR.
298
299 @param[in,out] pCtx The encoder context to initialize.
300 @param[in] Storage The buffer into which this encoded result
301 will be placed.
302
303 Call this once at the start of an encoding of a CBOR structure. Then
304 call the various @c QCBOREncode_AddXxx() functions to add the data
305 items. Then call QCBOREncode_Finish().
306
307 The maximum output buffer is @c UINT32_MAX (4GB). This is not a
308 practical limit in any way and reduces the memory needed by the
309 implementation. The error @ref QCBOR_ERR_BUFFER_TOO_LARGE will be
310 returned by QCBOREncode_Finish() if a larger buffer length is passed
311 in.
312
313 If this is called with @c Storage.ptr as @c NULL and @c Storage.len a
314 large value like @c UINT32_MAX, all the QCBOREncode_AddXxx()
315 functions and QCBOREncode_Finish() can still be called. No data will
316 be encoded, but the length of what would be encoded will be
317 calculated. The length of the encoded structure will be handed back
318 in the call to QCBOREncode_Finish(). You can then allocate a buffer
319 of that size and call all the encoding again, this time to fill in
320 the buffer.
321
322 A @ref QCBOREncodeContext can be reused over and over as long as
323 QCBOREncode_Init() is called.
324 */
325void QCBOREncode_Init(QCBOREncodeContext *pCtx, UsefulBuf Storage);
326
327
328/**
329 @brief Add a signed 64-bit integer to the encoded output.
330
331 @param[in] pCtx The encoding context to add the integer to.
332 @param[in] nNum The integer to add.
333
334 The integer will be encoded and added to the CBOR output.
335
336 This function figures out the size and the sign and encodes in the
337 correct minimal CBOR. Specifically, it will select CBOR major type 0
338 or 1 based on sign and will encode to 1, 2, 4 or 8 bytes depending on
339 the value of the integer. Values less than 24 effectively encode to
340 one byte because they are encoded in with the CBOR major type. This
341 is a neat and efficient characteristic of CBOR that can be taken
342 advantage of when designing CBOR-based protocols. If integers like
343 tags can be kept between -23 and 23 they will be encoded in one byte
344 including the major type.
345
346 If you pass a smaller int, say an @c int16_t or a small value, say
347 100, the encoding will still be CBOR's most compact that can
348 represent the value. For example, CBOR always encodes the value 0 as
349 one byte, 0x00. The representation as 0x00 includes identification of
350 the type as an integer too as the major type for an integer is 0. See
351 [RFC 7049] (https://tools.ietf.org/html/rfc7049) Appendix A for more
352 examples of CBOR encoding. This compact encoding is also canonical
353 CBOR as per section 3.9 in RFC 7049.
354
355 There are no functions to add @c int16_t or @c int32_t because they
356 are not necessary because this always encodes to the smallest number
357 of bytes based on the value (If this code is running on a 32-bit
358 machine having a way to add 32-bit integers would reduce code size
359 some).
360
361 If the encoding context is in an error state, this will do
362 nothing. If an error occurs when adding this integer, the internal
363 error flag will be set, and the error will be returned when
364 QCBOREncode_Finish() is called.
365
366 See also QCBOREncode_AddUInt64().
367 */
368void QCBOREncode_AddInt64(QCBOREncodeContext *pCtx, int64_t nNum);
369
370static void QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t uNum);
371
372static void QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t uNum);
373
374
375/**
376 @brief Add an unsigned 64-bit integer to the encoded output.
377
378 @param[in] pCtx The encoding context to add the integer to.
379 @param[in] uNum The integer to add.
380
381 The integer will be encoded and added to the CBOR output.
382
383 The only reason so use this function is for integers larger than @c
384 INT64_MAX and smaller than @c UINT64_MAX. Otherwise
385 QCBOREncode_AddInt64() will work fine.
386
387 Error handling is the same as for QCBOREncode_AddInt64().
388 */
389void QCBOREncode_AddUInt64(QCBOREncodeContext *pCtx, uint64_t uNum);
390
391static void QCBOREncode_AddUInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t uNum);
392
393static void QCBOREncode_AddUInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, uint64_t uNum);
394
395
396/**
397 @brief Add a UTF-8 text string to the encoded output.
398
399 @param[in] pCtx The encoding context to add the text to.
400 @param[in] Text Pointer and length of text to add.
401
402 The text passed in must be unencoded UTF-8 according to [RFC 3629]
403 (https://tools.ietf.org/html/rfc3629). There is no NULL
404 termination. The text is added as CBOR major type 3.
405
406 If called with @c nBytesLen equal to 0, an empty string will be
407 added. When @c nBytesLen is 0, @c pBytes may be @c NULL.
408
409 Note that the restriction of the buffer length to a @c uint32_t is
410 entirely intentional as this encoder is not capable of encoding
411 lengths greater. This limit to 4GB for a text string should not be a
412 problem.
413
414 Error handling is the same as QCBOREncode_AddInt64().
415 */
416static void QCBOREncode_AddText(QCBOREncodeContext *pCtx, UsefulBufC Text);
417
418static void QCBOREncode_AddTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Text);
419
420static void QCBOREncode_AddTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Text);
421
422
423/**
424 @brief Add a UTF-8 text string to the encoded output.
425
426 @param[in] pCtx The encoding context to add the text to.
427 @param[in] szString Null-terminated text to add.
428
429 This works the same as QCBOREncode_AddText().
430 */
431static void QCBOREncode_AddSZString(QCBOREncodeContext *pCtx, const char *szString);
432
433static void QCBOREncode_AddSZStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szString);
434
435static void QCBOREncode_AddSZStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szString);
436
437
438/**
439 @brief Add a floating-point number to the encoded output.
440
441 @param[in] pCtx The encoding context to add the double to.
442 @param[in] dNum The double-precision number to add.
443
444 This outputs a floating-point number with CBOR major type 7.
445
446 This will selectively encode the double-precision floating-point
447 number as either double-precision, single-precision or
448 half-precision. It will always encode infinity, NaN and 0 has half
449 precision. If no precision will be lost in the conversion to
450 half-precision, then it will be converted and encoded. If not and no
451 precision will be lost in conversion to single-precision, then it
452 will be converted and encoded. If not, then no conversion is
453 performed, and it encoded as a double.
454
455 Half-precision floating-point numbers take up 2 bytes, half that of
456 single-precision, one quarter of double-precision
457
458 This automatically reduces the size of encoded messages a lot, maybe
459 even by four if most of values are 0, infinity or NaN.
460
461 On decode, these will always be returned as a double.
462
463 Error handling is the same as QCBOREncode_AddInt64().
464 */
465void QCBOREncode_AddDouble(QCBOREncodeContext *pCtx, double dNum);
466
467static void QCBOREncode_AddDoubleToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum);
468
469static void QCBOREncode_AddDoubleToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum);
470
471
472/**
473 @brief Add an optional tag.
474
475 @param[in] pCtx The encoding context to add the tag to.
476 @param[in] uTag The tag to add
477
478 This outputs a CBOR major type 6 item that tags the next data item
479 that is output usually to indicate it is some new data type.
480
481 For many of the common standard tags, a function to encode data using
482 it is provided and this is not needed. For example,
483 QCBOREncode_AddDateEpoch() already exists to output integers
484 representing dates with the right tag.
485
486 The tag is applied to the next data item added to the encoded
487 output. That data item that is to be tagged can be of any major CBOR
488 type. Any number of tags can be added to a data item by calling this
489 multiple times before the data item is added.
490
491 See @ref Tags-Overview for discussion of creating new non-standard
492 tags. See QCBORDecode_GetNext() for discussion of decoding custom
493 tags.
494*/
495void QCBOREncode_AddTag(QCBOREncodeContext *pCtx,uint64_t uTag);
496
497
498/**
499 @brief Add an epoch-based date.
500
501 @param[in] pCtx The encoding context to add the date to.
502 @param[in] date Number of seconds since 1970-01-01T00:00Z in UTC time.
503
504 As per RFC 7049 this is similar to UNIX/Linux/POSIX dates. This is
505 the most compact way to specify a date and time in CBOR. Note that
506 this is always UTC and does not include the time zone. Use
507 QCBOREncode_AddDateString() if you want to include the time zone.
508
509 The integer encoding rules apply here so the date will be encoded in
510 a minimal number of bytes. Until about the year 2106 these dates will
511 encode in 6 bytes -- one byte for the tag, one byte for the type and
512 4 bytes for the integer. After that it will encode to 10 bytes.
513
514 Negative values are supported for dates before 1970.
515
516 If you care about leap-seconds and that level of accuracy, make sure
517 the system you are running this code on does it correctly. This code
518 just takes the value passed in.
519
520 This implementation cannot encode fractional seconds using float or
521 double even though that is allowed by CBOR, but you can encode them
522 if you want to by calling QCBOREncode_AddDouble() and
523 QCBOREncode_AddTag().
524
525 Error handling is the same as QCBOREncode_AddInt64().
526 */
527static void QCBOREncode_AddDateEpoch(QCBOREncodeContext *pCtx, int64_t date);
528
529static void QCBOREncode_AddDateEpochToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t date);
530
531static void QCBOREncode_AddDateEpochToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t date);
532
533
534/**
535 @brief Add a byte string to the encoded output.
536
537 @param[in] pCtx The encoding context to add the bytes to.
538 @param[in] Bytes Pointer and length of the input data.
539
540 Simply adds the bytes to the encoded output as CBOR major type 2.
541
542 If called with @c Bytes.len equal to 0, an empty string will be
543 added. When @c Bytes.len is 0, @c Bytes.ptr may be @c NULL.
544
545 Error handling is the same as QCBOREncode_AddInt64().
546 */
547static void QCBOREncode_AddBytes(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
548
549static void QCBOREncode_AddBytesToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
550
551static void QCBOREncode_AddBytesToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
552
553
554
555/**
556 @brief Add a binary UUID to the encoded output.
557
558 @param[in] pCtx The encoding context to add the UUID to.
559 @param[in] Bytes Pointer and length of the binary UUID.
560
561 A binary UUID as defined in [RFC 4122]
562 (https://tools.ietf.org/html/rfc4122) is added to the output.
563
564 It is output as CBOR major type 2, a binary string, with tag @ref
565 CBOR_TAG_BIN_UUID indicating the binary string is a UUID.
566 */
567static void QCBOREncode_AddBinaryUUID(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
568
569static void QCBOREncode_AddBinaryUUIDToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
570
571static void QCBOREncode_AddBinaryUUIDToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
572
573
574/**
575 @brief Add a positive big number to the encoded output.
576
577 @param[in] pCtx The encoding context to add the big number to.
578 @param[in] Bytes Pointer and length of the big number.
579
580 Big numbers are integers larger than 64-bits. Their format is
581 described in [RFC 7049] (https://tools.ietf.org/html/rfc7049).
582
583 It is output as CBOR major type 2, a binary string, with tag @ref
584 CBOR_TAG_POS_BIGNUM indicating the binary string is a positive big
585 number.
586
587 Often big numbers are used to represent cryptographic keys, however,
588 COSE which defines representations for keys chose not to use this
589 particular type.
590 */
591static void QCBOREncode_AddPositiveBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
592
593static void QCBOREncode_AddPositiveBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
594
595static void QCBOREncode_AddPositiveBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
596
597
598/**
599 @brief Add a negative big number to the encoded output.
600
601 @param[in] pCtx The encoding context to add the big number to.
602 @param[in] Bytes Pointer and length of the big number.
603
604 Big numbers are integers larger than 64-bits. Their format is
605 described in [RFC 7049] (https://tools.ietf.org/html/rfc7049).
606
607 It is output as CBOR major type 2, a binary string, with tag @ref
608 CBOR_TAG_NEG_BIGNUM indicating the binary string is a negative big
609 number.
610
611 Often big numbers are used to represent cryptographic keys, however,
612 COSE which defines representations for keys chose not to use this
613 particular type.
614 */
615static void QCBOREncode_AddNegativeBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
616
617static void QCBOREncode_AddNegativeBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
618
619static void QCBOREncode_AddNegativeBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
620
621
622#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
623/**
624 @brief Add a decimal fraction to the encoded output.
625
626 @param[in] pCtx The encoding context to add the decimal fraction to.
627 @param[in] nMantissa The mantissa.
628 @param[in] nBase10Exponent The exponent.
629
630 The value is nMantissa * 10 ^ nBase10Exponent.
631
632 A decimal fraction is good for exact representation of some values
633 that can't be represented exactly with standard C (IEEE 754)
634 floating-point numbers. Much larger and much smaller numbers can
635 also be represented than floating-point because of the larger number
636 of bits in the exponent.
637
638 The decimal fraction is conveyed as two integers, a mantissa and a
639 base-10 scaling factor.
640
641 For example, 273.15 is represented by the two integers 27315 and -2.
642
643 The exponent and mantissa have the range from @c INT64_MIN to
644 @c INT64_MAX for both encoding and decoding (CBOR allows @c -UINT64_MAX
645 to @c UINT64_MAX, but this implementation doesn't support this range to
646 reduce code size and interface complexity a little).
647
648 CBOR Preferred encoding of the integers is used, thus they will be encoded
649 in the smallest number of bytes possible.
650
651 See also QCBOREncode_AddDecimalFractionBigNum() for a decimal
652 fraction with arbitrarily large precision and QCBOREncode_AddBigFloat().
653
654 There is no representation of positive or negative infinity or NaN
655 (Not a Number). Use QCBOREncode_AddDouble() to encode them.
656
657 See @ref expAndMantissa for decoded representation.
658 */
659static void QCBOREncode_AddDecimalFraction(QCBOREncodeContext *pCtx,
660 int64_t nMantissa,
661 int64_t nBase10Exponent);
662
663static void QCBOREncode_AddDecimalFractionToMap(QCBOREncodeContext *pCtx,
664 const char *szLabel,
665 int64_t nMantissa,
666 int64_t nBase10Exponent);
667
668static void QCBOREncode_AddDecimalFractionToMapN(QCBOREncodeContext *pCtx,
669 int64_t nLabel,
670 int64_t nMantissa,
671 int64_t nBase10Exponent);
672
673/**
674 @brief Add a decimal fraction with a big number mantissa to the encoded output.
675
676 @param[in] pCtx The encoding context to add the decimal fraction to.
677 @param[in] Mantissa The mantissa.
678 @param[in] bIsNegative false if mantissa is positive, true if negative.
679 @param[in] nBase10Exponent The exponent.
680
681 This is the same as QCBOREncode_AddDecimalFraction() except the
682 mantissa is a big number (See QCBOREncode_AddPositiveBignum())
683 allowing for arbitrarily large precision.
684
685 See @ref expAndMantissa for decoded representation.
686 */
687static void QCBOREncode_AddDecimalFractionBigNum(QCBOREncodeContext *pCtx,
688 UsefulBufC Mantissa,
689 bool bIsNegative,
690 int64_t nBase10Exponent);
691
692static void QCBOREncode_AddDecimalFractionBigNumToMap(QCBOREncodeContext *pCtx,
693 const char *szLabel,
694 UsefulBufC Mantissa,
695 bool bIsNegative,
696 int64_t nBase10Exponent);
697
698static void QCBOREncode_AddDecimalFractionBigNumToMapN(QCBOREncodeContext *pCtx,
699 int64_t nLabel,
700 UsefulBufC Mantissa,
701 bool bIsNegative,
702 int64_t nBase10Exponent);
703
704/**
705 @brief Add a big floating-point number to the encoded output.
706
707 @param[in] pCtx The encoding context to add the bigfloat to.
708 @param[in] nMantissa The mantissa.
709 @param[in] nBase2Exponent The exponent.
710
711 The value is nMantissa * 2 ^ nBase2Exponent.
712
713 "Bigfloats", as CBOR terms them, are similar to IEEE floating-point
714 numbers in having a mantissa and base-2 exponent, but they are not
715 supported by hardware or encoded the same. They explicitly use two
716 CBOR-encoded integers to convey the mantissa and exponent, each of which
717 can be 8, 16, 32 or 64 bits. With both the mantissa and exponent
718 64 bits they can express more precision and a larger range than an
719 IEEE double floating-point number. See
720 QCBOREncode_AddBigFloatBigNum() for even more precision.
721
722 For example, 1.5 would be represented by a mantissa of 3 and an
723 exponent of -1.
724
725 The exponent and mantissa have the range from @c INT64_MIN to
726 @c INT64_MAX for both encoding and decoding (CBOR allows @c -UINT64_MAX
727 to @c UINT64_MAX, but this implementation doesn't support this range to
728 reduce code size and interface complexity a little).
729
730 CBOR Preferred encoding of the integers is used, thus they will be encoded
731 in the smallest number of bytes possible.
732
733 This can also be used to represent floating-point numbers in
734 environments that don't support IEEE 754.
735
736 See @ref expAndMantissa for decoded representation.
737 */
738static void QCBOREncode_AddBigFloat(QCBOREncodeContext *pCtx,
739 int64_t nMantissa,
740 int64_t nBase2Exponent);
741
742static void QCBOREncode_AddBigFloatToMap(QCBOREncodeContext *pCtx,
743 const char *szLabel,
744 int64_t nMantissa,
745 int64_t nBase2Exponent);
746
747static void QCBOREncode_AddBigFloatToMapN(QCBOREncodeContext *pCtx,
748 int64_t nLabel,
749 int64_t nMantissa,
750 int64_t nBase2Exponent);
751
752
753/**
754 @brief Add a big floating-point number with a big number mantissa to
755 the encoded output.
756
757 @param[in] pCtx The encoding context to add the bigfloat to.
758 @param[in] Mantissa The mantissa.
759 @param[in] bIsNegative false if mantissa is positive, true if negative.
760 @param[in] nBase2Exponent The exponent.
761
762 This is the same as QCBOREncode_AddBigFloat() except the mantissa is
763 a big number (See QCBOREncode_AddPositiveBignum()) allowing for
764 arbitrary precision.
765
766 See @ref expAndMantissa for decoded representation.
767 */
768static void QCBOREncode_AddBigFloatBigNum(QCBOREncodeContext *pCtx,
769 UsefulBufC Mantissa,
770 bool bIsNegative,
771 int64_t nBase2Exponent);
772
773static void QCBOREncode_AddBigFloatBigNumToMap(QCBOREncodeContext *pCtx,
774 const char *szLabel,
775 UsefulBufC Mantissa,
776 bool bIsNegative,
777 int64_t nBase2Exponent);
778
779static void QCBOREncode_AddBigFloatBigNumToMapN(QCBOREncodeContext *pCtx,
780 int64_t nLabel,
781 UsefulBufC Mantissa,
782 bool bIsNegative,
783 int64_t nBase2Exponent);
784#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
785
786
787/**
788 @brief Add a text URI to the encoded output.
789
790 @param[in] pCtx The encoding context to add the URI to.
791 @param[in] URI Pointer and length of the URI.
792
793 The format of URI must be per [RFC 3986]
794 (https://tools.ietf.org/html/rfc3986).
795
796 It is output as CBOR major type 3, a text string, with tag @ref
797 CBOR_TAG_URI indicating the text string is a URI.
798
799 A URI in a NULL-terminated string, @c szURI, can be easily added with
800 this code:
801
802 QCBOREncode_AddURI(pCtx, UsefulBuf_FromSZ(szURI));
803 */
804static void QCBOREncode_AddURI(QCBOREncodeContext *pCtx, UsefulBufC URI);
805
806static void QCBOREncode_AddURIToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC URI);
807
808static void QCBOREncode_AddURIToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC URI);
809
810
811/**
812 @brief Add Base64-encoded text to encoded output.
813
814 @param[in] pCtx The encoding context to add the base-64 text to.
815 @param[in] B64Text Pointer and length of the base-64 encoded text.
816
817 The text content is Base64 encoded data per [RFC 4648]
818 (https://tools.ietf.org/html/rfc4648).
819
820 It is output as CBOR major type 3, a text string, with tag @ref
821 CBOR_TAG_B64 indicating the text string is Base64 encoded.
822 */
823static void QCBOREncode_AddB64Text(QCBOREncodeContext *pCtx, UsefulBufC B64Text);
824
825static void QCBOREncode_AddB64TextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC B64Text);
826
827static void QCBOREncode_AddB64TextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC B64Text);
828
829
830/**
831 @brief Add base64url encoded data to encoded output.
832
833 @param[in] pCtx The encoding context to add the base64url to.
834 @param[in] B64Text Pointer and length of the base64url encoded text.
835
836 The text content is base64URL encoded text as per [RFC 4648]
837 (https://tools.ietf.org/html/rfc4648).
838
839 It is output as CBOR major type 3, a text string, with tag @ref
840 CBOR_TAG_B64URL indicating the text string is a Base64url encoded.
841 */
842static void QCBOREncode_AddB64URLText(QCBOREncodeContext *pCtx, UsefulBufC B64Text);
843
844static void QCBOREncode_AddB64URLTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC B64Text);
845
846static void QCBOREncode_AddB64URLTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC B64Text);
847
848
849/**
850 @brief Add Perl Compatible Regular Expression.
851
852 @param[in] pCtx The encoding context to add the regular expression to.
853 @param[in] Regex Pointer and length of the regular expression.
854
855 The text content is Perl Compatible Regular
856 Expressions (PCRE) / JavaScript syntax [ECMA262].
857
858 It is output as CBOR major type 3, a text string, with tag @ref
859 CBOR_TAG_REGEX indicating the text string is a regular expression.
860 */
861static void QCBOREncode_AddRegex(QCBOREncodeContext *pCtx, UsefulBufC Regex);
862
863static void QCBOREncode_AddRegexToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Regex);
864
865static void QCBOREncode_AddRegexToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Regex);
866
867
868/**
869 @brief MIME encoded text to the encoded output.
870
871 @param[in] pCtx The encoding context to add the MIME data to.
872 @param[in] MIMEData Pointer and length of the regular expression.
873
874 The text content is in MIME format per [RFC 2045]
875 (https://tools.ietf.org/html/rfc2045) including the headers. Note
876 that this only supports text-format MIME. Binary MIME is not
877 supported.
878
879 It is output as CBOR major type 3, a text string, with tag
880 @ref CBOR_TAG_MIME indicating the text string is MIME data.
881 */
882static void QCBOREncode_AddMIMEData(QCBOREncodeContext *pCtx, UsefulBufC MIMEData);
883
884static void QCBOREncode_AddMIMEDataToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC MIMEData);
885
886static void QCBOREncode_AddMIMEDataToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC MIMEData);
887
888
889/**
890 @brief Add an RFC 3339 date string
891
892 @param[in] pCtx The encoding context to add the date to.
893 @param[in] szDate Null-terminated string with date to add.
894
895 The string szDate should be in the form of [RFC 3339]
896 (https://tools.ietf.org/html/rfc3339) as defined by section 3.3 in
897 [RFC 4287] (https://tools.ietf.org/html/rfc4287). This is as
898 described in section 2.4.1 in [RFC 7049]
899 (https://tools.ietf.org/html/rfc7049).
900
901 Note that this function doesn't validate the format of the date string
902 at all. If you add an incorrect format date string, the generated
903 CBOR will be incorrect and the receiver may not be able to handle it.
904
905 Error handling is the same as QCBOREncode_AddInt64().
906 */
907static void QCBOREncode_AddDateString(QCBOREncodeContext *pCtx, const char *szDate);
908
909static void QCBOREncode_AddDateStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szDate);
910
911static void QCBOREncode_AddDateStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szDate);
912
913
914/**
915 @brief Add a standard Boolean.
916
917 @param[in] pCtx The encoding context to add the Boolean to.
918 @param[in] b true or false from @c <stdbool.h>.
919
920 Adds a Boolean value as CBOR major type 7.
921
922 Error handling is the same as QCBOREncode_AddInt64().
923 */
924static void QCBOREncode_AddBool(QCBOREncodeContext *pCtx, bool b);
925
926static void QCBOREncode_AddBoolToMap(QCBOREncodeContext *pCtx, const char *szLabel, bool b);
927
928static void QCBOREncode_AddBoolToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, bool b);
929
930
931
932/**
933 @brief Add a NULL to the encoded output.
934
935 @param[in] pCtx The encoding context to add the NULL to.
936
937 Adds the NULL value as CBOR major type 7.
938
939 This NULL doesn't have any special meaning in CBOR such as a
940 terminating value for a string or an empty value.
941
942 Error handling is the same as QCBOREncode_AddInt64().
943 */
944static void QCBOREncode_AddNULL(QCBOREncodeContext *pCtx);
945
946static void QCBOREncode_AddNULLToMap(QCBOREncodeContext *pCtx, const char *szLabel);
947
948static void QCBOREncode_AddNULLToMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
949
950
951/**
952 @brief Add an "undef" to the encoded output.
953
954 @param[in] pCtx The encoding context to add the "undef" to.
955
956 Adds the undef value as CBOR major type 7.
957
958 Note that this value will not translate to JSON.
959
960 This Undef doesn't have any special meaning in CBOR such as a
961 terminating value for a string or an empty value.
962
963 Error handling is the same as QCBOREncode_AddInt64().
964 */
965static void QCBOREncode_AddUndef(QCBOREncodeContext *pCtx);
966
967static void QCBOREncode_AddUndefToMap(QCBOREncodeContext *pCtx, const char *szLabel);
968
969static void QCBOREncode_AddUndefToMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
970
971
972/**
973 @brief Indicates that the next items added are in an array.
974
975 @param[in] pCtx The encoding context to open the array in.
976
977 Arrays are the basic CBOR aggregate or structure type. Call this
978 function to start or open an array. Then call the various @c
979 QCBOREncode_AddXxx() functions to add the items that go into the
980 array. Then call QCBOREncode_CloseArray() when all items have been
981 added. The data items in the array can be of any type and can be of
982 mixed types.
983
984 Nesting of arrays and maps is allowed and supported just by calling
985 QCBOREncode_OpenArray() again before calling
986 QCBOREncode_CloseArray(). While CBOR has no limit on nesting, this
987 implementation does in order to keep it smaller and simpler. The
988 limit is @ref QCBOR_MAX_ARRAY_NESTING. This is the max number of
989 times this can be called without calling
990 QCBOREncode_CloseArray(). QCBOREncode_Finish() will return @ref
991 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP when it is called as this function
992 just sets an error state and returns no value when this occurs.
993
994 If you try to add more than @ref QCBOR_MAX_ITEMS_IN_ARRAY items to a
995 single array or map, @ref QCBOR_ERR_ARRAY_TOO_LONG will be returned
996 when QCBOREncode_Finish() is called.
997
998 An array itself must have a label if it is being added to a map.
999 Note that array elements do not have labels (but map elements do).
1000
1001 An array itself may be tagged by calling QCBOREncode_AddTag() before this call.
1002 */
1003static void QCBOREncode_OpenArray(QCBOREncodeContext *pCtx);
1004
1005static void QCBOREncode_OpenArrayInMap(QCBOREncodeContext *pCtx, const char *szLabel);
1006
1007static void QCBOREncode_OpenArrayInMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
1008
1009
1010/**
1011 @brief Close an open array.
1012
1013 @param[in] pCtx The encoding context to close the array in.
1014
1015 The closes an array opened by QCBOREncode_OpenArray(). It reduces
1016 nesting level by one. All arrays (and maps) must be closed before
1017 calling QCBOREncode_Finish().
1018
1019 When an error occurs as a result of this call, the encoder records
1020 the error and enters the error state. The error will be returned when
1021 QCBOREncode_Finish() is called.
1022
1023 If this has been called more times than QCBOREncode_OpenArray(), then
1024 @ref QCBOR_ERR_TOO_MANY_CLOSES will be returned when QCBOREncode_Finish()
1025 is called.
1026
1027 If this is called and it is not an array that is currently open, @ref
1028 QCBOR_ERR_CLOSE_MISMATCH will be returned when QCBOREncode_Finish()
1029 is called.
1030 */
1031static void QCBOREncode_CloseArray(QCBOREncodeContext *pCtx);
1032
1033
1034/**
1035 @brief Indicates that the next items added are in a map.
1036
1037 @param[in] pCtx The encoding context to open the map in.
1038
1039 See QCBOREncode_OpenArray() for more information, particularly error
1040 handling.
1041
1042 CBOR maps are an aggregate type where each item in the map consists
1043 of a label and a value. They are similar to JSON objects.
1044
1045 The value can be any CBOR type including another map.
1046
1047 The label can also be any CBOR type, but in practice they are
1048 typically, integers as this gives the most compact output. They might
1049 also be text strings which gives readability and translation to JSON.
1050
1051 Every @c QCBOREncode_AddXxx() call has one version that ends with @c
1052 InMap for adding items to maps with string labels and one that ends
1053 with @c InMapN that is for adding with integer labels.
1054
1055 RFC 7049 uses the term "key" instead of "label".
1056
1057 If you wish to use map labels that are neither integer labels nor
1058 text strings, then just call the QCBOREncode_AddXxx() function
1059 explicitly to add the label. Then call it again to add the value.
1060
1061 See the [RFC 7049] (https://tools.ietf.org/html/rfc7049) for a lot
1062 more information on creating maps.
1063 */
1064static void QCBOREncode_OpenMap(QCBOREncodeContext *pCtx);
1065
1066static void QCBOREncode_OpenMapInMap(QCBOREncodeContext *pCtx, const char *szLabel);
1067
1068static void QCBOREncode_OpenMapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
1069
1070
1071
1072/**
1073 @brief Close an open map.
1074
1075 @param[in] pCtx The encoding context to close the map in .
1076
1077 This closes a map opened by QCBOREncode_OpenMap(). It reduces nesting
1078 level by one.
1079
1080 When an error occurs as a result of this call, the encoder records
1081 the error and enters the error state. The error will be returned when
1082 QCBOREncode_Finish() is called.
1083
1084 If this has been called more times than QCBOREncode_OpenMap(),
1085 then @ref QCBOR_ERR_TOO_MANY_CLOSES will be returned when
1086 QCBOREncode_Finish() is called.
1087
1088 If this is called and it is not a map that is currently open, @ref
1089 QCBOR_ERR_CLOSE_MISMATCH will be returned when QCBOREncode_Finish()
1090 is called.
1091 */
1092static void QCBOREncode_CloseMap(QCBOREncodeContext *pCtx);
1093
1094
1095/**
1096 @brief Indicate start of encoded CBOR to be wrapped in a bstr.
1097
1098 @param[in] pCtx The encoding context to open the bstr-wrapped CBOR in.
1099
1100 All added encoded items between this call and a call to
1101 QCBOREncode_CloseBstrWrap2() will be wrapped in a bstr. They will
1102 appear in the final output as a byte string. That byte string will
1103 contain encoded CBOR. This increases nesting level by one.
1104
1105 The typical use case is for encoded CBOR that is to be
1106 cryptographically hashed, as part of a [RFC 8152, COSE]
1107 (https://tools.ietf.org/html/rfc8152) implementation.
1108
1109 Using QCBOREncode_BstrWrap() and QCBOREncode_CloseBstrWrap2() avoids
1110 having to encode the items first in one buffer (e.g., the COSE
1111 payload) and then add that buffer as a bstr to another encoding
1112 (e.g. the COSE to-be-signed bytes, the @c Sig_structure) potentially
1113 halving the memory needed.
1114
1115 RFC 7049 states the purpose of this wrapping is to prevent code
1116 relaying the signed data but not verifying it from tampering with the
1117 signed data thus making the signature unverifiable. It is also quite
1118 beneficial for the signature verification code. Standard CBOR
1119 decoders usually do not give access to partially decoded CBOR as
1120 would be needed to check the signature of some CBOR. With this
1121 wrapping, standard CBOR decoders can be used to get to all the data
1122 needed for a signature verification.
1123 */
1124static void QCBOREncode_BstrWrap(QCBOREncodeContext *pCtx);
1125
1126static void QCBOREncode_BstrWrapInMap(QCBOREncodeContext *pCtx, const char *szLabel);
1127
1128static void QCBOREncode_BstrWrapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
1129
1130
1131/**
1132 @brief Close a wrapping bstr.
1133
1134 @param[in] pCtx The encoding context to close of bstr wrapping in.
1135 @param[in] bIncludeCBORHead Include the encoded CBOR head of the bstr
1136 as well as the bytes in @c pWrappedCBOR.
1137 @param[out] pWrappedCBOR A @ref UsefulBufC containing wrapped bytes.
1138
1139 The closes a wrapping bstr opened by QCBOREncode_BstrWrap(). It reduces
1140 nesting level by one.
1141
1142 A pointer and length of the enclosed encoded CBOR is returned in @c
1143 *pWrappedCBOR if it is not @c NULL. The main purpose of this is so
1144 this data can be hashed (e.g., with SHA-256) as part of a [RFC 8152,
1145 COSE] (https://tools.ietf.org/html/rfc8152)
1146 implementation. **WARNING**, this pointer and length should be used
1147 right away before any other calls to @c QCBOREncode_CloseXxx() as
1148 they will move data around and the pointer and length will no longer
1149 be to the correct encoded CBOR.
1150
1151 When an error occurs as a result of this call, the encoder records
1152 the error and enters the error state. The error will be returned when
1153 QCBOREncode_Finish() is called.
1154
1155 If this has been called more times than QCBOREncode_BstrWrap(), then
1156 @ref QCBOR_ERR_TOO_MANY_CLOSES will be returned when
1157 QCBOREncode_Finish() is called.
1158
1159 If this is called and it is not a wrapping bstr that is currently
1160 open, @ref QCBOR_ERR_CLOSE_MISMATCH will be returned when
1161 QCBOREncode_Finish() is called.
1162
1163 QCBOREncode_CloseBstrWrap() is a deprecated version of this function
1164 that is equivalent to the call with @c bIncludeCBORHead @c true.
1165 */
1166void QCBOREncode_CloseBstrWrap2(QCBOREncodeContext *pCtx, bool bIncludeCBORHead, UsefulBufC *pWrappedCBOR);
1167
1168static void QCBOREncode_CloseBstrWrap(QCBOREncodeContext *pCtx, UsefulBufC *pWrappedCBOR);
1169
1170
1171/**
1172 @brief Add some already-encoded CBOR bytes.
1173
1174 @param[in] pCtx The encoding context to add the already-encode CBOR to.
1175 @param[in] Encoded The already-encoded CBOR to add to the context.
1176
1177 The encoded CBOR being added must be fully conforming CBOR. It must
1178 be complete with no arrays or maps that are incomplete. While this
1179 encoder doesn't ever produce indefinite lengths, it is OK for the
1180 raw CBOR added here to have indefinite lengths.
1181
1182 The raw CBOR added here is not checked in anyway. If it is not
1183 conforming or has open arrays or such, the final encoded CBOR
1184 will probably be wrong or not what was intended.
1185
1186 If the encoded CBOR being added here contains multiple items, they
1187 must be enclosed in a map or array. At the top level the raw
1188 CBOR must be a single data item.
1189 */
1190static void QCBOREncode_AddEncoded(QCBOREncodeContext *pCtx, UsefulBufC Encoded);
1191
1192static void QCBOREncode_AddEncodedToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Encoded);
1193
1194static void QCBOREncode_AddEncodedToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Encoded);
1195
1196
1197/**
1198 @brief Get the encoded result.
1199
1200 @param[in] pCtx The context to finish encoding with.
1201 @param[out] pEncodedCBOR Pointer and length of encoded CBOR.
1202
1203 @retval QCBOR_ERR_TOO_MANY_CLOSES Nesting error
1204
1205 @retval QCBOR_ERR_CLOSE_MISMATCH Nesting error
1206
1207 @retval QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN Nesting error
1208
1209 @retval QCBOR_ERR_BUFFER_TOO_LARGE Encoded output buffer size
1210
1211 @retval QCBOR_ERR_BUFFER_TOO_SMALL Encoded output buffer size
1212
1213 @retval QCBOR_ERR_ARRAY_NESTING_TOO_DEEP Implementation limit
1214
1215 @retval QCBOR_ERR_ARRAY_TOO_LONG Implementation limit
1216
1217 If this returns success @ref QCBOR_SUCCESS the encoding was a success
1218 and the return length is correct and complete.
1219
1220 If no buffer was passed to QCBOREncode_Init(), then only the length
1221 was computed. If a buffer was passed, then the encoded CBOR is in the
1222 buffer.
1223
1224 Encoding errors primarily manifest here as most other encoding function
1225 do no return an error. They just set the error state in the encode
1226 context after which no encoding function does anything.
1227
1228 Three types of errors manifest here. The first type are nesting
1229 errors where the number of @c QCBOREncode_OpenXxx() calls do not
1230 match the number @c QCBOREncode_CloseXxx() calls. The solution is to
1231 fix the calling code.
1232
1233 The second type of error is because the buffer given is either too
1234 small or too large. The remedy is to give a correctly sized buffer.
1235
1236 The third type are due to limits in this implementation. @ref
1237 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP can be worked around by encoding the
1238 CBOR in two (or more) phases and adding the CBOR from the first phase
1239 to the second with @c QCBOREncode_AddEncoded().
1240
1241 If an error is returned, the buffer may have partially encoded
1242 incorrect CBOR in it and it should not be used. Likewise, the length
1243 may be incorrect and should not be used.
1244
1245 Note that the error could have occurred in one of the many @c
1246 QCBOREncode_AddXxx() calls long before QCBOREncode_Finish() was
1247 called. This error handling reduces the CBOR implementation size but
1248 makes debugging harder.
1249
1250 This may be called multiple times. It will always return the same. It
1251 can also be interleaved with calls to QCBOREncode_FinishGetSize().
1252
1253 QCBOREncode_GetErrorState() can be called to get the current
1254 error state and abort encoding early as an optimization, but is
1255 is never required.
1256 */
1257QCBORError QCBOREncode_Finish(QCBOREncodeContext *pCtx, UsefulBufC *pEncodedCBOR);
1258
1259
1260/**
1261 @brief Get the encoded CBOR and error status.
1262
1263 @param[in] pCtx The context to finish encoding with.
1264 @param[out] uEncodedLen The length of the encoded or potentially
1265 encoded CBOR in bytes.
1266
1267 @return The same errors as QCBOREncode_Finish().
1268
1269 This functions the same as QCBOREncode_Finish(), but only returns the
1270 size of the encoded output.
1271 */
1272QCBORError QCBOREncode_FinishGetSize(QCBOREncodeContext *pCtx, size_t *uEncodedLen);
1273
1274
1275/**
1276 @brief Indicate whether output buffer is NULL or not.
1277
1278 @param[in] pCtx The encoding context.
1279
1280 @return 1 if the output buffer is @c NULL.
1281
1282 Sometimes a @c NULL input buffer is given to QCBOREncode_Init() so
1283 that the size of the generated CBOR can be calculated without
1284 allocating a buffer for it. This returns 1 when the output buffer is
1285 NULL and 0 when it is not.
1286*/
1287static int QCBOREncode_IsBufferNULL(QCBOREncodeContext *pCtx);
1288
1289 /**
1290 @brief Get the encoding error state.
1291
1292 @param[in] pCtx The encoding context.
1293
1294 @return One of \ref QCBORError. See return values from
1295 QCBOREncode_Finish()
1296
1297 Normally encoding errors need only be handled at the end of encoding
1298 when QCBOREncode_Finish() is called. This can be called to get the
1299 error result before finish should there be a need to halt encoding
1300 before QCBOREncode_Finish() is called.
1301*/
1302static QCBORError QCBOREncode_GetErrorState(QCBOREncodeContext *pCtx);
1303
1304
1305/**
1306 Encode the "head" of a CBOR data item.
1307
1308 @param buffer Buffer to output the encoded head to; must be
1309 @ref QCBOR_HEAD_BUFFER_SIZE bytes in size.
1310 @param uMajorType One of CBOR_MAJOR_TYPE_XX.
1311 @param uMinLen The minimum number of bytes to encode uNumber. Almost always
1312 this is 0 to use preferred minimal encoding. If this is 4,
1313 then even the values 0xffff and smaller will be encoded
1314 as in 4 bytes. This is used primarily when encoding a
1315 float or double put into uNumber as the leading zero bytes
1316 for them must be encoded.
1317 @param uNumber The numeric argument part of the CBOR head.
1318 @return Pointer and length of the encoded head or
1319 @NULLUsefulBufC if the output buffer is too small.
1320
1321 Callers to need to call this for normal CBOR encoding. Note that it doesn't even
1322 take a @ref QCBOREncodeContext argument.
1323
1324 This encodes the major type and argument part of a data item. The
1325 argument is an integer that is usually either the value or the length
1326 of the data item.
1327
1328 This is exposed in the public interface to allow hashing of some CBOR
1329 data types, bstr in particular, a chunk at a time so the full CBOR
1330 doesn't have to be encoded in a contiguous buffer.
1331
1332 For example, if you have a 100,000 byte binary blob in a buffer that
1333 needs to be a bstr encoded and then hashed. You could allocate a
1334 100,010 byte buffer and encode it normally. Alternatively, you can
1335 encode the head in a 10 byte buffer with this function, hash that and
1336 then hash the 100,000 bytes using the same hash context.
1337
1338 See also QCBOREncode_AddBytesLenOnly();
1339 */
1340UsefulBufC QCBOREncode_EncodeHead(UsefulBuf buffer,
1341 uint8_t uMajorType,
1342 uint8_t uMinLen,
1343 uint64_t uNumber);
1344
1345
Michael Eckel5c531332020-03-02 01:35:30 +01001346
1347
1348/* ===========================================================================
1349 BEGINNING OF PRIVATE INLINE IMPLEMENTATION
1350
1351 =========================================================================== */
1352
1353/**
1354 @brief Semi-private method to add a buffer full of bytes to encoded output
1355
1356 @param[in] pCtx The encoding context to add the integer to.
1357 @param[in] uMajorType The CBOR major type of the bytes.
1358 @param[in] Bytes The bytes to add.
1359
1360 Use QCBOREncode_AddText() or QCBOREncode_AddBytes() or
1361 QCBOREncode_AddEncoded() instead. They are inline functions that call
1362 this and supply the correct major type. This function is public to
1363 make the inline functions work to keep the overall code size down and
1364 because the C language has no way to make it private.
1365
1366 If this is called the major type should be @c
1367 CBOR_MAJOR_TYPE_TEXT_STRING, @c CBOR_MAJOR_TYPE_BYTE_STRING or @c
1368 CBOR_MAJOR_NONE_TYPE_RAW. The last one is special for adding
1369 already-encoded CBOR.
1370 */
1371void QCBOREncode_AddBuffer(QCBOREncodeContext *pCtx, uint8_t uMajorType, UsefulBufC Bytes);
1372
1373
1374/**
1375 @brief Semi-private method to open a map, array or bstr-wrapped CBOR
1376
1377 @param[in] pCtx The context to add to.
1378 @param[in] uMajorType The major CBOR type to close
1379
1380 Call QCBOREncode_OpenArray(), QCBOREncode_OpenMap() or
1381 QCBOREncode_BstrWrap() instead of this.
1382 */
1383void QCBOREncode_OpenMapOrArray(QCBOREncodeContext *pCtx, uint8_t uMajorType);
1384
1385
1386/**
1387 @brief Semi-private method to open a map, array with indefinite length
1388
1389 @param[in] pCtx The context to add to.
1390 @param[in] uMajorType The major CBOR type to close
1391
1392 Call QCBOREncode_OpenArrayIndefiniteLength() or
1393 QCBOREncode_OpenMapIndefiniteLength() instead of this.
1394 */
1395void QCBOREncode_OpenMapOrArrayIndefiniteLength(QCBOREncodeContext *pCtx, uint8_t uMajorType);
1396
1397
1398/**
1399 @brief Semi-private method to close a map, array or bstr wrapped CBOR
1400
1401 @param[in] pCtx The context to add to.
1402 @param[in] uMajorType The major CBOR type to close.
1403
1404 Call QCBOREncode_CloseArray() or QCBOREncode_CloseMap() instead of this.
1405 */
1406void QCBOREncode_CloseMapOrArray(QCBOREncodeContext *pCtx, uint8_t uMajorType);
1407
1408
1409/**
1410 @brief Semi-private method to close a map, array with indefinite length
1411
1412 @param[in] pCtx The context to add to.
1413 @param[in] uMajorType The major CBOR type to close.
1414
1415 Call QCBOREncode_CloseArrayIndefiniteLength() or
1416 QCBOREncode_CloseMapIndefiniteLength() instead of this.
1417 */
1418void QCBOREncode_CloseMapOrArrayIndefiniteLength(QCBOREncodeContext *pCtx,
1419 uint8_t uMajorType);
1420
1421
1422/**
1423 @brief Semi-private method to add simple types.
1424
1425 @param[in] pCtx The encoding context to add the simple value to.
1426 @param[in] uMinLen Minimum encoding size for uNum. Usually 0.
1427 @param[in] uNum One of CBOR_SIMPLEV_FALSE through _UNDEF or other.
1428
1429 This is used to add simple types like true and false.
1430
1431 Call QCBOREncode_AddBool(), QCBOREncode_AddNULL(),
1432 QCBOREncode_AddUndef() instead of this.
1433
1434 This function can add simple values that are not defined by CBOR
1435 yet. This expansion point in CBOR should not be used unless they are
1436 standardized.
1437
1438 Error handling is the same as QCBOREncode_AddInt64().
1439 */
1440void QCBOREncode_AddType7(QCBOREncodeContext *pCtx, uint8_t uMinLen, uint64_t uNum);
1441
1442
1443/**
1444 @brief Semi-private method to add bigfloats and decimal fractions.
1445
1446 @param[in] pCtx The encoding context to add the value to.
1447 @param[in] uTag The type 6 tag indicating what this is to be
1448 @param[in] BigNumMantissa Is @ref NULLUsefulBufC if mantissa is an
1449 @c int64_t or the actual big number mantissa
1450 if not.
1451 @param[in] nMantissa The @c int64_t mantissa if it is not a big number.
1452 @param[in] nExponent The exponent.
1453
1454 This adds a tagged array with two members, the mantissa and exponent. The
1455 mantissa can be either a big number or an @c int64_t.
1456
1457 Typically, QCBOREncode_AddDecimalFraction(), QCBOREncode_AddBigFloat(),
1458 QCBOREncode_AddDecimalFractionBigNum() or QCBOREncode_AddBigFloatBigNum()
1459 is called instead of this.
1460 */
1461void QCBOREncode_AddExponentAndMantissa(QCBOREncodeContext *pCtx,
1462 uint64_t uTag,
1463 UsefulBufC BigNumMantissa,
1464 bool bBigNumIsNegative,
1465 int64_t nMantissa,
1466 int64_t nExponent);
1467
1468/**
1469 @brief Semi-private method to add only the type and length of a byte string.
1470
1471 @param[in] pCtx The context to initialize.
1472 @param[in] Bytes Pointer and length of the input data.
1473
1474 This is the same as QCBOREncode_AddBytes() except it only adds the
1475 CBOR encoding for the type and the length. It doesn't actually add
1476 the bytes. You can't actually produce correct CBOR with this and the
1477 rest of this API. It is only used for a special case where
1478 the valid CBOR is created manually by putting this type and length in
1479 and then adding the actual bytes. In particular, when only a hash of
1480 the encoded CBOR is needed, where the type and header are hashed
1481 separately and then the bytes is hashed. This makes it possible to
1482 implement COSE Sign1 with only one copy of the payload in the output
1483 buffer, rather than two, roughly cutting memory use in half.
1484
1485 This is only used for this odd case, but this is a supported
1486 tested function.
1487
1488 See also QCBOREncode_EncodeHead().
1489*/
1490static inline void QCBOREncode_AddBytesLenOnly(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
1491
1492static inline void QCBOREncode_AddBytesLenOnlyToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
1493
1494static inline void QCBOREncode_AddBytesLenOnlyToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
1495
1496
1497
1498
1499
1500static inline void QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t uNum)
1501{
1502 // Use _AddBuffer() because _AddSZString() is defined below, not above
1503 QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, UsefulBuf_FromSZ(szLabel));
1504 QCBOREncode_AddInt64(pCtx, uNum);
1505}
1506
1507static inline void QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t uNum)
1508{
1509 QCBOREncode_AddInt64(pCtx, nLabel);
1510 QCBOREncode_AddInt64(pCtx, uNum);
1511}
1512
1513
1514static inline void QCBOREncode_AddUInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t uNum)
1515{
1516 // Use _AddBuffer() because _AddSZString() is defined below, not above
1517 QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, UsefulBuf_FromSZ(szLabel));
1518 QCBOREncode_AddUInt64(pCtx, uNum);
1519}
1520
1521static inline void QCBOREncode_AddUInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, uint64_t uNum)
1522{
1523 QCBOREncode_AddInt64(pCtx, nLabel);
1524 QCBOREncode_AddUInt64(pCtx, uNum);
1525}
1526
1527
1528static inline void QCBOREncode_AddText(QCBOREncodeContext *pCtx, UsefulBufC Text)
1529{
1530 QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, Text);
1531}
1532
1533static inline void QCBOREncode_AddTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Text)
1534{
1535 // Use _AddBuffer() because _AddSZString() is defined below, not above
1536 QCBOREncode_AddText(pCtx, UsefulBuf_FromSZ(szLabel));
1537 QCBOREncode_AddText(pCtx, Text);
1538}
1539
1540static inline void QCBOREncode_AddTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Text)
1541{
1542 QCBOREncode_AddInt64(pCtx, nLabel);
1543 QCBOREncode_AddText(pCtx, Text);
1544}
1545
1546
1547inline static void QCBOREncode_AddSZString(QCBOREncodeContext *pCtx, const char *szString)
1548{
1549 QCBOREncode_AddText(pCtx, UsefulBuf_FromSZ(szString));
1550}
1551
1552static inline void QCBOREncode_AddSZStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szString)
1553{
1554 QCBOREncode_AddSZString(pCtx, szLabel);
1555 QCBOREncode_AddSZString(pCtx, szString);
1556}
1557
1558static inline void QCBOREncode_AddSZStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szString)
1559{
1560 QCBOREncode_AddInt64(pCtx, nLabel);
1561 QCBOREncode_AddSZString(pCtx, szString);
1562}
1563
1564
1565static inline void QCBOREncode_AddDoubleToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum)
1566{
1567 QCBOREncode_AddSZString(pCtx, szLabel);
1568 QCBOREncode_AddDouble(pCtx, dNum);
1569}
1570
1571static inline void QCBOREncode_AddDoubleToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum)
1572{
1573 QCBOREncode_AddInt64(pCtx, nLabel);
1574 QCBOREncode_AddDouble(pCtx, dNum);
1575}
1576
1577
1578static inline void QCBOREncode_AddDateEpoch(QCBOREncodeContext *pCtx, int64_t date)
1579{
1580 QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_EPOCH);
1581 QCBOREncode_AddInt64(pCtx, date);
1582}
1583
1584static inline void QCBOREncode_AddDateEpochToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t date)
1585{
1586 QCBOREncode_AddSZString(pCtx, szLabel);
1587 QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_EPOCH);
1588 QCBOREncode_AddInt64(pCtx, date);
1589}
1590
1591static inline void QCBOREncode_AddDateEpochToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t date)
1592{
1593 QCBOREncode_AddInt64(pCtx, nLabel);
1594 QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_EPOCH);
1595 QCBOREncode_AddInt64(pCtx, date);
1596}
1597
1598
1599static inline void QCBOREncode_AddBytes(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
1600{
1601 QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING, Bytes);
1602}
1603
1604static inline void QCBOREncode_AddBytesToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
1605{
1606 QCBOREncode_AddSZString(pCtx, szLabel);
1607 QCBOREncode_AddBytes(pCtx, Bytes);
1608}
1609
1610static inline void QCBOREncode_AddBytesToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
1611{
1612 QCBOREncode_AddInt64(pCtx, nLabel);
1613 QCBOREncode_AddBytes(pCtx, Bytes);
1614}
1615
1616static inline void QCBOREncode_AddBytesLenOnly(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
1617{
1618 QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY, Bytes);
1619}
1620
1621static inline void QCBOREncode_AddBytesLenOnlyToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
1622{
1623 QCBOREncode_AddSZString(pCtx, szLabel);
1624 QCBOREncode_AddBytesLenOnly(pCtx, Bytes);
1625}
1626
1627static inline void QCBOREncode_AddBytesLenOnlyToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
1628{
1629 QCBOREncode_AddInt64(pCtx, nLabel);
1630 QCBOREncode_AddBytesLenOnly(pCtx, Bytes);
1631}
1632
1633static inline void QCBOREncode_AddBinaryUUID(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
1634{
1635 QCBOREncode_AddTag(pCtx, CBOR_TAG_BIN_UUID);
1636 QCBOREncode_AddBytes(pCtx, Bytes);
1637}
1638
1639static inline void QCBOREncode_AddBinaryUUIDToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
1640{
1641 QCBOREncode_AddSZString(pCtx, szLabel);
1642 QCBOREncode_AddTag(pCtx, CBOR_TAG_BIN_UUID);
1643 QCBOREncode_AddBytes(pCtx, Bytes);
1644}
1645
1646static inline void QCBOREncode_AddBinaryUUIDToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
1647{
1648 QCBOREncode_AddInt64(pCtx, nLabel);
1649 QCBOREncode_AddTag(pCtx, CBOR_TAG_BIN_UUID);
1650 QCBOREncode_AddBytes(pCtx, Bytes);
1651}
1652
1653
1654static inline void QCBOREncode_AddPositiveBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
1655{
1656 QCBOREncode_AddTag(pCtx, CBOR_TAG_POS_BIGNUM);
1657 QCBOREncode_AddBytes(pCtx, Bytes);
1658}
1659
1660static inline void QCBOREncode_AddPositiveBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
1661{
1662 QCBOREncode_AddSZString(pCtx, szLabel);
1663 QCBOREncode_AddTag(pCtx, CBOR_TAG_POS_BIGNUM);
1664 QCBOREncode_AddBytes(pCtx, Bytes);
1665}
1666
1667static inline void QCBOREncode_AddPositiveBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
1668{
1669 QCBOREncode_AddInt64(pCtx, nLabel);
1670 QCBOREncode_AddTag(pCtx, CBOR_TAG_POS_BIGNUM);
1671 QCBOREncode_AddBytes(pCtx, Bytes);
1672}
1673
1674
1675static inline void QCBOREncode_AddNegativeBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
1676{
1677 QCBOREncode_AddTag(pCtx, CBOR_TAG_NEG_BIGNUM);
1678 QCBOREncode_AddBytes(pCtx, Bytes);
1679}
1680
1681static inline void QCBOREncode_AddNegativeBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
1682{
1683 QCBOREncode_AddSZString(pCtx, szLabel);
1684 QCBOREncode_AddTag(pCtx, CBOR_TAG_NEG_BIGNUM);
1685 QCBOREncode_AddBytes(pCtx, Bytes);
1686}
1687
1688static inline void QCBOREncode_AddNegativeBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
1689{
1690 QCBOREncode_AddInt64(pCtx, nLabel);
1691 QCBOREncode_AddTag(pCtx, CBOR_TAG_NEG_BIGNUM);
1692 QCBOREncode_AddBytes(pCtx, Bytes);
1693}
1694
1695
1696#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1697
1698static inline void QCBOREncode_AddDecimalFraction(QCBOREncodeContext *pCtx,
1699 int64_t nMantissa,
1700 int64_t nBase10Exponent)
1701{
1702 QCBOREncode_AddExponentAndMantissa(pCtx,
1703 CBOR_TAG_DECIMAL_FRACTION,
1704 NULLUsefulBufC,
1705 false,
1706 nMantissa,
1707 nBase10Exponent);
1708}
1709
1710static inline void QCBOREncode_AddDecimalFractionToMap(QCBOREncodeContext *pCtx,
1711 const char *szLabel,
1712 int64_t nMantissa,
1713 int64_t nBase10Exponent)
1714{
1715 QCBOREncode_AddSZString(pCtx, szLabel);
1716 QCBOREncode_AddDecimalFraction(pCtx, nMantissa, nBase10Exponent);
1717}
1718
1719static inline void QCBOREncode_AddDecimalFractionToMapN(QCBOREncodeContext *pCtx,
1720 int64_t nLabel,
1721 int64_t nMantissa,
1722 int64_t nBase10Exponent)
1723{
1724 QCBOREncode_AddInt64(pCtx, nLabel);
1725 QCBOREncode_AddDecimalFraction(pCtx, nMantissa, nBase10Exponent);
1726}
1727
1728static inline void QCBOREncode_AddDecimalFractionBigNum(QCBOREncodeContext *pCtx,
1729 UsefulBufC Mantissa,
1730 bool bIsNegative,
1731 int64_t nBase10Exponent)
1732{
1733 QCBOREncode_AddExponentAndMantissa(pCtx,
1734 CBOR_TAG_DECIMAL_FRACTION,
1735 Mantissa, bIsNegative,
1736 0,
1737 nBase10Exponent);
1738}
1739
1740static inline void QCBOREncode_AddDecimalFractionBigNumToMap(QCBOREncodeContext *pCtx,
1741 const char *szLabel,
1742 UsefulBufC Mantissa,
1743 bool bIsNegative,
1744 int64_t nBase10Exponent)
1745{
1746 QCBOREncode_AddSZString(pCtx, szLabel);
1747 QCBOREncode_AddDecimalFractionBigNum(pCtx, Mantissa, bIsNegative, nBase10Exponent);
1748}
1749
1750static inline void QCBOREncode_AddDecimalFractionBigNumToMapN(QCBOREncodeContext *pCtx,
1751 int64_t nLabel,
1752 UsefulBufC Mantissa,
1753 bool bIsNegative,
1754 int64_t nBase2Exponent)
1755{
1756 QCBOREncode_AddInt64(pCtx, nLabel);
1757 QCBOREncode_AddDecimalFractionBigNum(pCtx, Mantissa, bIsNegative, nBase2Exponent);
1758}
1759
1760static inline void QCBOREncode_AddBigFloat(QCBOREncodeContext *pCtx,
1761 int64_t nMantissa,
1762 int64_t nBase2Exponent)
1763{
1764 QCBOREncode_AddExponentAndMantissa(pCtx, CBOR_TAG_BIGFLOAT, NULLUsefulBufC, false, nMantissa, nBase2Exponent);
1765}
1766
1767static inline void QCBOREncode_AddBigFloatToMap(QCBOREncodeContext *pCtx,
1768 const char *szLabel,
1769 int64_t nMantissa,
1770 int64_t nBase2Exponent)
1771{
1772 QCBOREncode_AddSZString(pCtx, szLabel);
1773 QCBOREncode_AddBigFloat(pCtx, nMantissa, nBase2Exponent);
1774}
1775
1776static inline void QCBOREncode_AddBigFloatToMapN(QCBOREncodeContext *pCtx,
1777 int64_t nLabel,
1778 int64_t nMantissa,
1779 int64_t nBase2Exponent)
1780{
1781 QCBOREncode_AddInt64(pCtx, nLabel);
1782 QCBOREncode_AddBigFloat(pCtx, nMantissa, nBase2Exponent);
1783}
1784
1785static inline void QCBOREncode_AddBigFloatBigNum(QCBOREncodeContext *pCtx,
1786 UsefulBufC Mantissa,
1787 bool bIsNegative,
1788 int64_t nBase2Exponent)
1789{
1790 QCBOREncode_AddExponentAndMantissa(pCtx, CBOR_TAG_BIGFLOAT, Mantissa, bIsNegative, 0, nBase2Exponent);
1791}
1792
1793static inline void QCBOREncode_AddBigFloatBigNumToMap(QCBOREncodeContext *pCtx,
1794 const char *szLabel,
1795 UsefulBufC Mantissa,
1796 bool bIsNegative,
1797 int64_t nBase2Exponent)
1798{
1799 QCBOREncode_AddSZString(pCtx, szLabel);
1800 QCBOREncode_AddBigFloatBigNum(pCtx, Mantissa, bIsNegative, nBase2Exponent);
1801}
1802
1803static inline void QCBOREncode_AddBigFloatBigNumToMapN(QCBOREncodeContext *pCtx,
1804 int64_t nLabel,
1805 UsefulBufC Mantissa,
1806 bool bIsNegative,
1807 int64_t nBase2Exponent)
1808{
1809 QCBOREncode_AddInt64(pCtx, nLabel);
1810 QCBOREncode_AddBigFloatBigNum(pCtx, Mantissa, bIsNegative, nBase2Exponent);
1811}
1812#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1813
1814
1815static inline void QCBOREncode_AddURI(QCBOREncodeContext *pCtx, UsefulBufC URI)
1816{
1817 QCBOREncode_AddTag(pCtx, CBOR_TAG_URI);
1818 QCBOREncode_AddText(pCtx, URI);
1819}
1820
1821static inline void QCBOREncode_AddURIToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC URI)
1822{
1823 QCBOREncode_AddSZString(pCtx, szLabel);
1824 QCBOREncode_AddTag(pCtx, CBOR_TAG_URI);
1825 QCBOREncode_AddText(pCtx, URI);
1826}
1827
1828static inline void QCBOREncode_AddURIToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC URI)
1829{
1830 QCBOREncode_AddInt64(pCtx, nLabel);
1831 QCBOREncode_AddTag(pCtx, CBOR_TAG_URI);
1832 QCBOREncode_AddText(pCtx, URI);
1833}
1834
1835
1836
1837static inline void QCBOREncode_AddB64Text(QCBOREncodeContext *pCtx, UsefulBufC B64Text)
1838{
1839 QCBOREncode_AddTag(pCtx, CBOR_TAG_B64);
1840 QCBOREncode_AddText(pCtx, B64Text);
1841}
1842
1843static inline void QCBOREncode_AddB64TextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC B64Text)
1844{
1845 QCBOREncode_AddSZString(pCtx, szLabel);
1846 QCBOREncode_AddTag(pCtx, CBOR_TAG_B64);
1847 QCBOREncode_AddText(pCtx, B64Text);
1848}
1849
1850static inline void QCBOREncode_AddB64TextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC B64Text)
1851{
1852 QCBOREncode_AddInt64(pCtx, nLabel);
1853 QCBOREncode_AddTag(pCtx, CBOR_TAG_B64);
1854 QCBOREncode_AddText(pCtx, B64Text);
1855}
1856
1857
1858static inline void QCBOREncode_AddB64URLText(QCBOREncodeContext *pCtx, UsefulBufC B64Text)
1859{
1860 QCBOREncode_AddTag(pCtx, CBOR_TAG_B64URL);
1861 QCBOREncode_AddText(pCtx, B64Text);
1862}
1863
1864static inline void QCBOREncode_AddB64URLTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC B64Text)
1865{
1866 QCBOREncode_AddSZString(pCtx, szLabel);
1867 QCBOREncode_AddTag(pCtx, CBOR_TAG_B64URL);
1868 QCBOREncode_AddText(pCtx, B64Text);
1869}
1870
1871static inline void QCBOREncode_AddB64URLTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC B64Text)
1872{
1873 QCBOREncode_AddInt64(pCtx, nLabel);
1874 QCBOREncode_AddTag(pCtx, CBOR_TAG_B64URL);
1875 QCBOREncode_AddText(pCtx, B64Text);
1876}
1877
1878
1879static inline void QCBOREncode_AddRegex(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
1880{
1881 QCBOREncode_AddTag(pCtx, CBOR_TAG_REGEX);
1882 QCBOREncode_AddText(pCtx, Bytes);
1883}
1884
1885static inline void QCBOREncode_AddRegexToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
1886{
1887 QCBOREncode_AddSZString(pCtx, szLabel);
1888 QCBOREncode_AddTag(pCtx, CBOR_TAG_REGEX);
1889 QCBOREncode_AddText(pCtx, Bytes);
1890}
1891
1892static inline void QCBOREncode_AddRegexToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
1893{
1894 QCBOREncode_AddInt64(pCtx, nLabel);
1895 QCBOREncode_AddTag(pCtx, CBOR_TAG_REGEX);
1896 QCBOREncode_AddText(pCtx, Bytes);
1897}
1898
1899
1900static inline void QCBOREncode_AddMIMEData(QCBOREncodeContext *pCtx, UsefulBufC MIMEData)
1901{
1902 QCBOREncode_AddTag(pCtx, CBOR_TAG_MIME);
1903 QCBOREncode_AddText(pCtx, MIMEData);
1904}
1905
1906static inline void QCBOREncode_AddMIMEDataToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC MIMEData)
1907{
1908 QCBOREncode_AddSZString(pCtx, szLabel);
1909 QCBOREncode_AddTag(pCtx, CBOR_TAG_MIME);
1910 QCBOREncode_AddText(pCtx, MIMEData);
1911}
1912
1913static inline void QCBOREncode_AddMIMEDataToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC MIMEData)
1914{
1915 QCBOREncode_AddInt64(pCtx, nLabel);
1916 QCBOREncode_AddTag(pCtx, CBOR_TAG_MIME);
1917 QCBOREncode_AddText(pCtx, MIMEData);
1918}
1919
1920
1921static inline void QCBOREncode_AddDateString(QCBOREncodeContext *pCtx, const char *szDate)
1922{
1923 QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_STRING);
1924 QCBOREncode_AddSZString(pCtx, szDate);
1925}
1926
1927static inline void QCBOREncode_AddDateStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szDate)
1928{
1929 QCBOREncode_AddSZString(pCtx, szLabel);
1930 QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_STRING);
1931 QCBOREncode_AddSZString(pCtx, szDate);
1932}
1933
1934static inline void QCBOREncode_AddDateStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szDate)
1935{
1936 QCBOREncode_AddInt64(pCtx, nLabel);
1937 QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_STRING);
1938 QCBOREncode_AddSZString(pCtx, szDate);
1939}
1940
1941
1942static inline void QCBOREncode_AddSimple(QCBOREncodeContext *pCtx, uint64_t uNum)
1943{
1944 QCBOREncode_AddType7(pCtx, 0, uNum);
1945}
1946
1947static inline void QCBOREncode_AddSimpleToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint8_t uSimple)
1948{
1949 QCBOREncode_AddSZString(pCtx, szLabel);
1950 QCBOREncode_AddSimple(pCtx, uSimple);
1951}
1952
1953static inline void QCBOREncode_AddSimpleToMapN(QCBOREncodeContext *pCtx, int nLabel, uint8_t uSimple)
1954{
1955 QCBOREncode_AddInt64(pCtx, nLabel);
1956 QCBOREncode_AddSimple(pCtx, uSimple);
1957}
1958
1959
1960static inline void QCBOREncode_AddBool(QCBOREncodeContext *pCtx, bool b)
1961{
1962 uint8_t uSimple = CBOR_SIMPLEV_FALSE;
1963 if(b) {
1964 uSimple = CBOR_SIMPLEV_TRUE;
1965 }
1966 QCBOREncode_AddSimple(pCtx, uSimple);
1967}
1968
1969static inline void QCBOREncode_AddBoolToMap(QCBOREncodeContext *pCtx, const char *szLabel, bool b)
1970{
1971 QCBOREncode_AddSZString(pCtx, szLabel);
1972 QCBOREncode_AddBool(pCtx, b);
1973}
1974
1975static inline void QCBOREncode_AddBoolToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, bool b)
1976{
1977 QCBOREncode_AddInt64(pCtx, nLabel);
1978 QCBOREncode_AddBool(pCtx, b);
1979}
1980
1981
1982static inline void QCBOREncode_AddNULL(QCBOREncodeContext *pCtx)
1983{
1984 QCBOREncode_AddSimple(pCtx, CBOR_SIMPLEV_NULL);
1985}
1986
1987static inline void QCBOREncode_AddNULLToMap(QCBOREncodeContext *pCtx, const char *szLabel)
1988{
1989 QCBOREncode_AddSZString(pCtx, szLabel);
1990 QCBOREncode_AddNULL(pCtx);
1991}
1992
1993static inline void QCBOREncode_AddNULLToMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
1994{
1995 QCBOREncode_AddInt64(pCtx, nLabel);
1996 QCBOREncode_AddNULL(pCtx);
1997}
1998
1999
2000static inline void QCBOREncode_AddUndef(QCBOREncodeContext *pCtx)
2001{
2002 QCBOREncode_AddSimple(pCtx, CBOR_SIMPLEV_UNDEF);
2003}
2004
2005static inline void QCBOREncode_AddUndefToMap(QCBOREncodeContext *pCtx, const char *szLabel)
2006{
2007 QCBOREncode_AddSZString(pCtx, szLabel);
2008 QCBOREncode_AddUndef(pCtx);
2009}
2010
2011static inline void QCBOREncode_AddUndefToMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
2012{
2013 QCBOREncode_AddInt64(pCtx, nLabel);
2014 QCBOREncode_AddUndef(pCtx);
2015}
2016
2017
2018static inline void QCBOREncode_OpenArray(QCBOREncodeContext *pCtx)
2019{
2020 QCBOREncode_OpenMapOrArray(pCtx, CBOR_MAJOR_TYPE_ARRAY);
2021}
2022
2023static inline void QCBOREncode_OpenArrayInMap(QCBOREncodeContext *pCtx, const char *szLabel)
2024{
2025 QCBOREncode_AddSZString(pCtx, szLabel);
2026 QCBOREncode_OpenArray(pCtx);
2027}
2028
2029static inline void QCBOREncode_OpenArrayInMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
2030{
2031 QCBOREncode_AddInt64(pCtx, nLabel);
2032 QCBOREncode_OpenArray(pCtx);
2033}
2034
2035static inline void QCBOREncode_CloseArray(QCBOREncodeContext *pCtx)
2036{
2037 QCBOREncode_CloseMapOrArray(pCtx, CBOR_MAJOR_TYPE_ARRAY);
2038}
2039
2040
2041static inline void QCBOREncode_OpenMap(QCBOREncodeContext *pCtx)
2042{
2043 QCBOREncode_OpenMapOrArray(pCtx, CBOR_MAJOR_TYPE_MAP);
2044}
2045
2046static inline void QCBOREncode_OpenMapInMap(QCBOREncodeContext *pCtx, const char *szLabel)
2047{
2048 QCBOREncode_AddSZString(pCtx, szLabel);
2049 QCBOREncode_OpenMap(pCtx);
2050}
2051
2052static inline void QCBOREncode_OpenMapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
2053{
2054 QCBOREncode_AddInt64(pCtx, nLabel);
2055 QCBOREncode_OpenMap(pCtx);
2056}
2057
2058static inline void QCBOREncode_CloseMap(QCBOREncodeContext *pCtx)
2059{
2060 QCBOREncode_CloseMapOrArray(pCtx, CBOR_MAJOR_TYPE_MAP);
2061}
2062
2063static inline void QCBOREncode_OpenArrayIndefiniteLength(QCBOREncodeContext *pCtx)
2064{
2065 QCBOREncode_OpenMapOrArrayIndefiniteLength(pCtx, CBOR_MAJOR_NONE_TYPE_ARRAY_INDEFINITE_LEN);
2066}
2067
2068static inline void QCBOREncode_OpenArrayIndefiniteLengthInMap(QCBOREncodeContext *pCtx, const char *szLabel)
2069{
2070 QCBOREncode_AddSZString(pCtx, szLabel);
2071 QCBOREncode_OpenArrayIndefiniteLength(pCtx);
2072}
2073
2074static inline void QCBOREncode_OpenArrayIndefiniteLengthInMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
2075{
2076 QCBOREncode_AddInt64(pCtx, nLabel);
2077 QCBOREncode_OpenArrayIndefiniteLength(pCtx);
2078}
2079
2080static inline void QCBOREncode_CloseArrayIndefiniteLength(QCBOREncodeContext *pCtx)
2081{
2082 QCBOREncode_CloseMapOrArrayIndefiniteLength(pCtx, CBOR_MAJOR_NONE_TYPE_ARRAY_INDEFINITE_LEN);
2083}
2084
2085
2086static inline void QCBOREncode_OpenMapIndefiniteLength(QCBOREncodeContext *pCtx)
2087{
2088 QCBOREncode_OpenMapOrArrayIndefiniteLength(pCtx, CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN);
2089}
2090
2091static inline void QCBOREncode_OpenMapIndefiniteLengthInMap(QCBOREncodeContext *pCtx, const char *szLabel)
2092{
2093 QCBOREncode_AddSZString(pCtx, szLabel);
2094 QCBOREncode_OpenMapIndefiniteLength(pCtx);
2095}
2096
2097static inline void QCBOREncode_OpenMapIndefiniteLengthInMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
2098{
2099 QCBOREncode_AddInt64(pCtx, nLabel);
2100 QCBOREncode_OpenMapIndefiniteLength(pCtx);
2101}
2102
2103static inline void QCBOREncode_CloseMapIndefiniteLength(QCBOREncodeContext *pCtx)
2104{
2105 QCBOREncode_CloseMapOrArrayIndefiniteLength(pCtx, CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN);
2106}
2107
2108
2109static inline void QCBOREncode_BstrWrap(QCBOREncodeContext *pCtx)
2110{
2111 QCBOREncode_OpenMapOrArray(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING);
2112}
2113
2114static inline void QCBOREncode_BstrWrapInMap(QCBOREncodeContext *pCtx, const char *szLabel)
2115{
2116 QCBOREncode_AddSZString(pCtx, szLabel);
2117 QCBOREncode_BstrWrap(pCtx);
2118}
2119
2120static inline void QCBOREncode_BstrWrapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
2121{
2122 QCBOREncode_AddInt64(pCtx, nLabel);
2123 QCBOREncode_BstrWrap(pCtx);
2124}
2125
2126static inline void QCBOREncode_CloseBstrWrap(QCBOREncodeContext *pCtx, UsefulBufC *pWrappedCBOR)
2127{
2128 QCBOREncode_CloseBstrWrap2(pCtx, true, pWrappedCBOR);
2129}
2130
2131
2132static inline void QCBOREncode_AddEncoded(QCBOREncodeContext *pCtx, UsefulBufC Encoded)
2133{
2134 QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_NONE_TYPE_RAW, Encoded);
2135}
2136
2137static inline void QCBOREncode_AddEncodedToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Encoded)
2138{
2139 QCBOREncode_AddSZString(pCtx, szLabel);
2140 QCBOREncode_AddEncoded(pCtx, Encoded);
2141}
2142
2143static inline void QCBOREncode_AddEncodedToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Encoded)
2144{
2145 QCBOREncode_AddInt64(pCtx, nLabel);
2146 QCBOREncode_AddEncoded(pCtx, Encoded);
2147}
2148
2149
2150static inline int QCBOREncode_IsBufferNULL(QCBOREncodeContext *pCtx)
2151{
2152 return UsefulOutBuf_IsBufferNULL(&(pCtx->OutBuf));
2153}
2154
2155static inline QCBORError QCBOREncode_GetErrorState(QCBOREncodeContext *pCtx)
2156{
2157 if(UsefulOutBuf_GetError(&(pCtx->OutBuf))) {
2158 // Items didn't fit in the buffer.
2159 // This check catches this condition for all the appends and inserts
2160 // so checks aren't needed when the appends and inserts are performed.
2161 // And of course UsefulBuf will never overrun the input buffer given
2162 // to it. No complex analysis of the error handling in this file is
2163 // needed to know that is true. Just read the UsefulBuf code.
2164 pCtx->uError = QCBOR_ERR_BUFFER_TOO_SMALL;
2165 // QCBOR_ERR_BUFFER_TOO_SMALL masks other errors, but that is
2166 // OK. Once the caller fixes this, they'll be unmasked.
2167 }
2168
2169 return (QCBORError)pCtx->uError;
2170}
2171
2172
2173/* ===========================================================================
2174 END OF PRIVATE INLINE IMPLEMENTATION
2175
2176 =========================================================================== */
2177
2178#ifdef __cplusplus
2179}
2180#endif
2181
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002182#endif /* qcbor_encode_h */