QCBOR
Loading...
Searching...
No Matches
qcbor_encode.h File Reference
#include "qcbor/qcbor_common.h"
#include "qcbor/qcbor_private.h"
#include <stdbool.h>

Go to the source code of this file.

Macros

#define QCBOR_HEAD_BUFFER_SIZE   (sizeof(uint64_t) + 2)
#define QCBOR_ENCODE_AS_TAG   0
#define QCBOR_ENCODE_AS_BORROWED   1

Typedefs

typedef struct _QCBOREncodeContext QCBOREncodeContext

Functions

void QCBOREncode_Init (QCBOREncodeContext *pCtx, UsefulBuf Storage)
void QCBOREncode_AddInt64 (QCBOREncodeContext *pCtx, int64_t nNum)
 Add a signed 64-bit integer to the encoded output.
static void QCBOREncode_AddInt64ToMapSZ (QCBOREncodeContext *pCtx, const char *szLabel, int64_t nNum)
static void QCBOREncode_AddInt64ToMapN (QCBOREncodeContext *pCtx, int64_t nLabel, int64_t nNum)
static void QCBOREncode_AddUInt64 (QCBOREncodeContext *pCtx, uint64_t uNum)
 Add an unsigned 64-bit integer to the encoded output.
static void QCBOREncode_AddUInt64ToMapSZ (QCBOREncodeContext *pCtx, const char *szLabel, uint64_t uNum)
static void QCBOREncode_AddUInt64ToMapN (QCBOREncodeContext *pCtx, int64_t nLabel, uint64_t uNum)
static void QCBOREncode_AddText (QCBOREncodeContext *pCtx, UsefulBufC Text)
 Add a UTF-8 text string to the encoded output.
static void QCBOREncode_AddTextToMapSZ (QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Text)
static void QCBOREncode_AddTextToMapN (QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Text)
static void QCBOREncode_AddSZString (QCBOREncodeContext *pCtx, const char *szString)
 Add a UTF-8 text string to the encoded output.
static void QCBOREncode_AddSZStringToMapSZ (QCBOREncodeContext *pCtx, const char *szLabel, const char *szString)
static void QCBOREncode_AddSZStringToMapN (QCBOREncodeContext *pCtx, int64_t nLabel, const char *szString)
static void QCBOREncode_AddDouble (QCBOREncodeContext *pCtx, double dNum)
 Add a double-precision floating-point number to the encoded output.
static void QCBOREncode_AddDoubleToMapSZ (QCBOREncodeContext *pCtx, const char *szLabel, double dNum)
static void QCBOREncode_AddDoubleToMapN (QCBOREncodeContext *pCtx, int64_t nLabel, double dNum)
static void QCBOREncode_AddFloat (QCBOREncodeContext *pCtx, float fNum)
 Add a single-precision floating-point number to the encoded output.
static void QCBOREncode_AddFloatToMapSZ (QCBOREncodeContext *pCtx, const char *szLabel, float fNum)
static void QCBOREncode_AddFloatToMapN (QCBOREncodeContext *pCtx, int64_t nLabel, float dNum)
static void QCBOREncode_AddDoubleNoPreferred (QCBOREncodeContext *pCtx, double dNum)
 Add a double-precision floating-point number without preferred encoding.
static void QCBOREncode_AddDoubleNoPreferredToMapSZ (QCBOREncodeContext *pCtx, const char *szLabel, double dNum)
static void QCBOREncode_AddDoubleNoPreferredToMapN (QCBOREncodeContext *pCtx, int64_t nLabel, double dNum)
static void QCBOREncode_AddFloatNoPreferred (QCBOREncodeContext *pCtx, float fNum)
 Add a single-precision floating-point number without preferred encoding.
static void QCBOREncode_AddFloatNoPreferredToMapSZ (QCBOREncodeContext *pCtx, const char *szLabel, float fNum)
static void QCBOREncode_AddFloatNoPreferredToMapN (QCBOREncodeContext *pCtx, int64_t nLabel, float fNum)
static void QCBOREncode_AddTag (QCBOREncodeContext *pCtx, uint64_t uTag)
 Add a tag number.
static void QCBOREncode_AddTDateEpoch (QCBOREncodeContext *pCtx, uint8_t uTagRequirement, int64_t nDate)
 Add an epoch-based date.
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_AddTDaysEpoch (QCBOREncodeContext *pCtx, uint8_t uTagRequirement, int64_t nDays)
 Add an epoch-based day-count date.
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)
static void QCBOREncode_AddBytes (QCBOREncodeContext *pCtx, UsefulBufC Bytes)
 Add a byte string to the encoded output.
