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