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