blob: adda8248f22549c17d7a8c18e4e75c8b913ccc94 [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.
Laurence Lundblade2feb1e12020-07-15 03:50:45 -0700213
Laurence Lundbladee3553422020-05-02 11:11:17 -0700214 Many CBOR-based protocols start with an array or map. This makes them
215 self-delimiting. No external length or end marker is needed to know
216 the end. It is also possible not start this way, in which case this
217 it is usually called a CBOR sequence which is described in [RFC 8742] (https://tools.ietf.org/html/rfc8742 ).
218 This encoder supports either just by whether the first item added is an
219 array, map or other.
Michael Eckel5c531332020-03-02 01:35:30 +0100220
221 @anchor Tags-Overview
222 Any CBOR data item can be tagged to add semantics, define a new data
223 type or such. Some tags are fully standardized and some are just
224 registered. Others are not registered and used in a proprietary way.
225
226 Encoding and decoding of many of the registered tags is fully
227 implemented by QCBOR. It is also possible to encode and decode tags
228 that are not directly supported. For many use cases the built-in tag
229 support should be adequate.
230
231 For example, the registered epoch date tag is supported in encoding
232 by QCBOREncode_AddDateEpoch() and in decoding by @ref
233 QCBOR_TYPE_DATE_EPOCH and the @c epochDate member of @ref
234 QCBORItem. This is typical of the built-in tag support. There is an
235 API to encode data for it and a @c QCBOR_TYPE_XXX when it is decoded.
236
237 Tags are registered in the [IANA CBOR Tags Registry]
238 (https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml). There
239 are roughly three options to create a new tag. First, a public
240 specification can be created and the new tag registered with IANA.
241 This is the most formal. Second, the new tag can be registered with
242 IANA with just a short description rather than a full specification.
243 These tags must be greater than 256. Third, a tag can be used without
244 any IANA registration, though the registry should be checked to see
245 that the new value doesn't collide with one that is registered. The
246 value of these tags must be 256 or larger.
247
248 The encoding side of tags not built-in is handled by
249 QCBOREncode_AddTag() and is relatively simple. Tag decoding is more
250 complex and mainly handled by QCBORDecode_GetNext(). Decoding of the
251 structure of tagged data not built-in (if there is any) has to be
252 implemented by the caller.
253
Laurence Lundblade5fb6ab42020-07-16 03:28:47 -0700254 @anchor Floating-Point
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700255 By default QCBOR fully supports IEEE 754 floating-point:
Laurence Lundblade5fb6ab42020-07-16 03:28:47 -0700256 - Encode/decode of double, single and half-precision
257 - CBOR preferred serialization of floating-point
258 - Floating-point epoch dates
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700259
Laurence Lundblade5fb6ab42020-07-16 03:28:47 -0700260 For the most part, the type double is used in the interface for
261 floating-point values. In the default configuration, all decoded
262 floating-point values are returned as a double.
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700263
Laurence Lundblade5fb6ab42020-07-16 03:28:47 -0700264 With CBOR preferred serialization, the encoder outputs the smallest
265 representation of the double or float that preserves precision. Zero,
266 NaN and infinity are always output as a half-precision, each taking
267 just 2 bytes. This reduces the number of bytes needed to encode
268 doubles and floats, especially if the zero, NaN and infinity are
269 frequently used.
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700270
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700271 To avoid use of preferred serialization in the standard configuration when encoding, use
Laurence Lundblade5fb6ab42020-07-16 03:28:47 -0700272 QCBOREncode_AddDoubleNoPreferred() or
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700273 QCBOREncode_AddFloatNoPreferred().
274
Laurence Lundblade5fb6ab42020-07-16 03:28:47 -0700275 This implementation of preferred floating-point serialization and
276 half-precision does not depend on the CPU having floating-point HW or
277 the compiler bringing in a (sometimes large) library to compensate
278 for lack of CPU support. The implementation uses shifts and masks
279 rather than floating-point functions. It does however add object
280 code.
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700281
Laurence Lundblade5fb6ab42020-07-16 03:28:47 -0700282 To reduce object code, define QCBOR_DISABLE_PREFERRED_FLOAT. This
283 will eliminate all support for preferred serialization and
284 half-precision. An error will be returned when attempting to decode
285 half-precision. A float will always be encoded and decoded as 32-bits
Laurence Lundbladefe09bbf2020-07-16 12:14:51 -0700286 and a double will always be encoded and decoded as 64 bits. This
287 will reduce object code by about 900 bytes.
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700288
Laurence Lundblade5fb6ab42020-07-16 03:28:47 -0700289 Note that even if QCBOR_DISABLE_PREFERRED_FLOAT is not defined all
290 the float-point encoding object code can be avoided by never calling
Laurence Lundbladefe09bbf2020-07-16 12:14:51 -0700291 any functions that encode double or float. Just not calling
292 floating-point functions will reduce object code by about 500 bytes.
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700293
Laurence Lundblade5fb6ab42020-07-16 03:28:47 -0700294 On CPUs that have no floating-point hardware,
295 QCBOR_DISABLE_FLOAT_HW_USE should be defined in most cases. If it is
296 not, then the compiler will bring in possibly large software
297 libraries to compensate or QCBOR will not compile. Defining
298 QCBOR_DISABLE_FLOAT_HW_USE reduces object code size on CPUs with
299 floating-point hardware by a tiny amount.
300
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700301 When QCBOR_DISABLE_FLOAT_HW_USE is defined, trying to
302 decoding floating point dates will give error @ref QCBOR_ERR_FLOAT_DATE_DISABLED and decoded
303 single-precision
304 numbers will be returned as @ref QCBOR_TYPE_FLOAT instead of converting them to
305 double as usual.
306
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700307
308 If both QCBOR_DISABLE_FLOAT_HW_USE and QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade5fb6ab42020-07-16 03:28:47 -0700309 are defined, then the only thing QCBOR can do is encode/decode a
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700310 C float type as 32-bits and a C double type as 64-bits. Floating-point epoch dates
Laurence Lundblade5fb6ab42020-07-16 03:28:47 -0700311 will be unsupported.
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700312
Michael Eckel5c531332020-03-02 01:35:30 +0100313 Summary Limits of this implementation:
314 - The entire encoded CBOR must fit into contiguous memory.
315 - Max size of encoded / decoded CBOR data is @c UINT32_MAX (4GB).
316 - Max array / map nesting level when encoding / decoding is
317 @ref QCBOR_MAX_ARRAY_NESTING (this is typically 15).
318 - Max items in an array or map when encoding / decoding is
319 @ref QCBOR_MAX_ITEMS_IN_ARRAY (typically 65,536).
320 - Does not directly support labels in maps other than text strings & integers.
321 - Does not directly support integer labels greater than @c INT64_MAX.
322 - Epoch dates limited to @c INT64_MAX (+/- 292 billion years).
323 - Exponents for bigfloats and decimal integers are limited to @c INT64_MAX.
324 - Tags on labels are ignored during decoding.
325 - There is no duplicate detection of map labels (but duplicates are passed on).
326 - Works only on 32- and 64-bit CPUs (modifications could make it work
327 on 16-bit CPUs).
328
329 The public interface uses @c size_t for all lengths. Internally the
330 implementation uses 32-bit lengths by design to use less memory and
331 fit structures on the stack. This limits the encoded CBOR it can work
332 with to size @c UINT32_MAX (4GB) which should be enough.
333
334 This implementation assumes two's compliment integer machines. @c
335 <stdint.h> also requires this. It is possible to modify this
336 implementation for another integer representation, but all modern
337 machines seem to be two's compliment.
338
339 */
340
341
Michael Eckel5c531332020-03-02 01:35:30 +0100342/*
343 The size of the buffer to be passed to QCBOREncode_EncodeHead(). It is one
344 byte larger than sizeof(uint64_t) + 1, the actual maximum size of the
345 head of a CBOR data item. because QCBOREncode_EncodeHead() needs
346 one extra byte to work.
347 */
348#define QCBOR_HEAD_BUFFER_SIZE (sizeof(uint64_t) + 2)
349
Michael Eckel5c531332020-03-02 01:35:30 +0100350
351
352/**
353 QCBOREncodeContext is the data type that holds context for all the
354 encoding functions. It is less than 200 bytes, so it can go on the
355 stack. The contents are opaque, and the caller should not access
356 internal members. A context may be re used serially as long as it is
357 re initialized.
358 */
359typedef struct _QCBOREncodeContext QCBOREncodeContext;
360
361
362/**
363 Initialize the encoder to prepare to encode some CBOR.
364
365 @param[in,out] pCtx The encoder context to initialize.
366 @param[in] Storage The buffer into which this encoded result
367 will be placed.
368
369 Call this once at the start of an encoding of a CBOR structure. Then
370 call the various @c QCBOREncode_AddXxx() functions to add the data
371 items. Then call QCBOREncode_Finish().
372
373 The maximum output buffer is @c UINT32_MAX (4GB). This is not a
374 practical limit in any way and reduces the memory needed by the
375 implementation. The error @ref QCBOR_ERR_BUFFER_TOO_LARGE will be
376 returned by QCBOREncode_Finish() if a larger buffer length is passed
377 in.
378
379 If this is called with @c Storage.ptr as @c NULL and @c Storage.len a
380 large value like @c UINT32_MAX, all the QCBOREncode_AddXxx()
381 functions and QCBOREncode_Finish() can still be called. No data will
382 be encoded, but the length of what would be encoded will be
383 calculated. The length of the encoded structure will be handed back
384 in the call to QCBOREncode_Finish(). You can then allocate a buffer
385 of that size and call all the encoding again, this time to fill in
386 the buffer.
387
388 A @ref QCBOREncodeContext can be reused over and over as long as
389 QCBOREncode_Init() is called.
390 */
391void QCBOREncode_Init(QCBOREncodeContext *pCtx, UsefulBuf Storage);
392
393
394/**
395 @brief Add a signed 64-bit integer to the encoded output.
396
397 @param[in] pCtx The encoding context to add the integer to.
398 @param[in] nNum The integer to add.
399
400 The integer will be encoded and added to the CBOR output.
401
402 This function figures out the size and the sign and encodes in the
403 correct minimal CBOR. Specifically, it will select CBOR major type 0
404 or 1 based on sign and will encode to 1, 2, 4 or 8 bytes depending on
405 the value of the integer. Values less than 24 effectively encode to
406 one byte because they are encoded in with the CBOR major type. This
407 is a neat and efficient characteristic of CBOR that can be taken
408 advantage of when designing CBOR-based protocols. If integers like
409 tags can be kept between -23 and 23 they will be encoded in one byte
410 including the major type.
411
412 If you pass a smaller int, say an @c int16_t or a small value, say
413 100, the encoding will still be CBOR's most compact that can
414 represent the value. For example, CBOR always encodes the value 0 as
415 one byte, 0x00. The representation as 0x00 includes identification of
416 the type as an integer too as the major type for an integer is 0. See
417 [RFC 7049] (https://tools.ietf.org/html/rfc7049) Appendix A for more
418 examples of CBOR encoding. This compact encoding is also canonical
419 CBOR as per section 3.9 in RFC 7049.
420
421 There are no functions to add @c int16_t or @c int32_t because they
422 are not necessary because this always encodes to the smallest number
423 of bytes based on the value (If this code is running on a 32-bit
424 machine having a way to add 32-bit integers would reduce code size
425 some).
426
427 If the encoding context is in an error state, this will do
428 nothing. If an error occurs when adding this integer, the internal
429 error flag will be set, and the error will be returned when
430 QCBOREncode_Finish() is called.
431
432 See also QCBOREncode_AddUInt64().
433 */
434void QCBOREncode_AddInt64(QCBOREncodeContext *pCtx, int64_t nNum);
435
436static void QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t uNum);
437
438static void QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t uNum);
439
440
441/**
442 @brief Add an unsigned 64-bit integer to the encoded output.
443
444 @param[in] pCtx The encoding context to add the integer to.
445 @param[in] uNum The integer to add.
446
447 The integer will be encoded and added to the CBOR output.
448
449 The only reason so use this function is for integers larger than @c
450 INT64_MAX and smaller than @c UINT64_MAX. Otherwise
451 QCBOREncode_AddInt64() will work fine.
452
453 Error handling is the same as for QCBOREncode_AddInt64().
454 */
455void QCBOREncode_AddUInt64(QCBOREncodeContext *pCtx, uint64_t uNum);
456
457static void QCBOREncode_AddUInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t uNum);
458
459static void QCBOREncode_AddUInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, uint64_t uNum);
460
461
462/**
463 @brief Add a UTF-8 text string to the encoded output.
464
465 @param[in] pCtx The encoding context to add the text to.
466 @param[in] Text Pointer and length of text to add.
467
468 The text passed in must be unencoded UTF-8 according to [RFC 3629]
469 (https://tools.ietf.org/html/rfc3629). There is no NULL
470 termination. The text is added as CBOR major type 3.
471
472 If called with @c nBytesLen equal to 0, an empty string will be
473 added. When @c nBytesLen is 0, @c pBytes may be @c NULL.
474
475 Note that the restriction of the buffer length to a @c uint32_t is
476 entirely intentional as this encoder is not capable of encoding
477 lengths greater. This limit to 4GB for a text string should not be a
478 problem.
479
480 Error handling is the same as QCBOREncode_AddInt64().
481 */
482static void QCBOREncode_AddText(QCBOREncodeContext *pCtx, UsefulBufC Text);
483
484static void QCBOREncode_AddTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Text);
485
486static void QCBOREncode_AddTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Text);
487
488
489/**
490 @brief Add a UTF-8 text string to the encoded output.
491
492 @param[in] pCtx The encoding context to add the text to.
493 @param[in] szString Null-terminated text to add.
494
495 This works the same as QCBOREncode_AddText().
496 */
497static void QCBOREncode_AddSZString(QCBOREncodeContext *pCtx, const char *szString);
498
499static void QCBOREncode_AddSZStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szString);
500
501static void QCBOREncode_AddSZStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szString);
502
503
504/**
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700505 @brief Add a double-precision floating-point number to the encoded output.
Michael Eckel5c531332020-03-02 01:35:30 +0100506
507 @param[in] pCtx The encoding context to add the double to.
508 @param[in] dNum The double-precision number to add.
509
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700510 This encodes and outputs a floating-point number. CBOR major type 7
511 is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100512
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700513 This implements preferred serialization, selectively encoding the
514 double-precision floating-point number as either double-precision,
515 single-precision or half-precision. Infinity, NaN and 0 are always
516 encoded as half-precision. If no precision will be lost in the
517 conversion to half-precision, then it will be converted and
518 encoded. If not and no precision will be lost in conversion to
519 single-precision, then it will be converted and encoded. If not, then
520 no conversion is performed, and it encoded as a double-precision.
Michael Eckel5c531332020-03-02 01:35:30 +0100521
522 Half-precision floating-point numbers take up 2 bytes, half that of
523 single-precision, one quarter of double-precision
524
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700525 This automatically reduces the size of encoded CBOR, maybe even by
526 four if most of values are 0, infinity or NaN.
Michael Eckel5c531332020-03-02 01:35:30 +0100527
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700528 When decoded, QCBOR will usually return these values as
529 double-precision.
530
531 It is possible to disable this preferred serialization when compiling
532 QCBOR. In that case, this functions the same as
533 QCBOREncode_AddDoubleNoPreferred().
Michael Eckel5c531332020-03-02 01:35:30 +0100534
535 Error handling is the same as QCBOREncode_AddInt64().
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700536
537 See also QCBOREncode_AddDoubleNoPreferred(), QCBOREncode_AddFloat()
538 and QCBOREncode_AddFloatNoPreferred() and @ref Floating-Point.
Michael Eckel5c531332020-03-02 01:35:30 +0100539 */
540void QCBOREncode_AddDouble(QCBOREncodeContext *pCtx, double dNum);
541
542static void QCBOREncode_AddDoubleToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum);
543
544static void QCBOREncode_AddDoubleToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum);
545
546
547/**
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700548 @brief Add a single-precision floating-point number to the encoded output.
549
550 @param[in] pCtx The encoding context to add the double to.
551 @param[in] fNum The single-precision number to add.
552
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700553 This is identical to QCBOREncode_AddDouble() except the input is
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700554 single-precision.
555
556 See also QCBOREncode_AddDouble(), QCBOREncode_AddDoubleNoPreferred(),
557 and QCBOREncode_AddFloatNoPreferred() and @ref Floating-Point.
558*/
559void QCBOREncode_AddFloat(QCBOREncodeContext *pCtx, float fNum);
560
561static void QCBOREncode_AddFloatToMap(QCBOREncodeContext *pCtx, const char *szLabel, float fNum);
562
563static void QCBOREncode_AddFloatToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, float dNum);
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700564
565
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700566/**
567 @brief Add a double-precision floating-point number without preferred encoding.
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700568
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700569 @param[in] pCtx The encoding context to add the double to.
570 @param[in] dNum The double-precision number to add.
571
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700572 This always outputs the number as a 64-bit double-precision.
573 Preferred serialization is not used.
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700574
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700575 Error handling is the same as QCBOREncode_AddInt64().
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700576
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700577 See also QCBOREncode_AddDouble(), QCBOREncode_AddFloat(), and
578 QCBOREncode_AddFloatNoPreferred() and @ref Floating-Point.
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700579*/
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700580void QCBOREncode_AddDoubleNoPreferred(QCBOREncodeContext *pCtx, double dNum);
581
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700582static void QCBOREncode_AddDoubleNoPreferredToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum);
583
584static void QCBOREncode_AddDoubleNoPreferredToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum);
585
586
587/**
588 @brief Add a single-precision floating-point number without preferred encoding.
589
590 @param[in] pCtx The encoding context to add the double to.
591 @param[in] fNum The single-precision number to add.
592
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700593 This always outputs the number as a 32-bit single-precision.
594 Preferred serialization is not used.
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700595
596 Error handling is the same as QCBOREncode_AddInt64().
597
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700598 See also QCBOREncode_AddDouble(), QCBOREncode_AddFloat(), and
599 QCBOREncode_AddDoubleNoPreferred() and @ref Floating-Point.
Laurence Lundblade32f3e622020-07-13 20:35:11 -0700600*/
601void QCBOREncode_AddFloatNoPreferred(QCBOREncodeContext *pCtx, float fNum);
602
603static void QCBOREncode_AddFloatNoPreferredToMap(QCBOREncodeContext *pCtx, const char *szLabel, float fNum);
604
605static void QCBOREncode_AddFloatNoPreferredToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, float fNum);
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700606
607
Michael Eckel5c531332020-03-02 01:35:30 +0100608
609/**
610 @brief Add an optional tag.
611
612 @param[in] pCtx The encoding context to add the tag to.
613 @param[in] uTag The tag to add
614
615 This outputs a CBOR major type 6 item that tags the next data item
616 that is output usually to indicate it is some new data type.
617
618 For many of the common standard tags, a function to encode data using
619 it is provided and this is not needed. For example,
620 QCBOREncode_AddDateEpoch() already exists to output integers
621 representing dates with the right tag.
622
623 The tag is applied to the next data item added to the encoded
624 output. That data item that is to be tagged can be of any major CBOR
625 type. Any number of tags can be added to a data item by calling this
626 multiple times before the data item is added.
627
628 See @ref Tags-Overview for discussion of creating new non-standard
629 tags. See QCBORDecode_GetNext() for discussion of decoding custom
630 tags.
631*/
632void QCBOREncode_AddTag(QCBOREncodeContext *pCtx,uint64_t uTag);
633
634
635/**
636 @brief Add an epoch-based date.
637
638 @param[in] pCtx The encoding context to add the date to.
639 @param[in] date Number of seconds since 1970-01-01T00:00Z in UTC time.
640
641 As per RFC 7049 this is similar to UNIX/Linux/POSIX dates. This is
642 the most compact way to specify a date and time in CBOR. Note that
643 this is always UTC and does not include the time zone. Use
644 QCBOREncode_AddDateString() if you want to include the time zone.
645
646 The integer encoding rules apply here so the date will be encoded in
647 a minimal number of bytes. Until about the year 2106 these dates will
648 encode in 6 bytes -- one byte for the tag, one byte for the type and
649 4 bytes for the integer. After that it will encode to 10 bytes.
650
651 Negative values are supported for dates before 1970.
652
653 If you care about leap-seconds and that level of accuracy, make sure
654 the system you are running this code on does it correctly. This code
655 just takes the value passed in.
656
657 This implementation cannot encode fractional seconds using float or
658 double even though that is allowed by CBOR, but you can encode them
659 if you want to by calling QCBOREncode_AddDouble() and
660 QCBOREncode_AddTag().
661
662 Error handling is the same as QCBOREncode_AddInt64().
663 */
664static void QCBOREncode_AddDateEpoch(QCBOREncodeContext *pCtx, int64_t date);
665
666static void QCBOREncode_AddDateEpochToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t date);
667
668static void QCBOREncode_AddDateEpochToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t date);
669
670
671/**
672 @brief Add a byte string to the encoded output.
673
674 @param[in] pCtx The encoding context to add the bytes to.
675 @param[in] Bytes Pointer and length of the input data.
676
677 Simply adds the bytes to the encoded output as CBOR major type 2.
678
679 If called with @c Bytes.len equal to 0, an empty string will be
680 added. When @c Bytes.len is 0, @c Bytes.ptr may be @c NULL.
681
682 Error handling is the same as QCBOREncode_AddInt64().
683 */
684static void QCBOREncode_AddBytes(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
685
686static void QCBOREncode_AddBytesToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
687
688static void QCBOREncode_AddBytesToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
689
690
691
692/**
693 @brief Add a binary UUID to the encoded output.
694
695 @param[in] pCtx The encoding context to add the UUID to.
696 @param[in] Bytes Pointer and length of the binary UUID.
697
698 A binary UUID as defined in [RFC 4122]
699 (https://tools.ietf.org/html/rfc4122) is added to the output.
700
701 It is output as CBOR major type 2, a binary string, with tag @ref
702 CBOR_TAG_BIN_UUID indicating the binary string is a UUID.
703 */
704static void QCBOREncode_AddBinaryUUID(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
705
706static void QCBOREncode_AddBinaryUUIDToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
707
708static void QCBOREncode_AddBinaryUUIDToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
709
710
711/**
712 @brief Add a positive big number to the encoded output.
713
714 @param[in] pCtx The encoding context to add the big number to.
715 @param[in] Bytes Pointer and length of the big number.
716
717 Big numbers are integers larger than 64-bits. Their format is
718 described in [RFC 7049] (https://tools.ietf.org/html/rfc7049).
719
720 It is output as CBOR major type 2, a binary string, with tag @ref
721 CBOR_TAG_POS_BIGNUM indicating the binary string is a positive big
722 number.
723
724 Often big numbers are used to represent cryptographic keys, however,
725 COSE which defines representations for keys chose not to use this
726 particular type.
727 */
728static void QCBOREncode_AddPositiveBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
729
730static void QCBOREncode_AddPositiveBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
731
732static void QCBOREncode_AddPositiveBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
733
734
735/**
736 @brief Add a negative big number to the encoded output.
737
738 @param[in] pCtx The encoding context to add the big number to.
739 @param[in] Bytes Pointer and length of the big number.
740
741 Big numbers are integers larger than 64-bits. Their format is
742 described in [RFC 7049] (https://tools.ietf.org/html/rfc7049).
743
744 It is output as CBOR major type 2, a binary string, with tag @ref
745 CBOR_TAG_NEG_BIGNUM indicating the binary string is a negative big
746 number.
747
748 Often big numbers are used to represent cryptographic keys, however,
749 COSE which defines representations for keys chose not to use this
750 particular type.
751 */
752static void QCBOREncode_AddNegativeBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
753
754static void QCBOREncode_AddNegativeBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
755
756static void QCBOREncode_AddNegativeBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
757
758
759#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
760/**
761 @brief Add a decimal fraction to the encoded output.
762
763 @param[in] pCtx The encoding context to add the decimal fraction to.
764 @param[in] nMantissa The mantissa.
765 @param[in] nBase10Exponent The exponent.
766
767 The value is nMantissa * 10 ^ nBase10Exponent.
768
769 A decimal fraction is good for exact representation of some values
770 that can't be represented exactly with standard C (IEEE 754)
771 floating-point numbers. Much larger and much smaller numbers can
772 also be represented than floating-point because of the larger number
773 of bits in the exponent.
774
775 The decimal fraction is conveyed as two integers, a mantissa and a
776 base-10 scaling factor.
777
778 For example, 273.15 is represented by the two integers 27315 and -2.
779
780 The exponent and mantissa have the range from @c INT64_MIN to
781 @c INT64_MAX for both encoding and decoding (CBOR allows @c -UINT64_MAX
782 to @c UINT64_MAX, but this implementation doesn't support this range to
783 reduce code size and interface complexity a little).
784
785 CBOR Preferred encoding of the integers is used, thus they will be encoded
786 in the smallest number of bytes possible.
787
788 See also QCBOREncode_AddDecimalFractionBigNum() for a decimal
789 fraction with arbitrarily large precision and QCBOREncode_AddBigFloat().
790
791 There is no representation of positive or negative infinity or NaN
792 (Not a Number). Use QCBOREncode_AddDouble() to encode them.
793
794 See @ref expAndMantissa for decoded representation.
795 */
796static void QCBOREncode_AddDecimalFraction(QCBOREncodeContext *pCtx,
797 int64_t nMantissa,
798 int64_t nBase10Exponent);
799
800static void QCBOREncode_AddDecimalFractionToMap(QCBOREncodeContext *pCtx,
801 const char *szLabel,
802 int64_t nMantissa,
803 int64_t nBase10Exponent);
804
805static void QCBOREncode_AddDecimalFractionToMapN(QCBOREncodeContext *pCtx,
806 int64_t nLabel,
807 int64_t nMantissa,
808 int64_t nBase10Exponent);
809
810/**
811 @brief Add a decimal fraction with a big number mantissa to the encoded output.
812
813 @param[in] pCtx The encoding context to add the decimal fraction to.
814 @param[in] Mantissa The mantissa.
815 @param[in] bIsNegative false if mantissa is positive, true if negative.
816 @param[in] nBase10Exponent The exponent.
817
818 This is the same as QCBOREncode_AddDecimalFraction() except the
819 mantissa is a big number (See QCBOREncode_AddPositiveBignum())
820 allowing for arbitrarily large precision.
821
822 See @ref expAndMantissa for decoded representation.
823 */
824static void QCBOREncode_AddDecimalFractionBigNum(QCBOREncodeContext *pCtx,
825 UsefulBufC Mantissa,
826 bool bIsNegative,
827 int64_t nBase10Exponent);
828
829static void QCBOREncode_AddDecimalFractionBigNumToMap(QCBOREncodeContext *pCtx,
830 const char *szLabel,
831 UsefulBufC Mantissa,
832 bool bIsNegative,
833 int64_t nBase10Exponent);
834
835static void QCBOREncode_AddDecimalFractionBigNumToMapN(QCBOREncodeContext *pCtx,
836 int64_t nLabel,
837 UsefulBufC Mantissa,
838 bool bIsNegative,
839 int64_t nBase10Exponent);
840
841/**
842 @brief Add a big floating-point number to the encoded output.
843
844 @param[in] pCtx The encoding context to add the bigfloat to.
845 @param[in] nMantissa The mantissa.
846 @param[in] nBase2Exponent The exponent.
847
848 The value is nMantissa * 2 ^ nBase2Exponent.
849
850 "Bigfloats", as CBOR terms them, are similar to IEEE floating-point
851 numbers in having a mantissa and base-2 exponent, but they are not
852 supported by hardware or encoded the same. They explicitly use two
853 CBOR-encoded integers to convey the mantissa and exponent, each of which
854 can be 8, 16, 32 or 64 bits. With both the mantissa and exponent
855 64 bits they can express more precision and a larger range than an
856 IEEE double floating-point number. See
857 QCBOREncode_AddBigFloatBigNum() for even more precision.
858
859 For example, 1.5 would be represented by a mantissa of 3 and an
860 exponent of -1.
861
862 The exponent and mantissa have the range from @c INT64_MIN to
863 @c INT64_MAX for both encoding and decoding (CBOR allows @c -UINT64_MAX
864 to @c UINT64_MAX, but this implementation doesn't support this range to
865 reduce code size and interface complexity a little).
866
867 CBOR Preferred encoding of the integers is used, thus they will be encoded
868 in the smallest number of bytes possible.
869
870 This can also be used to represent floating-point numbers in
871 environments that don't support IEEE 754.
872
873 See @ref expAndMantissa for decoded representation.
874 */
875static void QCBOREncode_AddBigFloat(QCBOREncodeContext *pCtx,
876 int64_t nMantissa,
877 int64_t nBase2Exponent);
878
879static void QCBOREncode_AddBigFloatToMap(QCBOREncodeContext *pCtx,
880 const char *szLabel,
881 int64_t nMantissa,
882 int64_t nBase2Exponent);
883
884static void QCBOREncode_AddBigFloatToMapN(QCBOREncodeContext *pCtx,
885 int64_t nLabel,
886 int64_t nMantissa,
887 int64_t nBase2Exponent);
888
889
890/**
891 @brief Add a big floating-point number with a big number mantissa to
892 the encoded output.
893
894 @param[in] pCtx The encoding context to add the bigfloat to.
895 @param[in] Mantissa The mantissa.
896 @param[in] bIsNegative false if mantissa is positive, true if negative.
897 @param[in] nBase2Exponent The exponent.
898
899 This is the same as QCBOREncode_AddBigFloat() except the mantissa is
900 a big number (See QCBOREncode_AddPositiveBignum()) allowing for
901 arbitrary precision.
902
903 See @ref expAndMantissa for decoded representation.
904 */
905static void QCBOREncode_AddBigFloatBigNum(QCBOREncodeContext *pCtx,
906 UsefulBufC Mantissa,
907 bool bIsNegative,
908 int64_t nBase2Exponent);
909
910static void QCBOREncode_AddBigFloatBigNumToMap(QCBOREncodeContext *pCtx,
911 const char *szLabel,
912 UsefulBufC Mantissa,
913 bool bIsNegative,
914 int64_t nBase2Exponent);
915
916static void QCBOREncode_AddBigFloatBigNumToMapN(QCBOREncodeContext *pCtx,
917 int64_t nLabel,
918 UsefulBufC Mantissa,
919 bool bIsNegative,
920 int64_t nBase2Exponent);
921#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
922
923
924/**
925 @brief Add a text URI to the encoded output.
926
927 @param[in] pCtx The encoding context to add the URI to.
928 @param[in] URI Pointer and length of the URI.
929
930 The format of URI must be per [RFC 3986]
931 (https://tools.ietf.org/html/rfc3986).
932
933 It is output as CBOR major type 3, a text string, with tag @ref
934 CBOR_TAG_URI indicating the text string is a URI.
935
936 A URI in a NULL-terminated string, @c szURI, can be easily added with
937 this code:
938
939 QCBOREncode_AddURI(pCtx, UsefulBuf_FromSZ(szURI));
940 */
941static void QCBOREncode_AddURI(QCBOREncodeContext *pCtx, UsefulBufC URI);
942
943static void QCBOREncode_AddURIToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC URI);
944
945static void QCBOREncode_AddURIToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC URI);
946
947
948/**
949 @brief Add Base64-encoded text to encoded output.
950
951 @param[in] pCtx The encoding context to add the base-64 text to.
952 @param[in] B64Text Pointer and length of the base-64 encoded text.
953
954 The text content is Base64 encoded data per [RFC 4648]
955 (https://tools.ietf.org/html/rfc4648).
956
957 It is output as CBOR major type 3, a text string, with tag @ref
958 CBOR_TAG_B64 indicating the text string is Base64 encoded.
959 */
960static void QCBOREncode_AddB64Text(QCBOREncodeContext *pCtx, UsefulBufC B64Text);
961
962static void QCBOREncode_AddB64TextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC B64Text);
963
964static void QCBOREncode_AddB64TextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC B64Text);
965
966
967/**
968 @brief Add base64url encoded data to encoded output.
969
970 @param[in] pCtx The encoding context to add the base64url to.
971 @param[in] B64Text Pointer and length of the base64url encoded text.
972
973 The text content is base64URL encoded text as per [RFC 4648]
974 (https://tools.ietf.org/html/rfc4648).
975
976 It is output as CBOR major type 3, a text string, with tag @ref
977 CBOR_TAG_B64URL indicating the text string is a Base64url encoded.
978 */
979static void QCBOREncode_AddB64URLText(QCBOREncodeContext *pCtx, UsefulBufC B64Text);
980
981static void QCBOREncode_AddB64URLTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC B64Text);
982
983static void QCBOREncode_AddB64URLTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC B64Text);
984
985
986/**
987 @brief Add Perl Compatible Regular Expression.
988
989 @param[in] pCtx The encoding context to add the regular expression to.
990 @param[in] Regex Pointer and length of the regular expression.
991
992 The text content is Perl Compatible Regular
993 Expressions (PCRE) / JavaScript syntax [ECMA262].
994
995 It is output as CBOR major type 3, a text string, with tag @ref
996 CBOR_TAG_REGEX indicating the text string is a regular expression.
997 */
998static void QCBOREncode_AddRegex(QCBOREncodeContext *pCtx, UsefulBufC Regex);
999
1000static void QCBOREncode_AddRegexToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Regex);
1001
1002static void QCBOREncode_AddRegexToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Regex);
1003
1004
1005/**
1006 @brief MIME encoded text to the encoded output.
1007
1008 @param[in] pCtx The encoding context to add the MIME data to.
1009 @param[in] MIMEData Pointer and length of the regular expression.
1010
1011 The text content is in MIME format per [RFC 2045]
1012 (https://tools.ietf.org/html/rfc2045) including the headers. Note
1013 that this only supports text-format MIME. Binary MIME is not
1014 supported.
1015
1016 It is output as CBOR major type 3, a text string, with tag
1017 @ref CBOR_TAG_MIME indicating the text string is MIME data.
1018 */
1019static void QCBOREncode_AddMIMEData(QCBOREncodeContext *pCtx, UsefulBufC MIMEData);
1020
1021static void QCBOREncode_AddMIMEDataToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC MIMEData);
1022
1023static void QCBOREncode_AddMIMEDataToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC MIMEData);
1024
1025
1026/**
1027 @brief Add an RFC 3339 date string
1028
1029 @param[in] pCtx The encoding context to add the date to.
1030 @param[in] szDate Null-terminated string with date to add.
1031
1032 The string szDate should be in the form of [RFC 3339]
1033 (https://tools.ietf.org/html/rfc3339) as defined by section 3.3 in
1034 [RFC 4287] (https://tools.ietf.org/html/rfc4287). This is as
1035 described in section 2.4.1 in [RFC 7049]
1036 (https://tools.ietf.org/html/rfc7049).
1037
1038 Note that this function doesn't validate the format of the date string
1039 at all. If you add an incorrect format date string, the generated
1040 CBOR will be incorrect and the receiver may not be able to handle it.
1041
1042 Error handling is the same as QCBOREncode_AddInt64().
1043 */
1044static void QCBOREncode_AddDateString(QCBOREncodeContext *pCtx, const char *szDate);
1045
1046static void QCBOREncode_AddDateStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szDate);
1047
1048static void QCBOREncode_AddDateStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szDate);
1049
1050
1051/**
1052 @brief Add a standard Boolean.
1053
1054 @param[in] pCtx The encoding context to add the Boolean to.
1055 @param[in] b true or false from @c <stdbool.h>.
1056
1057 Adds a Boolean value as CBOR major type 7.
1058
1059 Error handling is the same as QCBOREncode_AddInt64().
1060 */
1061static void QCBOREncode_AddBool(QCBOREncodeContext *pCtx, bool b);
1062
1063static void QCBOREncode_AddBoolToMap(QCBOREncodeContext *pCtx, const char *szLabel, bool b);
1064
1065static void QCBOREncode_AddBoolToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, bool b);
1066
1067
1068
1069/**
1070 @brief Add a NULL to the encoded output.
1071
1072 @param[in] pCtx The encoding context to add the NULL to.
1073
1074 Adds the NULL value as CBOR major type 7.
1075
1076 This NULL doesn't have any special meaning in CBOR such as a
1077 terminating value for a string or an empty value.
1078
1079 Error handling is the same as QCBOREncode_AddInt64().
1080 */
1081static void QCBOREncode_AddNULL(QCBOREncodeContext *pCtx);
1082
1083static void QCBOREncode_AddNULLToMap(QCBOREncodeContext *pCtx, const char *szLabel);
1084
1085static void QCBOREncode_AddNULLToMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
1086
1087
1088/**
1089 @brief Add an "undef" to the encoded output.
1090
1091 @param[in] pCtx The encoding context to add the "undef" to.
1092
1093 Adds the undef value as CBOR major type 7.
1094
1095 Note that this value will not translate to JSON.
1096
1097 This Undef doesn't have any special meaning in CBOR such as a
1098 terminating value for a string or an empty value.
1099
1100 Error handling is the same as QCBOREncode_AddInt64().
1101 */
1102static void QCBOREncode_AddUndef(QCBOREncodeContext *pCtx);
1103
1104static void QCBOREncode_AddUndefToMap(QCBOREncodeContext *pCtx, const char *szLabel);
1105
1106static void QCBOREncode_AddUndefToMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
1107
1108
1109/**
1110 @brief Indicates that the next items added are in an array.
1111
1112 @param[in] pCtx The encoding context to open the array in.
1113
1114 Arrays are the basic CBOR aggregate or structure type. Call this
1115 function to start or open an array. Then call the various @c
1116 QCBOREncode_AddXxx() functions to add the items that go into the
1117 array. Then call QCBOREncode_CloseArray() when all items have been
1118 added. The data items in the array can be of any type and can be of
1119 mixed types.
1120
1121 Nesting of arrays and maps is allowed and supported just by calling
1122 QCBOREncode_OpenArray() again before calling
1123 QCBOREncode_CloseArray(). While CBOR has no limit on nesting, this
1124 implementation does in order to keep it smaller and simpler. The
1125 limit is @ref QCBOR_MAX_ARRAY_NESTING. This is the max number of
1126 times this can be called without calling
1127 QCBOREncode_CloseArray(). QCBOREncode_Finish() will return @ref
1128 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP when it is called as this function
1129 just sets an error state and returns no value when this occurs.
1130
1131 If you try to add more than @ref QCBOR_MAX_ITEMS_IN_ARRAY items to a
1132 single array or map, @ref QCBOR_ERR_ARRAY_TOO_LONG will be returned
1133 when QCBOREncode_Finish() is called.
1134
1135 An array itself must have a label if it is being added to a map.
1136 Note that array elements do not have labels (but map elements do).
1137
1138 An array itself may be tagged by calling QCBOREncode_AddTag() before this call.
1139 */
1140static void QCBOREncode_OpenArray(QCBOREncodeContext *pCtx);
1141
1142static void QCBOREncode_OpenArrayInMap(QCBOREncodeContext *pCtx, const char *szLabel);
1143
1144static void QCBOREncode_OpenArrayInMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
1145
1146
1147/**
1148 @brief Close an open array.
1149
1150 @param[in] pCtx The encoding context to close the array in.
1151
1152 The closes an array opened by QCBOREncode_OpenArray(). It reduces
1153 nesting level by one. All arrays (and maps) must be closed before
1154 calling QCBOREncode_Finish().
1155
1156 When an error occurs as a result of this call, the encoder records
1157 the error and enters the error state. The error will be returned when
1158 QCBOREncode_Finish() is called.
1159
1160 If this has been called more times than QCBOREncode_OpenArray(), then
1161 @ref QCBOR_ERR_TOO_MANY_CLOSES will be returned when QCBOREncode_Finish()
1162 is called.
1163
1164 If this is called and it is not an array that is currently open, @ref
1165 QCBOR_ERR_CLOSE_MISMATCH will be returned when QCBOREncode_Finish()
1166 is called.
1167 */
1168static void QCBOREncode_CloseArray(QCBOREncodeContext *pCtx);
1169
1170
1171/**
1172 @brief Indicates that the next items added are in a map.
1173
1174 @param[in] pCtx The encoding context to open the map in.
1175
1176 See QCBOREncode_OpenArray() for more information, particularly error
1177 handling.
1178
1179 CBOR maps are an aggregate type where each item in the map consists
1180 of a label and a value. They are similar to JSON objects.
1181
1182 The value can be any CBOR type including another map.
1183
1184 The label can also be any CBOR type, but in practice they are
1185 typically, integers as this gives the most compact output. They might
1186 also be text strings which gives readability and translation to JSON.
1187
1188 Every @c QCBOREncode_AddXxx() call has one version that ends with @c
1189 InMap for adding items to maps with string labels and one that ends
1190 with @c InMapN that is for adding with integer labels.
1191
1192 RFC 7049 uses the term "key" instead of "label".
1193
1194 If you wish to use map labels that are neither integer labels nor
1195 text strings, then just call the QCBOREncode_AddXxx() function
1196 explicitly to add the label. Then call it again to add the value.
1197
1198 See the [RFC 7049] (https://tools.ietf.org/html/rfc7049) for a lot
1199 more information on creating maps.
1200 */
1201static void QCBOREncode_OpenMap(QCBOREncodeContext *pCtx);
1202
1203static void QCBOREncode_OpenMapInMap(QCBOREncodeContext *pCtx, const char *szLabel);
1204
1205static void QCBOREncode_OpenMapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
1206
1207
1208
1209/**
1210 @brief Close an open map.
1211
1212 @param[in] pCtx The encoding context to close the map in .
1213
1214 This closes a map opened by QCBOREncode_OpenMap(). It reduces nesting
1215 level by one.
1216
1217 When an error occurs as a result of this call, the encoder records
1218 the error and enters the error state. The error will be returned when
1219 QCBOREncode_Finish() is called.
1220
1221 If this has been called more times than QCBOREncode_OpenMap(),
1222 then @ref QCBOR_ERR_TOO_MANY_CLOSES will be returned when
1223 QCBOREncode_Finish() is called.
1224
1225 If this is called and it is not a map that is currently open, @ref
1226 QCBOR_ERR_CLOSE_MISMATCH will be returned when QCBOREncode_Finish()
1227 is called.
1228 */
1229static void QCBOREncode_CloseMap(QCBOREncodeContext *pCtx);
1230
1231
1232/**
1233 @brief Indicate start of encoded CBOR to be wrapped in a bstr.
1234
1235 @param[in] pCtx The encoding context to open the bstr-wrapped CBOR in.
1236
1237 All added encoded items between this call and a call to
1238 QCBOREncode_CloseBstrWrap2() will be wrapped in a bstr. They will
1239 appear in the final output as a byte string. That byte string will
1240 contain encoded CBOR. This increases nesting level by one.
1241
1242 The typical use case is for encoded CBOR that is to be
1243 cryptographically hashed, as part of a [RFC 8152, COSE]
1244 (https://tools.ietf.org/html/rfc8152) implementation.
1245
1246 Using QCBOREncode_BstrWrap() and QCBOREncode_CloseBstrWrap2() avoids
1247 having to encode the items first in one buffer (e.g., the COSE
1248 payload) and then add that buffer as a bstr to another encoding
1249 (e.g. the COSE to-be-signed bytes, the @c Sig_structure) potentially
1250 halving the memory needed.
1251
1252 RFC 7049 states the purpose of this wrapping is to prevent code
1253 relaying the signed data but not verifying it from tampering with the
1254 signed data thus making the signature unverifiable. It is also quite
1255 beneficial for the signature verification code. Standard CBOR
1256 decoders usually do not give access to partially decoded CBOR as
1257 would be needed to check the signature of some CBOR. With this
1258 wrapping, standard CBOR decoders can be used to get to all the data
1259 needed for a signature verification.
1260 */
1261static void QCBOREncode_BstrWrap(QCBOREncodeContext *pCtx);
1262
1263static void QCBOREncode_BstrWrapInMap(QCBOREncodeContext *pCtx, const char *szLabel);
1264
1265static void QCBOREncode_BstrWrapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
1266
1267
1268/**
1269 @brief Close a wrapping bstr.
1270
1271 @param[in] pCtx The encoding context to close of bstr wrapping in.
1272 @param[in] bIncludeCBORHead Include the encoded CBOR head of the bstr
1273 as well as the bytes in @c pWrappedCBOR.
1274 @param[out] pWrappedCBOR A @ref UsefulBufC containing wrapped bytes.
1275
1276 The closes a wrapping bstr opened by QCBOREncode_BstrWrap(). It reduces
1277 nesting level by one.
1278
1279 A pointer and length of the enclosed encoded CBOR is returned in @c
1280 *pWrappedCBOR if it is not @c NULL. The main purpose of this is so
1281 this data can be hashed (e.g., with SHA-256) as part of a [RFC 8152,
1282 COSE] (https://tools.ietf.org/html/rfc8152)
1283 implementation. **WARNING**, this pointer and length should be used
1284 right away before any other calls to @c QCBOREncode_CloseXxx() as
1285 they will move data around and the pointer and length will no longer
1286 be to the correct encoded CBOR.
1287
1288 When an error occurs as a result of this call, the encoder records
1289 the error and enters the error state. The error will be returned when
1290 QCBOREncode_Finish() is called.
1291
1292 If this has been called more times than QCBOREncode_BstrWrap(), then
1293 @ref QCBOR_ERR_TOO_MANY_CLOSES will be returned when
1294 QCBOREncode_Finish() is called.
1295
1296 If this is called and it is not a wrapping bstr that is currently
1297 open, @ref QCBOR_ERR_CLOSE_MISMATCH will be returned when
1298 QCBOREncode_Finish() is called.
1299
1300 QCBOREncode_CloseBstrWrap() is a deprecated version of this function
1301 that is equivalent to the call with @c bIncludeCBORHead @c true.
1302 */
1303void QCBOREncode_CloseBstrWrap2(QCBOREncodeContext *pCtx, bool bIncludeCBORHead, UsefulBufC *pWrappedCBOR);
1304
1305static void QCBOREncode_CloseBstrWrap(QCBOREncodeContext *pCtx, UsefulBufC *pWrappedCBOR);
1306
1307
1308/**
1309 @brief Add some already-encoded CBOR bytes.
1310
1311 @param[in] pCtx The encoding context to add the already-encode CBOR to.
1312 @param[in] Encoded The already-encoded CBOR to add to the context.
1313
1314 The encoded CBOR being added must be fully conforming CBOR. It must
1315 be complete with no arrays or maps that are incomplete. While this
1316 encoder doesn't ever produce indefinite lengths, it is OK for the
1317 raw CBOR added here to have indefinite lengths.
1318
1319 The raw CBOR added here is not checked in anyway. If it is not
1320 conforming or has open arrays or such, the final encoded CBOR
1321 will probably be wrong or not what was intended.
1322
1323 If the encoded CBOR being added here contains multiple items, they
1324 must be enclosed in a map or array. At the top level the raw
1325 CBOR must be a single data item.
1326 */
1327static void QCBOREncode_AddEncoded(QCBOREncodeContext *pCtx, UsefulBufC Encoded);
1328
1329static void QCBOREncode_AddEncodedToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Encoded);
1330
1331static void QCBOREncode_AddEncodedToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Encoded);
1332
1333
1334/**
1335 @brief Get the encoded result.
1336
1337 @param[in] pCtx The context to finish encoding with.
1338 @param[out] pEncodedCBOR Pointer and length of encoded CBOR.
1339
1340 @retval QCBOR_ERR_TOO_MANY_CLOSES Nesting error
1341
1342 @retval QCBOR_ERR_CLOSE_MISMATCH Nesting error
1343
1344 @retval QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN Nesting error
1345
1346 @retval QCBOR_ERR_BUFFER_TOO_LARGE Encoded output buffer size
1347
1348 @retval QCBOR_ERR_BUFFER_TOO_SMALL Encoded output buffer size
1349
1350 @retval QCBOR_ERR_ARRAY_NESTING_TOO_DEEP Implementation limit
1351
1352 @retval QCBOR_ERR_ARRAY_TOO_LONG Implementation limit
1353
1354 If this returns success @ref QCBOR_SUCCESS the encoding was a success
1355 and the return length is correct and complete.
1356
1357 If no buffer was passed to QCBOREncode_Init(), then only the length
1358 was computed. If a buffer was passed, then the encoded CBOR is in the
1359 buffer.
1360
1361 Encoding errors primarily manifest here as most other encoding function
1362 do no return an error. They just set the error state in the encode
1363 context after which no encoding function does anything.
1364
1365 Three types of errors manifest here. The first type are nesting
1366 errors where the number of @c QCBOREncode_OpenXxx() calls do not
1367 match the number @c QCBOREncode_CloseXxx() calls. The solution is to
1368 fix the calling code.
1369
1370 The second type of error is because the buffer given is either too
1371 small or too large. The remedy is to give a correctly sized buffer.
1372
1373 The third type are due to limits in this implementation. @ref
1374 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP can be worked around by encoding the
1375 CBOR in two (or more) phases and adding the CBOR from the first phase
1376 to the second with @c QCBOREncode_AddEncoded().
1377
1378 If an error is returned, the buffer may have partially encoded
1379 incorrect CBOR in it and it should not be used. Likewise, the length
1380 may be incorrect and should not be used.
1381
1382 Note that the error could have occurred in one of the many @c
1383 QCBOREncode_AddXxx() calls long before QCBOREncode_Finish() was
1384 called. This error handling reduces the CBOR implementation size but
1385 makes debugging harder.
1386
1387 This may be called multiple times. It will always return the same. It
1388 can also be interleaved with calls to QCBOREncode_FinishGetSize().
1389
1390 QCBOREncode_GetErrorState() can be called to get the current
1391 error state and abort encoding early as an optimization, but is
1392 is never required.
1393 */
1394QCBORError QCBOREncode_Finish(QCBOREncodeContext *pCtx, UsefulBufC *pEncodedCBOR);
1395
1396
1397/**
1398 @brief Get the encoded CBOR and error status.
1399
1400 @param[in] pCtx The context to finish encoding with.
1401 @param[out] uEncodedLen The length of the encoded or potentially
1402 encoded CBOR in bytes.
1403
1404 @return The same errors as QCBOREncode_Finish().
1405
1406 This functions the same as QCBOREncode_Finish(), but only returns the
1407 size of the encoded output.
1408 */
1409QCBORError QCBOREncode_FinishGetSize(QCBOREncodeContext *pCtx, size_t *uEncodedLen);
1410
1411
1412/**
1413 @brief Indicate whether output buffer is NULL or not.
1414
1415 @param[in] pCtx The encoding context.
1416
1417 @return 1 if the output buffer is @c NULL.
1418
1419 Sometimes a @c NULL input buffer is given to QCBOREncode_Init() so
1420 that the size of the generated CBOR can be calculated without
1421 allocating a buffer for it. This returns 1 when the output buffer is
1422 NULL and 0 when it is not.
1423*/
1424static int QCBOREncode_IsBufferNULL(QCBOREncodeContext *pCtx);
1425
1426 /**
1427 @brief Get the encoding error state.
1428
1429 @param[in] pCtx The encoding context.
1430
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07001431 @return One of @ref QCBORError. See return values from
Michael Eckel5c531332020-03-02 01:35:30 +01001432 QCBOREncode_Finish()
1433
1434 Normally encoding errors need only be handled at the end of encoding
1435 when QCBOREncode_Finish() is called. This can be called to get the
1436 error result before finish should there be a need to halt encoding
1437 before QCBOREncode_Finish() is called.
1438*/
1439static QCBORError QCBOREncode_GetErrorState(QCBOREncodeContext *pCtx);
1440
1441
1442/**
1443 Encode the "head" of a CBOR data item.
1444
1445 @param buffer Buffer to output the encoded head to; must be
1446 @ref QCBOR_HEAD_BUFFER_SIZE bytes in size.
1447 @param uMajorType One of CBOR_MAJOR_TYPE_XX.
1448 @param uMinLen The minimum number of bytes to encode uNumber. Almost always
1449 this is 0 to use preferred minimal encoding. If this is 4,
1450 then even the values 0xffff and smaller will be encoded
1451 as in 4 bytes. This is used primarily when encoding a
1452 float or double put into uNumber as the leading zero bytes
1453 for them must be encoded.
1454 @param uNumber The numeric argument part of the CBOR head.
1455 @return Pointer and length of the encoded head or
1456 @NULLUsefulBufC if the output buffer is too small.
1457
1458 Callers to need to call this for normal CBOR encoding. Note that it doesn't even
1459 take a @ref QCBOREncodeContext argument.
1460
1461 This encodes the major type and argument part of a data item. The
1462 argument is an integer that is usually either the value or the length
1463 of the data item.
1464
1465 This is exposed in the public interface to allow hashing of some CBOR
1466 data types, bstr in particular, a chunk at a time so the full CBOR
1467 doesn't have to be encoded in a contiguous buffer.
1468
1469 For example, if you have a 100,000 byte binary blob in a buffer that
1470 needs to be a bstr encoded and then hashed. You could allocate a
1471 100,010 byte buffer and encode it normally. Alternatively, you can
1472 encode the head in a 10 byte buffer with this function, hash that and
1473 then hash the 100,000 bytes using the same hash context.
1474
1475 See also QCBOREncode_AddBytesLenOnly();
1476 */
1477UsefulBufC QCBOREncode_EncodeHead(UsefulBuf buffer,
1478 uint8_t uMajorType,
1479 uint8_t uMinLen,
1480 uint64_t uNumber);
1481
1482
Michael Eckel5c531332020-03-02 01:35:30 +01001483
1484
1485/* ===========================================================================
1486 BEGINNING OF PRIVATE INLINE IMPLEMENTATION
1487
1488 =========================================================================== */
1489
1490/**
1491 @brief Semi-private method to add a buffer full of bytes to encoded output
1492
1493 @param[in] pCtx The encoding context to add the integer to.
1494 @param[in] uMajorType The CBOR major type of the bytes.
1495 @param[in] Bytes The bytes to add.
1496
1497 Use QCBOREncode_AddText() or QCBOREncode_AddBytes() or
1498 QCBOREncode_AddEncoded() instead. They are inline functions that call
1499 this and supply the correct major type. This function is public to
1500 make the inline functions work to keep the overall code size down and
1501 because the C language has no way to make it private.
1502
1503 If this is called the major type should be @c
1504 CBOR_MAJOR_TYPE_TEXT_STRING, @c CBOR_MAJOR_TYPE_BYTE_STRING or @c
1505 CBOR_MAJOR_NONE_TYPE_RAW. The last one is special for adding
1506 already-encoded CBOR.
1507 */
1508void QCBOREncode_AddBuffer(QCBOREncodeContext *pCtx, uint8_t uMajorType, UsefulBufC Bytes);
1509
1510
1511/**
1512 @brief Semi-private method to open a map, array or bstr-wrapped CBOR
1513
1514 @param[in] pCtx The context to add to.
1515 @param[in] uMajorType The major CBOR type to close
1516
1517 Call QCBOREncode_OpenArray(), QCBOREncode_OpenMap() or
1518 QCBOREncode_BstrWrap() instead of this.
1519 */
1520void QCBOREncode_OpenMapOrArray(QCBOREncodeContext *pCtx, uint8_t uMajorType);
1521
1522
1523/**
1524 @brief Semi-private method to open a map, array with indefinite length
1525
1526 @param[in] pCtx The context to add to.
1527 @param[in] uMajorType The major CBOR type to close
1528
1529 Call QCBOREncode_OpenArrayIndefiniteLength() or
1530 QCBOREncode_OpenMapIndefiniteLength() instead of this.
1531 */
1532void QCBOREncode_OpenMapOrArrayIndefiniteLength(QCBOREncodeContext *pCtx, uint8_t uMajorType);
1533
1534
1535/**
1536 @brief Semi-private method to close a map, array or bstr wrapped CBOR
1537
1538 @param[in] pCtx The context to add to.
1539 @param[in] uMajorType The major CBOR type to close.
1540
1541 Call QCBOREncode_CloseArray() or QCBOREncode_CloseMap() instead of this.
1542 */
1543void QCBOREncode_CloseMapOrArray(QCBOREncodeContext *pCtx, uint8_t uMajorType);
1544
1545
1546/**
1547 @brief Semi-private method to close a map, array with indefinite length
1548
1549 @param[in] pCtx The context to add to.
1550 @param[in] uMajorType The major CBOR type to close.
1551
1552 Call QCBOREncode_CloseArrayIndefiniteLength() or
1553 QCBOREncode_CloseMapIndefiniteLength() instead of this.
1554 */
1555void QCBOREncode_CloseMapOrArrayIndefiniteLength(QCBOREncodeContext *pCtx,
1556 uint8_t uMajorType);
1557
1558
1559/**
1560 @brief Semi-private method to add simple types.
1561
1562 @param[in] pCtx The encoding context to add the simple value to.
1563 @param[in] uMinLen Minimum encoding size for uNum. Usually 0.
1564 @param[in] uNum One of CBOR_SIMPLEV_FALSE through _UNDEF or other.
1565
1566 This is used to add simple types like true and false.
1567
1568 Call QCBOREncode_AddBool(), QCBOREncode_AddNULL(),
1569 QCBOREncode_AddUndef() instead of this.
1570
1571 This function can add simple values that are not defined by CBOR
1572 yet. This expansion point in CBOR should not be used unless they are
1573 standardized.
1574
1575 Error handling is the same as QCBOREncode_AddInt64().
1576 */
1577void QCBOREncode_AddType7(QCBOREncodeContext *pCtx, uint8_t uMinLen, uint64_t uNum);
1578
1579
1580/**
1581 @brief Semi-private method to add bigfloats and decimal fractions.
1582
1583 @param[in] pCtx The encoding context to add the value to.
1584 @param[in] uTag The type 6 tag indicating what this is to be
1585 @param[in] BigNumMantissa Is @ref NULLUsefulBufC if mantissa is an
1586 @c int64_t or the actual big number mantissa
1587 if not.
1588 @param[in] nMantissa The @c int64_t mantissa if it is not a big number.
1589 @param[in] nExponent The exponent.
1590
1591 This adds a tagged array with two members, the mantissa and exponent. The
1592 mantissa can be either a big number or an @c int64_t.
1593
1594 Typically, QCBOREncode_AddDecimalFraction(), QCBOREncode_AddBigFloat(),
1595 QCBOREncode_AddDecimalFractionBigNum() or QCBOREncode_AddBigFloatBigNum()
1596 is called instead of this.
1597 */
1598void QCBOREncode_AddExponentAndMantissa(QCBOREncodeContext *pCtx,
1599 uint64_t uTag,
1600 UsefulBufC BigNumMantissa,
1601 bool bBigNumIsNegative,
1602 int64_t nMantissa,
1603 int64_t nExponent);
1604
1605/**
1606 @brief Semi-private method to add only the type and length of a byte string.
1607
1608 @param[in] pCtx The context to initialize.
1609 @param[in] Bytes Pointer and length of the input data.
1610
1611 This is the same as QCBOREncode_AddBytes() except it only adds the
1612 CBOR encoding for the type and the length. It doesn't actually add
1613 the bytes. You can't actually produce correct CBOR with this and the
1614 rest of this API. It is only used for a special case where
1615 the valid CBOR is created manually by putting this type and length in
1616 and then adding the actual bytes. In particular, when only a hash of
1617 the encoded CBOR is needed, where the type and header are hashed
1618 separately and then the bytes is hashed. This makes it possible to
1619 implement COSE Sign1 with only one copy of the payload in the output
1620 buffer, rather than two, roughly cutting memory use in half.
1621
1622 This is only used for this odd case, but this is a supported
1623 tested function.
1624
1625 See also QCBOREncode_EncodeHead().
1626*/
1627static inline void QCBOREncode_AddBytesLenOnly(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
1628
1629static inline void QCBOREncode_AddBytesLenOnlyToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
1630
1631static inline void QCBOREncode_AddBytesLenOnlyToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
1632
1633
1634
1635
1636
1637static inline void QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t uNum)
1638{
1639 // Use _AddBuffer() because _AddSZString() is defined below, not above
1640 QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, UsefulBuf_FromSZ(szLabel));
1641 QCBOREncode_AddInt64(pCtx, uNum);
1642}
1643
1644static inline void QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t uNum)
1645{
1646 QCBOREncode_AddInt64(pCtx, nLabel);
1647 QCBOREncode_AddInt64(pCtx, uNum);
1648}
1649
1650
1651static inline void QCBOREncode_AddUInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t uNum)
1652{
1653 // Use _AddBuffer() because _AddSZString() is defined below, not above
1654 QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, UsefulBuf_FromSZ(szLabel));
1655 QCBOREncode_AddUInt64(pCtx, uNum);
1656}
1657
1658static inline void QCBOREncode_AddUInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, uint64_t uNum)
1659{
1660 QCBOREncode_AddInt64(pCtx, nLabel);
1661 QCBOREncode_AddUInt64(pCtx, uNum);
1662}
1663
1664
1665static inline void QCBOREncode_AddText(QCBOREncodeContext *pCtx, UsefulBufC Text)
1666{
1667 QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, Text);
1668}
1669
1670static inline void QCBOREncode_AddTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Text)
1671{
1672 // Use _AddBuffer() because _AddSZString() is defined below, not above
1673 QCBOREncode_AddText(pCtx, UsefulBuf_FromSZ(szLabel));
1674 QCBOREncode_AddText(pCtx, Text);
1675}
1676
1677static inline void QCBOREncode_AddTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Text)
1678{
1679 QCBOREncode_AddInt64(pCtx, nLabel);
1680 QCBOREncode_AddText(pCtx, Text);
1681}
1682
1683
1684inline static void QCBOREncode_AddSZString(QCBOREncodeContext *pCtx, const char *szString)
1685{
1686 QCBOREncode_AddText(pCtx, UsefulBuf_FromSZ(szString));
1687}
1688
1689static inline void QCBOREncode_AddSZStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szString)
1690{
1691 QCBOREncode_AddSZString(pCtx, szLabel);
1692 QCBOREncode_AddSZString(pCtx, szString);
1693}
1694
1695static inline void QCBOREncode_AddSZStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szString)
1696{
1697 QCBOREncode_AddInt64(pCtx, nLabel);
1698 QCBOREncode_AddSZString(pCtx, szString);
1699}
1700
1701
1702static inline void QCBOREncode_AddDoubleToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum)
1703{
1704 QCBOREncode_AddSZString(pCtx, szLabel);
1705 QCBOREncode_AddDouble(pCtx, dNum);
1706}
1707
1708static inline void QCBOREncode_AddDoubleToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum)
1709{
1710 QCBOREncode_AddInt64(pCtx, nLabel);
1711 QCBOREncode_AddDouble(pCtx, dNum);
1712}
1713
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -07001714static inline void QCBOREncode_AddFloatToMap(QCBOREncodeContext *pCtx, const char *szLabel, float dNum)
1715{
1716 QCBOREncode_AddSZString(pCtx, szLabel);
1717 QCBOREncode_AddFloat(pCtx, dNum);
1718}
1719
1720static inline void QCBOREncode_AddFloatToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, float fNum)
1721{
1722 QCBOREncode_AddInt64(pCtx, nLabel);
1723 QCBOREncode_AddFloat(pCtx, fNum);
1724}
1725
Laurence Lundblade32f3e622020-07-13 20:35:11 -07001726static inline void QCBOREncode_AddDoubleNoPreferredToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum)
1727{
1728 QCBOREncode_AddSZString(pCtx, szLabel);
1729 QCBOREncode_AddDoubleNoPreferred(pCtx, dNum);
1730}
1731
1732static inline void QCBOREncode_AddDoubleNoPreferredToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum)
1733{
1734 QCBOREncode_AddInt64(pCtx, nLabel);
1735 QCBOREncode_AddDoubleNoPreferred(pCtx, dNum);
1736}
1737
1738static inline void QCBOREncode_AddFloatNoPreferredToMap(QCBOREncodeContext *pCtx, const char *szLabel, float dNum)
1739{
1740 QCBOREncode_AddSZString(pCtx, szLabel);
1741 QCBOREncode_AddFloatNoPreferred(pCtx, dNum);
1742}
1743
1744static inline void QCBOREncode_AddFloatNoPreferredToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, float dNum)
1745{
1746 QCBOREncode_AddInt64(pCtx, nLabel);
1747 QCBOREncode_AddFloatNoPreferred(pCtx, dNum);
1748}
1749
Michael Eckel5c531332020-03-02 01:35:30 +01001750
1751static inline void QCBOREncode_AddDateEpoch(QCBOREncodeContext *pCtx, int64_t date)
1752{
1753 QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_EPOCH);
1754 QCBOREncode_AddInt64(pCtx, date);
1755}
1756
1757static inline void QCBOREncode_AddDateEpochToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t date)
1758{
1759 QCBOREncode_AddSZString(pCtx, szLabel);
1760 QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_EPOCH);
1761 QCBOREncode_AddInt64(pCtx, date);
1762}
1763
1764static inline void QCBOREncode_AddDateEpochToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t date)
1765{
1766 QCBOREncode_AddInt64(pCtx, nLabel);
1767 QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_EPOCH);
1768 QCBOREncode_AddInt64(pCtx, date);
1769}
1770
1771
1772static inline void QCBOREncode_AddBytes(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
1773{
1774 QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING, Bytes);
1775}
1776
1777static inline void QCBOREncode_AddBytesToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
1778{
1779 QCBOREncode_AddSZString(pCtx, szLabel);
1780 QCBOREncode_AddBytes(pCtx, Bytes);
1781}
1782
1783static inline void QCBOREncode_AddBytesToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
1784{
1785 QCBOREncode_AddInt64(pCtx, nLabel);
1786 QCBOREncode_AddBytes(pCtx, Bytes);
1787}
1788
1789static inline void QCBOREncode_AddBytesLenOnly(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
1790{
1791 QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY, Bytes);
1792}
1793
1794static inline void QCBOREncode_AddBytesLenOnlyToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
1795{
1796 QCBOREncode_AddSZString(pCtx, szLabel);
1797 QCBOREncode_AddBytesLenOnly(pCtx, Bytes);
1798}
1799
1800static inline void QCBOREncode_AddBytesLenOnlyToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
1801{
1802 QCBOREncode_AddInt64(pCtx, nLabel);
1803 QCBOREncode_AddBytesLenOnly(pCtx, Bytes);
1804}
1805
1806static inline void QCBOREncode_AddBinaryUUID(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
1807{
1808 QCBOREncode_AddTag(pCtx, CBOR_TAG_BIN_UUID);
1809 QCBOREncode_AddBytes(pCtx, Bytes);
1810}
1811
1812static inline void QCBOREncode_AddBinaryUUIDToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
1813{
1814 QCBOREncode_AddSZString(pCtx, szLabel);
1815 QCBOREncode_AddTag(pCtx, CBOR_TAG_BIN_UUID);
1816 QCBOREncode_AddBytes(pCtx, Bytes);
1817}
1818
1819static inline void QCBOREncode_AddBinaryUUIDToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
1820{
1821 QCBOREncode_AddInt64(pCtx, nLabel);
1822 QCBOREncode_AddTag(pCtx, CBOR_TAG_BIN_UUID);
1823 QCBOREncode_AddBytes(pCtx, Bytes);
1824}
1825
1826
1827static inline void QCBOREncode_AddPositiveBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
1828{
1829 QCBOREncode_AddTag(pCtx, CBOR_TAG_POS_BIGNUM);
1830 QCBOREncode_AddBytes(pCtx, Bytes);
1831}
1832
1833static inline void QCBOREncode_AddPositiveBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
1834{
1835 QCBOREncode_AddSZString(pCtx, szLabel);
1836 QCBOREncode_AddTag(pCtx, CBOR_TAG_POS_BIGNUM);
1837 QCBOREncode_AddBytes(pCtx, Bytes);
1838}
1839
1840static inline void QCBOREncode_AddPositiveBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
1841{
1842 QCBOREncode_AddInt64(pCtx, nLabel);
1843 QCBOREncode_AddTag(pCtx, CBOR_TAG_POS_BIGNUM);
1844 QCBOREncode_AddBytes(pCtx, Bytes);
1845}
1846
1847
1848static inline void QCBOREncode_AddNegativeBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
1849{
1850 QCBOREncode_AddTag(pCtx, CBOR_TAG_NEG_BIGNUM);
1851 QCBOREncode_AddBytes(pCtx, Bytes);
1852}
1853
1854static inline void QCBOREncode_AddNegativeBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
1855{
1856 QCBOREncode_AddSZString(pCtx, szLabel);
1857 QCBOREncode_AddTag(pCtx, CBOR_TAG_NEG_BIGNUM);
1858 QCBOREncode_AddBytes(pCtx, Bytes);
1859}
1860
1861static inline void QCBOREncode_AddNegativeBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
1862{
1863 QCBOREncode_AddInt64(pCtx, nLabel);
1864 QCBOREncode_AddTag(pCtx, CBOR_TAG_NEG_BIGNUM);
1865 QCBOREncode_AddBytes(pCtx, Bytes);
1866}
1867
1868
1869#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1870
1871static inline void QCBOREncode_AddDecimalFraction(QCBOREncodeContext *pCtx,
1872 int64_t nMantissa,
1873 int64_t nBase10Exponent)
1874{
1875 QCBOREncode_AddExponentAndMantissa(pCtx,
1876 CBOR_TAG_DECIMAL_FRACTION,
1877 NULLUsefulBufC,
1878 false,
1879 nMantissa,
1880 nBase10Exponent);
1881}
1882
1883static inline void QCBOREncode_AddDecimalFractionToMap(QCBOREncodeContext *pCtx,
1884 const char *szLabel,
1885 int64_t nMantissa,
1886 int64_t nBase10Exponent)
1887{
1888 QCBOREncode_AddSZString(pCtx, szLabel);
1889 QCBOREncode_AddDecimalFraction(pCtx, nMantissa, nBase10Exponent);
1890}
1891
1892static inline void QCBOREncode_AddDecimalFractionToMapN(QCBOREncodeContext *pCtx,
1893 int64_t nLabel,
1894 int64_t nMantissa,
1895 int64_t nBase10Exponent)
1896{
1897 QCBOREncode_AddInt64(pCtx, nLabel);
1898 QCBOREncode_AddDecimalFraction(pCtx, nMantissa, nBase10Exponent);
1899}
1900
1901static inline void QCBOREncode_AddDecimalFractionBigNum(QCBOREncodeContext *pCtx,
1902 UsefulBufC Mantissa,
1903 bool bIsNegative,
1904 int64_t nBase10Exponent)
1905{
1906 QCBOREncode_AddExponentAndMantissa(pCtx,
1907 CBOR_TAG_DECIMAL_FRACTION,
1908 Mantissa, bIsNegative,
1909 0,
1910 nBase10Exponent);
1911}
1912
1913static inline void QCBOREncode_AddDecimalFractionBigNumToMap(QCBOREncodeContext *pCtx,
1914 const char *szLabel,
1915 UsefulBufC Mantissa,
1916 bool bIsNegative,
1917 int64_t nBase10Exponent)
1918{
1919 QCBOREncode_AddSZString(pCtx, szLabel);
1920 QCBOREncode_AddDecimalFractionBigNum(pCtx, Mantissa, bIsNegative, nBase10Exponent);
1921}
1922
1923static inline void QCBOREncode_AddDecimalFractionBigNumToMapN(QCBOREncodeContext *pCtx,
1924 int64_t nLabel,
1925 UsefulBufC Mantissa,
1926 bool bIsNegative,
1927 int64_t nBase2Exponent)
1928{
1929 QCBOREncode_AddInt64(pCtx, nLabel);
1930 QCBOREncode_AddDecimalFractionBigNum(pCtx, Mantissa, bIsNegative, nBase2Exponent);
1931}
1932
1933static inline void QCBOREncode_AddBigFloat(QCBOREncodeContext *pCtx,
1934 int64_t nMantissa,
1935 int64_t nBase2Exponent)
1936{
1937 QCBOREncode_AddExponentAndMantissa(pCtx, CBOR_TAG_BIGFLOAT, NULLUsefulBufC, false, nMantissa, nBase2Exponent);
1938}
1939
1940static inline void QCBOREncode_AddBigFloatToMap(QCBOREncodeContext *pCtx,
1941 const char *szLabel,
1942 int64_t nMantissa,
1943 int64_t nBase2Exponent)
1944{
1945 QCBOREncode_AddSZString(pCtx, szLabel);
1946 QCBOREncode_AddBigFloat(pCtx, nMantissa, nBase2Exponent);
1947}
1948
1949static inline void QCBOREncode_AddBigFloatToMapN(QCBOREncodeContext *pCtx,
1950 int64_t nLabel,
1951 int64_t nMantissa,
1952 int64_t nBase2Exponent)
1953{
1954 QCBOREncode_AddInt64(pCtx, nLabel);
1955 QCBOREncode_AddBigFloat(pCtx, nMantissa, nBase2Exponent);
1956}
1957
1958static inline void QCBOREncode_AddBigFloatBigNum(QCBOREncodeContext *pCtx,
1959 UsefulBufC Mantissa,
1960 bool bIsNegative,
1961 int64_t nBase2Exponent)
1962{
1963 QCBOREncode_AddExponentAndMantissa(pCtx, CBOR_TAG_BIGFLOAT, Mantissa, bIsNegative, 0, nBase2Exponent);
1964}
1965
1966static inline void QCBOREncode_AddBigFloatBigNumToMap(QCBOREncodeContext *pCtx,
1967 const char *szLabel,
1968 UsefulBufC Mantissa,
1969 bool bIsNegative,
1970 int64_t nBase2Exponent)
1971{
1972 QCBOREncode_AddSZString(pCtx, szLabel);
1973 QCBOREncode_AddBigFloatBigNum(pCtx, Mantissa, bIsNegative, nBase2Exponent);
1974}
1975
1976static inline void QCBOREncode_AddBigFloatBigNumToMapN(QCBOREncodeContext *pCtx,
1977 int64_t nLabel,
1978 UsefulBufC Mantissa,
1979 bool bIsNegative,
1980 int64_t nBase2Exponent)
1981{
1982 QCBOREncode_AddInt64(pCtx, nLabel);
1983 QCBOREncode_AddBigFloatBigNum(pCtx, Mantissa, bIsNegative, nBase2Exponent);
1984}
1985#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1986
1987
1988static inline void QCBOREncode_AddURI(QCBOREncodeContext *pCtx, UsefulBufC URI)
1989{
1990 QCBOREncode_AddTag(pCtx, CBOR_TAG_URI);
1991 QCBOREncode_AddText(pCtx, URI);
1992}
1993
1994static inline void QCBOREncode_AddURIToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC URI)
1995{
1996 QCBOREncode_AddSZString(pCtx, szLabel);
1997 QCBOREncode_AddTag(pCtx, CBOR_TAG_URI);
1998 QCBOREncode_AddText(pCtx, URI);
1999}
2000
2001static inline void QCBOREncode_AddURIToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC URI)
2002{
2003 QCBOREncode_AddInt64(pCtx, nLabel);
2004 QCBOREncode_AddTag(pCtx, CBOR_TAG_URI);
2005 QCBOREncode_AddText(pCtx, URI);
2006}
2007
2008
2009
2010static inline void QCBOREncode_AddB64Text(QCBOREncodeContext *pCtx, UsefulBufC B64Text)
2011{
2012 QCBOREncode_AddTag(pCtx, CBOR_TAG_B64);
2013 QCBOREncode_AddText(pCtx, B64Text);
2014}
2015
2016static inline void QCBOREncode_AddB64TextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC B64Text)
2017{
2018 QCBOREncode_AddSZString(pCtx, szLabel);
2019 QCBOREncode_AddTag(pCtx, CBOR_TAG_B64);
2020 QCBOREncode_AddText(pCtx, B64Text);
2021}
2022
2023static inline void QCBOREncode_AddB64TextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC B64Text)
2024{
2025 QCBOREncode_AddInt64(pCtx, nLabel);
2026 QCBOREncode_AddTag(pCtx, CBOR_TAG_B64);
2027 QCBOREncode_AddText(pCtx, B64Text);
2028}
2029
2030
2031static inline void QCBOREncode_AddB64URLText(QCBOREncodeContext *pCtx, UsefulBufC B64Text)
2032{
2033 QCBOREncode_AddTag(pCtx, CBOR_TAG_B64URL);
2034 QCBOREncode_AddText(pCtx, B64Text);
2035}
2036
2037static inline void QCBOREncode_AddB64URLTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC B64Text)
2038{
2039 QCBOREncode_AddSZString(pCtx, szLabel);
2040 QCBOREncode_AddTag(pCtx, CBOR_TAG_B64URL);
2041 QCBOREncode_AddText(pCtx, B64Text);
2042}
2043
2044static inline void QCBOREncode_AddB64URLTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC B64Text)
2045{
2046 QCBOREncode_AddInt64(pCtx, nLabel);
2047 QCBOREncode_AddTag(pCtx, CBOR_TAG_B64URL);
2048 QCBOREncode_AddText(pCtx, B64Text);
2049}
2050
2051
2052static inline void QCBOREncode_AddRegex(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
2053{
2054 QCBOREncode_AddTag(pCtx, CBOR_TAG_REGEX);
2055 QCBOREncode_AddText(pCtx, Bytes);
2056}
2057
2058static inline void QCBOREncode_AddRegexToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
2059{
2060 QCBOREncode_AddSZString(pCtx, szLabel);
2061 QCBOREncode_AddTag(pCtx, CBOR_TAG_REGEX);
2062 QCBOREncode_AddText(pCtx, Bytes);
2063}
2064
2065static inline void QCBOREncode_AddRegexToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
2066{
2067 QCBOREncode_AddInt64(pCtx, nLabel);
2068 QCBOREncode_AddTag(pCtx, CBOR_TAG_REGEX);
2069 QCBOREncode_AddText(pCtx, Bytes);
2070}
2071
2072
2073static inline void QCBOREncode_AddMIMEData(QCBOREncodeContext *pCtx, UsefulBufC MIMEData)
2074{
2075 QCBOREncode_AddTag(pCtx, CBOR_TAG_MIME);
2076 QCBOREncode_AddText(pCtx, MIMEData);
2077}
2078
2079static inline void QCBOREncode_AddMIMEDataToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC MIMEData)
2080{
2081 QCBOREncode_AddSZString(pCtx, szLabel);
2082 QCBOREncode_AddTag(pCtx, CBOR_TAG_MIME);
2083 QCBOREncode_AddText(pCtx, MIMEData);
2084}
2085
2086static inline void QCBOREncode_AddMIMEDataToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC MIMEData)
2087{
2088 QCBOREncode_AddInt64(pCtx, nLabel);
2089 QCBOREncode_AddTag(pCtx, CBOR_TAG_MIME);
2090 QCBOREncode_AddText(pCtx, MIMEData);
2091}
2092
2093
2094static inline void QCBOREncode_AddDateString(QCBOREncodeContext *pCtx, const char *szDate)
2095{
2096 QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_STRING);
2097 QCBOREncode_AddSZString(pCtx, szDate);
2098}
2099
2100static inline void QCBOREncode_AddDateStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szDate)
2101{
2102 QCBOREncode_AddSZString(pCtx, szLabel);
2103 QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_STRING);
2104 QCBOREncode_AddSZString(pCtx, szDate);
2105}
2106
2107static inline void QCBOREncode_AddDateStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szDate)
2108{
2109 QCBOREncode_AddInt64(pCtx, nLabel);
2110 QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_STRING);
2111 QCBOREncode_AddSZString(pCtx, szDate);
2112}
2113
2114
2115static inline void QCBOREncode_AddSimple(QCBOREncodeContext *pCtx, uint64_t uNum)
2116{
2117 QCBOREncode_AddType7(pCtx, 0, uNum);
2118}
2119
2120static inline void QCBOREncode_AddSimpleToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint8_t uSimple)
2121{
2122 QCBOREncode_AddSZString(pCtx, szLabel);
2123 QCBOREncode_AddSimple(pCtx, uSimple);
2124}
2125
2126static inline void QCBOREncode_AddSimpleToMapN(QCBOREncodeContext *pCtx, int nLabel, uint8_t uSimple)
2127{
2128 QCBOREncode_AddInt64(pCtx, nLabel);
2129 QCBOREncode_AddSimple(pCtx, uSimple);
2130}
2131
2132
2133static inline void QCBOREncode_AddBool(QCBOREncodeContext *pCtx, bool b)
2134{
2135 uint8_t uSimple = CBOR_SIMPLEV_FALSE;
2136 if(b) {
2137 uSimple = CBOR_SIMPLEV_TRUE;
2138 }
2139 QCBOREncode_AddSimple(pCtx, uSimple);
2140}
2141
2142static inline void QCBOREncode_AddBoolToMap(QCBOREncodeContext *pCtx, const char *szLabel, bool b)
2143{
2144 QCBOREncode_AddSZString(pCtx, szLabel);
2145 QCBOREncode_AddBool(pCtx, b);
2146}
2147
2148static inline void QCBOREncode_AddBoolToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, bool b)
2149{
2150 QCBOREncode_AddInt64(pCtx, nLabel);
2151 QCBOREncode_AddBool(pCtx, b);
2152}
2153
2154
2155static inline void QCBOREncode_AddNULL(QCBOREncodeContext *pCtx)
2156{
2157 QCBOREncode_AddSimple(pCtx, CBOR_SIMPLEV_NULL);
2158}
2159
2160static inline void QCBOREncode_AddNULLToMap(QCBOREncodeContext *pCtx, const char *szLabel)
2161{
2162 QCBOREncode_AddSZString(pCtx, szLabel);
2163 QCBOREncode_AddNULL(pCtx);
2164}
2165
2166static inline void QCBOREncode_AddNULLToMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
2167{
2168 QCBOREncode_AddInt64(pCtx, nLabel);
2169 QCBOREncode_AddNULL(pCtx);
2170}
2171
2172
2173static inline void QCBOREncode_AddUndef(QCBOREncodeContext *pCtx)
2174{
2175 QCBOREncode_AddSimple(pCtx, CBOR_SIMPLEV_UNDEF);
2176}
2177
2178static inline void QCBOREncode_AddUndefToMap(QCBOREncodeContext *pCtx, const char *szLabel)
2179{
2180 QCBOREncode_AddSZString(pCtx, szLabel);
2181 QCBOREncode_AddUndef(pCtx);
2182}
2183
2184static inline void QCBOREncode_AddUndefToMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
2185{
2186 QCBOREncode_AddInt64(pCtx, nLabel);
2187 QCBOREncode_AddUndef(pCtx);
2188}
2189
2190
2191static inline void QCBOREncode_OpenArray(QCBOREncodeContext *pCtx)
2192{
2193 QCBOREncode_OpenMapOrArray(pCtx, CBOR_MAJOR_TYPE_ARRAY);
2194}
2195
2196static inline void QCBOREncode_OpenArrayInMap(QCBOREncodeContext *pCtx, const char *szLabel)
2197{
2198 QCBOREncode_AddSZString(pCtx, szLabel);
2199 QCBOREncode_OpenArray(pCtx);
2200}
2201
2202static inline void QCBOREncode_OpenArrayInMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
2203{
2204 QCBOREncode_AddInt64(pCtx, nLabel);
2205 QCBOREncode_OpenArray(pCtx);
2206}
2207
2208static inline void QCBOREncode_CloseArray(QCBOREncodeContext *pCtx)
2209{
2210 QCBOREncode_CloseMapOrArray(pCtx, CBOR_MAJOR_TYPE_ARRAY);
2211}
2212
2213
2214static inline void QCBOREncode_OpenMap(QCBOREncodeContext *pCtx)
2215{
2216 QCBOREncode_OpenMapOrArray(pCtx, CBOR_MAJOR_TYPE_MAP);
2217}
2218
2219static inline void QCBOREncode_OpenMapInMap(QCBOREncodeContext *pCtx, const char *szLabel)
2220{
2221 QCBOREncode_AddSZString(pCtx, szLabel);
2222 QCBOREncode_OpenMap(pCtx);
2223}
2224
2225static inline void QCBOREncode_OpenMapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
2226{
2227 QCBOREncode_AddInt64(pCtx, nLabel);
2228 QCBOREncode_OpenMap(pCtx);
2229}
2230
2231static inline void QCBOREncode_CloseMap(QCBOREncodeContext *pCtx)
2232{
2233 QCBOREncode_CloseMapOrArray(pCtx, CBOR_MAJOR_TYPE_MAP);
2234}
2235
2236static inline void QCBOREncode_OpenArrayIndefiniteLength(QCBOREncodeContext *pCtx)
2237{
2238 QCBOREncode_OpenMapOrArrayIndefiniteLength(pCtx, CBOR_MAJOR_NONE_TYPE_ARRAY_INDEFINITE_LEN);
2239}
2240
2241static inline void QCBOREncode_OpenArrayIndefiniteLengthInMap(QCBOREncodeContext *pCtx, const char *szLabel)
2242{
2243 QCBOREncode_AddSZString(pCtx, szLabel);
2244 QCBOREncode_OpenArrayIndefiniteLength(pCtx);
2245}
2246
2247static inline void QCBOREncode_OpenArrayIndefiniteLengthInMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
2248{
2249 QCBOREncode_AddInt64(pCtx, nLabel);
2250 QCBOREncode_OpenArrayIndefiniteLength(pCtx);
2251}
2252
2253static inline void QCBOREncode_CloseArrayIndefiniteLength(QCBOREncodeContext *pCtx)
2254{
2255 QCBOREncode_CloseMapOrArrayIndefiniteLength(pCtx, CBOR_MAJOR_NONE_TYPE_ARRAY_INDEFINITE_LEN);
2256}
2257
2258
2259static inline void QCBOREncode_OpenMapIndefiniteLength(QCBOREncodeContext *pCtx)
2260{
2261 QCBOREncode_OpenMapOrArrayIndefiniteLength(pCtx, CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN);
2262}
2263
2264static inline void QCBOREncode_OpenMapIndefiniteLengthInMap(QCBOREncodeContext *pCtx, const char *szLabel)
2265{
2266 QCBOREncode_AddSZString(pCtx, szLabel);
2267 QCBOREncode_OpenMapIndefiniteLength(pCtx);
2268}
2269
2270static inline void QCBOREncode_OpenMapIndefiniteLengthInMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
2271{
2272 QCBOREncode_AddInt64(pCtx, nLabel);
2273 QCBOREncode_OpenMapIndefiniteLength(pCtx);
2274}
2275
2276static inline void QCBOREncode_CloseMapIndefiniteLength(QCBOREncodeContext *pCtx)
2277{
2278 QCBOREncode_CloseMapOrArrayIndefiniteLength(pCtx, CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN);
2279}
2280
2281
2282static inline void QCBOREncode_BstrWrap(QCBOREncodeContext *pCtx)
2283{
2284 QCBOREncode_OpenMapOrArray(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING);
2285}
2286
2287static inline void QCBOREncode_BstrWrapInMap(QCBOREncodeContext *pCtx, const char *szLabel)
2288{
2289 QCBOREncode_AddSZString(pCtx, szLabel);
2290 QCBOREncode_BstrWrap(pCtx);
2291}
2292
2293static inline void QCBOREncode_BstrWrapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
2294{
2295 QCBOREncode_AddInt64(pCtx, nLabel);
2296 QCBOREncode_BstrWrap(pCtx);
2297}
2298
2299static inline void QCBOREncode_CloseBstrWrap(QCBOREncodeContext *pCtx, UsefulBufC *pWrappedCBOR)
2300{
2301 QCBOREncode_CloseBstrWrap2(pCtx, true, pWrappedCBOR);
2302}
2303
2304
2305static inline void QCBOREncode_AddEncoded(QCBOREncodeContext *pCtx, UsefulBufC Encoded)
2306{
2307 QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_NONE_TYPE_RAW, Encoded);
2308}
2309
2310static inline void QCBOREncode_AddEncodedToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Encoded)
2311{
2312 QCBOREncode_AddSZString(pCtx, szLabel);
2313 QCBOREncode_AddEncoded(pCtx, Encoded);
2314}
2315
2316static inline void QCBOREncode_AddEncodedToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Encoded)
2317{
2318 QCBOREncode_AddInt64(pCtx, nLabel);
2319 QCBOREncode_AddEncoded(pCtx, Encoded);
2320}
2321
2322
2323static inline int QCBOREncode_IsBufferNULL(QCBOREncodeContext *pCtx)
2324{
2325 return UsefulOutBuf_IsBufferNULL(&(pCtx->OutBuf));
2326}
2327
2328static inline QCBORError QCBOREncode_GetErrorState(QCBOREncodeContext *pCtx)
2329{
2330 if(UsefulOutBuf_GetError(&(pCtx->OutBuf))) {
2331 // Items didn't fit in the buffer.
2332 // This check catches this condition for all the appends and inserts
2333 // so checks aren't needed when the appends and inserts are performed.
2334 // And of course UsefulBuf will never overrun the input buffer given
2335 // to it. No complex analysis of the error handling in this file is
2336 // needed to know that is true. Just read the UsefulBuf code.
2337 pCtx->uError = QCBOR_ERR_BUFFER_TOO_SMALL;
2338 // QCBOR_ERR_BUFFER_TOO_SMALL masks other errors, but that is
2339 // OK. Once the caller fixes this, they'll be unmasked.
2340 }
2341
2342 return (QCBORError)pCtx->uError;
2343}
2344
2345
2346/* ===========================================================================
2347 END OF PRIVATE INLINE IMPLEMENTATION
2348
2349 =========================================================================== */
2350
2351#ifdef __cplusplus
2352}
2353#endif
2354
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002355#endif /* qcbor_encode_h */