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