blob: 0cee39151e9c49e3f5921e0539ba3133462335d8 [file] [log] [blame]
/* ===========================================================================
* Copyright (c) 2016-2018, The Linux Foundation.
* Copyright (c) 2018-2024, Laurence Lundblade.
* Copyright (c) 2021, Arm Limited.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors, nor the name "Laurence Lundblade" may be used to
* endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ========================================================================= */
#ifndef qcbor_encode_h
#define qcbor_encode_h
#include "qcbor/qcbor_common.h"
#include "qcbor/qcbor_private.h"
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#if 0
} // Keep editor indention formatting happy
#endif
#endif
/**
* @file qcbor_encode.h
*
* @anchor Overview
*
* # QCBOR Overview
*
* This implements CBOR -- Concise Binary Object Representation as
* defined in [RFC 8949] (https://tools.ietf.org/html/rfc8949). More
* information is at http://cbor.io. This is a near-complete implementation of
* the specification. [RFC 8742] (https://tools.ietf.org/html/rfc8742) CBOR
* Sequences is also supported. Limitations are listed further down.
*
* See @ref Encoding for general discussion on encoding,
* @ref BasicDecode for general discussion on the basic decode features
* and @ref SpiffyDecode for general discussion on the easier-to-use
* decoder functions.
*
* CBOR is intentionally designed to be translatable to JSON, but not
* all CBOR can convert to JSON. See RFC 8949 for more info on how to
* construct CBOR that is the most JSON friendly.
*
* The memory model for encoding and decoding is that encoded CBOR must
* be in a contiguous buffer in memory. During encoding the caller must
* supply an output buffer and if the encoding would go off the end of
* the buffer an error is returned. During decoding the caller supplies
* the encoded CBOR in a contiguous buffer and the decoder returns
* pointers and lengths into that buffer for strings.
*
* This implementation does not require malloc. All data structures
* passed in/out of the APIs can fit on the stack.
*
* Decoding of indefinite-length strings is a special case that requires
* a "string allocator" to allocate memory into which the segments of
* the string are coalesced. Without this, decoding will error out if an
* indefinite-length string is encountered (indefinite-length maps and
* arrays do not require the string allocator). A simple string
* allocator called MemPool is built-in and will work if supplied with a
* block of memory to allocate. The string allocator can optionally use
* malloc() or some other custom scheme.
*
* Here are some terms and definitions:
*
* - "Item", "Data Item": An integer or string or such. The basic "thing" that
* CBOR is about. An array is an item itself that contains some items.
*
* - "Array": An ordered sequence of items, the same as JSON.
*
* - "Map": A collection of label/value pairs. Each pair is a data
* item. A JSON "object" is the same as a CBOR "map".
*
* - "Label": The data item in a pair in a map that names or identifies
* the pair, not the value. This implementation refers to it as a
* "label". JSON refers to it as the "name". The CBOR RFC refers to it
* this as a "key". This implementation chooses label instead because
* key is too easily confused with a cryptographic key. The COSE
* standard, which uses CBOR, has also chosen to use the term "label"
* rather than "key" for this same reason.
*
* - "Key": See "Label" above.
*
* - "Tag": A data item that is an explicitly labeled new data
* type made up of the tagging integer and the tag content.
* See @ref Tags-Overview and @ref Tag-Usage.
*
* - "Initial Byte": The first byte of an encoded item. Encoding and
* decoding of this byte is taken care of by the implementation.
*
* - "Additional Info": In addition to the major type, all data items
* have some other info. This is usually the length of the data but can
* be several other things. Encoding and decoding of this is taken care
* of by the implementation.
*
* CBOR has two mechanisms for tagging and labeling the data values like
* integers and strings. For example, an integer that represents
* someone's birthday in epoch seconds since Jan 1, 1970 could be
* encoded like this:
*
* - First it is CBOR_MAJOR_TYPE_POSITIVE_INT (@ref QCBOR_TYPE_INT64),
* the primitive positive integer.
*
* - Next it has a "tag" @ref CBOR_TAG_DATE_EPOCH indicating the integer
* represents a date in the form of the number of seconds since Jan 1,
* 1970.
*
* - Last it has a string "label" like "BirthDate" indicating the
* meaning of the data.
*
* The encoded binary looks like this:
*
* a1 # Map of 1 item
* 69 # Indicates text string of 9 bytes
* 426972746844617465 # The text "BirthDate"
* c1 # Tags next integer as epoch date
* 1a # Indicates a 4-byte integer
* 580d4172 # unsigned integer date 1477263730
*
* Implementors using this API will primarily work with
* labels. Generally, tags are only needed for making up new data
* types. This implementation covers most of the data types defined in
* the RFC using tags. It also, allows for the use of custom tags if
* necessary.
*
* This implementation explicitly supports labels that are text strings
* and integers. Text strings translate nicely into JSON objects and are
* very readable. Integer labels are much less readable but can be very
* compact. If they are in the range of 0 to 23, they take up only one
* byte.
*
* CBOR allows a label to be any type of data including an array or a
* map. It is possible to use this API to construct and parse such
* labels, but it is not explicitly supported.
*
* @anchor Encoding
*
* ## Encoding
*
* A common encoding usage mode is to invoke the encoding twice. First
* with the output buffer as @ref SizeCalculateUsefulBuf to compute the
* length of the needed output buffer. The correct sized output buffer
* is allocated. The encoder is invoked a second time with the allocated
* output buffer.
*
* The double invocation is not required if the maximum output buffer
* size can be predicted. This is usually possible for simple CBOR
* structures.
*
* If a buffer too small to hold the encoded output is given, the error
* @ref QCBOR_ERR_BUFFER_TOO_SMALL will be returned. Data will never be
* written off the end of the output buffer no matter which functions
* here are called or what parameters are passed to them.
*
* The encoding error handling is simple. The only possible errors are
* trying to encode structures that are too large or too complex. There
* are no internal malloc calls so there will be no failures for out of
* memory. The error state is tracked internally, so there is no need
* to check for errors when encoding. Only the return code from
* QCBOREncode_Finish() need be checked as once an error happens, the
* encoder goes into an error state and calls to it to add more data
* will do nothing. An error check is not needed after every data item
* is added.
*
* Encoding generally proceeds by calling QCBOREncode_Init(), calling
* lots of @c QCBOREncode_AddXxx() functions and calling
* QCBOREncode_Finish(). There are many @c QCBOREncode_AddXxx()
* functions for various data types. The input buffers need only to be
* valid during the @c QCBOREncode_AddXxx() calls as the data is copied
* into the output buffer.
*
* There are three `Add` functions for each data type. The first / main
* one for the type is for adding the data item to an array. The second
* one's name ends in `ToMap`, is used for adding data items to maps and
* takes a string argument that is its label in the map. The third one
* ends in `ToMapN`, is also used for adding data items to maps, and
* takes an integer argument that is its label in the map.
*
* The simplest aggregate type is an array, which is a simple ordered
* set of items without labels the same as JSON arrays. Call
* QCBOREncode_OpenArray() to open a new array, then various @c
* QCBOREncode_AddXxx() functions to put items in the array and then
* QCBOREncode_CloseArray(). Nesting to the limit @ref
* QCBOR_MAX_ARRAY_NESTING is allowed. All opens must be matched by
* closes or an encoding error will be returned.
*
* The other aggregate type is a map which does use labels. The `Add`
* functions that end in `ToMap` and `ToMapN` are convenient ways to add
* labeled data items to a map. You can also call any type of `Add`
* function once to add a label of any type and then call any type of
* `Add` again to add its value.
*
* Note that when you nest arrays or maps in a map, the nested array or
* map has a label.
*
* Many CBOR-based protocols start with an array or map. This makes them
* self-delimiting. No external length or end marker is needed to know
* the end. It is also possible not start this way, in which case this
* it is usually called a CBOR sequence which is described in
* [RFC 8742] (https://tools.ietf.org/html/rfc8742). This encoder supports
* either just by whether the first item added is an array, map or other.
*
* If QCBOR is compiled with QCBOR_DISABLE_ENCODE_USAGE_GUARDS defined,
* the errors QCBOR_ERR_CLOSE_MISMATCH, QCBOR_ERR_ARRAY_TOO_LONG,
* QCBOR_ERR_TOO_MANY_CLOSES, QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN, and
* QCBOR_ERR_ENCODE_UNSUPPORTED will never be returned. It is up to the
* caller to make sure that opened maps, arrays and byte-string wrapping
* is closed correctly and that QCBOREncode_AddType7() is called
* correctly. With this defined, it is easier to make a mistake when
* authoring the encoding of a protocol that will output not well formed
* CBOR, but as long as the calling code is correct, it is safe to
* disable these checks. Bounds checking that prevents security issues
* in the code is still enforced. This define reduces the size of
* encoding object code by about 150 bytes.
*
* @anchor Tags-Overview
*
* ## Tags Overview
*
* Any CBOR data item can be made into a tag to add semantics, define a
* new data type or such. Some tags are fully standardized and some are
* just registered. Others are not registered and used in a proprietary
* way.
*
* Encoding and decoding of many of the registered tags is fully
* implemented by QCBOR. It is also possible to encode and decode tags
* that are not directly supported. For many use cases the built-in tag
* support should be adequate.
*
* For example, the registered epoch date tag is supported in encoding
* by QCBOREncode_AddDateEpoch() and in decoding by @ref
* QCBOR_TYPE_DATE_EPOCH and the @c epochDate member of @ref
* QCBORItem. This is typical of the built-in tag support. There is an
* API to encode data for it and a @c QCBOR_TYPE_XXX when it is decoded.
*
* Tags are registered in the [IANA CBOR Tags Registry]
* (https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml). There
* are roughly three options to create a new tag. First, a public
* specification can be created and the new tag registered with IANA.
* This is the most formal. Second, the new tag can be registered with
* IANA with just a short description rather than a full specification.
* These tags must be greater than 256. Third, a tag can be used without
* any IANA registration, though the registry should be checked to see
* that the new value doesn't collide with one that is registered. The
* value of these tags must be 256 or larger.
*
* See also @ref CBORTags and @ref Tag-Usage
*
* The encoding side of tags not built-in is handled by
* QCBOREncode_AddTag() and is relatively simple. Tag decoding is more
* complex and mainly handled by QCBORDecode_GetNext(). Decoding of the
* structure of tagged data not built-in (if there is any) has to be
* implemented by the caller.
*
* @anchor Floating-Point
*
* ## Floating-Point
*
* By default QCBOR fully supports IEEE 754 floating-point:
* - Encode/decode of double, single and half-precision
* - CBOR preferred serialization of floating-point
* - Floating-point epoch dates
*
* For the most part, the type double is used in the interface for
* floating-point values. In the default configuration, all decoded
* floating-point values are returned as a double.
*
* With CBOR preferred serialization, the encoder outputs the smallest
* representation of the double or float that preserves precision. Zero,
* NaN and infinity are always output as a half-precision, each taking
* just 2 bytes. This reduces the number of bytes needed to encode
* double and single-precision, especially if zero, NaN and infinity are
* frequently used.
*
* To avoid use of preferred serialization in the standard configuration
* when encoding, use QCBOREncode_AddDoubleNoPreferred() or
* QCBOREncode_AddFloatNoPreferred().
*
* This implementation of preferred floating-point serialization and
* half-precision does not depend on the CPU having floating-point HW or
* the compiler bringing in a (sometimes large) library to compensate
* for lack of CPU support. This implementation uses shifts and masks
* rather than floating-point functions.
*
* To reduce overall object code by about 900 bytes, define
* QCBOR_DISABLE_PREFERRED_FLOAT. This will eliminate all support for
* preferred serialization and half-precision. An error will be returned
* when attempting to decode half-precision. A float will always be
* encoded and decoded as 32-bits and a double will always be encoded
* and decoded as 64 bits.
*
* Note that even if QCBOR_DISABLE_PREFERRED_FLOAT is not defined all
* the float-point encoding object code can be avoided by never calling
* any functions that encode double or float. Just not calling
* floating-point functions will reduce object code by about 500 bytes.
*
* On CPUs that have no floating-point hardware,
* QCBOR_DISABLE_FLOAT_HW_USE should be defined in most cases. If it is
* not, then the compiler will bring in possibly large software
* libraries to compensate. Defining QCBOR_DISABLE_FLOAT_HW_USE reduces
* object code size on CPUs with floating-point hardware by a tiny
* amount and eliminates the need for <math.h>
*
* When QCBOR_DISABLE_FLOAT_HW_USE is defined, trying to decoding
* floating-point dates will give error
* @ref QCBOR_ERR_FLOAT_DATE_DISABLED and decoded single-precision
* numbers will be returned as @ref QCBOR_TYPE_FLOAT instead of
* converting them to double as usual.
*
* If both QCBOR_DISABLE_FLOAT_HW_USE and QCBOR_DISABLE_PREFERRED_FLOAT
* are defined, then the only thing QCBOR can do is encode/decode a C
* float type as 32-bits and a C double type as 64-bits. Floating-point
* epoch dates will be unsupported.
*
* If USEFULBUF_DISABLE_ALL_FLOATis defined, then floating point
* support is completely disabled. Decoding functions return
* @ref QCBOR_ERR_ALL_FLOAT_DISABLED if a floating point value is
* encountered during decoding. Functions that are encoding floating
* point values are not available.
*
* ## Limitations
*
* Summary Limits of this implementation:
* - The entire encoded CBOR must fit into contiguous memory.
* - Max size of encoded / decoded CBOR data is a few bytes less than @c UINT32_MAX (4GB).
* - Max array / map nesting level when encoding / decoding is
* @ref QCBOR_MAX_ARRAY_NESTING (this is typically 15).
* - Max items in an array or map when encoding / decoding is
* @ref QCBOR_MAX_ITEMS_IN_ARRAY (typically 65,536).
* - Does not directly support labels in maps other than text strings & integers.
* - Does not directly support integer labels greater than @c INT64_MAX.
* - Epoch dates limited to @c INT64_MAX (+/- 292 billion years).
* - Exponents for bigfloats and decimal integers are limited to @c INT64_MAX.
* - Tags on labels are ignored during decoding.
* - The maximum tag nesting is @c QCBOR_MAX_TAGS_PER_ITEM (typically 4).
* - Works only on 32- and 64-bit CPUs (modifications could make it work
* on 16-bit CPUs).
*
* The public interface uses @c size_t for all lengths. Internally the
* implementation uses 32-bit lengths by design to use less memory and
* fit structures on the stack. This limits the encoded CBOR it can
* work with to size @c UINT32_MAX (4GB) which should be enough.
*
* This implementation assumes two's compliment integer machines.
* @c <stdint.h> also requires this. It is possible to modify this
* implementation for another integer representation, but all modern
* machines seem to be two's compliment.
*/
/**
* The size of the buffer to be passed to QCBOREncode_EncodeHead(). It
* is one byte larger than sizeof(uint64_t) + 1, the actual maximum
* size of the head of a CBOR data item because
* QCBOREncode_EncodeHead() needs one extra byte to work.
*/
#define QCBOR_HEAD_BUFFER_SIZE (sizeof(uint64_t) + 2)
/**
* Output the full CBOR tag. See @ref CBORTags, @ref Tag-Usage and
* @ref Tags-Overview.
*/
#define QCBOR_ENCODE_AS_TAG 0
/**
* Output only the 'borrowed' content format for the relevant tag.
* See @ref CBORTags, @ref Tag-Usage and @ref Tags-Overview.
*/
#define QCBOR_ENCODE_AS_BORROWED 1
/**
* QCBOREncodeContext is the data type that holds context for all the
* encoding functions. It is less than 200 bytes, so it can go on the
* stack. The contents are opaque, and the caller should not access
* internal members. A context may be re used serially as long as it is
* re initialized.
*/
typedef struct _QCBOREncodeContext QCBOREncodeContext;
/**
* Initialize the encoder to prepare to encode some CBOR.
*
* @param[in,out] pCtx The encoder context to initialize.
* @param[in] Storage The buffer into which the encoded result
* will be written.
*
* Call this once at the start of an encoding of some CBOR. Then call
* the many functions like QCBOREncode_AddInt64() and
* QCBOREncode_AddText() to add the different data items. Finally,
* call QCBOREncode_Finish() to get the pointer and length of the
* encoded result.
*
* The primary purpose of this function is to give the pointer and
* length of the output buffer into which the encoded CBOR will be
* written. This is done with a @ref UsefulBuf structure, which is
* just a pointer and length (it is equivalent to two parameters, one
* a pointer and one a length, but a little prettier).
*
* The output buffer can be allocated any way (malloc, stack,
* static). It is just some memory that QCBOR writes to. The length
* must be the length of the allocated buffer. QCBOR will never write
* past that length, but might write up to that length. If the buffer
* is too small, encoding will go into an error state and not write
* anything further.
*
* If allocating on the stack, the convenience macro
* UsefulBuf_MAKE_STACK_UB() can be used, but its use is not required.
*
* Since there is no reallocation or such, the output buffer must be
* correctly sized when passed in here. It is OK, but wasteful if it
* is too large. One way to pick the size is to figure out the maximum
* size that will ever be needed and hard code a buffer of that size.
*
* Another way to do it is to have QCBOR calculate it for you. To do
* this, pass @ref SizeCalculateUsefulBuf for @c Storage. Then call
* all the functions to add the CBOR exactly as if encoding for
* real. Finally, call QCBOREncode_FinishGetSize(). Once the length
* is obtained, allocate a buffer of that size, call
* QCBOREncode_Init() again with the real buffer. Call all the add
* functions again and finally, QCBOREncode_Finish() to obtain the
* final result. This uses twice the CPU time, but that is usually not
* an issue.
*
* See QCBOREncode_Finish() for how the pointer and length for the
* encoded CBOR is returned.
*
* For practical purposes QCBOR can't output encoded CBOR larger than
* @c UINT32_MAX (4GB) even on 64-bit CPUs because the internal
* offsets used to track the start of an array/map are 32 bits to
* reduce the size of the encoding context.
*
* A @ref QCBOREncodeContext can be reused over and over as long as
* QCBOREncode_Init() is called before each use.
*/
void
QCBOREncode_Init(QCBOREncodeContext *pCtx, UsefulBuf Storage);
/**
* @brief Select preferred serialization mode.
*
* @param[in] pCtx The encoding context for mode set.
*
* Setting this mode will cause QCBOR to return an error if an attempt
* is made to use one of the methods that produce non-preferred
* serialization. It doesn't change anything else as QCBOR produces
* preferred serialization by default.
*
* The non-preferred methods are: QCBOREncode_AddFloatNoPreferred(),
* QCBOREncode_AddDoubleNoPreferred(),
* QCBOREncode_OpenArrayIndefiniteLength(),
* QCBOREncode_CloseArrayIndefiniteLength(),
* QCBOREncode_OpenMapIndefiniteLength(),
* QCBOREncode_CloseMapIndefiniteLength(), plus those derived from the
* above listed.
*
* This mode is just a user guard to prevent accidentally calling
* something that produces non-preferred serialization. It doesn't do
* anything but causes errors to occur on attempts to call the above
* listed functions. This does nothing if the library is compiled
* QCBOR_DISABLE_ENCODE_USAGE_GUARDS.
*
* See @ref Serialization. It is usually not necessary to set this
* mode, but there is usually no issue in setting it. Preferred
* Serialization is defined in RFC 8949, section 4.1.
*/
static void
QCBOREncode_SerializationPreferred(QCBOREncodeContext *pCtx);
/**
* @brief Select CBOR deterministic encoding mode.
*
* @param[in] pCtx The encoding context for mode set.
* This causes QCBOR to produce CBOR Deterministic Encoding (CDE).
* With CDE, two distant unrelated CBOR encoders will produce exactly
* the same encoded CBOR for a given input.
*
* In addition to doing everything
* QCBOREncode_SerializationPreferred() does (including exclusion of
* indefinite lengths), this causes maps to be sorted. The map is
* sorted automatically when QCBOREncode_CloseMap() is called.
* QCBOREncode_CloseMap() becomes equivalent to
* QCBOREncode_CloseAndSortMap().
*
* Note that linking this function causese about 30% more code from
* the QCBOR library to be linked. Also, QCBOREncode_CloseMap() runs
* slower, but this is probably only of consequence in very
* constrained environments.
*
* See @ref Serialization. It is usually not necessary to set this
* mode as determinism is very rarely needed. However it will
* usually work with most protocols. CDE is defined in
* draft-ietf-cbor-cde.
*/
static void
QCBOREncode_SerializationCDE(QCBOREncodeContext *pCtx);
/**
* @brief Select "dCBOR" encoding mode.
*
* @param[in] pCtx The encoding context for mode set.
*
* This is a superset of CDE. This function does everything
* QCBOREncode_SerializationCDE() does. Also it is a super set of
* preferred serialization and does everything
* QCBOREncode_SerializationPreferred() does.
*
* The main feature of dCBOR is that there is only one way to serialize a
* particular numeric value. This changes the behavior of functions
* that add floating-point numbers. If the floating-point number is
* whole, it will be encoded as an integer, not a floating-point number.
* 0.000 will be encoded as 0x00. Precision is never lost in this
* conversion.
*
* dCBOR also disallows NaN payloads. QCBOR will allow NaN payloads if
* you pass a NaN to one of the floating-point encoding functions.
* This mode forces all NaNs to the half-precision queit NaN. Also see
* QCBOREncode_Allow().
*
* dCBOR also disallows 65-bit negative integers.
*
* dCBOR disallows use of any simple type other than true, false and
* NULL. In particular it disallows use of "undef" produced by
* QCBOREncode_AddUndef().
*
* See @ref Serialization. Set this mode only if the protocol you are
* implementing requires dCBOR. This mode is usually not compatible
* with protocols that don't use dCBOR. dCBOR is defined in
* draft-mcnally-deterministic-cbor.
*/
static void
QCBOREncode_SerializationdCBOR(QCBOREncodeContext *pCtx);
/** Bit flag to be passed to QCBOREncode_Allow() to allow NaN payloads
* to be output by QCBOREncode_AddDouble() and
* QCBORENcode_AddFloat(). */
#define QCBOR_ENCODE_ALLOW_NAN_PAYLOAD 0x01
/** Bit flag to be passed to QCBOREncode_Allow() to allow use of
* QCBOREncode_AddNegativeUInt64(). */
#define QCBOR_ENCODE_ALLOW_65_BIG_NEG 0x02
/** Bit flag to be passed to QCBOREncode_Allow() output of less
* interoperable values. See @ref QCBOR_ENCODE_ALLOW_NAN_PAYLOAD, and
* @ref QCBOR_ENCODE_ALLOW_65_BIG_NEG. */
#define QCBOR_ENCODE_ALLOW_ALL 0xFF
/*
* @brief Allow encoding output of less-interoperable values.
*
* @param[in] pCtx The encoding context.
* @param[in] uAllow Bit flags indicating what to allow.
*
* There are a few things in the CBOR standard that are often not
* supported and are thus not very interoperable. By default QCBOR
* will error if you attempt to output them. This disables that
* error.
*
* See @ref QCBOR_ENCODE_ALLOW_NAN_PAYLOAD and @ref
* QCBOR_ENCODE_ALLOW_65_BIG_NEG.
*
* This does nothing if the library is compiled
* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
static void
QCBOREncode_Allow(QCBOREncodeContext *pCtx, uint8_t uAllow);
/**
* @brief Add a signed 64-bit integer to the encoded output.
*
* @param[in] pCtx The encoding context to add the integer to.
* @param[in] nNum The integer to add.
*
* The integer will be encoded and added to the CBOR output.
*
* This function figures out the size and the sign and encodes in the
* correct minimal CBOR. Specifically, it will select CBOR major type
* 0 or 1 based on sign and will encode to 1, 2, 4 or 8 bytes
* depending on the value of the integer. Values less than 24
* effectively encode to one byte because they are encoded in with the
* CBOR major type. This is a neat and efficient characteristic of
* CBOR that can be taken advantage of when designing CBOR-based
* protocols. If integers like tags can be kept between -23 and 23
* they will be encoded in one byte including the major type.
*
* If you pass a smaller int, say an @c int16_t or a small value, say
* 100, the encoding will still be CBOR's most compact that can
* represent the value. For example, CBOR always encodes the value 0
* as one byte, 0x00. The representation as 0x00 includes
* identification of the type as an integer too as the major type for
* an integer is 0. See [RFC 8949]
* (https://tools.ietf.org/html/rfc8949) Appendix A for more examples
* of CBOR encoding. This compact encoding is also preferred
* serialization CBOR as per section 34.1 in RFC 8949.
*
* There are no functions to add @c int16_t or @c int32_t because they
* are not necessary because this always encodes to the smallest
* number of bytes based on the value (If this code is running on a
* 32-bit machine having a way to add 32-bit integers would reduce
* code size some).
*
* If the encoding context is in an error state, this will do
* nothing. If an error occurs when adding this integer, the internal
* error flag will be set, and the error will be returned when
* QCBOREncode_Finish() is called.
*
* See also QCBOREncode_AddUInt64().
*/
void
QCBOREncode_AddInt64(QCBOREncodeContext *pCtx, int64_t nNum);
static void
QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t uNum);
static void
QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t uNum);
/**
* @brief Add an unsigned 64-bit integer to the encoded output.
*
* @param[in] pCtx The encoding context to add the integer to.
* @param[in] uNum The integer to add.
*
* The integer will be encoded and added to the CBOR output.
*
* The only reason so use this function is for integers larger than
* @c INT64_MAX and smaller than @c UINT64_MAX. Otherwise
* QCBOREncode_AddInt64() will work fine.
*
* Error handling is the same as for QCBOREncode_AddInt64().
*/
void
QCBOREncode_AddUInt64(QCBOREncodeContext *pCtx, uint64_t uNum);
static void
QCBOREncode_AddUInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t uNum);
static void
QCBOREncode_AddUInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, uint64_t uNum);
/**
* @brief Add a negative 64-bit integer to encoded output
*
* @param[in] pCtx The encoding context to add the integer to.
* @param[in] uNum The integer to add.
*
* QCBOREncode_AddInt64() is much better to encode negative integers
* than this. What this can do is add integers with one more
* significant bit than an int64_t (a "65-bit" integer if you count
* the sign as a bit) which is possible because CBOR happens to
* support such integers.
*
* The actual value encoded is -uNum - 1. That is, give 0 for uNum to
* transmit -1, give 1 to transmit -2 and give UINT64_MAX to transmit
* -UINT64_MAX-1 (18446744073709551616). The interface is odd like
* this so all negative values CBOR can represent can be encoded by
* QCBOR (making this a complete CBOR implementation).
*
* The most negative value QCBOREncode_AddInt64() can encode is
* -9223372036854775808 which is -2^63 or negative
* 0x800000000000. This can encode from -9223372036854775809 to
* -18446744073709551616 or -2^63 - 1 to -2^64. Note that
* it is not possible to represent plus or minus 18446744073709551616
* in any standard C data type.
*
* Negative integers are normally decoded in QCBOR with type
* @ref QCBOR_TYPE_INT64. Integers in the range of -9223372036854775809
* to -18446744073709551616 are returned as @ref QCBOR_TYPE_65BIT_NEG_INT.
*
* WARNING: some CBOR decoders will be unable to decode -2^63 - 1 to
* -2^64. Also, most CPUs do not have registers that can represent
* this range. If you need 65-bit negative integers, you likely need
* negative 66, 67 and 68-bit negative integers so it is likely better
* to use CBOR big numbers where you can have any number of bits. See
* QCBOREncode_AddTNegativeBignum() and TODO: also xxxx
*/
void
QCBOREncode_AddNegativeUInt64(QCBOREncodeContext *pCtx, uint64_t uNum);
static void
QCBOREncode_AddNegativeUInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t uNum);
static void
QCBOREncode_AddNegativeUInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, uint64_t uNum);
/**
* @brief Add a UTF-8 text string to the encoded output.
*
* @param[in] pCtx The encoding context to add the text to.
* @param[in] Text Pointer and length of text to add.
*
* The text passed in must be unencoded UTF-8 according to [RFC 3629]
* (https://tools.ietf.org/html/rfc3629). There is no NULL
* termination. The text is added as CBOR major type 3.
*
* If called with @c nBytesLen equal to 0, an empty string will be
* added. When @c nBytesLen is 0, @c pBytes may be @c NULL.
*
* Note that the restriction of the buffer length to a @c uint32_t is
* entirely intentional as this encoder is not capable of encoding
* lengths greater. This limit to 4GB for a text string should not be
* a problem.
*
* Text lines in Internet protocols (on the wire) are delimited by
* either a CRLF or just an LF. Officially many protocols specify
* CRLF, but implementations often work with either. CBOR type 3 text
* can be either line ending, even a mixture of both.
*
* Operating systems usually have a line end convention. Windows uses
* CRLF. Linux and MacOS use LF. Some applications on a given OS may
* work with either and some may not.
*
* The majority of use cases and CBOR protocols using type 3 text will
* work with either line ending. However, some use cases or protocols
* may not work with either in which case translation to and/or from
* the local line end convention, typically that of the OS, is
* necessary.
*
* QCBOR does no line ending translation for type 3 text when encoding
* and decoding.
*
* Error handling is the same as QCBOREncode_AddInt64().
*/
static void
QCBOREncode_AddText(QCBOREncodeContext *pCtx, UsefulBufC Text);
static void
QCBOREncode_AddTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Text);
static void
QCBOREncode_AddTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Text);
/**
* @brief Add a UTF-8 text string to the encoded output.
*
* @param[in] pCtx The encoding context to add the text to.
* @param[in] szString Null-terminated text to add.
*
* This works the same as QCBOREncode_AddText().
*/
static void
QCBOREncode_AddSZString(QCBOREncodeContext *pCtx, const char *szString);
static void
QCBOREncode_AddSZStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szString);
static void
QCBOREncode_AddSZStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szString);
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
/**
* @brief Add a double-precision floating-point number to the encoded output.
*
* @param[in] pCtx The encoding context to add the double to.
* @param[in] dNum The double-precision number to add.
*
* This encodes and outputs a floating-point number. CBOR major type 7
* is used.
*
* This implements preferred serialization, selectively encoding the
* double-precision floating-point number as either double-precision,
* single-precision or half-precision. Infinity, NaN and 0 are always
* encoded as half-precision. If no precision will be lost in the
* conversion to half-precision, then it will be converted and
* encoded. If not and no precision will be lost in conversion to
* single-precision, then it will be converted and encoded. If not,
* then no conversion is performed, and it encoded as a
* double-precision.
*
* Half-precision floating-point numbers take up 2 bytes, half that of
* single-precision, one quarter of double-precision
*
* This automatically reduces the size of encoded CBOR, maybe even by
* four if most of values are 0, infinity or NaN.
*
* When decoded, QCBOR will usually return these values as
* double-precision.
*
* It is possible to disable this preferred serialization when compiling
* QCBOR. In that case, this functions the same as
* QCBOREncode_AddDoubleNoPreferred().
*
* Error handling is the same as QCBOREncode_AddInt64().
*
* See also QCBOREncode_AddDoubleNoPreferred(), QCBOREncode_AddFloat()
* and QCBOREncode_AddFloatNoPreferred() and @ref Floating-Point.
*
* By default, this will error out on an attempt to encode a NaN with
* a payload. See QCBOREncode_Allow() and @ref QCBOR_ENCODE_ALLOW_NAN_PAYLOAD.
*/
void
QCBOREncode_AddDouble(QCBOREncodeContext *pCtx, double dNum);
static void
QCBOREncode_AddDoubleToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum);
static void
QCBOREncode_AddDoubleToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum);
/**
* @brief Add a single-precision floating-point number to the encoded output.
*
* @param[in] pCtx The encoding context to add the double to.
* @param[in] fNum The single-precision number to add.
*
* This is identical to QCBOREncode_AddDouble() except the input is
* single-precision.
*
* See also QCBOREncode_AddDouble(), QCBOREncode_AddDoubleNoPreferred(),
* and QCBOREncode_AddFloatNoPreferred() and @ref Floating-Point.
*/
void
QCBOREncode_AddFloat(QCBOREncodeContext *pCtx, float fNum);
static void
QCBOREncode_AddFloatToMap(QCBOREncodeContext *pCtx, const char *szLabel, float fNum);
static void
QCBOREncode_AddFloatToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, float dNum);
/**
* @brief Add a double-precision floating-point number without preferred encoding.
*
* @param[in] pCtx The encoding context to add the double to.
* @param[in] dNum The double-precision number to add.
*
* This always outputs the number as a 64-bit double-precision.
* Preferred serialization is not used.
*
* Error handling is the same as QCBOREncode_AddInt64().
*
* By default, this will error out on an attempt to encode a NaN with
* a payload. See QCBOREncode_Allow() and @ref QCBOR_ENCODE_ALLOW_NAN_PAYLOAD.
*
* See also QCBOREncode_AddDouble(), QCBOREncode_AddFloat(), and
* QCBOREncode_AddFloatNoPreferred() and @ref Floating-Point.
*/
void
QCBOREncode_AddDoubleNoPreferred(QCBOREncodeContext *pCtx, double dNum);
static void
QCBOREncode_AddDoubleNoPreferredToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum);
static void
QCBOREncode_AddDoubleNoPreferredToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum);
/**
* @brief Add a single-precision floating-point number without preferred encoding.
*
* @param[in] pCtx The encoding context to add the double to.
* @param[in] fNum The single-precision number to add.
*
* This always outputs the number as a 32-bit single-precision.
* Preferred serialization is not used.
*
* Error handling is the same as QCBOREncode_AddInt64().
*
* By default, this will error out on an attempt to encode a NaN with
* a payload. See QCBOREncode_Allow() and @ref QCBOR_ENCODE_ALLOW_NAN_PAYLOAD.
*
* See also QCBOREncode_AddDouble(), QCBOREncode_AddFloat(), and
* QCBOREncode_AddDoubleNoPreferred() and @ref Floating-Point.
*/
void
QCBOREncode_AddFloatNoPreferred(QCBOREncodeContext *pCtx, float fNum);
static void
QCBOREncode_AddFloatNoPreferredToMap(QCBOREncodeContext *pCtx, const char *szLabel, float fNum);
static void
QCBOREncode_AddFloatNoPreferredToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, float fNum);
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
/**
* @brief Add an optional tag.
*
* @param[in] pCtx The encoding context to add the tag to.
* @param[in] uTag The tag to add
*
* This outputs a CBOR major type 6 item that tags the next data item
* that is output usually to indicate it is some new data type.
*
* For many of the common standard tags, a function to encode data
* using it is provided and this is not needed. For example,
* QCBOREncode_AddDateEpoch() already exists to output integers
* representing dates with the right tag.
*
* The tag is applied to the next data item added to the encoded
* output. That data item that is to be tagged can be of any major
* CBOR type. Any number of tags can be added to a data item by
* calling this multiple times before the data item is added.
*
* See @ref Tags-Overview for discussion of creating new non-standard
* tags. See QCBORDecode_GetNext() for discussion of decoding custom
* tags.
*/
void
QCBOREncode_AddTag(QCBOREncodeContext *pCtx, uint64_t uTag);
/**
* @brief Add an epoch-based date.
*
* @param[in] pCtx The encoding context to add the date to.
* @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
* @ref QCBOR_ENCODE_AS_BORROWED.
* @param[in] nDate Number of seconds since 1970-01-01T00:00Z
* in UTC time.
*
* As per RFC 8949 this is similar to UNIX/Linux/POSIX dates. This is
* the most compact way to specify a date and time in CBOR. Note that
* this is always UTC and does not include the time zone. Use
* QCBOREncode_AddDateString() if you want to include the time zone.
*
* The preferred integer serialization rules apply here so the date will be
* encoded in a minimal number of bytes. Until about the year 2106
* these dates will encode in 6 bytes -- one byte for the tag, one
* byte for the type and 4 bytes for the integer. After that it will
* encode to 10 bytes.
*
* Negative values are supported for dates before 1970.
*
* If you care about leap-seconds and that level of accuracy, make sure
* the system you are running this code on does it correctly. This code
* just takes the value passed in.
*
* This implementation cannot encode fractional seconds using float or
* double even though that is allowed by CBOR, but you can encode them
* if you want to by calling QCBOREncode_AddTag() and QCBOREncode_AddDouble().
*
* Error handling is the same as QCBOREncode_AddInt64().
*
* See also QCBOREncode_AddTDaysEpoch().
*/
static void
QCBOREncode_AddTDateEpoch(QCBOREncodeContext *pCtx,
uint8_t uTagRequirement,
int64_t nDate);
static void
QCBOREncode_AddTDateEpochToMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
uint8_t uTagRequirement,
int64_t nDate);
static void
QCBOREncode_AddTDateEpochToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
uint8_t uTagRequirement,
int64_t nDate);
static void
QCBOREncode_AddDateEpoch(QCBOREncodeContext *pCtx,
int64_t nDate);
static void
QCBOREncode_AddDateEpochToMap(QCBOREncodeContext *pCtx,
const char *szLabel,
int64_t nDate);
static void
QCBOREncode_AddDateEpochToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
int64_t nDate);
/**
* @brief Add an epoch-based day-count date.
*
* @param[in] pCtx The encoding context to add the date to.
* @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
* @ref QCBOR_ENCODE_AS_BORROWED.
* @param[in] nDays Number of days before or after 1970-01-0.
*
* This date format is described in
* [RFC 8943] (https://tools.ietf.org/html/rfc8943).
*
* The preferred integer serialization rules apply here so the date
* will be encoded in a minimal number of bytes. Until about the year
* 2149 these dates will encode in 4 bytes -- one byte for the tag,
* one byte for the type and 2 bytes for the integer.
*
* See also QCBOREncode_AddTDateEpoch().
*/
static void
QCBOREncode_AddTDaysEpoch(QCBOREncodeContext *pCtx,
uint8_t uTagRequirement,
int64_t nDays);
static void
QCBOREncode_AddTDaysEpochToMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
uint8_t uTagRequirement,
int64_t nDays);
static void
QCBOREncode_AddTDaysEpochToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
uint8_t uTagRequirement,
int64_t nDays);
/**
* @brief Add a byte string to the encoded output.
*
* @param[in] pCtx The encoding context to add the bytes to.
* @param[in] Bytes Pointer and length of the input data.
*
* Simply adds the bytes to the encoded output as CBOR major type 2.
*
* If called with @c Bytes.len equal to 0, an empty string will be
* added. When @c Bytes.len is 0, @c Bytes.ptr may be @c NULL.
*
* Error handling is the same as QCBOREncode_AddInt64().
*/
static void
QCBOREncode_AddBytes(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
static void
QCBOREncode_AddBytesToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
static void
QCBOREncode_AddBytesToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
/**
* @brief Set up to write a byte string value directly to encoded output.
*
* @param[in] pCtx The encoding context to add the bytes to.
* @param[out] pPlace Pointer and length of place to write byte string value.
*
* QCBOREncode_AddBytes() is the normal way to encode a byte string.
* This is for special cases and by passes some of the pointer safety.
*
* The purpose of this is to output the bytes that make up a byte
* string value directly to the QCBOR output buffer so you don't need
* to have a copy of it in memory. This is particularly useful if the
* byte string is large, for example, the encrypted payload of a
* COSE_Encrypt message. The payload encryption algorithm can output
* directly to the encoded CBOR buffer, perhaps by making it the
* output buffer for some function (e.g. symmetric encryption) or by
* multiple writes.
*
* The pointer in @c pPlace is where to start writing. Writing is just
* copying bytes to the location by the pointer in \c pPlace. Writing
* past the length in @c pPlace will be writing off the end of the
* output buffer.
*
* If there is no room in the output buffer @ref NULLUsefulBuf will be
* returned and there is no need to call QCBOREncode_CloseBytes().
*
* The byte string must be closed by calling QCBOREncode_CloseBytes().
*
* Warning: this bypasses some of the usual checks provided by QCBOR
* against writing off the end of the encoded output buffer.
*/
void
QCBOREncode_OpenBytes(QCBOREncodeContext *pCtx, UsefulBuf *pPlace);
static void
QCBOREncode_OpenBytesInMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
UsefulBuf *pPlace);
static void
QCBOREncode_OpenBytesInMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
UsefulBuf *pPlace);
/**
* @brief Close out a byte string written directly to encoded output.
*
* @param[in] pCtx The encoding context to add the bytes to.
* @param[out] uAmount The number of bytes written, the length of the
* byte string.
*
* This closes out a call to QCBOREncode_OpenBytes(). This inserts a
* CBOR header at the front of the byte string value to make it a
* well-formed byte string.
*
* If there was no call to QCBOREncode_OpenBytes() then @ref
* QCBOR_ERR_TOO_MANY_CLOSES is set.
*/
void
QCBOREncode_CloseBytes(QCBOREncodeContext *pCtx, size_t uAmount);
/**
* @brief Add a binary UUID to the encoded output.
*
* @param[in] pCtx The encoding context to add the UUID to.
* @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
* @ref QCBOR_ENCODE_AS_BORROWED.
* @param[in] Bytes Pointer and length of the binary UUID.
*
* A binary UUID as defined in [RFC 4122]
* (https://tools.ietf.org/html/rfc4122) is added to the output.
*
* It is output as CBOR major type 2, a binary string, with tag @ref
* CBOR_TAG_BIN_UUID indicating the binary string is a UUID.
*/
static void
QCBOREncode_AddTBinaryUUID(QCBOREncodeContext *pCtx,
uint8_t uTagRequirement,
UsefulBufC Bytes);
static void
QCBOREncode_AddTBinaryUUIDToMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
uint8_t uTagRequirement,
UsefulBufC Bytes);
static void
QCBOREncode_AddTBinaryUUIDToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
uint8_t uTagRequirement,
UsefulBufC Bytes);
static void
QCBOREncode_AddBinaryUUID(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
static void
QCBOREncode_AddBinaryUUIDToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
static void
QCBOREncode_AddBinaryUUIDToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
/**
* @brief Add a positive big number to the encoded output.
*
* @param[in] pCtx The encoding context to add the big number to.
* @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
* @ref QCBOR_ENCODE_AS_BORROWED.
* @param[in] Bytes Pointer and length of the big number.
*
* Big numbers are integers larger than 64-bits. Their format is
* described in [RFC 8949] (https://tools.ietf.org/html/rfc8949).
*
* It is output as CBOR major type 2, a binary string, with tag
* @ref CBOR_TAG_POS_BIGNUM indicating the binary string is a positive
* big number.
*
* Often big numbers are used to represent cryptographic keys,
* however, COSE which defines representations for keys chose not to
* use this particular type.
*/
static void
QCBOREncode_AddTPositiveBignum(QCBOREncodeContext *pCtx,
uint8_t uTagRequirement,
UsefulBufC Bytes);
static void
QCBOREncode_AddTPositiveBignumToMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
uint8_t uTagRequirement,
UsefulBufC Bytes);
static void
QCBOREncode_AddTPositiveBignumToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
uint8_t uTagRequirement,
UsefulBufC Bytes);
static void
QCBOREncode_AddPositiveBignum(QCBOREncodeContext *pCtx,
UsefulBufC Bytes);
static void
QCBOREncode_AddPositiveBignumToMap(QCBOREncodeContext *pCtx,
const char *szLabel,
UsefulBufC Bytes);
static void
QCBOREncode_AddPositiveBignumToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
UsefulBufC Bytes);
/**
* @brief Add a negative big number to the encoded output.
*
* @param[in] pCtx The encoding context to add the big number to.
* @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
* @ref QCBOR_ENCODE_AS_BORROWED.
* @param[in] Bytes Pointer and length of the big number.
*
* Big numbers are integers larger than 64-bits. Their format is
* described in [RFC 8949] (https://tools.ietf.org/html/rfc8949).
*
* It is output as CBOR major type 2, a binary string, with tag
* @ref CBOR_TAG_NEG_BIGNUM indicating the binary string is a negative
* big number.
*
* Often big numbers are used to represent cryptographic keys,
* however, COSE which defines representations for keys chose not to
* use this particular type.
*/
static void
QCBOREncode_AddTNegativeBignum(QCBOREncodeContext *pCtx,
uint8_t uTagRequirement,
UsefulBufC Bytes);
static void
QCBOREncode_AddTNegativeBignumToMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
uint8_t uTagRequirement,
UsefulBufC Bytes);
static void
QCBOREncode_AddTNegativeBignumToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
uint8_t uTagRequirement,
UsefulBufC Bytes);
static void
QCBOREncode_AddNegativeBignum(QCBOREncodeContext *pCtx,
UsefulBufC Bytes);
static void
QCBOREncode_AddNegativeBignumToMap(QCBOREncodeContext *pCtx,
const char *szLabel,
UsefulBufC Bytes);
static void
QCBOREncode_AddNegativeBignumToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
UsefulBufC Bytes);
#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
/**
* @brief Add a decimal fraction to the encoded output.
*
* @param[in] pCtx Encoding context to add the decimal fraction to.
* @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
* @ref QCBOR_ENCODE_AS_BORROWED.
* @param[in] nMantissa The mantissa.
* @param[in] nBase10Exponent The exponent.
*
* The value is nMantissa * 10 ^ nBase10Exponent.
*
* A decimal fraction is good for exact representation of some values
* that can't be represented exactly with standard C (IEEE 754)
* floating-point numbers. Much larger and much smaller numbers can
* also be represented than floating-point because of the larger
* number of bits in the exponent.
*
* The decimal fraction is conveyed as two integers, a mantissa and a
* base-10 scaling factor.
*
* For example, 273.15 is represented by the two integers 27315 and -2.
*
* The exponent and mantissa have the range from @c INT64_MIN to
* @c INT64_MAX for both encoding and decoding (CBOR allows
* @c -UINT64_MAX to @c UINT64_MAX, but this implementation doesn't
* support this range to reduce code size and interface complexity a
* little).
*
* CBOR Preferred serialization of the integers is used, thus they
* will be encoded in the smallest number of bytes possible.
*
* See also QCBOREncode_AddDecimalFractionBigNum() for a decimal
* fraction with arbitrarily large precision and
* QCBOREncode_AddBigFloat().
*
* There is no representation of positive or negative infinity or NaN
* (Not a Number). Use QCBOREncode_AddDouble() to encode them.
*
* See @ref expAndMantissa for decoded representation.
*/
static void
QCBOREncode_AddTDecimalFraction(QCBOREncodeContext *pCtx,
uint8_t uTagRequirement,
int64_t nMantissa,
int64_t nBase10Exponent);
static void
QCBOREncode_AddTDecimalFractionToMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
uint8_t uTagRequirement,
int64_t nMantissa,
int64_t nBase10Exponent);
static void
QCBOREncode_AddTDecimalFractionToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
uint8_t uTagRequirement,
int64_t nMantissa,
int64_t nBase10Exponent);
static void
QCBOREncode_AddDecimalFraction(QCBOREncodeContext *pCtx,
int64_t nMantissa,
int64_t nBase10Exponent);
static void
QCBOREncode_AddDecimalFractionToMap(QCBOREncodeContext *pCtx,
const char *szLabel,
int64_t nMantissa,
int64_t nBase10Exponent);
static void
QCBOREncode_AddDecimalFractionToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
int64_t nMantissa,
int64_t nBase10Exponent);
/**
* @brief Add a decimal fraction with a big number mantissa to the encoded output.
*
* @param[in] pCtx Encoding context to add the decimal fraction to.
* @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
* @ref QCBOR_ENCODE_AS_BORROWED.
* @param[in] Mantissa The mantissa.
* @param[in] bIsNegative false if mantissa is positive, true if negative.
* @param[in] nBase10Exponent The exponent.
*
* This is the same as QCBOREncode_AddDecimalFraction() except the
* mantissa is a big number (See QCBOREncode_AddPositiveBignum())
* allowing for arbitrarily large precision.
*
* See @ref expAndMantissa for decoded representation.
*/
static void
QCBOREncode_AddTDecimalFractionBigNum(QCBOREncodeContext *pCtx,
uint8_t uTagRequirement,
UsefulBufC Mantissa,
bool bIsNegative,
int64_t nBase10Exponent);
static void
QCBOREncode_AddTDecimalFractionBigNumToMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
uint8_t uTagRequirement,
UsefulBufC Mantissa,
bool bIsNegative,
int64_t nBase10Exponent);
static void
QCBOREncode_AddTDecimalFractionBigNumToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
uint8_t uTagRequirement,
UsefulBufC Mantissa,
bool bIsNegative,
int64_t nBase10Exponent);
static void
QCBOREncode_AddDecimalFractionBigNum(QCBOREncodeContext *pCtx,
UsefulBufC Mantissa,
bool bIsNegative,
int64_t nBase10Exponent);
static void
QCBOREncode_AddDecimalFractionBigNumToMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
UsefulBufC Mantissa,
bool bIsNegative,
int64_t nBase10Exponent);
static void
QCBOREncode_AddDecimalFractionBigNumToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
UsefulBufC Mantissa,
bool bIsNegative,
int64_t nBase10Exponent);
/**
* @brief Add a big floating-point number to the encoded output.
*
* @param[in] pCtx The encoding context to add the bigfloat to.
* @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
* @ref QCBOR_ENCODE_AS_BORROWED.
* @param[in] nMantissa The mantissa.
* @param[in] nBase2Exponent The exponent.
*
* The value is nMantissa * 2 ^ nBase2Exponent.
*
* "Bigfloats", as CBOR terms them, are similar to IEEE floating-point
* numbers in having a mantissa and base-2 exponent, but they are not
* supported by hardware or encoded the same. They explicitly use two
* CBOR-encoded integers to convey the mantissa and exponent, each of
* which can be 8, 16, 32 or 64 bits. With both the mantissa and
* exponent 64 bits they can express more precision and a larger range
* than an IEEE double floating-point number. See
* QCBOREncode_AddBigFloatBigNum() for even more precision.
*
* For example, 1.5 would be represented by a mantissa of 3 and an
* exponent of -1.
*
* The exponent and mantissa have the range from @c INT64_MIN to
* @c INT64_MAX for both encoding and decoding (CBOR allows @c
* -UINT64_MAX to @c UINT64_MAX, but this implementation doesn't
* support this range to reduce code size and interface complexity a
* little).
*
* CBOR preferred serialization of the integers is used, thus they will
* be encoded in the smallest number of bytes possible.
*
* This can also be used to represent floating-point numbers in
* environments that don't support IEEE 754.
*
* See @ref expAndMantissa for decoded representation.
*/
static void
QCBOREncode_AddTBigFloat(QCBOREncodeContext *pCtx,
uint8_t uTagRequirement,
int64_t nMantissa,
int64_t nBase2Exponent);
static void
QCBOREncode_AddTBigFloatToMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
uint8_t uTagRequirement,
int64_t nMantissa,
int64_t nBase2Exponent);
static void
QCBOREncode_AddTBigFloatToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
uint8_t uTagRequirement,
int64_t nMantissa,
int64_t nBase2Exponent);
static void
QCBOREncode_AddBigFloat(QCBOREncodeContext *pCtx,
int64_t nMantissa,
int64_t nBase2Exponent);
static void
QCBOREncode_AddBigFloatToMap(QCBOREncodeContext *pCtx,
const char *szLabel,
int64_t nMantissa,
int64_t nBase2Exponent);
static void
QCBOREncode_AddBigFloatToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
int64_t nMantissa,
int64_t nBase2Exponent);
/**
* @brief Add a big floating-point number with a big number mantissa to
* the encoded output.
*
* @param[in] pCtx The encoding context to add the bigfloat to.
* @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
* @ref QCBOR_ENCODE_AS_BORROWED.
* @param[in] Mantissa The mantissa.
* @param[in] bIsNegative false if mantissa is positive, true if negative.
* @param[in] nBase2Exponent The exponent.
*
* This is the same as QCBOREncode_AddBigFloat() except the mantissa
* is a big number (See QCBOREncode_AddPositiveBignum()) allowing for
* arbitrary precision.
*
* See @ref expAndMantissa for decoded representation.
*/
static void
QCBOREncode_AddTBigFloatBigNum(QCBOREncodeContext *pCtx,
uint8_t uTagRequirement,
UsefulBufC Mantissa,
bool bIsNegative,
int64_t nBase2Exponent);
static void
QCBOREncode_AddTBigFloatBigNumToMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
uint8_t uTagRequirement,
UsefulBufC Mantissa,
bool bIsNegative,
int64_t nBase2Exponent);
static void
QCBOREncode_AddTBigFloatBigNumToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
uint8_t uTagRequirement,
UsefulBufC Mantissa,
bool bIsNegative,
int64_t nBase2Exponent);
static void
QCBOREncode_AddBigFloatBigNum(QCBOREncodeContext *pCtx,
UsefulBufC Mantissa,
bool bIsNegative,
int64_t nBase2Exponent);
static void
QCBOREncode_AddBigFloatBigNumToMap(QCBOREncodeContext *pCtx,
const char *szLabel,
UsefulBufC Mantissa,
bool bIsNegative,
int64_t nBase2Exponent);
static void
QCBOREncode_AddBigFloatBigNumToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
UsefulBufC Mantissa,
bool bIsNegative,
int64_t nBase2Exponent);
#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
/**
* @brief Add a text URI to the encoded output.
*
* @param[in] pCtx The encoding context to add the URI to.
* @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
* @ref QCBOR_ENCODE_AS_BORROWED.
* @param[in] URI Pointer and length of the URI.
*
* The format of URI must be per [RFC 3986]
* (https://tools.ietf.org/html/rfc3986).
*
* It is output as CBOR major type 3, a text string, with tag @ref
* CBOR_TAG_URI indicating the text string is a URI.
*
* A URI in a NULL-terminated string, @c szURI, can be easily added with
* this code:
*
* QCBOREncode_AddURI(pCtx, UsefulBuf_FromSZ(szURI));
*/
static void
QCBOREncode_AddTURI(QCBOREncodeContext *pCtx,
uint8_t uTagRequirement,
UsefulBufC URI);
static void
QCBOREncode_AddTURIToMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
uint8_t uTagRequirement,
UsefulBufC URI);
static void
QCBOREncode_AddTURIToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
uint8_t uTagRequirement,
UsefulBufC URI);
static void
QCBOREncode_AddURI(QCBOREncodeContext *pCtx,
UsefulBufC URI);
static void
QCBOREncode_AddURIToMap(QCBOREncodeContext *pCtx,
const char *szLabel,
UsefulBufC URI);
static void
QCBOREncode_AddURIToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
UsefulBufC URI);
/**
* @brief Add Base64-encoded text to encoded output.
*
* @param[in] pCtx The encoding context to add the base-64 text to.
* @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
* @ref QCBOR_ENCODE_AS_BORROWED.
* @param[in] B64Text Pointer and length of the base-64 encoded text.
*
* The text content is Base64 encoded data per [RFC 4648]
* (https://tools.ietf.org/html/rfc4648).
*
* It is output as CBOR major type 3, a text string, with tag @ref
* CBOR_TAG_B64 indicating the text string is Base64 encoded.
*/
static void
QCBOREncode_AddTB64Text(QCBOREncodeContext *pCtx,
uint8_t uTagRequirement,
UsefulBufC B64Text);
static void
QCBOREncode_AddTB64TextToMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
uint8_t uTagRequirement,
UsefulBufC B64Text);
static void
QCBOREncode_AddTB64TextToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
uint8_t uTagRequirement,
UsefulBufC B64Text);
static void
QCBOREncode_AddB64Text(QCBOREncodeContext *pCtx,
UsefulBufC B64Text);
static void
QCBOREncode_AddB64TextToMap(QCBOREncodeContext *pCtx,
const char *szLabel,
UsefulBufC B64Text);
static void
QCBOREncode_AddB64TextToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
UsefulBufC B64Text);
/**
* @brief Add base64url encoded data to encoded output.
*
* @param[in] pCtx The encoding context to add the base64url to.
* @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
* @ref QCBOR_ENCODE_AS_BORROWED.
* @param[in] B64Text Pointer and length of the base64url encoded text.
*
* The text content is base64URL encoded text as per [RFC 4648]
* (https://tools.ietf.org/html/rfc4648).
*
* It is output as CBOR major type 3, a text string, with tag
* @ref CBOR_TAG_B64URL indicating the text string is a Base64url
* encoded.
*/
static void
QCBOREncode_AddTB64URLText(QCBOREncodeContext *pCtx,
uint8_t uTagRequirement,
UsefulBufC B64Text);
static void
QCBOREncode_AddTB64URLTextToMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
uint8_t uTagRequirement,
UsefulBufC B64Text);
static void
QCBOREncode_AddTB64URLTextToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
uint8_t uTagRequirement,
UsefulBufC B64Text);
static void
QCBOREncode_AddB64URLText(QCBOREncodeContext *pCtx,
UsefulBufC B64Text);
static void
QCBOREncode_AddB64URLTextToMap(QCBOREncodeContext *pCtx,
const char *szLabel,
UsefulBufC B64Text);
static void
QCBOREncode_AddB64URLTextToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
UsefulBufC B64Text);
/**
* @brief Add Perl Compatible Regular Expression.
*
* @param[in] pCtx Encoding context to add the regular expression to.
* @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
* @ref QCBOR_ENCODE_AS_BORROWED.
* @param[in] Regex Pointer and length of the regular expression.
*
* The text content is Perl Compatible Regular
* Expressions (PCRE) / JavaScript syntax [ECMA262].
*
* It is output as CBOR major type 3, a text string, with tag @ref
* CBOR_TAG_REGEX indicating the text string is a regular expression.
*/
static void
QCBOREncode_AddTRegex(QCBOREncodeContext *pCtx,
uint8_t uTagRequirement,
UsefulBufC Regex);
static void
QCBOREncode_AddTRegexToMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
uint8_t uTagRequirement,
UsefulBufC Regex);
static void
QCBOREncode_AddTRegexToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
uint8_t uTagRequirement,
UsefulBufC Regex);
static void
QCBOREncode_AddRegex(QCBOREncodeContext *pCtx,
UsefulBufC Regex);
static void
QCBOREncode_AddRegexToMap(QCBOREncodeContext *pCtx,
const char *szLabel,
UsefulBufC Regex);
static void
QCBOREncode_AddRegexToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
UsefulBufC Regex);
/**
* @brief MIME encoded data to the encoded output.
*
* @param[in] pCtx The encoding context to add the MIME data to.
* @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
* @ref QCBOR_ENCODE_AS_BORROWED.
* @param[in] MIMEData Pointer and length of the MIME data.
*
* The text content is in MIME format per [RFC 2045]
* (https://tools.ietf.org/html/rfc2045) including the headers.
*
* It is output as CBOR major type 2, a binary string, with tag
* @ref CBOR_TAG_BINARY_MIME indicating the string is MIME data. This
* outputs tag 257, not tag 36, as it can carry any type of MIME
* binary, 7-bit, 8-bit, quoted-printable and base64 where tag 36
* cannot.
*
* Previous versions of QCBOR, those before spiffy decode, output tag
* 36. Decoding supports both tag 36 and 257. (if the old behavior
* with tag 36 is needed, copy the inline functions below and change
* the tag number).
*
* See also QCBORDecode_GetMIMEMessage() and
* @ref QCBOR_TYPE_BINARY_MIME.
*
* This does no translation of line endings. See QCBOREncode_AddText()
* for a discussion of line endings in CBOR.
*/
static void
QCBOREncode_AddTMIMEData(QCBOREncodeContext *pCtx,
uint8_t uTagRequirement,
UsefulBufC MIMEData);
static void
QCBOREncode_AddTMIMEDataToMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
uint8_t uTagRequirement,
UsefulBufC MIMEData);
static void
QCBOREncode_AddTMIMEDataToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
uint8_t uTagRequirement,
UsefulBufC MIMEData);
static void
QCBOREncode_AddMIMEData(QCBOREncodeContext *pCtx,
UsefulBufC MIMEData);
static void
QCBOREncode_AddMIMEDataToMap(QCBOREncodeContext *pCtx,
const char *szLabel,
UsefulBufC MIMEData);
static void
QCBOREncode_AddMIMEDataToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
UsefulBufC MIMEData);
/**
* @brief Add an RFC 3339 date string
*
* @param[in] pCtx The encoding context to add the date to.
* @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
* @ref QCBOR_ENCODE_AS_BORROWED.
* @param[in] szDate Null-terminated string with date to add.
*
* The string szDate should be in the form of [RFC 3339]
* (https://tools.ietf.org/html/rfc3339) as defined by section 3.3 in
* [RFC 4287] (https://tools.ietf.org/html/rfc4287). This is as
* described in section 3.4.1 in [RFC 8949]
* (https://tools.ietf.org/html/rfc8949).
*
* Note that this function doesn't validate the format of the date
* string at all. If you add an incorrect format date string, the
* generated CBOR will be incorrect and the receiver may not be able
* to handle it.
*
* Error handling is the same as QCBOREncode_AddInt64().
*
* See also QCBOREncode_AddTDayString().
*/
static void
QCBOREncode_AddTDateString(QCBOREncodeContext *pCtx,
uint8_t uTagRequirement,
const char *szDate);
static void
QCBOREncode_AddTDateStringToMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
uint8_t uTagRequirement,
const char *szDate);
static void
QCBOREncode_AddTDateStringToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
uint8_t uTagRequirement,
const char *szDate);
static void
QCBOREncode_AddDateString(QCBOREncodeContext *pCtx,
const char *szDate);
static void
QCBOREncode_AddDateStringToMap(QCBOREncodeContext *pCtx,
const char *szLabel,
const char *szDate);
static void
QCBOREncode_AddDateStringToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
const char *szDate);
/**
* @brief Add a date-only string.
*
* @param[in] pCtx The encoding context to add the date to.
* @param[in] uTagRequirement Either @ref QCBOR_ENCODE_AS_TAG or
* @ref QCBOR_ENCODE_AS_BORROWED.
* @param[in] szDate Null-terminated string with date to add.
*
* This date format is described in
* [RFC 8943] (https://tools.ietf.org/html/rfc8943), but that mainly
* references RFC 3339. The string szDate must be in the forrm
* specified the ABNF for a full-date in
* [RFC 3339] (https://tools.ietf.org/html/rfc3339). Examples of this
* are "1985-04-12" and "1937-01-01". The time and the time zone are
* never included.
*
* Note that this function doesn't validate the format of the date
* string at all. If you add an incorrect format date string, the
* generated CBOR will be incorrect and the receiver may not be able
* to handle it.
*
* Error handling is the same as QCBOREncode_AddInt64().
*
* See also QCBOREncode_AddTDateString().
*/
static void
QCBOREncode_AddTDaysString(QCBOREncodeContext *pCtx,
uint8_t uTagRequirement,
const char *szDate);
static void
QCBOREncode_AddTDaysStringToMapSZ(QCBOREncodeContext *pCtx,
const char *szLabel,
uint8_t uTagRequirement,
const char *szDate);
static void
QCBOREncode_AddTDaysStringToMapN(QCBOREncodeContext *pCtx,
int64_t nLabel,
uint8_t uTagRequirement,
const char *szDate);
/**
* @brief Add a standard Boolean.
*
* @param[in] pCtx The encoding context to add the Boolean to.
* @param[in] b true or false from @c <stdbool.h>.
*
* Adds a Boolean value as CBOR major type 7.
*
* Error handling is the same as QCBOREncode_AddInt64().
*/
static void
QCBOREncode_AddBool(QCBOREncodeContext *pCtx, bool b);
static void
QCBOREncode_AddBoolToMap(QCBOREncodeContext *pCtx, const char *szLabel, bool b);
static void
QCBOREncode_AddBoolToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, bool b);
/**
* @brief Add a NULL to the encoded output.
*
* @param[in] pCtx The encoding context to add the NULL to.
*
* Adds the NULL value as CBOR major type 7.
*
* This NULL doesn't have any special meaning in CBOR such as a
* terminating value for a string or an empty value.
*
* Error handling is the same as QCBOREncode_AddInt64().
*/
static void
QCBOREncode_AddNULL(QCBOREncodeContext *pCtx);
static void
QCBOREncode_AddNULLToMap(QCBOREncodeContext *pCtx, const char *szLabel);
static void
QCBOREncode_AddNULLToMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
/**
* @brief Add an "undef" to the encoded output.
*
* @param[in] pCtx The encoding context to add the "undef" to.
*
* Adds the undef value as CBOR major type 7.
*
* Note that this value will not translate to JSON.
*
* This Undef doesn't have any special meaning in CBOR such as a
* terminating value for a string or an empty value.
*
* Error handling is the same as QCBOREncode_AddInt64().
*/
static void
QCBOREncode_AddUndef(QCBOREncodeContext *pCtx);
static void
QCBOREncode_AddUndefToMap(QCBOREncodeContext *pCtx, const char *szLabel);
static void
QCBOREncode_AddUndefToMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
/**
* @brief Indicates that the next items added are in an array.
*
* @param[in] pCtx The encoding context to open the array in.
*
* Arrays are the basic CBOR aggregate or structure type. Call this
* function to start or open an array. Then call the various
* @c QCBOREncode_AddXxx() functions to add the items that go into the
* array. Then call QCBOREncode_CloseArray() when all items have been
* added. The data items in the array can be of any type and can be of
* mixed types.
*
* Nesting of arrays and maps is allowed and supported just by calling
* QCBOREncode_OpenArray() again before calling
* QCBOREncode_CloseArray(). While CBOR has no limit on nesting, this
* implementation does in order to keep it smaller and simpler. The
* limit is @ref QCBOR_MAX_ARRAY_NESTING. This is the max number of
* times this can be called without calling
* QCBOREncode_CloseArray(). QCBOREncode_Finish() will return
* @ref QCBOR_ERR_ARRAY_NESTING_TOO_DEEP when it is called as this
* function just sets an error state and returns no value when this
* occurs.
*
* If you try to add more than @ref QCBOR_MAX_ITEMS_IN_ARRAY items to
* a single array or map, @ref QCBOR_ERR_ARRAY_TOO_LONG will be
* returned when QCBOREncode_Finish() is called.
*
* An array itself must have a label if it is being added to a map.
* Note that array elements do not have labels (but map elements do).
*
* An array itself may be tagged by calling QCBOREncode_AddTag()
* before this call.
*/
static void
QCBOREncode_OpenArray(QCBOREncodeContext *pCtx);
static void
QCBOREncode_OpenArrayInMap(QCBOREncodeContext *pCtx, const char *szLabel);
static void
QCBOREncode_OpenArrayInMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
/**
* @brief Close an open array.
*
* @param[in] pCtx The encoding context to close the array in.
*
* The closes an array opened by QCBOREncode_OpenArray(). It reduces
* nesting level by one. All arrays (and maps) must be closed before
* calling QCBOREncode_Finish().
*
* When an error occurs as a result of this call, the encoder records
* the error and enters the error state. The error will be returned
* when QCBOREncode_Finish() is called.
*
* If this has been called more times than QCBOREncode_OpenArray(), then
* @ref QCBOR_ERR_TOO_MANY_CLOSES will be returned when QCBOREncode_Finish()
* is called.
*
* If this is called and it is not an array that is currently open,
* @ref QCBOR_ERR_CLOSE_MISMATCH will be returned when
* QCBOREncode_Finish() is called.
*/
static void
QCBOREncode_CloseArray(QCBOREncodeContext *pCtx);
/**
* @brief Indicates that the next items added are in a map.
*
* @param[in] pCtx The encoding context to open the map in.
*
* See QCBOREncode_OpenArray() for more information, particularly
* error handling.
*
* CBOR maps are an aggregate type where each item in the map consists
* of a label and a value. They are similar to JSON objects.
*
* The value can be any CBOR type including another map.
*
* The label can also be any CBOR type, but in practice they are
* typically, integers as this gives the most compact output. They
* might also be text strings which gives readability and translation
* to JSON.
*
* Every @c QCBOREncode_AddXxx() call has one version that ends with
* @c InMap for adding items to maps with string labels and one that
* ends with @c InMapN that is for adding with integer labels.
*
* RFC 8949 uses the term "key" instead of "label".
*
* If you wish to use map labels that are neither integer labels nor
* text strings, then just call the QCBOREncode_AddXxx() function
* explicitly to add the label. Then call it again to add the value.
*
* See the [RFC 8949] (https://tools.ietf.org/html/rfc8949) for a lot
* more information on creating maps.
*/
static void
QCBOREncode_OpenMap(QCBOREncodeContext *pCtx);
static void
QCBOREncode_OpenMapInMap(QCBOREncodeContext *pCtx, const char *szLabel);
static void
QCBOREncode_OpenMapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
/**
* @brief Close an open map.
*
* @param[in] pCtx The encoding context to close the map in.
*
* This closes a map opened by QCBOREncode_OpenMap(). It reduces
* nesting level by one.
*
* When an error occurs as a result of this call, the encoder records
* the error and enters the error state. The error will be returned
* when QCBOREncode_Finish() is called.
*
* If this has been called more times than QCBOREncode_OpenMap(), then
* @ref QCBOR_ERR_TOO_MANY_CLOSES will be returned when
* QCBOREncode_Finish() is called.
*
* If this is called and it is not a map that is currently open,
* @ref QCBOR_ERR_CLOSE_MISMATCH will be returned when
* QCBOREncode_Finish() is called.
*/
static void
QCBOREncode_CloseMap(QCBOREncodeContext *pCtx);
/**
* @brief Indicates that the next items added are in an indefinite length array.
*
* @param[in] pCtx The encoding context to open the array in.
*
* This is the same as QCBOREncode_OpenArray() except the array is
* indefinite length.
*
* This must be closed with QCBOREncode_CloseArrayIndefiniteLength().
*/
static void
QCBOREncode_OpenArrayIndefiniteLength(QCBOREncodeContext *pCtx);
static void
QCBOREncode_OpenArrayIndefiniteLengthInMap(QCBOREncodeContext *pCtx,
const char *szLabel);
static void
QCBOREncode_OpenArrayIndefiniteLengthInMapN(QCBOREncodeContext *pCtx,
int64_t nLabel);
/**
* @brief Close an open indefinite length array.
*
* @param[in] pCtx The encoding context to close the array in.
*
* This is the same as QCBOREncode_CloseArray(), but the open array
* that is being close must be of indefinite length.
*/
static void
QCBOREncode_CloseArrayIndefiniteLength(QCBOREncodeContext *pCtx);
/**
* @brief Indicates that the next items added are in an indefinite length map.
*
* @param[in] pCtx The encoding context to open the map in.
*
* This is the same as QCBOREncode_OpenMap() except the array is
* indefinite length.
*
* This must be closed with QCBOREncode_CloseMapIndefiniteLength().
*/
static void
QCBOREncode_OpenMapIndefiniteLength(QCBOREncodeContext *pCtx);
static void
QCBOREncode_OpenMapIndefiniteLengthInMap(QCBOREncodeContext *pCtx,
const char *szLabel);
static void
QCBOREncode_OpenMapIndefiniteLengthInMapN(QCBOREncodeContext *pCtx,
int64_t nLabel);
/**
* @brief Close an open indefinite length map.
*
* @param[in] pCtx The encoding context to close the map in.
*
* This is the same as QCBOREncode_CloseMap(), but the open map that
* is being close must be of indefinite length.
*/
static void
QCBOREncode_CloseMapIndefiniteLength(QCBOREncodeContext *pCtx);
/**
* @brief Close and sort an open map.
*
* @param[in] pCtx The encoding context to close the map in .
*
* This is the same as QCBOREncode_CloseMap() except it sorts the map
* per RFC 8949 Section 4.2.1. This sort is lexicographic of the CBOR-
* encoded map labels.
*
* This is more expensive than most things in the encoder. It uses
* bubble sort which runs in n-squared time where n is the number of
* map items. Sorting large maps on slow CPUs might be slow. This is
* also increases the object code size of the encoder by about 30%
* (500-1000 bytes).
*
* Bubble sort was selected so as to not need an extra buffer to track
* map item offsets. Bubble sort works well even though map items are
* not all the same size because it always swaps adjacent items.
*/
void QCBOREncode_CloseAndSortMap(QCBOREncodeContext *pCtx);
void QCBOREncode_CloseAndSortMapIndef(QCBOREncodeContext *pCtx);
/**
* @brief Indicate start of encoded CBOR to be wrapped in a bstr.
*
* @param[in] pCtx The encoding context to open the bstr-wrapped CBOR in.
*
* All added encoded items between this call and a call to
* QCBOREncode_CloseBstrWrap2() will be wrapped in a bstr. They will
* appear in the final output as a byte string. That byte string will
* contain encoded CBOR. This increases nesting level by one.
*
* The typical use case is for encoded CBOR that is to be
* cryptographically hashed, as part of a [RFC 8152, COSE]
* (https://tools.ietf.org/html/rfc8152) implementation. The wrapping
* byte string is taken as input by the hash function (which is why it
* is returned by QCBOREncode_CloseBstrWrap2()). It is also easy to
* recover on decoding with standard CBOR decoders.
*
* Using QCBOREncode_BstrWrap() and QCBOREncode_CloseBstrWrap2()
* avoids having to encode the items first in one buffer (e.g., the
* COSE payload) and then add that buffer as a bstr to another
* encoding (e.g. the COSE to-be-signed bytes, the @c Sig_structure)
* potentially halving the memory needed.
*
* CBOR by nature must be decoded item by item in order from the
* start. By wrapping some CBOR in a byte string, the decoding of
* that wrapped CBOR can be skipped. This is another use of wrapping,
* perhaps because the CBOR is large and deeply nested. Perhaps APIs
* for handling one defined CBOR message that is being embedded in
* another only take input as a byte string. Perhaps the desire is to
* be able to decode the out layer even in the wrapped has errors.
*/
static void
QCBOREncode_BstrWrap(QCBOREncodeContext *pCtx);
static void
QCBOREncode_BstrWrapInMap(QCBOREncodeContext *pCtx, const char *szLabel);
static void
QCBOREncode_BstrWrapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
/**
* @brief Close a wrapping bstr.
*
* @param[in] pCtx The encoding context to close of bstr wrapping in.
* @param[in] bIncludeCBORHead Include the encoded CBOR head of the bstr
* as well as the bytes in @c pWrappedCBOR.
* @param[out] pWrappedCBOR A @ref UsefulBufC containing wrapped bytes.
*
* The closes a wrapping bstr opened by QCBOREncode_BstrWrap(). It reduces
* nesting level by one.
*
* A pointer and length of the enclosed encoded CBOR is returned in @c
* *pWrappedCBOR if it is not @c NULL. The main purpose of this is so
* this data can be hashed (e.g., with SHA-256) as part of a [RFC
* 8152, COSE] (https://tools.ietf.org/html/rfc8152)
* implementation. **WARNING**, this pointer and length should be used
* right away before any other calls to @c QCBOREncode_CloseXxx() as
* they will move data around and the pointer and length will no
* longer be to the correct encoded CBOR.
*
* When an error occurs as a result of this call, the encoder records
* the error and enters the error state. The error will be returned
* when QCBOREncode_Finish() is called.
*
* If this has been called more times than QCBOREncode_BstrWrap(),
* then @ref QCBOR_ERR_TOO_MANY_CLOSES will be returned when
* QCBOREncode_Finish() is called.
*
* If this is called and it is not a wrapping bstr that is currently
* open, @ref QCBOR_ERR_CLOSE_MISMATCH will be returned when
* QCBOREncode_Finish() is called.
*
* QCBOREncode_CloseBstrWrap() is a deprecated version of this function
* that is equivalent to the call with @c bIncludeCBORHead @c true.
*/
void
QCBOREncode_CloseBstrWrap2(QCBOREncodeContext *pCtx, bool bIncludeCBORHead, UsefulBufC *pWrappedCBOR);
static void
QCBOREncode_CloseBstrWrap(QCBOREncodeContext *pCtx, UsefulBufC *pWrappedCBOR);
/**
* @brief Cancel byte string wrapping.
*
* @param[in] pCtx The encoding context.
*
* This cancels QCBOREncode_BstrWrap() making tghe encoding as if it
* were never called.
*
* WARNING: This does not work on QCBOREncode_BstrWrapInMap()
* or QCBOREncode_BstrWrapInMapN() and there is no error detection
* of an attempt at their use.
*
* This only works if nothing has been added into the wrapped byte
* string. If something has been added, this sets the error
* @ref QCBOR_ERR_CANNOT_CANCEL.
*/
void
QCBOREncode_CancelBstrWrap(QCBOREncodeContext *pCtx);
/**
* @brief Add some already-encoded CBOR bytes.
*
* @param[in] pCtx The encoding context to add the already-encode CBOR to.
* @param[in] Encoded The already-encoded CBOR to add to the context.
*
* The encoded CBOR being added must be fully conforming CBOR. It must
* be complete with no arrays or maps that are incomplete. While this
* encoder doesn't ever produce indefinite lengths, it is OK for the
* raw CBOR added here to have indefinite lengths.
*
* The raw CBOR added here is not checked in anyway. If it is not
* conforming or has open arrays or such, the final encoded CBOR
* will probably be wrong or not what was intended.
*
* If the encoded CBOR being added here contains multiple items, they
* must be enclosed in a map or array. At the top level the raw
* CBOR must be a single data item.
*/
static void
QCBOREncode_AddEncoded(QCBOREncodeContext *pCtx, UsefulBufC Encoded);
static void
QCBOREncode_AddEncodedToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Encoded);
static void
QCBOREncode_AddEncodedToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Encoded);
/**
* @brief Get the encoded result.
*
* @param[in] pCtx The context to finish encoding with.
* @param[out] pEncodedCBOR Structure in which the pointer and length of
* the encoded CBOR is returned.
*
* @retval QCBOR_SUCCESS Encoded CBOR is returned.
*
* @retval QCBOR_ERR_TOO_MANY_CLOSES Nesting error
*
* @retval QCBOR_ERR_CLOSE_MISMATCH Nesting error
*
* @retval QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN Nesting error
*
* @retval QCBOR_ERR_BUFFER_TOO_LARGE Encoded output buffer size
*
* @retval QCBOR_ERR_BUFFER_TOO_SMALL Encoded output buffer size
*
* @retval QCBOR_ERR_ARRAY_NESTING_TOO_DEEP Implementation limit
*
* @retval QCBOR_ERR_ARRAY_TOO_LONG Implementation limit
*
* On success, the pointer and length of the encoded CBOR are returned
* in @c *pEncodedCBOR. The pointer is the same pointer that was passed
* in to QCBOREncode_Init(). Note that it is not const when passed to
* QCBOREncode_Init(), but it is const when returned here. The length
* will be smaller than or equal to the length passed in when
* QCBOREncode_Init() as this is the length of the actual result, not
* the size of the buffer it was written to.
*
* If a @c NULL was passed for @c Storage.ptr when QCBOREncode_Init()
* was called, @c NULL will be returned here, but the length will be
* that of the CBOR that would have been encoded.
*
* Encoding errors primarily manifest here as most other encoding function
* do no return an error. They just set the error state in the encode
* context after which no encoding function does anything.
*
* Three types of errors manifest here. The first type are nesting
* errors where the number of @c QCBOREncode_OpenXxx() calls do not
* match the number @c QCBOREncode_CloseXxx() calls. The solution is to
* fix the calling code.
*
* The second type of error is because the buffer given is either too
* small or too large. The remedy is to give a correctly sized buffer.
*
* The third type are due to limits in this implementation.
* @ref QCBOR_ERR_ARRAY_NESTING_TOO_DEEP can be worked around by
* encoding the CBOR in two (or more) phases and adding the CBOR from
* the first phase to the second with @c QCBOREncode_AddEncoded().
*
* If an error is returned, the buffer may have partially encoded
* incorrect CBOR in it and it should not be used. Likewise, the length
* may be incorrect and should not be used.
*
* Note that the error could have occurred in one of the many
* @c QCBOREncode_AddXxx() calls long before QCBOREncode_Finish() was
* called. This error handling reduces the CBOR implementation size
* but makes debugging harder.
*
* This may be called multiple times. It will always return the
* same. It can also be interleaved with calls to
* QCBOREncode_FinishGetSize().
*
* QCBOREncode_GetErrorState() can be called to get the current
* error state in order to abort encoding early as an optimization, but
* calling it is is never required.
*/
QCBORError
QCBOREncode_Finish(QCBOREncodeContext *pCtx, UsefulBufC *pEncodedCBOR);
/**
* @brief Get the encoded CBOR and error status.
*
* @param[in] pCtx The context to finish encoding with.
* @param[out] uEncodedLen The length of the encoded or potentially
* encoded CBOR in bytes.
*
* @return The same errors as QCBOREncode_Finish().
*
* This functions the same as QCBOREncode_Finish(), but only returns the
* size of the encoded output.
*/
QCBORError
QCBOREncode_FinishGetSize(QCBOREncodeContext *pCtx, size_t *uEncodedLen);
/**
* @brief Indicate whether output buffer is NULL or not.
*
* @param[in] pCtx The encoding context.
*
* @return 1 if the output buffer is @c NULL.
*
* Sometimes a @c NULL input buffer is given to QCBOREncode_Init() so
* that the size of the generated CBOR can be calculated without
* allocating a buffer for it. This returns 1 when the output buffer
* is @c NULL and 0 when it is not.
*/
static int
QCBOREncode_IsBufferNULL(QCBOREncodeContext *pCtx);
/**
* @brief Get the encoding error state.
*
* @param[in] pCtx The encoding context.
*
* @return One of @ref QCBORError. See return values from
* QCBOREncode_Finish()
*
* Normally encoding errors need only be handled at the end of
* encoding when QCBOREncode_Finish() is called. This can be called to
* get the error result before finish should there be a need to halt
* encoding before QCBOREncode_Finish() is called.
*/
static QCBORError
QCBOREncode_GetErrorState(QCBOREncodeContext *pCtx);
/**
* Encode the "head" of a CBOR data item.
*
* @param Buffer Buffer to output the encoded head to; must be
* @ref QCBOR_HEAD_BUFFER_SIZE bytes in size.
* @param uMajorType One of CBOR_MAJOR_TYPE_XX.
* @param uMinLen The minimum number of bytes to encode uNumber. Almost
* always this is 0 to use preferred
* serialization. If this is 4, then even the
* values 0xffff and smaller will be encoded in 4
* bytes. This is used primarily when encoding a
* float or double put into uNumber as the leading
* zero bytes for them must be encoded.
* @param uNumber The numeric argument part of the CBOR head.
* @return Pointer and length of the encoded head or
* @ref NULLUsefulBufC if the output buffer is too small.
*
* Callers do not to need to call this for normal CBOR encoding. Note
* that it doesn't even take a @ref QCBOREncodeContext argument.
*
* This encodes the major type and argument part of a data item. The
* argument is an integer that is usually either the value or the length
* of the data item.
*
* This is exposed in the public interface to allow hashing of some CBOR
* data types, bstr in particular, a chunk at a time so the full CBOR
* doesn't have to be encoded in a contiguous buffer.
*
* For example, if you have a 100,000 byte binary blob in a buffer that
* needs to be a bstr encoded and then hashed. You could allocate a
* 100,010 byte buffer and encode it normally. Alternatively, you can
* encode the head in a 10 byte buffer with this function, hash that and
* then hash the 100,000 bytes using the same hash context.
*/
UsefulBufC
QCBOREncode_EncodeHead(UsefulBuf Buffer,
uint8_t uMajorType,
uint8_t uMinLen,
uint64_t uNumber);
/* =========================================================================
BEGINNING OF PRIVATE IMPLEMENTATION
========================================================================= */
/* Semi-private funcion used by public inline functions. See qcbor_encode.c */
void
QCBOREncode_Private_AddBuffer(QCBOREncodeContext *pCtx,
uint8_t uMajorType,
UsefulBufC Bytes);
/* Semi-private funcion used by public inline functions. See qcbor_encode.c */
void
QCBOREncode_Private_OpenMapOrArray(QCBOREncodeContext *pCtx,
uint8_t uMajorType);
/* Semi-private funcion used by public inline functions. See qcbor_encode.c */
void
QCBOREncode_Private_OpenMapOrArrayIndefiniteLength(QCBOREncodeContext *pCtx,
uint8_t uMajorType);
/* Semi-private funcion used by public inline functions. See qcbor_encode.c */
void
QCBOREncode_Private_CloseMapOrArray(QCBOREncodeContext *pCtx,
uint8_t uMajorType);
/* Semi-private funcion used by public inline functions. See qcbor_encode.c */
void
QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(QCBOREncodeContext *pCtx,
uint8_t uMajorType);
/* Semi-private funcion used by public inline functions. See qcbor_encode.c */
void
QCBOREncode_Private_AddType7(QCBOREncodeContext *pCtx,
uint8_t uMinLen,
uint64_t uNum);
/* Semi-private funcion used by public inline functions. See qcbor_encode.c */
void
QCBOREncode_Private_AddExpMantissa(QCBOREncodeContext *pCtx,
uint64_t uTag,
UsefulBufC BigNumMantissa,
bool bBigNumIsNegative,
int64_t nMantissa,
int64_t nExponent);
static inline void
QCBOREncode_SerializationCDE(QCBOREncodeContext *pMe)
{
/* The use of a function pointer here is a little trick to reduce
* code linked for the common use cases that don't sort. If this
* function is never linked, then QCBOREncode_CloseAndSortMap() is
* never linked and the amount of code pulled in is small. If the
* mode switch between sorting and not sorting were an if
* statement, then QCBOREncode_CloseAndSortMap() would always be
* linked even when not used. */
pMe->pfnCloseMap = QCBOREncode_CloseAndSortMap;
pMe->uMode = QCBOR_ENCODE_MODE_CDE;
}
static inline void
QCBOREncode_SerializationdCBOR(QCBOREncodeContext *pMe)
{
pMe->pfnCloseMap = QCBOREncode_CloseAndSortMap;
pMe->uMode = QCBOR_ENCODE_MODE_DCBOR;
}
static inline void
QCBOREncode_SerializationPreferred(QCBOREncodeContext *pMe)
{
pMe->uMode = QCBOR_ENCODE_MODE_PREFERRED;
}
static inline void
QCBOREncode_Allow(QCBOREncodeContext *pMe, const uint8_t uAllow)
{
#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
pMe->uAllow = uAllow;
#else
(void)uAllow;
(void)pMe;
#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
}
static inline void
QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const int64_t uNum)
{
/* Use _AddBuffer() because _AddSZString() is defined below, not above */
QCBOREncode_Private_AddBuffer(pMe,
CBOR_MAJOR_TYPE_TEXT_STRING,
UsefulBuf_FromSZ(szLabel));
QCBOREncode_AddInt64(pMe, uNum);
}
static inline void
QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const int64_t uNum)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddInt64(pMe, uNum);
}
static inline void
QCBOREncode_AddUInt64ToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const uint64_t uNum)
{
/* Use _AddBuffer() because _AddSZString() is defined below, not above */
QCBOREncode_Private_AddBuffer(pMe,
CBOR_MAJOR_TYPE_TEXT_STRING,
UsefulBuf_FromSZ(szLabel));
QCBOREncode_AddUInt64(pMe, uNum);
}
static inline void
QCBOREncode_AddUInt64ToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint64_t uNum)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddUInt64(pMe, uNum);
}
static inline void
QCBOREncode_AddNegativeUInt64ToMap(QCBOREncodeContext *pMe, const char *szLabel, uint64_t uNum)
{
/* Use _AddBuffer() because _AddSZString() is defined below, not above */
QCBOREncode_Private_AddBuffer(pMe,
CBOR_MAJOR_TYPE_TEXT_STRING,
UsefulBuf_FromSZ(szLabel));
QCBOREncode_AddNegativeUInt64(pMe, uNum);
}
static inline void
QCBOREncode_AddNegativeUInt64ToMapN(QCBOREncodeContext *pMe, int64_t nLabel, uint64_t uNum)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddNegativeUInt64(pMe, uNum);
}
static inline void
QCBOREncode_AddText(QCBOREncodeContext *pMe, const UsefulBufC Text)
{
QCBOREncode_Private_AddBuffer(pMe, CBOR_MAJOR_TYPE_TEXT_STRING, Text);
}
static inline void
QCBOREncode_AddTextToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const UsefulBufC Text)
{
QCBOREncode_AddText(pMe, UsefulBuf_FromSZ(szLabel));
QCBOREncode_AddText(pMe, Text);
}
static inline void
QCBOREncode_AddTextToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const UsefulBufC Text)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddText(pMe, Text);
}
inline static void
QCBOREncode_AddSZString(QCBOREncodeContext *pMe, const char *szString)
{
QCBOREncode_AddText(pMe, UsefulBuf_FromSZ(szString));
}
static inline void
QCBOREncode_AddSZStringToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const char *szString)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddSZString(pMe, szString);
}
static inline void
QCBOREncode_AddSZStringToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const char *szString)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddSZString(pMe, szString);
}
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
static inline void
QCBOREncode_AddDoubleToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const double dNum)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddDouble(pMe, dNum);
}
static inline void
QCBOREncode_AddDoubleToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const double dNum)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddDouble(pMe, dNum);
}
static inline void
QCBOREncode_AddFloatToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const float dNum)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddFloat(pMe, dNum);
}
static inline void
QCBOREncode_AddFloatToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const float fNum)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddFloat(pMe, fNum);
}
static inline void
QCBOREncode_AddDoubleNoPreferredToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const double dNum)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddDoubleNoPreferred(pMe, dNum);
}
static inline void
QCBOREncode_AddDoubleNoPreferredToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const double dNum)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddDoubleNoPreferred(pMe, dNum);
}
static inline void
QCBOREncode_AddFloatNoPreferredToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const float dNum)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddFloatNoPreferred(pMe, dNum);
}
static inline void
QCBOREncode_AddFloatNoPreferredToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const float dNum)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddFloatNoPreferred(pMe, dNum);
}
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
static inline void
QCBOREncode_AddTDateEpoch(QCBOREncodeContext *pMe,
const uint8_t uTag,
const int64_t nDate)
{
if(uTag == QCBOR_ENCODE_AS_TAG) {
QCBOREncode_AddTag(pMe, CBOR_TAG_DATE_EPOCH);
}
QCBOREncode_AddInt64(pMe, nDate);
}
static inline void
QCBOREncode_AddTDateEpochToMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
const uint8_t uTag,
const int64_t nDate)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddTDateEpoch(pMe, uTag, nDate);
}
static inline void
QCBOREncode_AddTDateEpochToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint8_t uTag,
const int64_t nDate)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddTDateEpoch(pMe, uTag, nDate);
}
static inline void
QCBOREncode_AddDateEpoch(QCBOREncodeContext *pMe,
const int64_t nDate)
{
QCBOREncode_AddTDateEpoch(pMe, QCBOR_ENCODE_AS_TAG, nDate);
}
static inline void
QCBOREncode_AddDateEpochToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const int64_t nDate)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddDateEpoch(pMe, nDate);
}
static inline void
QCBOREncode_AddDateEpochToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const int64_t nDate)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddDateEpoch(pMe, nDate);
}
static inline void
QCBOREncode_AddTDaysEpoch(QCBOREncodeContext *pMe,
const uint8_t uTag,
const int64_t nDays)
{
if(uTag == QCBOR_ENCODE_AS_TAG) {
QCBOREncode_AddTag(pMe, CBOR_TAG_DAYS_EPOCH);
}
QCBOREncode_AddInt64(pMe, nDays);
}
static inline void
QCBOREncode_AddTDaysEpochToMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
const uint8_t uTag,
const int64_t nDays)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddTDaysEpoch(pMe, uTag, nDays);
}
static inline void
QCBOREncode_AddTDaysEpochToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint8_t uTag,
const int64_t nDays)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddTDaysEpoch(pMe, uTag, nDays);
}
static inline void
QCBOREncode_AddBytes(QCBOREncodeContext *pMe,
const UsefulBufC Bytes)
{
QCBOREncode_Private_AddBuffer(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, Bytes);
}
static inline void
QCBOREncode_AddBytesToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const UsefulBufC Bytes)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddBytes(pMe, Bytes);
}
static inline void
QCBOREncode_AddBytesToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const UsefulBufC Bytes)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddBytes(pMe, Bytes);
}
static inline void
QCBOREncode_OpenBytesInMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
UsefulBuf *pPlace)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_OpenBytes(pMe, pPlace);
}
static inline void
QCBOREncode_OpenBytesInMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
UsefulBuf *pPlace)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_OpenBytes(pMe, pPlace);
}
static inline void
QCBOREncode_AddTBinaryUUID(QCBOREncodeContext *pMe,
const uint8_t uTagRequirement,
const UsefulBufC Bytes)
{
if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
QCBOREncode_AddTag(pMe, CBOR_TAG_BIN_UUID);
}
QCBOREncode_AddBytes(pMe, Bytes);
}
static inline void
QCBOREncode_AddTBinaryUUIDToMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
const uint8_t uTagRequirement,
const UsefulBufC Bytes)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddTBinaryUUID(pMe, uTagRequirement, Bytes);
}
static inline void
QCBOREncode_AddTBinaryUUIDToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint8_t uTagRequirement,
const UsefulBufC Bytes)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddTBinaryUUID(pMe, uTagRequirement, Bytes);
}
static inline void
QCBOREncode_AddBinaryUUID(QCBOREncodeContext *pMe, const UsefulBufC Bytes)
{
QCBOREncode_AddTBinaryUUID(pMe, QCBOR_ENCODE_AS_TAG, Bytes);
}
static inline void
QCBOREncode_AddBinaryUUIDToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const UsefulBufC Bytes)
{
QCBOREncode_AddTBinaryUUIDToMapSZ(pMe, szLabel, QCBOR_ENCODE_AS_TAG, Bytes);
}
static inline void
QCBOREncode_AddBinaryUUIDToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const UsefulBufC Bytes)
{
QCBOREncode_AddTBinaryUUIDToMapN(pMe,
nLabel,
QCBOR_ENCODE_AS_TAG,
Bytes);
}
static inline void
QCBOREncode_AddTPositiveBignum(QCBOREncodeContext *pMe,
const uint8_t uTagRequirement,
const UsefulBufC Bytes)
{
if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
QCBOREncode_AddTag(pMe, CBOR_TAG_POS_BIGNUM);
}
QCBOREncode_AddBytes(pMe, Bytes);
}
static inline void
QCBOREncode_AddTPositiveBignumToMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
const uint8_t uTagRequirement,
const UsefulBufC Bytes)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddTPositiveBignum(pMe, uTagRequirement, Bytes);
}
static inline void
QCBOREncode_AddTPositiveBignumToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint8_t uTagRequirement,
const UsefulBufC Bytes)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddTPositiveBignum(pMe, uTagRequirement, Bytes);
}
static inline void
QCBOREncode_AddPositiveBignum(QCBOREncodeContext *pMe, const UsefulBufC Bytes)
{
QCBOREncode_AddTPositiveBignum(pMe, QCBOR_ENCODE_AS_TAG, Bytes);
}
static inline void
QCBOREncode_AddPositiveBignumToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const UsefulBufC Bytes)
{
QCBOREncode_AddTPositiveBignumToMapSZ(pMe,
szLabel,
QCBOR_ENCODE_AS_TAG,
Bytes);
}
static inline void
QCBOREncode_AddPositiveBignumToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const UsefulBufC Bytes)
{
QCBOREncode_AddTPositiveBignumToMapN(pMe,
nLabel,
QCBOR_ENCODE_AS_TAG,
Bytes);
}
static inline void
QCBOREncode_AddTNegativeBignum(QCBOREncodeContext *pMe,
const uint8_t uTagRequirement,
const UsefulBufC Bytes)
{
if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
QCBOREncode_AddTag(pMe, CBOR_TAG_NEG_BIGNUM);
}
QCBOREncode_AddBytes(pMe, Bytes);
}
static inline void
QCBOREncode_AddTNegativeBignumToMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
const uint8_t uTagRequirement,
const UsefulBufC Bytes)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddTNegativeBignum(pMe, uTagRequirement, Bytes);
}
static inline void
QCBOREncode_AddTNegativeBignumToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint8_t uTagRequirement,
const UsefulBufC Bytes)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddTNegativeBignum(pMe, uTagRequirement, Bytes);
}
static inline void
QCBOREncode_AddNegativeBignum(QCBOREncodeContext *pMe, const UsefulBufC Bytes)
{
QCBOREncode_AddTNegativeBignum(pMe, QCBOR_ENCODE_AS_TAG, Bytes);
}
static inline void
QCBOREncode_AddNegativeBignumToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const UsefulBufC Bytes)
{
QCBOREncode_AddTNegativeBignumToMapSZ(pMe,
szLabel,
QCBOR_ENCODE_AS_TAG,
Bytes);
}
static inline void
QCBOREncode_AddNegativeBignumToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const UsefulBufC Bytes)
{
QCBOREncode_AddTNegativeBignumToMapN(pMe,
nLabel,
QCBOR_ENCODE_AS_TAG,
Bytes);
}
#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
static inline void
QCBOREncode_AddTDecimalFraction(QCBOREncodeContext *pMe,
const uint8_t uTagRequirement,
const int64_t nMantissa,
const int64_t nBase10Exponent)
{
uint64_t uTag;
if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
uTag = CBOR_TAG_DECIMAL_FRACTION;
} else {
uTag = CBOR_TAG_INVALID64;
}
QCBOREncode_Private_AddExpMantissa(pMe,
uTag,
NULLUsefulBufC,
false,
nMantissa,
nBase10Exponent);
}
static inline void
QCBOREncode_AddTDecimalFractionToMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
const uint8_t uTagRequirement,
const int64_t nMantissa,
const int64_t nBase10Exponent)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddTDecimalFraction(pMe,
uTagRequirement,
nMantissa,
nBase10Exponent);
}
static inline void
QCBOREncode_AddTDecimalFractionToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint8_t uTagRequirement,
const int64_t nMantissa,
const int64_t nBase10Exponent)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddTDecimalFraction(pMe,
uTagRequirement,
nMantissa,
nBase10Exponent);
}
static inline void
QCBOREncode_AddDecimalFraction(QCBOREncodeContext *pMe,
const int64_t nMantissa,
const int64_t nBase10Exponent)
{
QCBOREncode_AddTDecimalFraction(pMe,
QCBOR_ENCODE_AS_TAG,
nMantissa,
nBase10Exponent);
}
static inline void
QCBOREncode_AddDecimalFractionToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const int64_t nMantissa,
const int64_t nBase10Exponent)
{
QCBOREncode_AddTDecimalFractionToMapSZ(pMe,
szLabel,
QCBOR_ENCODE_AS_TAG,
nMantissa,
nBase10Exponent);
}
static inline void
QCBOREncode_AddDecimalFractionToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const int64_t nMantissa,
const int64_t nBase10Exponent)
{
QCBOREncode_AddTDecimalFractionToMapN(pMe,
nLabel,
QCBOR_ENCODE_AS_TAG,
nMantissa,
nBase10Exponent);
}
static inline void
QCBOREncode_AddTDecimalFractionBigNum(QCBOREncodeContext *pMe,
const uint8_t uTagRequirement,
const UsefulBufC Mantissa,
const bool bIsNegative,
const int64_t nBase10Exponent)
{
uint64_t uTag;
if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
uTag = CBOR_TAG_DECIMAL_FRACTION;
} else {
uTag = CBOR_TAG_INVALID64;
}
QCBOREncode_Private_AddExpMantissa(pMe,
uTag,
Mantissa,
bIsNegative,
0,
nBase10Exponent);
}
static inline void
QCBOREncode_AddTDecimalFractionBigNumToMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
const uint8_t uTagRequirement,
const UsefulBufC Mantissa,
const bool bIsNegative,
const int64_t nBase10Exponent)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddTDecimalFractionBigNum(pMe,
uTagRequirement,
Mantissa,
bIsNegative,
nBase10Exponent);
}
static inline void
QCBOREncode_AddTDecimalFractionBigNumToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint8_t uTagRequirement,
const UsefulBufC Mantissa,
const bool bIsNegative,
const int64_t nBase10Exponent)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddTDecimalFractionBigNum(pMe,
uTagRequirement,
Mantissa,
bIsNegative,
nBase10Exponent);
}
static inline void
QCBOREncode_AddDecimalFractionBigNum(QCBOREncodeContext *pMe,
const UsefulBufC Mantissa,
const bool bIsNegative,
const int64_t nBase10Exponent)
{
QCBOREncode_AddTDecimalFractionBigNum(pMe,
QCBOR_ENCODE_AS_TAG,
Mantissa,
bIsNegative,
nBase10Exponent);
}
static inline void
QCBOREncode_AddDecimalFractionBigNumToMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
const UsefulBufC Mantissa,
const bool bIsNegative,
const int64_t nBase10Exponent)
{
QCBOREncode_AddTDecimalFractionBigNumToMapSZ(pMe,
szLabel,
QCBOR_ENCODE_AS_TAG,
Mantissa,
bIsNegative,
nBase10Exponent);
}
static inline void
QCBOREncode_AddDecimalFractionBigNumToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const UsefulBufC Mantissa,
const bool bIsNegative,
const int64_t nBase2Exponent)
{
QCBOREncode_AddTDecimalFractionBigNumToMapN(pMe,
nLabel,
QCBOR_ENCODE_AS_TAG,
Mantissa,
bIsNegative,
nBase2Exponent);
}
static inline void
QCBOREncode_AddTBigFloat(QCBOREncodeContext *pMe,
const uint8_t uTagRequirement,
const int64_t nMantissa,
const int64_t nBase2Exponent)
{
uint64_t uTag;
if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
uTag = CBOR_TAG_BIGFLOAT;
} else {
uTag = CBOR_TAG_INVALID64;
}
QCBOREncode_Private_AddExpMantissa(pMe,
uTag,
NULLUsefulBufC,
false,
nMantissa,
nBase2Exponent);
}
static inline void
QCBOREncode_AddTBigFloatToMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
const uint8_t uTagRequirement,
const int64_t nMantissa,
const int64_t nBase2Exponent)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddTBigFloat(pMe, uTagRequirement, nMantissa, nBase2Exponent);
}
static inline void
QCBOREncode_AddTBigFloatToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint8_t uTagRequirement,
const int64_t nMantissa,
const int64_t nBase2Exponent)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddTBigFloat(pMe, uTagRequirement, nMantissa, nBase2Exponent);
}
static inline void
QCBOREncode_AddBigFloat(QCBOREncodeContext *pMe,
const int64_t nMantissa,
const int64_t nBase2Exponent)
{
QCBOREncode_AddTBigFloat(pMe,
QCBOR_ENCODE_AS_TAG,
nMantissa,
nBase2Exponent);
}
static inline void
QCBOREncode_AddBigFloatToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const int64_t nMantissa,
const int64_t nBase2Exponent)
{
QCBOREncode_AddTBigFloatToMapSZ(pMe,
szLabel,
QCBOR_ENCODE_AS_TAG,
nMantissa,
nBase2Exponent);
}
static inline void
QCBOREncode_AddBigFloatToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const int64_t nMantissa,
const int64_t nBase2Exponent)
{
QCBOREncode_AddTBigFloatToMapN(pMe,
nLabel,
QCBOR_ENCODE_AS_TAG,
nMantissa,
nBase2Exponent);
}
static inline void
QCBOREncode_AddTBigFloatBigNum(QCBOREncodeContext *pMe,
const uint8_t uTagRequirement,
const UsefulBufC Mantissa,
const bool bIsNegative,
const int64_t nBase2Exponent)
{
uint64_t uTag;
if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
uTag = CBOR_TAG_BIGFLOAT;
} else {
uTag = CBOR_TAG_INVALID64;
}
QCBOREncode_Private_AddExpMantissa(pMe,
uTag,
Mantissa,
bIsNegative,
0,
nBase2Exponent);
}
static inline void
QCBOREncode_AddTBigFloatBigNumToMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
const uint8_t uTagRequirement,
const UsefulBufC Mantissa,
const bool bIsNegative,
const int64_t nBase2Exponent)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddTBigFloatBigNum(pMe,
uTagRequirement,
Mantissa,
bIsNegative,
nBase2Exponent);
}
static inline void
QCBOREncode_AddTBigFloatBigNumToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint8_t uTagRequirement,
const UsefulBufC Mantissa,
const bool bIsNegative,
const int64_t nBase2Exponent)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddTBigFloatBigNum(pMe,
uTagRequirement,
Mantissa,
bIsNegative,
nBase2Exponent);
}
static inline void
QCBOREncode_AddBigFloatBigNum(QCBOREncodeContext *pMe,
const UsefulBufC Mantissa,
const bool bIsNegative,
const int64_t nBase2Exponent)
{
QCBOREncode_AddTBigFloatBigNum(pMe,
QCBOR_ENCODE_AS_TAG,
Mantissa, bIsNegative,
nBase2Exponent);
}
static inline void
QCBOREncode_AddBigFloatBigNumToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const UsefulBufC Mantissa,
const bool bIsNegative,
const int64_t nBase2Exponent)
{
QCBOREncode_AddTBigFloatBigNumToMapSZ(pMe,
szLabel,
QCBOR_ENCODE_AS_TAG,
Mantissa,
bIsNegative,
nBase2Exponent);
}
static inline void
QCBOREncode_AddBigFloatBigNumToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const UsefulBufC Mantissa,
const bool bIsNegative,
const int64_t nBase2Exponent)
{
QCBOREncode_AddTBigFloatBigNumToMapN(pMe,
nLabel,
QCBOR_ENCODE_AS_TAG,
Mantissa,
bIsNegative,
nBase2Exponent);
}
#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
static inline void
QCBOREncode_AddTURI(QCBOREncodeContext *pMe,
const uint8_t uTagRequirement,
const UsefulBufC URI)
{
if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
QCBOREncode_AddTag(pMe, CBOR_TAG_URI);
}
QCBOREncode_AddText(pMe, URI);
}
static inline void
QCBOREncode_AddTURIToMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
const uint8_t uTagRequirement,
const UsefulBufC URI)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddTURI(pMe, uTagRequirement, URI);
}
static inline void
QCBOREncode_AddTURIToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint8_t uTagRequirement,
const UsefulBufC URI)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddTURI(pMe, uTagRequirement, URI);
}
static inline void
QCBOREncode_AddURI(QCBOREncodeContext *pMe, const UsefulBufC URI)
{
QCBOREncode_AddTURI(pMe, QCBOR_ENCODE_AS_TAG, URI);
}
static inline void
QCBOREncode_AddURIToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const UsefulBufC URI)
{
QCBOREncode_AddTURIToMapSZ(pMe, szLabel, QCBOR_ENCODE_AS_TAG, URI);
}
static inline void
QCBOREncode_AddURIToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const UsefulBufC URI)
{
QCBOREncode_AddTURIToMapN(pMe, nLabel, QCBOR_ENCODE_AS_TAG, URI);
}
static inline void
QCBOREncode_AddTB64Text(QCBOREncodeContext *pMe,
const uint8_t uTagRequirement,
const UsefulBufC B64Text)
{
if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
QCBOREncode_AddTag(pMe, CBOR_TAG_B64);
}
QCBOREncode_AddText(pMe, B64Text);
}
static inline void
QCBOREncode_AddTB64TextToMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
const uint8_t uTagRequirement,
const UsefulBufC B64Text)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddTB64Text(pMe, uTagRequirement, B64Text);
}
static inline void
QCBOREncode_AddTB64TextToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint8_t uTagRequirement,
const UsefulBufC B64Text)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddTB64Text(pMe, uTagRequirement, B64Text);
}
static inline void
QCBOREncode_AddB64Text(QCBOREncodeContext *pMe, const UsefulBufC B64Text)
{
QCBOREncode_AddTB64Text(pMe, QCBOR_ENCODE_AS_TAG, B64Text);
}
static inline void
QCBOREncode_AddB64TextToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const UsefulBufC B64Text)
{
QCBOREncode_AddTB64TextToMapSZ(pMe, szLabel, QCBOR_ENCODE_AS_TAG, B64Text);
}
static inline void
QCBOREncode_AddB64TextToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const UsefulBufC B64Text)
{
QCBOREncode_AddTB64TextToMapN(pMe, nLabel, QCBOR_ENCODE_AS_TAG, B64Text);
}
static inline void
QCBOREncode_AddTB64URLText(QCBOREncodeContext *pMe,
const uint8_t uTagRequirement,
const UsefulBufC B64Text)
{
if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
QCBOREncode_AddTag(pMe, CBOR_TAG_B64URL);
}
QCBOREncode_AddText(pMe, B64Text);
}
static inline void
QCBOREncode_AddTB64URLTextToMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
const uint8_t uTagRequirement,
const UsefulBufC B64Text)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddTB64URLText(pMe, uTagRequirement, B64Text);
}
static inline void
QCBOREncode_AddTB64URLTextToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint8_t uTagRequirement,
const UsefulBufC B64Text)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddTB64URLText(pMe, uTagRequirement, B64Text);
}
static inline void
QCBOREncode_AddB64URLText(QCBOREncodeContext *pMe, const UsefulBufC B64Text)
{
QCBOREncode_AddTB64URLText(pMe, QCBOR_ENCODE_AS_TAG, B64Text);
}
static inline void
QCBOREncode_AddB64URLTextToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const UsefulBufC B64Text)
{
QCBOREncode_AddTB64URLTextToMapSZ(pMe,
szLabel,
QCBOR_ENCODE_AS_TAG,
B64Text);
}
static inline void
QCBOREncode_AddB64URLTextToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const UsefulBufC B64Text)
{
QCBOREncode_AddTB64URLTextToMapN(pMe, nLabel, QCBOR_ENCODE_AS_TAG, B64Text);
}
static inline void
QCBOREncode_AddTRegex(QCBOREncodeContext *pMe,
const uint8_t uTagRequirement,
const UsefulBufC Bytes)
{
if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
QCBOREncode_AddTag(pMe, CBOR_TAG_REGEX);
}
QCBOREncode_AddText(pMe, Bytes);
}
static inline void
QCBOREncode_AddTRegexToMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
const uint8_t uTagRequirement,
const UsefulBufC Bytes)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddTRegex(pMe, uTagRequirement, Bytes);
}
static inline void
QCBOREncode_AddTRegexToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint8_t uTagRequirement,
const UsefulBufC Bytes)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddTRegex(pMe, uTagRequirement, Bytes);
}
static inline void
QCBOREncode_AddRegex(QCBOREncodeContext *pMe, const UsefulBufC Bytes)
{
QCBOREncode_AddTRegex(pMe, QCBOR_ENCODE_AS_TAG, Bytes);
}
static inline void
QCBOREncode_AddRegexToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const UsefulBufC Bytes)
{
QCBOREncode_AddTRegexToMapSZ(pMe, szLabel, QCBOR_ENCODE_AS_TAG, Bytes);
}
static inline void
QCBOREncode_AddRegexToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const UsefulBufC Bytes)
{
QCBOREncode_AddTRegexToMapN(pMe, nLabel, QCBOR_ENCODE_AS_TAG, Bytes);
}
static inline void
QCBOREncode_AddTMIMEData(QCBOREncodeContext *pMe,
const uint8_t uTagRequirement,
const UsefulBufC MIMEData)
{
if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
QCBOREncode_AddTag(pMe, CBOR_TAG_BINARY_MIME);
}
QCBOREncode_AddBytes(pMe, MIMEData);
}
static inline void
QCBOREncode_AddTMIMEDataToMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
const uint8_t uTagRequirement,
const UsefulBufC MIMEData)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddTMIMEData(pMe, uTagRequirement, MIMEData);
}
static inline void
QCBOREncode_AddTMIMEDataToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint8_t uTagRequirement,
const UsefulBufC MIMEData)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddTMIMEData(pMe, uTagRequirement, MIMEData);
}
static inline void
QCBOREncode_AddMIMEData(QCBOREncodeContext *pMe, UsefulBufC MIMEData)
{
QCBOREncode_AddTMIMEData(pMe, QCBOR_ENCODE_AS_TAG, MIMEData);
}
static inline void
QCBOREncode_AddMIMEDataToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const UsefulBufC MIMEData)
{
QCBOREncode_AddTMIMEDataToMapSZ(pMe, szLabel, QCBOR_ENCODE_AS_TAG, MIMEData);
}
static inline void
QCBOREncode_AddMIMEDataToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const UsefulBufC MIMEData)
{
QCBOREncode_AddTMIMEDataToMapN(pMe, nLabel, QCBOR_ENCODE_AS_TAG, MIMEData);
}
static inline void
QCBOREncode_AddTDateString(QCBOREncodeContext *pMe,
const uint8_t uTagRequirement,
const char *szDate)
{
if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
QCBOREncode_AddTag(pMe, CBOR_TAG_DATE_STRING);
}
QCBOREncode_AddSZString(pMe, szDate);
}
static inline void
QCBOREncode_AddTDateStringToMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
const uint8_t uTagRequirement,
const char *szDate)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddTDateString(pMe, uTagRequirement, szDate);
}
static inline void
QCBOREncode_AddTDateStringToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint8_t uTagRequirement,
const char *szDate)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddTDateString(pMe, uTagRequirement, szDate);
}
static inline void
QCBOREncode_AddDateString(QCBOREncodeContext *pMe, const char *szDate)
{
QCBOREncode_AddTDateString(pMe, QCBOR_ENCODE_AS_TAG, szDate);
}
static inline void
QCBOREncode_AddDateStringToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const char *szDate)
{
QCBOREncode_AddTDateStringToMapSZ(pMe, szLabel, QCBOR_ENCODE_AS_TAG, szDate);
}
static inline void
QCBOREncode_AddDateStringToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const char *szDate)
{
QCBOREncode_AddTDateStringToMapN(pMe, nLabel, QCBOR_ENCODE_AS_TAG, szDate);
}
static inline void
QCBOREncode_AddTDaysString(QCBOREncodeContext *pMe,
const uint8_t uTagRequirement,
const char *szDate)
{
if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
QCBOREncode_AddTag(pMe, CBOR_TAG_DAYS_STRING);
}
QCBOREncode_AddSZString(pMe, szDate);
}
static inline void
QCBOREncode_AddTDaysStringToMapSZ(QCBOREncodeContext *pMe,
const char *szLabel,
const uint8_t uTagRequirement,
const char *szDate)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddTDaysString(pMe, uTagRequirement, szDate);
}
static inline void
QCBOREncode_AddTDaysStringToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint8_t uTagRequirement,
const char *szDate)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddTDaysString(pMe, uTagRequirement, szDate);
}
static inline void
QCBOREncode_Private_AddSimple(QCBOREncodeContext *pMe, const uint64_t uNum)
{
#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
if(pMe->uMode >= QCBOR_ENCODE_MODE_DCBOR) {
if(uNum < CBOR_SIMPLEV_FALSE ||
uNum > CBOR_SIMPLEV_NULL) {
pMe->uError = QCBOR_ERR_NOT_PREFERRED;
return;
}
}
#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
QCBOREncode_Private_AddType7(pMe, 0, uNum);
}
static inline void
QCBOREncode_Private_AddSimpleToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const uint8_t uSimple)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_Private_AddSimple(pMe, uSimple);
}
static inline void
QCBOREncode_Private_AddSimpleToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const uint8_t uSimple)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_Private_AddSimple(pMe, uSimple);
}
static inline void
QCBOREncode_AddBool(QCBOREncodeContext *pMe, const bool b)
{
uint8_t uSimple = CBOR_SIMPLEV_FALSE;
if(b) {
uSimple = CBOR_SIMPLEV_TRUE;
}
QCBOREncode_Private_AddSimple(pMe, uSimple);
}
static inline void
QCBOREncode_AddBoolToMap(QCBOREncodeContext *pMe, const char *szLabel, const bool b)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddBool(pMe, b);
}
static inline void
QCBOREncode_AddBoolToMapN(QCBOREncodeContext *pMe, const int64_t nLabel, const bool b)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddBool(pMe, b);
}
static inline void
QCBOREncode_AddNULL(QCBOREncodeContext *pMe)
{
QCBOREncode_Private_AddSimple(pMe, CBOR_SIMPLEV_NULL);
}
static inline void
QCBOREncode_AddNULLToMap(QCBOREncodeContext *pMe, const char *szLabel)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddNULL(pMe);
}
static inline void
QCBOREncode_AddNULLToMapN(QCBOREncodeContext *pMe, const int64_t nLabel)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddNULL(pMe);
}
static inline void
QCBOREncode_AddUndef(QCBOREncodeContext *pMe)
{
QCBOREncode_Private_AddSimple(pMe, CBOR_SIMPLEV_UNDEF);
}
static inline void
QCBOREncode_AddUndefToMap(QCBOREncodeContext *pMe, const char *szLabel)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddUndef(pMe);
}
static inline void
QCBOREncode_AddUndefToMapN(QCBOREncodeContext *pMe, const int64_t nLabel)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddUndef(pMe);
}
static inline void
QCBOREncode_OpenArray(QCBOREncodeContext *pMe)
{
QCBOREncode_Private_OpenMapOrArray(pMe, CBOR_MAJOR_TYPE_ARRAY);
}
static inline void
QCBOREncode_OpenArrayInMap(QCBOREncodeContext *pMe, const char *szLabel)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_OpenArray(pMe);
}
static inline void
QCBOREncode_OpenArrayInMapN(QCBOREncodeContext *pMe, const int64_t nLabel)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_OpenArray(pMe);
}
static inline void
QCBOREncode_CloseArray(QCBOREncodeContext *pMe)
{
QCBOREncode_Private_CloseMapOrArray(pMe, CBOR_MAJOR_TYPE_ARRAY);
}
static inline void
QCBOREncode_OpenMap(QCBOREncodeContext *pMe)
{
QCBOREncode_Private_OpenMapOrArray(pMe, CBOR_MAJOR_TYPE_MAP);
}
static inline void
QCBOREncode_OpenMapInMap(QCBOREncodeContext *pMe, const char *szLabel)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_OpenMap(pMe);
}
static inline void
QCBOREncode_OpenMapInMapN(QCBOREncodeContext *pMe, const int64_t nLabel)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_OpenMap(pMe);
}
static inline void
QCBOREncode_CloseMap(QCBOREncodeContext *pMe)
{
(pMe->pfnCloseMap)(pMe);
}
static inline void
QCBOREncode_OpenArrayIndefiniteLength(QCBOREncodeContext *pMe)
{
QCBOREncode_Private_OpenMapOrArrayIndefiniteLength(pMe, CBOR_MAJOR_NONE_TYPE_ARRAY_INDEFINITE_LEN);
}
static inline void
QCBOREncode_OpenArrayIndefiniteLengthInMap(QCBOREncodeContext *pMe,
const char *szLabel)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_OpenArrayIndefiniteLength(pMe);
}
static inline void
QCBOREncode_OpenArrayIndefiniteLengthInMapN(QCBOREncodeContext *pMe,
const int64_t nLabel)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_OpenArrayIndefiniteLength(pMe);
}
static inline void
QCBOREncode_CloseArrayIndefiniteLength(QCBOREncodeContext *pMe)
{
QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(pMe, CBOR_MAJOR_NONE_TYPE_ARRAY_INDEFINITE_LEN);
}
static inline void
QCBOREncode_OpenMapIndefiniteLength(QCBOREncodeContext *pMe)
{
QCBOREncode_Private_OpenMapOrArrayIndefiniteLength(pMe, CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN);
}
static inline void
QCBOREncode_OpenMapIndefiniteLengthInMap(QCBOREncodeContext *pMe,
const char *szLabel)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_OpenMapIndefiniteLength(pMe);
}
static inline void
QCBOREncode_OpenMapIndefiniteLengthInMapN(QCBOREncodeContext *pMe,
const int64_t nLabel)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_OpenMapIndefiniteLength(pMe);
}
static inline void
QCBOREncode_CloseMapIndefiniteLength(QCBOREncodeContext *pMe)
{
QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(pMe, CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN);
}
static inline void
QCBOREncode_BstrWrap(QCBOREncodeContext *pMe)
{
QCBOREncode_Private_OpenMapOrArray(pMe, CBOR_MAJOR_TYPE_BYTE_STRING);
}
static inline void
QCBOREncode_BstrWrapInMap(QCBOREncodeContext *pMe, const char *szLabel)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_BstrWrap(pMe);
}
static inline void
QCBOREncode_BstrWrapInMapN(QCBOREncodeContext *pMe, const int64_t nLabel)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_BstrWrap(pMe);
}
static inline void
QCBOREncode_CloseBstrWrap(QCBOREncodeContext *pMe, UsefulBufC *pWrappedCBOR)
{
QCBOREncode_CloseBstrWrap2(pMe, true, pWrappedCBOR);
}
static inline void
QCBOREncode_AddEncoded(QCBOREncodeContext *pMe, const UsefulBufC Encoded)
{
QCBOREncode_Private_AddBuffer(pMe, CBOR_MAJOR_NONE_TYPE_RAW, Encoded);
}
static inline void
QCBOREncode_AddEncodedToMap(QCBOREncodeContext *pMe,
const char *szLabel,
const UsefulBufC Encoded)
{
QCBOREncode_AddSZString(pMe, szLabel);
QCBOREncode_AddEncoded(pMe, Encoded);
}
static inline void
QCBOREncode_AddEncodedToMapN(QCBOREncodeContext *pMe,
const int64_t nLabel,
const UsefulBufC Encoded)
{
QCBOREncode_AddInt64(pMe, nLabel);
QCBOREncode_AddEncoded(pMe, Encoded);
}
static inline int
QCBOREncode_IsBufferNULL(QCBOREncodeContext *pMe)
{
return UsefulOutBuf_IsBufferNULL(&(pMe->OutBuf));
}
static inline QCBORError
QCBOREncode_GetErrorState(QCBOREncodeContext *pMe)
{
if(UsefulOutBuf_GetError(&(pMe->OutBuf))) {
// Items didn't fit in the buffer.
// This check catches this condition for all the appends and inserts
// so checks aren't needed when the appends and inserts are performed.
// And of course UsefulBuf will never overrun the input buffer given
// to it. No complex analysis of the error handling in this file is
// needed to know that is true. Just read the UsefulBuf code.
pMe->uError = QCBOR_ERR_BUFFER_TOO_SMALL;
// QCBOR_ERR_BUFFER_TOO_SMALL masks other errors, but that is
// OK. Once the caller fixes this, they'll be unmasked.
}
return (QCBORError)pMe->uError;
}
/* ========================================================================
END OF PRIVATE INLINE IMPLEMENTATION
======================================================================== */
#ifdef __cplusplus
}
#endif
#endif /* qcbor_encode_h */