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