static void QCBOREncode_AddBytesToMapSZ (QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
static void QCBOREncode_AddBytesToMapN (QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
void QCBOREncode_OpenBytes (QCBOREncodeContext *pCtx, UsefulBuf *pPlace)
 Set up to write a byte string value directly to encoded output.
static void QCBOREncode_OpenBytesInMapSZ (QCBOREncodeContext *pCtx, const char *szLabel, UsefulBuf *pPlace)
static void QCBOREncode_OpenBytesInMapN (QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBuf *pPlace)
void QCBOREncode_CloseBytes (QCBOREncodeContext *pCtx, size_t uAmount)
 Close out a byte string written directly to encoded output.
static void QCBOREncode_AddTBinaryUUID (QCBOREncodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC Bytes)
 Add a binary UUID to the encoded output.
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_AddTPositiveBignum (QCBOREncodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC BigNumber)
 Add a positive big number to the encoded output.
static void QCBOREncode_AddTPositiveBignumToMapSZ (QCBOREncodeContext *pCtx, const char *szLabel, uint8_t uTagRequirement, UsefulBufC BigNumber)
static void QCBOREncode_AddTPositiveBignumToMapN (QCBOREncodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC BigNumber)
static void QCBOREncode_AddTNegativeBignum (QCBOREncodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC BigNumber)
 Add a negative big number to the encoded output.
static void QCBOREncode_AddTNegativeBignumToMapSZ (QCBOREncodeContext *pCtx, const char *szLabel, uint8_t uTagRequirement, UsefulBufC BigNumber)
static void QCBOREncode_AddTNegativeBignumToMapN (QCBOREncodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC BigNumber)
static void QCBOREncode_AddTDecimalFraction (QCBOREncodeContext *pCtx, uint8_t uTagRequirement, int64_t nMantissa, int64_t nBase10Exponent)
 Add a decimal fraction to the encoded output.
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_AddTDecimalFractionBigNum (QCBOREncodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC Mantissa, bool bIsNegative, int64_t nBase10Exponent)
 Add a decimal fraction with a big number mantissa to the encoded output.
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_AddTBigFloat (QCBOREncodeContext *pCtx, uint8_t uTagRequirement, int64_t nMantissa, int64_t nBase2Exponent)
 Add a big floating-point number to the encoded output.
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_AddTBigFloatBigNum (QCBOREncodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC Mantissa, bool bIsNegative, int64_t nBase2Exponent)
 Add a big floating-point number with a big number mantissa to the encoded output.
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_AddTURI (QCBOREncodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC URI)
 Add a text URI to the encoded output.
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_AddTB64Text (QCBOREncodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC B64Text)
 Add Base64-encoded text to encoded output.
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_AddTB64URLText (QCBOREncodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC B64Text)
 Add base64url encoded data to encoded output.
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_AddTRegex (QCBOREncodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC Regex)
 Add Perl Compatible Regular Expression.
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_AddTMIMEData (QCBOREncodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC MIMEData)
 MIME encoded data to the encoded output.
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_AddTDateString (QCBOREncodeContext *pCtx, uint8_t uTagRequirement, const char *szDate)
 Add an RFC 3339 date string.
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_AddTDaysString (QCBOREncodeContext *pCtx, uint8_t uTagRequirement, const char *szDate)
 Add a date-only string.
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)
static void QCBOREncode_AddBool (QCBOREncodeContext *pCtx, bool b)
 Add a standard Boolean.
static void QCBOREncode_AddBoolToMapSZ (QCBOREncodeContext *pCtx, const char *szLabel, bool b)
static void QCBOREncode_AddBoolToMapN (QCBOREncodeContext *pCtx, int64_t nLabel, bool b)
static void QCBOREncode_AddNULL (QCBOREncodeContext *pCtx)
 Add a NULL to the encoded output.
static void QCBOREncode_AddNULLToMapSZ (QCBOREncodeContext *pCtx, const char *szLabel)
static void QCBOREncode_AddNULLToMapN (QCBOREncodeContext *pCtx, int64_t nLabel)
static void QCBOREncode_AddUndef (QCBOREncodeContext *pCtx)
 Add an "undef" to the encoded output.
static void QCBOREncode_AddUndefToMapSZ (QCBOREncodeContext *pCtx, const char *szLabel)
static void QCBOREncode_AddUndefToMapN (QCBOREncodeContext *pCtx, int64_t nLabel)
static void QCBOREncode_AddSimple (QCBOREncodeContext *pCtx, const uint8_t uNum)
 Add a simple value.
static void QCBOREncode_AddSimpleToMapSZ (QCBOREncodeContext *pCtx, const char *szLabel, const uint8_t uSimple)
static void QCBOREncode_AddSimpleToMapN (QCBOREncodeContext *pCtx, const int64_t nLabel, const uint8_t uSimple)
static void QCBOREncode_OpenArray (QCBOREncodeContext *pCtx)
 Indicates that the next items added are in an array.
static void QCBOREncode_OpenArrayInMapSZ (QCBOREncodeContext *pCtx, const char *szLabel)
static void QCBOREncode_OpenArrayInMapN (QCBOREncodeContext *pCtx, int64_t nLabel)
static void QCBOREncode_CloseArray (QCBOREncodeContext *pCtx)
 Close an open array.
static void QCBOREncode_OpenMap (QCBOREncodeContext *pCtx)
 Indicates that the next items added are in a map.
static void QCBOREncode_OpenMapInMapSZ (QCBOREncodeContext *pCtx, const char *szLabel)
static void QCBOREncode_OpenMapInMapN (QCBOREncodeContext *pCtx, int64_t nLabel)
static void QCBOREncode_CloseMap (QCBOREncodeContext *pCtx)
 Close an open map.
static void QCBOREncode_OpenArrayIndefiniteLength (QCBOREncodeContext *pCtx)
 Indicates that the next items added are in an indefinite length array.
static void QCBOREncode_OpenArrayIndefiniteLengthInMapSZ (QCBOREncodeContext *pCtx, const char *szLabel)
static void QCBOREncode_OpenArrayIndefiniteLengthInMapN (QCBOREncodeContext *pCtx, int64_t nLabel)
static void QCBOREncode_CloseArrayIndefiniteLength (QCBOREncodeContext *pCtx)
 Close an open indefinite length array.
static void QCBOREncode_OpenMapIndefiniteLength (QCBOREncodeContext *pCtx)
 Indicates that the next items added are in an indefinite length map.
static void QCBOREncode_OpenMapIndefiniteLengthInMapSZ (QCBOREncodeContext *pCtx, const char *szLabel)
static void QCBOREncode_OpenMapIndefiniteLengthInMapN (QCBOREncodeContext *pCtx, int64_t nLabel)
static void QCBOREncode_CloseMapIndefiniteLength (QCBOREncodeContext *pCtx)
 Close an open indefinite length map.
static void QCBOREncode_BstrWrap (QCBOREncodeContext *pCtx)
 Indicate start of encoded CBOR to be wrapped in a bstr.
static void QCBOREncode_BstrWrapInMapSZ (QCBOREncodeContext *pCtx, const char *szLabel)
static void QCBOREncode_BstrWrapInMapN (QCBOREncodeContext *pCtx, int64_t nLabel)
void QCBOREncode_CloseBstrWrap2 (QCBOREncodeContext *pCtx, bool bIncludeCBORHead, UsefulBufC *pWrappedCBOR)
 Close a wrapping bstr.
static void QCBOREncode_CloseBstrWrap (QCBOREncodeContext *pCtx, UsefulBufC *pWrappedCBOR)
void QCBOREncode_CancelBstrWrap (QCBOREncodeContext *pCtx)
 Cancel byte string wrapping.
void QCBOREncode_AddEncoded (QCBOREncodeContext *pCtx, UsefulBufC Encoded)
 Add some already-encoded CBOR bytes.
static void QCBOREncode_AddEncodedToMapSZ (QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Encoded)
static void QCBOREncode_AddEncodedToMapN (QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Encoded)
QCBORError QCBOREncode_Finish (QCBOREncodeContext *pCtx, UsefulBufC *pEncodedCBOR)
 Get the encoded result.
QCBORError QCBOREncode_FinishGetSize (QCBOREncodeContext *pCtx, size_t *uEncodedLen)
 Get the encoded CBOR and error status.
static int QCBOREncode_IsBufferNULL (QCBOREncodeContext *pCtx)
 Indicate whether the output storage buffer is NULL.
static UsefulBuf QCBOREncode_RetrieveOutputStorage (QCBOREncodeContext *pCtx)
 Retrieve the storage buffer passed in to QCBOREncode_Init().
static QCBORError QCBOREncode_GetErrorState (QCBOREncodeContext *pCtx)
 Get the encoding error state.
static size_t QCBOREncode_Tell (QCBOREncodeContext *pCtx)
 Returns current end of encoded data.
UsefulBufC QCBOREncode_SubString (QCBOREncodeContext *pCtx, const size_t uStart)
 Get a substring of encoded CBOR for cryptographic hash.
UsefulBufC QCBOREncode_EncodeHead (UsefulBuf Buffer, uint8_t uMajorType, uint8_t uMinLen, uint64_t uNumber)
 Encode the head of a CBOR data item.
static void QCBOREncode_AddInt64ToMap (QCBOREncodeContext *pCtx, const char *szLabel, int64_t nNum)
static void QCBOREncode_AddUInt64ToMap (QCBOREncodeContext *pCtx, const char *szLabel, uint64_t uNum)
static void QCBOREncode_AddTextToMap (QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Text)
static void QCBOREncode_AddSZStringToMap (QCBOREncodeContext *pCtx, const char *szLabel, const char *szString)
static void QCBOREncode_AddDoubleToMap (QCBOREncodeContext *pCtx, const char *szLabel, double dNum)
static void QCBOREncode_AddFloatToMap (QCBOREncodeContext *pCtx, const char *szLabel, float fNum)
static void QCBOREncode_AddDoubleNoPreferredToMap (QCBOREncodeContext *pCtx, const char *szLabel, double dNum)
static void QCBOREncode_AddFloatNoPreferredToMap (QCBOREncodeContext *pCtx, const char *szLabel, float fNum)
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)
static void QCBOREncode_AddBytesToMap (QCBOREncodeContext *pCtx, const char *szLabel, 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)
static void QCBOREncode_AddPositiveBignum (QCBOREncodeContext *pCtx, UsefulBufC BigNumber)
static void QCBOREncode_AddPositiveBignumToMap (QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC BigNumber)
static void QCBOREncode_AddPositiveBignumToMapN (QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC BigNumber)
static void QCBOREncode_AddNegativeBignum (QCBOREncodeContext *pCtx, UsefulBufC BigNumber)
static void QCBOREncode_AddNegativeBignumToMap (QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC BigNumber)
static void QCBOREncode_AddNegativeBignumToMapN (QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC BigNumber)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
static void QCBOREncode_AddBoolToMap (QCBOREncodeContext *pCtx, const char *szLabel, bool b)
static void QCBOREncode_AddNULLToMap (QCBOREncodeContext *pCtx, const char *szLabel)
static void QCBOREncode_AddUndefToMap (QCBOREncodeContext *pCtx, const char *szLabel)
static void QCBOREncode_AddSimpleToMap (QCBOREncodeContext *pCtx, const char *szLabel, const uint8_t uSimple)
static void QCBOREncode_OpenArrayInMap (QCBOREncodeContext *pCtx, const char *szLabel)
static void QCBOREncode_OpenMapInMap (QCBOREncodeContext *pCtx, const char *szLabel)
static void QCBOREncode_OpenArrayIndefiniteLengthInMap (QCBOREncodeContext *pCtx, const char *szLabel)
static void QCBOREncode_OpenMapIndefiniteLengthInMap (QCBOREncodeContext *pCtx, const char *szLabel)
static void QCBOREncode_BstrWrapInMap (QCBOREncodeContext *pCtx, const char *szLabel)
static void QCBOREncode_AddEncodedToMap (QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Encoded)
void QCBOREncode_Private_AppendCBORHead (QCBOREncodeContext *pMe, const uint8_t uMajorType, const uint64_t uArgument, const uint8_t uMinLen)
void QCBOREncode_Private_AddBuffer (QCBOREncodeContext *pCtx, uint8_t uMajorType, UsefulBufC Bytes)
void QCBOREncode_Private_AddPreferredDouble (QCBOREncodeContext *pMe, const double dNum)
void QCBOREncode_Private_AddPreferredFloat (QCBOREncodeContext *pMe, const float fNum)
void QCBOREncode_Private_OpenMapOrArray (QCBOREncodeContext *pCtx, uint8_t uMajorType)
void QCBOREncode_Private_OpenMapOrArrayIndefiniteLength (QCBOREncodeContext *pCtx, uint8_t uMajorType)
void QCBOREncode_Private_CloseMapOrArray (QCBOREncodeContext *pCtx, uint8_t uMajorType)
void QCBOREncode_Private_CloseMapOrArrayIndefiniteLength (QCBOREncodeContext *pCtx, uint8_t uMajorType)
void QCBOREncode_Private_AddExpMantissa (QCBOREncodeContext *pCtx, uint64_t uTag, UsefulBufC BigNumMantissa, bool bBigNumIsNegative, int64_t nMantissa, int64_t nExponent)
static void QCBOREncode_Private_AddType7 (QCBOREncodeContext *pMe, const uint8_t uMinLen, const uint64_t uArgument)
 Semi-private method to add simple items and floating-point.
