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