static void QCBOREncode_AddBytesLenOnly (QCBOREncodeContext *pCtx, UsefulBufC Bytes)
 Semi-private method to add only the type and length of a byte string.
static void QCBOREncode_AddBytesLenOnlyToMap (QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
static void QCBOREncode_AddBytesLenOnlyToMapN (QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)

Detailed Description

QCBOR Overview

This implements CBOR – Concise Binary Object Representation as defined in [RFC 8949] (https://www.rfc-editor.org/rfc/rfc8949.html). More information is at http://cbor.io. This is a near-complete implementation of the specification. [RFC 8742] (https://www.rfc-editor.org/rfc/rfc8742.html) CBOR Sequences is also supported. Limitations are listed further down.

See Encoding for general discussion on encoding, BasicDecode for general discussion on the basic decode features and 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 Tags-Overview and 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 (QCBOR_TYPE_INT64), the primitive positive integer.
  • Next it has a "tag" 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.

Encoding

A common encoding usage mode is to invoke the encoding twice. First with the output buffer as 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 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 QCBOREncode_AddXxx() functions and calling QCBOREncode_Finish(). There are many QCBOREncode_AddXxx() functions for various data types. The input buffers need only to be valid during the 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 QCBOREncode_AddXxx() functions to put items in the array and then QCBOREncode_CloseArray(). Nesting to the limit 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://www.rfc-editor.org/rfc/rfc8742.html). 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.

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_AddTDateEpoch() and in decoding by QCBOR_TYPE_DATE_EPOCH and the epochDate member of QCBORItem. This is typical of the built-in tag support. There is an API to encode data for it and a 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 CBORTags and 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.

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 and infinity are always encoded 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.

Typically, a NaN is a "quiet NaN" with no payload. The NAN constant defined in <math.h> is the quiet NaN with no payload. Preferred serilization reduces this to half-precision. If your use case goes out of its way to set NaN payloads, they are encoded using a reduction that is the same as for numeric values. If the right most bits of the NaN's significand that are removed in a reduction are zero, the reduction is performed. For example, if the rightmost 29 bits of a double NaN significand are zero, then it will be reduced to a single.

To avoid use of preferred serialization in the standard configuration when encoding, use QCBOREncode_AddDoubleNoPreferred() or QCBOREncode_AddFloatNoPreferred().

This implementation of floating-point preferred serialization and half-precision is independent of the CPU floating-point hardware or any floating-point library brought in by the compiler. Instead, it relies solely on bit shifts and masks.

Several compile-time options can reduce the library size and dependencies. Internal dependencies are already minimized, so little floating-point code is linked unless explicitly used. During encoding, no floating-point code is linked unless called; during decoding, only a small amount is linked.

Defining QCBOR_DISABLE_PREFERRED_FLOAT can reduce object code by as much a 2.5KB. The effect is: (TODO: size)

  • No preferred serialization encoding of float-point numbers
  • Half-precision decoding is disabled (decoding attempts will fail)
  • Single-precision values are not converted to double during decoding

On CPUs without floating-point hardware, define QCBOR_DISABLE_FLOAT_HW_USE elimate the possibility of the compiler adding large software emulation libraries. On CPUs with floating-point hardware, defining it can still save up to 1.5 KB of (TODO: size) object code and removes the need for <math.h>.

When QCBOR_DISABLE_FLOAT_HW_USE is defined:

  • Decoding of floating-point dates is not possible
  • Decode conversions involving floating-point are disabled

If both QCBOR_DISABLE_FLOAT_HW_USE and QCBOR_DISABLE_PREFERRED_FLOAT are defined:

  • Single-precision and double-precision values can only be encoded/decoded as-is (no conversions between them).

If USEFULBUF_DISABLE_ALL_FLOAT is defined, then floating-point support is completely disabled:

  • No double or float types are used anywhere
  • Decoding functions return QCBOR_ERR_ALL_FLOAT_DISABLED if a floating-point value is encountered
  • Encoding functions for floating-point values are unavailable

Limitations

Summary limitations:

  • The entire encoded CBOR must fit into contiguous memory.
  • Max size of encoded CBOR data is a few bytes less than UINT32_MAX (4GB).
  • Max array / map nesting level when encoding or decoding is QCBOR_MAX_ARRAY_NESTING (this is typically 15).
  • Max items in an array or map when encoding or decoding is 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 beyond whats fits in int64_t or uint64_t.
  • Epoch dates limited to INT64_MAX (+/- 292 billion years).
  • Exponents for bigfloats and decimal integers are limited to whats fits in int64_t.
  • Tags on labels are ignored during decoding.
  • The maximum tag nesting is QCBOR_MAX_TAGS_PER_ITEM (typically 4).
  • Works only on 32- and 64-bit CPUs.
  • QCBORDecode_EnterBstrWrapped() doesn't work on indefinite-length strings.
  • Numeric reduction of big numbers to integers for preferred serialization is not performed.

The public interface uses 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 UINT32_MAX (4GB).

This implementation requires two's compliment integers. While C doesn't require two's compliment, <stdint.h> does. Other parts of this implementation may also require two's compliment.

Macro Definition Documentation

◆ QCBOR_ENCODE_AS_BORROWED

#define QCBOR_ENCODE_AS_BORROWED   1

Output only the 'borrowed' content format for the relevant tag. See CBORTags, Tag-Usage and Tags-Overview.

◆ QCBOR_ENCODE_AS_TAG

#define QCBOR_ENCODE_AS_TAG   0

Output the full CBOR tag. See CBORTags, Tag-Usage and Tags-Overview.

◆ QCBOR_HEAD_BUFFER_SIZE

#define QCBOR_HEAD_BUFFER_SIZE   (sizeof(uint64_t) + 2)

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.

Typedef Documentation

◆ QCBOREncodeContext

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.

Function Documentation

◆ QCBOREncode_AddBool()

void QCBOREncode_AddBool ( QCBOREncodeContext * pCtx,
bool b )
inlinestatic

Add a standard Boolean.

Parameters
[in]pCtxThe encoding context to add the Boolean to.
[in]btrue or false from <stdbool.h>.

Adds a Boolean value as CBOR major type 7.

Error handling is the same as QCBOREncode_AddInt64().

◆ QCBOREncode_AddBytes()

void QCBOREncode_AddBytes ( QCBOREncodeContext * pCtx,
UsefulBufC Bytes )
inlinestatic

Add a byte string to the encoded output.

Parameters
[in]pCtxThe encoding context to add the bytes to.
[in]BytesPointer and length of the input data.

Simply adds the bytes to the encoded output as CBOR major type 2.

If called with Bytes.len equal to 0, an empty string will be added. When Bytes.len is 0, Bytes.ptr may be NULL.

Error handling is the same as QCBOREncode_AddInt64().

◆ QCBOREncode_AddBytesLenOnly()

void QCBOREncode_AddBytesLenOnly ( QCBOREncodeContext * pCtx,
UsefulBufC Bytes )
inlinestatic

Semi-private method to add only the type and length of a byte string.

Parameters
[in]pCtxThe context to initialize.
[in]BytesPointer and length of the input data.

This will be removed in QCBOR 2.0. It was never a public function.

This is the same as QCBOREncode_AddBytes() except it only adds the CBOR encoding for the type and the length. It doesn't actually add the bytes. You can't actually produce correct CBOR with this and the rest of this API. It is only used for a special case where the valid CBOR is created manually by putting this type and length in and then adding the actual bytes. In particular, when only a hash of the encoded CBOR is needed, where the type and header are hashed separately and then the bytes is hashed. This makes it possible to implement COSE Sign1 with only one copy of the payload in the output buffer, rather than two, roughly cutting memory use in half.

This is only used for this odd case, but this is a supported tested function for QCBOR 1.0.

See also QCBOREncode_EncodeHead().

◆ QCBOREncode_AddDouble()

void QCBOREncode_AddDouble ( QCBOREncodeContext * pCtx,
double dNum )
inlinestatic

Add a double-precision floating-point number to the encoded output.

Parameters
[in]pCtxThe encoding context to add the double to.
[in]dNumThe double-precision number to add.

This encodes and outputs a double-precision 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 zero 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 two bytes, half that of single-precision, one quarter of double-precision. Preferred serialization can therefore reduce message size down to one quarter of the original if most of the values are zero, infinity or NaN.

When decoded, QCBOR returns these values as double-precision even if they were encoded as single or half-precision.

It is possible to disable preferred serialization when compiling QCBOR. In that case, this operates the same as QCBOREncode_AddDoubleNoPreferred().

Error handling is the same as QCBOREncode_AddInt64().

See also QCBOREncode_AddDoubleNoPreferred(), QCBOREncode_AddFloat() and QCBOREncode_AddFloatNoPreferred() and Floating-Point.

◆ QCBOREncode_AddDoubleNoPreferred()

void QCBOREncode_AddDoubleNoPreferred ( QCBOREncodeContext * pCtx,
double dNum )
inlinestatic

Add a double-precision floating-point number without preferred encoding.

Parameters
[in]pCtxThe encoding context to add the double to.
[in]dNumThe 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().

See also QCBOREncode_AddDouble(), QCBOREncode_AddFloat(), and QCBOREncode_AddFloatNoPreferred() and Floating-Point.

◆ QCBOREncode_AddEncoded()

void QCBOREncode_AddEncoded ( QCBOREncodeContext * pCtx,
UsefulBufC Encoded )

Add some already-encoded CBOR bytes.

Parameters
[in]pCtxThe encoding context to add the already-encode CBOR to.
[in]EncodedThe 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. 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.

◆ QCBOREncode_AddFloat()

void QCBOREncode_AddFloat ( QCBOREncodeContext * pCtx,
float fNum )
inlinestatic

Add a single-precision floating-point number to the encoded output.

Parameters
[in]pCtxThe encoding context to add the single to.
[in]fNumThe single-precision number to add.

This is identical to QCBOREncode_AddDouble() except the input is single-precision. The preferred serialization output will be either single-precision or half-precision.

See also QCBOREncode_AddDouble(), QCBOREncode_AddDoubleNoPreferred(), and QCBOREncode_AddFloatNoPreferred() and Floating-Point.

◆ QCBOREncode_AddFloatNoPreferred()

void QCBOREncode_AddFloatNoPreferred ( QCBOREncodeContext * pCtx,
float fNum )
inlinestatic

Add a single-precision floating-point number without preferred encoding.

Parameters
[in]pCtxThe encoding context to add the double to.
[in]fNumThe 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().

See also QCBOREncode_AddDouble(), QCBOREncode_AddFloat(), and QCBOREncode_AddDoubleNoPreferred() and Floating-Point.

◆ QCBOREncode_AddInt64()

void QCBOREncode_AddInt64 ( QCBOREncodeContext * pCtx,
int64_t nNum )

Add a signed 64-bit integer to the encoded output.

Parameters
[in]pCtxThe encoding context to add the integer to.
[in]nNumThe 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 integer, like int16_t or a small value, like 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 Appendix A] (https://www.rfc-editor.org/rfc/rfc8949.html#section-appendix.a) for more examples of CBOR encoding. This compact encoding is preferred serialization CBOR as per [RFC 8949 section 4.1] (https://www.rfc-editor.org/rfc/rfc8949.html#section-4.1)

There are no functions to add int16_t or int32_t because they are not necessary because this always encodes to the smallest number of bytes based on the value.

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().

◆ QCBOREncode_AddNULL()

void QCBOREncode_AddNULL ( QCBOREncodeContext * pCtx)
inlinestatic

Add a NULL to the encoded output.

Parameters
[in]pCtxThe 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().

◆ QCBOREncode_AddSimple()

void QCBOREncode_AddSimple ( QCBOREncodeContext * pCtx,
const uint8_t uNum )
inlinestatic

Add a simple value.

Parameters
[in]pCtxThe encode context.
[in]uNumThe simple value.

QCBOREncode_AddBool(), QCBOREncode_AddUndef() and QCBOREncode_AddNull() are preferred to this for the simple values defined in RFC 8949, but this can be used for them too.

The main purpose of this is to add simple values beyond those in defined RFC 8949. Note that simple values must be registered with IANA. Those in the range of 0 to 19 must be standardized. Those in the range of 32 to 255 do not require a standard, but must be publically specified. There is no range of values for proprietary use. See https://www.iana.org/assignments/cbor-simple-values/cbor-simple-values.xhtml

◆ QCBOREncode_AddSZString()

void QCBOREncode_AddSZString ( QCBOREncodeContext * pCtx,
const char * szString )
inlinestatic

Add a UTF-8 text string to the encoded output.

Parameters
[in]pCtxThe encoding context to add the text to.
[in]szStringNull-terminated text to add.

This works the same as QCBOREncode_AddText().

◆ QCBOREncode_AddTag()

void QCBOREncode_AddTag ( QCBOREncodeContext * pCtx,
uint64_t uTag )
inlinestatic

Add a tag number.

Parameters
[in]pCtxThe encoding context to add the tag to.
[in]uTagThe 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_AddTDateEpoch() 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 Tags-Overview for discussion of creating new non-standard tags. See QCBORDecode_GetNext() for discussion of decoding custom tags.

◆ QCBOREncode_AddTB64Text()

void QCBOREncode_AddTB64Text ( QCBOREncodeContext * pCtx,
uint8_t uTagRequirement,
UsefulBufC B64Text )
inlinestatic

Add Base64-encoded text to encoded output.

Parameters
[in]pCtxThe encoding context to add the base-64 text to.
[in]uTagRequirementEither QCBOR_ENCODE_AS_TAG or QCBOR_ENCODE_AS_BORROWED.
[in]B64TextPointer and length of the base-64 encoded text.

The text content is Base64 encoded data per [RFC 4648] (https://www.rfc-editor.org/rfc/rfc4648.html).

It is output as CBOR major type 3, a text string, with tag CBOR_TAG_B64 indicating the text string is Base64 encoded.

◆ QCBOREncode_AddTB64URLText()

void QCBOREncode_AddTB64URLText ( QCBOREncodeContext * pCtx,
uint8_t uTagRequirement,
UsefulBufC B64Text )
inlinestatic

Add base64url encoded data to encoded output.

Parameters
[in]pCtxThe encoding context to add the base64url to.
[in]uTagRequirementEither QCBOR_ENCODE_AS_TAG or QCBOR_ENCODE_AS_BORROWED.
[in]B64TextPointer and length of the base64url encoded text.

The text content is base64URL encoded text as per [RFC 4648] (https://www.rfc-editor.org/rfc/rfc4648.html).

It is output as CBOR major type 3, a text string, with tag CBOR_TAG_B64URL indicating the text string is a Base64url encoded.

◆ QCBOREncode_AddTBigFloat()

void QCBOREncode_AddTBigFloat ( QCBOREncodeContext * pCtx,
uint8_t uTagRequirement,
int64_t nMantissa,
int64_t nBase2Exponent )
inlinestatic

Add a big floating-point number to the encoded output.

Parameters
[in]pCtxThe encoding context to add the bigfloat to.
[in]uTagRequirementEither QCBOR_ENCODE_AS_TAG or QCBOR_ENCODE_AS_BORROWED.
[in]nMantissaThe mantissa.
[in]nBase2ExponentThe 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_AddTBigFloatBigNum() 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 INT64_MIN to INT64_MAX for both encoding and decoding (CBOR allows -UINT64_MAX to UINT64_MAX, but this implementation doesn't support this range to reduce code size and interface complexity a little).

Preferred serialization is used when the mantissa or exponent are integers, thus they will be encoded in the smallest number of bytes.

This can also be used to represent floating-point numbers in environments that don't support IEEE 754.

See expAndMantissa for decoded representation.

◆ QCBOREncode_AddTBigFloatBigNum()

void QCBOREncode_AddTBigFloatBigNum ( QCBOREncodeContext * pCtx,
uint8_t uTagRequirement,
UsefulBufC Mantissa,
bool bIsNegative,
int64_t nBase2Exponent )
inlinestatic

Add a big floating-point number with a big number mantissa to the encoded output.

Parameters
[in]pCtxThe encoding context to add the bigfloat to.
[in]uTagRequirementEither QCBOR_ENCODE_AS_TAG or QCBOR_ENCODE_AS_BORROWED.
[in]MantissaThe mantissa.
[in]bIsNegativefalse if mantissa is positive, true if negative.
[in]nBase2ExponentThe exponent.

This is the same as QCBOREncode_AddTBigFloat() except the mantissa is a big number (See QCBOREncode_AddTPositiveBignum()) allowing for arbitrary precision.

RFC 8949 preferred serialization requires reduction of big numbers that can fit into integers be encoded as integers, not big numbers. This implementation does NOT do that.

See expAndMantissa for decoded representation.

◆ QCBOREncode_AddTBinaryUUID()

void QCBOREncode_AddTBinaryUUID ( QCBOREncodeContext * pCtx,
uint8_t uTagRequirement,
UsefulBufC Bytes )
inlinestatic

Add a binary UUID to the encoded output.

Parameters
[in]pCtxThe encoding context to add the UUID to.
[in]uTagRequirementEither QCBOR_ENCODE_AS_TAG or QCBOR_ENCODE_AS_BORROWED.
[in]BytesPointer and length of the binary UUID.

A binary UUID as defined in [RFC 4122] (https://www.rfc-editor.org/rfc/rfc4122.html) is added to the output.

It is output as CBOR major type 2, a binary string, with tag CBOR_TAG_BIN_UUID indicating the binary string is a UUID.

◆ QCBOREncode_AddTDateEpoch()

void QCBOREncode_AddTDateEpoch ( QCBOREncodeContext * pCtx,
uint8_t uTagRequirement,
int64_t nDate )
inlinestatic

Add an epoch-based date.

Parameters
[in]pCtxThe encoding context to add the date to.
[in]uTagRequirementEither QCBOR_ENCODE_AS_TAG or QCBOR_ENCODE_AS_BORROWED.
[in]nDateNumber 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().

◆ QCBOREncode_AddTDateString()

void QCBOREncode_AddTDateString ( QCBOREncodeContext * pCtx,
uint8_t uTagRequirement,
const char * szDate )
inlinestatic

Add an RFC 3339 date string.

Parameters
[in]pCtxThe encoding context to add the date to.
[in]uTagRequirementEither QCBOR_ENCODE_AS_TAG or QCBOR_ENCODE_AS_BORROWED.
[in]szDateNull-terminated string with date to add.

The string szDate should be in the form of [RFC 3339] (https://www.rfc-editor.org/rfc/rfc3339.html) as defined by section 3.3 in [RFC 4287] (https://www.rfc-editor.org/rfc/rfc4287.html). This is as described in section 3.4.1 in [RFC 8949] (https://www.rfc-editor.org/rfc/rfc8949.html#section3.1.4).

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().

◆ QCBOREncode_AddTDaysEpoch()

void QCBOREncode_AddTDaysEpoch ( QCBOREncodeContext * pCtx,
uint8_t uTagRequirement,
int64_t nDays )
inlinestatic

Add an epoch-based day-count date.

Parameters
[in]pCtxThe encoding context to add the date to.
[in]uTagRequirementEither QCBOR_ENCODE_AS_TAG or QCBOR_ENCODE_AS_BORROWED.
[in]nDaysNumber of days before or after 1970-01-0.

This date format is described in [RFC 8943] (https://www.rfc-editor.org/rfc/rfc8943.html).

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().

◆ QCBOREncode_AddTDaysString()

void QCBOREncode_AddTDaysString ( QCBOREncodeContext * pCtx,
uint8_t uTagRequirement,
const char * szDate )
inlinestatic

Add a date-only string.

Parameters
[in]pCtxThe encoding context to add the date to.
[in]uTagRequirementEither QCBOR_ENCODE_AS_TAG or QCBOR_ENCODE_AS_BORROWED.
[in]szDateNull-terminated string with date to add.

This date format is described in [RFC 8943] (https://www.rfc-editor.org/rfc/rfc8943.html), 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://www.rfc-editor.org/rfc/rfc3339.html). 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().

◆ QCBOREncode_AddTDecimalFraction()

void QCBOREncode_AddTDecimalFraction ( QCBOREncodeContext * pCtx,
uint8_t uTagRequirement,
int64_t nMantissa,
int64_t nBase10Exponent )
inlinestatic

Add a decimal fraction to the encoded output.

Parameters
[in]pCtxEncoding context to add the decimal fraction to.
[in]uTagRequirementEither QCBOR_ENCODE_AS_TAG or QCBOR_ENCODE_AS_BORROWED.
[in]nMantissaThe mantissa.
[in]nBase10ExponentThe 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 INT64_MIN to INT64_MAX for both encoding and decoding (CBOR allows -UINT64_MAX to UINT64_MAX, but this implementation doesn't support this range to reduce code size and interface complexity a little).

Preferred serialization is used when the mantissa or exponent are integers, thus they will be encoded in the smallest number of bytes.

See also QCBOREncode_AddTDecimalFractionBigNum() for a decimal fraction with arbitrarily large precision and QCBOREncode_AddTBigFloat().

There is no representation of positive or negative infinity or NaN (Not a Number). Use QCBOREncode_AddDouble() to encode them.

See expAndMantissa for decoded representation.

◆ QCBOREncode_AddTDecimalFractionBigNum()

void QCBOREncode_AddTDecimalFractionBigNum ( QCBOREncodeContext * pCtx,
uint8_t uTagRequirement,
UsefulBufC Mantissa,
bool bIsNegative,
int64_t nBase10Exponent )
inlinestatic

Add a decimal fraction with a big number mantissa to the encoded output.

Parameters
[in]pCtxEncoding context to add the decimal fraction to.
[in]uTagRequirementEither QCBOR_ENCODE_AS_TAG or QCBOR_ENCODE_AS_BORROWED.
[in]MantissaThe mantissa.
[in]bIsNegativefalse if mantissa is positive, true if negative.
[in]nBase10ExponentThe exponent.

This is the same as QCBOREncode_AddTDecimalFraction() except the mantissa is a big number (See QCBOREncode_AddTPositiveBignum()) allowing for arbitrarily large precision.

RFC 8949 preferred serialization requires reduction of big numbers that can fit into integers be encoded as integers, not big numbers. This implementation does NOT do that.

See expAndMantissa for decoded representation.

◆ QCBOREncode_AddText()

void QCBOREncode_AddText ( QCBOREncodeContext * pCtx,
UsefulBufC Text )
inlinestatic

Add a UTF-8 text string to the encoded output.

Parameters
[in]pCtxThe encoding context to add the text to.
[in]TextPointer and length of text to add.

The text passed in must be unencoded UTF-8 according to [RFC 3629] (https://www.rfc-editor.org/rfc/rfc3629.html). There is no NULL termination. The text is added as CBOR major type 3.

If called with nBytesLen equal to 0, an empty string will be added. When nBytesLen is 0, pBytes may be NULL.

Note that the restriction of the buffer length to a 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().

◆ QCBOREncode_AddTMIMEData()

void QCBOREncode_AddTMIMEData ( QCBOREncodeContext * pCtx,
uint8_t uTagRequirement,
UsefulBufC MIMEData )
inlinestatic

MIME encoded data to the encoded output.

Parameters
[in]pCtxThe encoding context to add the MIME data to.
[in]uTagRequirementEither QCBOR_ENCODE_AS_TAG or QCBOR_ENCODE_AS_BORROWED.
[in]MIMEDataPointer and length of the MIME data.

The text content is in MIME format per [RFC 2045] (https://www.rfc-editor.org/rfc/rfc2045.html) including the headers.

It is output as CBOR major type 2, a binary string, with tag 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

  1. 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 QCBOR_TYPE_BINARY_MIME.

This does no translation of line endings. See QCBOREncode_AddText() for a discussion of line endings in CBOR.

◆ QCBOREncode_AddTNegativeBignum()

void QCBOREncode_AddTNegativeBignum ( QCBOREncodeContext * pCtx,
uint8_t uTagRequirement,
UsefulBufC BigNumber )
inlinestatic

Add a negative big number to the encoded output.

Parameters
[in]pCtxThe encoding context.
[in]uTagRequirementEither QCBOR_ENCODE_AS_TAG or QCBOR_ENCODE_AS_BORROWED.
[in]BigNumberPointer and length of the big number.

BigNumber makes up an aribtrary precision integer in network/big-endian byte order. The first byte is the most significant.

It is encoded as CBOR major type 2, a binary string, possibly with tag CBOR_TAG_NEG_BIGNUM. See [RFC 8949 section 3.4.3] (https://www.rfc-editor.org/rfc/rfc8949.html#section-3.4.3). No processing, such as removal of leading zeros or the required offset of 1 for negative values, is perfomed.

RFC 8949 preferred serialization requires big numbers that will fit in integers be encoded as integers. That is NOT performed.

◆ QCBOREncode_AddTPositiveBignum()

void QCBOREncode_AddTPositiveBignum ( QCBOREncodeContext * pCtx,
uint8_t uTagRequirement,
UsefulBufC BigNumber )
inlinestatic

Add a positive big number to the encoded output.

Parameters
[in]pCtxThe encoding context.
[in]uTagRequirementEither QCBOR_ENCODE_AS_TAG or QCBOR_ENCODE_AS_BORROWED.
[in]BigNumberPointer and length of the big number.

BigNumber makes up an aribtrary precision integer in network/big-endian byte order. The first byte is the most significant.

It is encoded as CBOR major type 2, a binary string, possibly with tag CBOR_TAG_POS_BIGNUM. See [RFC 8949 section 3.4.3] (https://www.rfc-editor.org/rfc/rfc8949.html#section-3.4.3). No processing, such as removal of leading zeros, is perfomed.

RFC 8949 preferred serialization requires big numbers that will fit in integers be encoded as integers. That is NOT performed.

◆ QCBOREncode_AddTRegex()

void QCBOREncode_AddTRegex ( QCBOREncodeContext * pCtx,
uint8_t uTagRequirement,
UsefulBufC Regex )
inlinestatic

Add Perl Compatible Regular Expression.

Parameters
[in]pCtxEncoding context to add the regular expression to.
[in]uTagRequirementEither QCBOR_ENCODE_AS_TAG or QCBOR_ENCODE_AS_BORROWED.
[in]RegexPointer 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 CBOR_TAG_REGEX indicating the text string is a regular expression.

◆ QCBOREncode_AddTURI()

void QCBOREncode_AddTURI ( QCBOREncodeContext * pCtx,
uint8_t uTagRequirement,
UsefulBufC URI )
inlinestatic

Add a text URI to the encoded output.

Parameters
[in]pCtxThe encoding context to add the URI to.
[in]uTagRequirementEither QCBOR_ENCODE_AS_TAG or QCBOR_ENCODE_AS_BORROWED.
[in]URIPointer and length of the URI.

The format of URI must be per [RFC 3986] (https://www.rfc-editor.org/rfc/rfc3986.html).

It is output as CBOR major type 3, a text string, with tag CBOR_TAG_URI indicating the text string is a URI.

A URI in a NULL-terminated string, szURI, can be easily added with this code:

 QCBOREncode_AddTURI(pCtx, QCBOR_ENCODE_AS_TAG, UsefulBuf_FromSZ(szURI));

◆ QCBOREncode_AddUInt64()

void QCBOREncode_AddUInt64 ( QCBOREncodeContext * pCtx,
uint64_t uNum )
inlinestatic

Add an unsigned 64-bit integer to the encoded output.

Parameters
[in]pCtxThe encoding context to add the integer to.
[in]uNumThe 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 INT64_MAX and smaller than UINT64_MAX. Otherwise QCBOREncode_AddInt64() will work fine.

Error handling is the same as for QCBOREncode_AddInt64().

◆ QCBOREncode_AddUndef()

void QCBOREncode_AddUndef ( QCBOREncodeContext * pCtx)
inlinestatic

Add an "undef" to the encoded output.

Parameters
[in]pCtxThe 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.

"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().

◆ QCBOREncode_BstrWrap()

void QCBOREncode_BstrWrap ( QCBOREncodeContext * pCtx)
inlinestatic

Indicate start of encoded CBOR to be wrapped in a bstr.

Parameters
[in]pCtxThe 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 9052, COSE] (https://www.rfc-editor.org/rfc/rfc9052.html) 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 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.

◆ QCBOREncode_CancelBstrWrap()

void QCBOREncode_CancelBstrWrap ( QCBOREncodeContext * pCtx)

Cancel byte string wrapping.

Parameters
[in]pCtxThe encoding context.

This cancels QCBOREncode_BstrWrap() making the encoding as if it were never called.

WARNING: This does not work on QCBOREncode_BstrWrapInMapSZ() 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 QCBOR_ERR_CANNOT_CANCEL.

◆ QCBOREncode_CloseArray()

void QCBOREncode_CloseArray ( QCBOREncodeContext * pCtx)
inlinestatic

Close an open array.

Parameters
[in]pCtxThe 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 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, QCBOR_ERR_CLOSE_MISMATCH will be returned when QCBOREncode_Finish() is called.

◆ QCBOREncode_CloseArrayIndefiniteLength()

void QCBOREncode_CloseArrayIndefiniteLength ( QCBOREncodeContext * pCtx)
inlinestatic

Close an open indefinite length array.

Parameters
[in]pCtxThe 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.

◆ QCBOREncode_CloseBstrWrap2()

void QCBOREncode_CloseBstrWrap2 ( QCBOREncodeContext * pCtx,
bool bIncludeCBORHead,
UsefulBufC * pWrappedCBOR )

Close a wrapping bstr.

Parameters
[in]pCtxThe encoding context to close of bstr wrapping in.
[in]bIncludeCBORHeadInclude the encoded CBOR head of the bstr as well as the bytes in pWrappedCBOR.
[out]pWrappedCBORA 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 *pWrappedCBOR if it is not NULL. The main purpose of this is so this data can be hashed (e.g., with SHA-256) as part of a [RFC 9052, COSE] (https://www.rfc-editor.org/rfc/rfc9052.html) implementation. WARNING, this pointer and length should be used right away before any other calls to 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 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, 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 bIncludeCBORHead true.

◆ QCBOREncode_CloseBytes()

void QCBOREncode_CloseBytes ( QCBOREncodeContext * pCtx,
size_t uAmount )

Close out a byte string written directly to encoded output.

Parameters
[in]pCtxThe encoding context to add the bytes to.
[out]uAmountThe 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 QCBOR_ERR_TOO_MANY_CLOSES is set.

◆ QCBOREncode_CloseMap()

void QCBOREncode_CloseMap ( QCBOREncodeContext * pCtx)
inlinestatic

Close an open map.

Parameters
[in]pCtxThe 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 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, QCBOR_ERR_CLOSE_MISMATCH will be returned when QCBOREncode_Finish() is called.

◆ QCBOREncode_CloseMapIndefiniteLength()

void QCBOREncode_CloseMapIndefiniteLength ( QCBOREncodeContext * pCtx)
inlinestatic

Close an open indefinite length map.

Parameters
[in]pCtxThe 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.

◆ QCBOREncode_EncodeHead()

UsefulBufC QCBOREncode_EncodeHead ( UsefulBuf Buffer,
uint8_t uMajorType,
uint8_t uMinLen,
uint64_t uNumber )

Encode the head of a CBOR data item.

Parameters
BufferBuffer to output the encoded head to; must be QCBOR_HEAD_BUFFER_SIZE bytes in size.
uMajorTypeOne of CBOR_MAJOR_TYPE_XX.
uMinLenThe 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.
uNumberThe numeric argument part of the CBOR head.
Returns
Pointer and length of the encoded head or 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 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 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.

◆ QCBOREncode_Finish()

QCBORError QCBOREncode_Finish ( QCBOREncodeContext * pCtx,
UsefulBufC * pEncodedCBOR )

Get the encoded result.

Parameters
[in]pCtxThe context to finish encoding with.
[out]pEncodedCBORStructure in which the pointer and length of the encoded CBOR is returned.
Return values
QCBOR_SUCCESSEncoded CBOR is returned.
QCBOR_ERR_TOO_MANY_CLOSESNesting error
QCBOR_ERR_CLOSE_MISMATCHNesting error
QCBOR_ERR_ARRAY_OR_MAP_STILL_OPENNesting error
QCBOR_ERR_BUFFER_TOO_LARGEEncoded output buffer size
QCBOR_ERR_BUFFER_TOO_SMALLEncoded output buffer size
QCBOR_ERR_ARRAY_NESTING_TOO_DEEPImplementation limit
QCBOR_ERR_ARRAY_TOO_LONGImplementation limit

On success, the pointer and length of the encoded CBOR are returned in *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 NULL was passed for Storage.ptr when QCBOREncode_Init() was called, 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 QCBOREncode_OpenXxx() calls do not match the number 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. 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 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 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(). See QCBOREncode_SubString() for a means to get the thus-far-encoded CBOR.

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.

◆ QCBOREncode_FinishGetSize()

QCBORError QCBOREncode_FinishGetSize ( QCBOREncodeContext * pCtx,
size_t * uEncodedLen )

Get the encoded CBOR and error status.

Parameters
[in]pCtxThe context to finish encoding with.
[out]uEncodedLenThe length of the encoded or potentially encoded CBOR in bytes.
Returns
The same errors as QCBOREncode_Finish().

This functions the same as QCBOREncode_Finish(), but only returns the size of the encoded output.

◆ QCBOREncode_GetErrorState()

QCBORError QCBOREncode_GetErrorState ( QCBOREncodeContext * pCtx)
inlinestatic

Get the encoding error state.

Parameters
[in]pCtxThe encoding context.
Returns
One of 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.

◆ QCBOREncode_Init()

void QCBOREncode_Init ( QCBOREncodeContext * pCtx,
UsefulBuf Storage )

Initialize the encoder.

Parameters
[in,out]pCtxThe encoder context to initialize.
[in]StorageThe 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 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 SizeCalculateUsefulBuf for 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 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 QCBOREncodeContext can be reused over and over as long as QCBOREncode_Init() is called before each use.

◆ QCBOREncode_IsBufferNULL()

int QCBOREncode_IsBufferNULL ( QCBOREncodeContext * pCtx)
inlinestatic

Indicate whether the output storage buffer is NULL.

Parameters
[in]pCtxThe encoding context.
Returns
1 if the output buffer is NULL.

As described in QCBOREncode_Init(), Storage.ptr may be give as NULL for output size calculation. This returns 1 when that is the true, and 0 if not.

◆ QCBOREncode_OpenArray()

void QCBOREncode_OpenArray ( QCBOREncodeContext * pCtx)
inlinestatic

Indicates that the next items added are in an array.

Parameters
[in]pCtxThe 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 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 QCBOR_MAX_ARRAY_NESTING. This is the max number of times this can be called without calling QCBOREncode_CloseArray(). QCBOREncode_Finish() will return 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 QCBOR_MAX_ITEMS_IN_ARRAY items to a single array or map, 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.

◆ QCBOREncode_OpenArrayIndefiniteLength()

void QCBOREncode_OpenArrayIndefiniteLength ( QCBOREncodeContext * pCtx)
inlinestatic

Indicates that the next items added are in an indefinite length array.

Parameters
[in]pCtxThe 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().

◆ QCBOREncode_OpenBytes()

void QCBOREncode_OpenBytes ( QCBOREncodeContext * pCtx,
UsefulBuf * pPlace )

Set up to write a byte string value directly to encoded output.

Parameters
[in]pCtxThe encoding context to add the bytes to.
[out]pPlacePointer 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 pPlace is where to start writing. Writing is just copying bytes to the location by the pointer in pPlace. Writing past the length in pPlace will be writing off the end of the output buffer.

If there is no room in the output buffer 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.

◆ QCBOREncode_OpenMap()

void QCBOREncode_OpenMap ( QCBOREncodeContext * pCtx)
inlinestatic

Indicates that the next items added are in a map.

Parameters
[in]pCtxThe 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 QCBOREncode_AddXxx() call has one version that ends with InMap for adding items to maps with string labels and one that ends with 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://www.rfc-editor.org/rfc/rfc8949.html) for a lot more information on creating maps.

◆ QCBOREncode_OpenMapIndefiniteLength()

void QCBOREncode_OpenMapIndefiniteLength ( QCBOREncodeContext * pCtx)
inlinestatic

Indicates that the next items added are in an indefinite length map.

Parameters
[in]pCtxThe 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().

◆ QCBOREncode_Private_AddType7()

void QCBOREncode_Private_AddType7 ( QCBOREncodeContext * pMe,
const uint8_t uMinLen,
const uint64_t uArgument )
inlinestatic

Semi-private method to add simple items and floating-point.

Parameters
[in]pMeThe encoding context.
[in]uMinLenMinimum encoding size for uNum. Usually 0.
[in]uArgumentThe value to add.

This is used to add simple types like true and false and float-point values, both of which are type 7.

Call QCBOREncode_AddBool(), QCBOREncode_AddNULL(), QCBOREncode_AddUndef() QCBOREncode_AddDouble() instead of this.

Error handling is the same as QCBOREncode_AddInt64().

◆ QCBOREncode_RetrieveOutputStorage()

UsefulBuf QCBOREncode_RetrieveOutputStorage ( QCBOREncodeContext * pCtx)
inlinestatic

Retrieve the storage buffer passed in to QCBOREncode_Init().

Parameters
[in]pCtxThe encoding context.
Returns
The output storage buffer passed to QCBOREncode_Init().

This doesn't give any information about how much has been encoded or the error state. It just returns the exact UsefulOutBuf given to QCBOREncode_Init().

◆ QCBOREncode_SubString()

UsefulBufC QCBOREncode_SubString ( QCBOREncodeContext * pCtx,
const size_t uStart )

Get a substring of encoded CBOR for cryptographic hash.

Parameters
[in]pCtxThe encoding context.
[in]uStartThe start offset of substring.
Returns
Pointer and length of of substring.

uStart is obtained by calling QCBOREncode_Tell() before encoding the first item in the substring. Then encode some data items. Then call this. The substring returned contains the encoded data items.

The substring may have deeply nested arrays and maps as long as any opened after the call to QCBOREncode_Tell() are closed before this is called.

This will return NULLUsefulBufC if the encoder is in the error state or if uStart is beyond the end of the thus-far encoded data items.

If uStart is 0, all the thus-far-encoded CBOR will be returned. Unlike QCBOREncode_Finish(), this will succeed even if some arrays and maps are not closed.

See important usage WARNING in QCBOREncode_Tell()

◆ QCBOREncode_Tell()

size_t QCBOREncode_Tell ( QCBOREncodeContext * pCtx)
inlinestatic

Returns current end of encoded data.

Parameters
[in]pCtxThe encoding context.
Returns
Byte offset of end of encoded data.

The purpose of this is to enable cryptographic hashing over a subpart of thus far CBOR-encoded data. Then perhaps a signature over the hashed CBOR is added to the encoded output. There is nothing specific to hashing or signing in this, so this can be used for other too.

Call this to get the offset of the start of the encoded to-be-hashed CBOR items, then call QCBOREncode_SubString(). QCBOREncode_Tell() can also be called twice, first to get the offset of the start and second for the offset of the end. Those offsets can be applied to the output storage buffer.

This will return successfully even if the encoder is in the error state.

WARNING: All definite-length arrays and maps opened before the first call to QCBOREncode_Tell() must not be closed until the substring is obtained and processed. Similarly, every definite-length array or map opened after the first call to QCBOREncode_Tell() must be closed before the substring is obtained and processed. The same applies for opened byte strings. There is no detection of these errors. This occurs because QCBOR goes back and inserts the lengths of definite-length arrays and maps when they are closed. This insertion will make the offsets incorrect.