/*============================================================================ qcbor_spiffy_decode.h -- higher-level easier-to-use CBOR decoding. Copyright (c) 2020-2021, Laurence Lundblade. All rights reserved. Copyright (c) 2021, Arm Limited. All rights reserved. SPDX-License-Identifier: BSD-3-Clause See BSD-3-Clause license in README.md Forked from qcbor_decode.h on 7/23/2020 ============================================================================*/ #ifndef qcbor_spiffy_decode_h #define qcbor_spiffy_decode_h #include "qcbor/qcbor_decode.h" #ifdef __cplusplus extern "C" { #if 0 } // Keep editor indention formatting happy #endif #endif /** @file qcbor_spiffy_decode.h @anchor SpiffyDecode # Spiffy Decode This section discusses spiffy decoding assuming familiarity with the general description of decoding in the @ref BasicDecode section. Spiffy decode is extra decode features over and above the @ref BasicDecode features that generally are easier to use, mirror the encoding functions better and can result in smaller code size for larger and more complex CBOR protocols. In particular, spiffy decode facilitates getting the next data item of a specific type, setting an error if it is not of that type. It facilitates explicitly entering and exiting arrays and maps. It facilates fetching items by label from a map including duplicate label detection. Encoded CBOR can be viewed to have a tree structure where the leaf nodes are non-aggregate types like integers and strings and the intermediate nodes are either arrays or maps. Fundamentally, all decoding is a pre-order traversal of the tree. Calling QCBORDecode_GetNext() repeatedly will perform this. This pre-order traversal gives natural decoding of arrays where the array members are taken in order, but does not give natural decoding of maps where access by label is usually preferred. Using the QCBORDecode_EnterMap() and QCBORDecode_GetXxxxInMapX() methods like QCBORDecode_GetInt64InMapN(), map items can be accessed by label. QCBORDecode_EnterMap() bounds decoding to a particular map. QCBORDecode_GetXxxxInMapX() methods allows decoding the item of a particular label in the particular map. This can be used with nested maps by using QCBORDecode_EnterMapFromMapX(). When QCBORDecode_EnterMap() is called, pre-order traversal continues to work. There is a cursor that is run over the tree with calls to QCBORDecode_GetNext(). This can be intermixed with calls to QCBORDecode_GetXxxxInMapX(). The pre-order traversal is limited just to the map entered. Attempts to QCBORDecode_GetNext() beyond the end of the map will give the @ref QCBOR_ERR_NO_MORE_ITEMS error. There is also QCBORDecode_EnterArray() to decode arrays. It will narrow the traversal to the extent of the array entered. All the QCBORDecode_GetXxxxInMapX() methods support duplicate label detection and will result in an error if the map has duplicate labels. All the QCBORDecode_GetXxxxInMapX() methods are implemented by performing the pre-order traversal of the map to find the labeled item everytime it is called. It doesn't build up a hash table, a binary search tree or some other efficiently searchable structure internally. For simple trees this is fine and for high-speed CPUs this is fine, but for complex trees on slow CPUs, it may have performance issues (these have not be quantified yet). One way ease this is to use QCBORDecode_GetItemsInMap() which allows decoding of a list of items expected in an map in one traveral. @anchor Tag-Usage ## Tag Usage Data types beyond the basic CBOR types of numbers, strings, maps and arrays are called tags. The main registry of these new types is in in the IANA CBOR tags registry. These new types may be simple such a number that is to be interpreted as a date, or of moderate complexity such as defining a decimal fraction that is an array containing a mantissa and exponent, or complex such as format for signing and encryption. When a tag occurs in a protocol it is encoded as an integer tag number plus the content of the tag. The content format of a tag may also be "borrowed". For example, a protocol definition may say that a particular data item is an epoch date just like tag 1, but not actually tag 1. In practice the difference is the presence or absence of the integer tag number in the encoded CBOR. The decoding functions for these new types takes a tag requirement parameter to say whether the item is a tag, is just borrowing the content format and is not a tag, or whether either is OK. If the parameter indicates the item must be a tag (@ref QCBOR_TAG_REQUIREMENT_TAG), then @ref QCBOR_ERR_UNEXPECTED_TYPE is set if it is not one of the expected tag types. To decode correctly the contents of the tag must also be of the correct type. For example, to decode an epoch date tag the content must be an integer or floating-point value. If the parameter indicates it should not be a tag (@ref QCBOR_TAG_REQUIREMENT_NOT_A_TAG), then @ref QCBOR_ERR_UNEXPECTED_TYPE set if it is a tag or the type of the encoded CBOR is not what is expected. In the example of an epoch date, the data type must be an integer or floating-point value. This is the case where the content format of a tag is borrowed. The parameter can also indicate that either a tag or no tag is allowed ( @ref QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG ). A good protocol design should however be clear and choose one or the other and not need this option. This is a way to implement "be liberal in what you accept", however these days that is less in favor. See https://tools.ietf.org/id/draft-thomson-postel-was-wrong-03.html. Map searching works with indefinite length strings. A string allocator must be set up the same as for any handling of indefinite length strings. However, It currently over-allocates memory from the string pool and thus requires a much larger string pool than it should. The over-allocation happens every time a map is searched by label. (This may be corrected in the future). */ /** The data item must be a tag of the expected type. It is an error if it is not. For example when calling QCBORDecode_GetEpochDate(), the data item must be an @ref CBOR_TAG_DATE_EPOCH tag. See @ref Tag-Usage. */ #define QCBOR_TAG_REQUIREMENT_TAG 0 /** The data item must be of the type expected for content data type being fetched. It is an error if it is not. For example, when calling QCBORDecode_GetEpochDate() and it must not be an @ref CBOR_TAG_DATE_EPOCH tag. See @ref Tag-Usage. */ #define QCBOR_TAG_REQUIREMENT_NOT_A_TAG 1 /** Either of the above two are allowed. This allows implementation of being liberal in what you receive, but it is better if CBOR-based protocols pick one and stick to and not required the reciever to take either. See @ref Tag-Usage. */ #define QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG 2 /** Add this into the above value if other tags not processed by QCBOR are to be allowed to surround the data item. See @ref Tag-Usage. */ #define QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS 0x80 /** Conversion will proceed if the CBOR item to be decoded is an integer or either type 0 (unsigned) or type 1 (negative). */ #define QCBOR_CONVERT_TYPE_XINT64 0x01 /** Conversion will proceed if the CBOR item to be decoded is either double, single or half-precision floating-point (major type 7). */ #define QCBOR_CONVERT_TYPE_FLOAT 0x02 /** Conversion will proceed if the CBOR item to be decoded is a big number, positive or negative (tag 2 or tag 3). */ #define QCBOR_CONVERT_TYPE_BIG_NUM 0x04 /** Conversion will proceed if the CBOR item to be decoded is a decimal fraction (tag 4). */ #define QCBOR_CONVERT_TYPE_DECIMAL_FRACTION 0x08 /** Conversion will proceed if the CBOR item to be decoded is a big float (tag 5). */ #define QCBOR_CONVERT_TYPE_BIGFLOAT 0x10 /** @brief Decode next item into a signed 64-bit integer. @param[in] pCtx The decode context. @param[out] pnValue The returned 64-bit signed integer. The CBOR data item to decode must be a positive or negative integer (CBOR major type 0 or 1). If not @ref QCBOR_ERR_UNEXPECTED_TYPE is set. If the CBOR integer is either too large or too small to fit in an int64_t, the error @ref QCBOR_ERR_INT_OVERFLOW or @ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW is set. Note that type 0 unsigned integers can be larger than will fit in an int64_t and type 1 negative integers can be smaller than will fit in an int64_t. Please see @ref Decode-Errors-Overview "Decode Errors Overview". See also QCBORDecode_GetUInt64(), QCBORDecode_GetInt64Convert() and QCBORDecode_GetInt64ConvertAll(). */ static void QCBORDecode_GetInt64(QCBORDecodeContext *pCtx, int64_t *pnValue); static void QCBORDecode_GetInt64InMapN(QCBORDecodeContext *pCtx, int64_t nLabel, int64_t *pnValue); static void QCBORDecode_GetInt64InMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, int64_t *pnValue); /** @brief Decode next item into a signed 64-bit integer with basic conversions. @param[in] pCtx The decode context. @param[in] uConvertTypes The integer conversion options. @param[out] pnValue The returned 64-bit signed integer. @c uConvertTypes controls what conversions this will perform and thus what CBOR types will be decoded. @c uConvertType is a bit map listing the conversions to be allowed. This function supports @ref QCBOR_CONVERT_TYPE_XINT64 and @ref QCBOR_CONVERT_TYPE_FLOAT conversions. Please see @ref Decode-Errors-Overview "Decode Errors Overview". If the CBOR data type can never be convered by this function or the conversion was not selected in @c uConversionTypes @ref @ref QCBOR_ERR_UNEXPECTED_TYPE is set. When converting floating-point values, the integer is rounded to the nearest integer using llround(). By default, floating-point suport is enabled for QCBOR. If floating-point HW use is disabled this will set @ref QCBOR_ERR_HW_FLOAT_DISABLED if a single-precision number is encountered. If half-precision support is disabled, this will set QCBOR_ERR_HALF_PRECISION_DISABLED if a half-precision number is encountered. If floating-point usage is disabled this will set @ref QCBOR_ERR_ALL_FLOAT_DISABLED if a floating point value is encountered. See also QCBORDecode_GetInt64ConvertAll() which will perform the same conversions as this and a lot more at the cost of adding more object code to your executable. */ static void QCBORDecode_GetInt64Convert(QCBORDecodeContext *pCtx, uint32_t uConvertTypes, int64_t *pnValue); static void QCBORDecode_GetInt64ConvertInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint32_t uConvertTypes, int64_t *pnValue); static void QCBORDecode_GetInt64ConvertInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint32_t uConvertTypes, int64_t *pnValue); /** @brief Decode next item into a signed 64-bit integer with conversions. @param[in] pCtx The decode context. @param[in] uConvertTypes The integer conversion options. @param[out] pnValue The returned 64-bit signed integer. This is the same as QCBORDecode_GetInt64Convert() but additionally supports conversion from positive and negative bignums, decimal fractions and big floats, including decimal fractions and big floats that use bignums. The conversion types supported are @ref QCBOR_CONVERT_TYPE_XINT64, @ref QCBOR_CONVERT_TYPE_FLOAT, @ref QCBOR_CONVERT_TYPE_BIG_NUM, @ref QCBOR_CONVERT_TYPE_DECIMAL_FRACTION and @ref QCBOR_CONVERT_TYPE_BIGFLOAT. Please see @ref Decode-Errors-Overview "Decode Errors Overview". Note that most these types can support numbers much larger that can be represented by in a 64-bit integer, so @ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW may often be encountered. When converting bignums and decimal fractions @ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will be set if the result is below 1, unless the mantissa is zero, in which case the coversion is successful and the value of 0 is returned. See also QCBORDecode_GetInt64ConvertAll() which does some of these conversions, but links in much less object code. See also QCBORDecode_GetUInt64ConvertAll(). */ void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pCtx, uint32_t uConvertTypes, int64_t *pnValue); void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint32_t uConvertTypes, int64_t *pnValue); void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint32_t uConvertTypes, int64_t *pnValue); /** @brief Decode next item into an unsigned 64-bit integer. @param[in] pCtx The decode context. @param[out] puValue The returned 64-bit unsigned integer. This is the same as QCBORDecode_GetInt64(), but returns an unsigned integer and thus can only decode CBOR positive integers. @ref QCBOR_ERR_NUMBER_SIGN_CONVERSION is set if the input is a negative integer. Please see @ref Decode-Errors-Overview "Decode Errors Overview". See also QCBORDecode_GetUInt64Convert() and QCBORDecode_GetUInt64ConvertAll(). */ static void QCBORDecode_GetUInt64(QCBORDecodeContext *pCtx, uint64_t *puValue); static void QCBORDecode_GetUInt64InMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint64_t *puValue); static void QCBORDecode_GetUInt64InMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint64_t *puValue); /** @brief Decode next item as an unsigned 64-bit integer with basic conversions. @param[in] pCtx The decode context. @param[in] uConvertTypes The integer conversion options. @param[out] puValue The returned 64-bit unsigned integer. This is the same as QCBORDecode_GetInt64Convert(), but returns an unsigned integer and thus sets @ref QCBOR_ERR_NUMBER_SIGN_CONVERSION is set if the value to be decoded is negatve. If floating-point HW use is disabled this will set @ref QCBOR_ERR_HW_FLOAT_DISABLED if a single-precision number is encountered. If half-precision support is disabled, this will set QCBOR_ERR_HALF_PRECISION_DISABLED if a half-precision number is encountered. If floating-point usage is disabled this will set @ref QCBOR_ERR_ALL_FLOAT_DISABLED if a floating point value is encountered. See also QCBORDecode_GetUInt64Convert() and QCBORDecode_GetUInt64ConvertAll(). */ static void QCBORDecode_GetUInt64Convert(QCBORDecodeContext *pCtx, uint32_t uConvertTypes, uint64_t *puValue); static void QCBORDecode_GetUInt64ConvertInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint32_t uConvertTypes, uint64_t *puValue); static void QCBORDecode_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint32_t uConvertTypes, uint64_t *puValue); /** @brief Decode next item into an unsigned 64-bit integer with conversions @param[in] pCtx The decode context. @param[in] uConvertTypes The integer conversion options. @param[out] puValue The returned 64-bit unsigned integer. This is the same as QCBORDecode_GetInt64ConvertAll(), but returns an unsigned integer and thus sets @ref QCBOR_ERR_NUMBER_SIGN_CONVERSION if the value to be decoded is negatve. See also QCBORDecode_GetUInt64() and QCBORDecode_GetUInt64Convert(). */ void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pCtx, uint32_t uConvertTypes, uint64_t *puValue); void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint32_t uConvertTypes, uint64_t *puValue); void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint32_t uConvertTypes, uint64_t *puValue); /** @brief Decode the next item as a byte string @param[in] pCtx The decode context @param[out] pBytes The decoded byte string The CBOR item to decode must be a byte string, CBOR type 2. Please see @ref Decode-Errors-Overview "Decode Errors Overview". If the CBOR item to decode is not a byte string, the @ref QCBOR_ERR_UNEXPECTED_TYPE error is set. */ static void QCBORDecode_GetByteString(QCBORDecodeContext *pCtx, UsefulBufC *pBytes); static void QCBORDecode_GetByteStringInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, UsefulBufC *pBytes); static void QCBORDecode_GetByteStringInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, UsefulBufC *pBytes); /** @brief Decode the next item as a text string. @param[in] pCtx The decode context. @param[out] pText The decoded byte string. The CBOR item to decode must be a text string, CBOR type 3. Please see @ref Decode-Errors-Overview "Decode Errors Overview". It the CBOR item to decode is not a text string, the @ref QCBOR_ERR_UNEXPECTED_TYPE error is set. This does no translation of line endings. See QCBOREncode_AddText() for a discussion of line endings in CBOR. */ static void QCBORDecode_GetTextString(QCBORDecodeContext *pCtx, UsefulBufC *pText); static void QCBORDecode_GetTextStringInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, UsefulBufC *pText); static void QCBORDecode_GetTextStringInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, UsefulBufC *pText); #ifndef USEFULBUF_DISABLE_ALL_FLOAT /** @brief Decode next item into a double floating-point value. @param[in] pCtx The decode context @param[out] pValue The returned floating-point value. The CBOR data item to decode must be a half-precision, single-precision or double-precision floating-point value. If not @ref QCBOR_ERR_UNEXPECTED_TYPE is set. If floating-point HW use is disabled this will set @ref QCBOR_ERR_HW_FLOAT_DISABLED if a single-precision number is encountered. If half-precision support is disabled, this will set QCBOR_ERR_HALF_PRECISION_DISABLED if a half-precision number is encountered. Please see @ref Decode-Errors-Overview "Decode Errors Overview". See also QCBORDecode_GetDoubleConvert() and QCBORDecode_GetDoubleConvertAll(). */ static void QCBORDecode_GetDouble(QCBORDecodeContext *pCtx, double *pValue); static void QCBORDecode_GetDoubleInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, double *pdValue); static void QCBORDecode_GetDoubleInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, double *pdValue); /** @brief Decode next item into a double floating-point value with basic conversion. @param[in] pCtx The decode context. @param[in] uConvertTypes The integer conversion options. @param[out] pdValue The returned floating-point value. This will decode CBOR integer and floating-point numbers, returning them as a double floating-point number. This function supports @ref QCBOR_CONVERT_TYPE_XINT64 and @ref QCBOR_CONVERT_TYPE_FLOAT conversions. If the encoded CBOR is not one of the requested types or a type not supported by this function, @ref QCBOR_ERR_UNEXPECTED_TYPE is set. Please see @ref Decode-Errors-Overview "Decode Errors Overview". If floating-point HW use is disabled this will set @ref QCBOR_ERR_HW_FLOAT_DISABLED if a single-precision number is encountered. If half-precision support is disabled, this will set QCBOR_ERR_HALF_PRECISION_DISABLED if a half-precision number is encountered. Positive and negative integers can always be converted to floating-point, so this will never error on CBOR major type 0 or 1. Note that a large 64-bit integer can have more precision (64 bits) than even a double floating-point (52 bits) value, so there is loss of precision in some conversions. See also QCBORDecode_GetDouble() and QCBORDecode_GetDoubleConvertAll(). */ static void QCBORDecode_GetDoubleConvert(QCBORDecodeContext *pCtx, uint32_t uConvertTypes, double *pdValue); static void QCBORDecode_GetDoubleConvertInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint32_t uConvertTypes, double *pdValue); static void QCBORDecode_GetDoubleConvertInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint32_t uConvertTypes, double *pdValue); /** @brief Decode next item as a double floating-point value with conversion. @param[in] pCtx The decode context. @param[in] uConvertTypes The integer conversion options. @param[out] pdValue The returned floating-point value. This is the same as QCBORDecode_GetDoubleConvert() but supports many more conversions at the cost of linking in more object code. The conversion types supported are @ref QCBOR_CONVERT_TYPE_XINT64, @ref QCBOR_CONVERT_TYPE_FLOAT, @ref QCBOR_CONVERT_TYPE_BIG_NUM, @ref QCBOR_CONVERT_TYPE_DECIMAL_FRACTION and @ref QCBOR_CONVERT_TYPE_BIGFLOAT. Big numbers, decimal fractions and big floats that are too small or too large to be reprented as a double floating-point number will be returned as plus or minus zero or infinity rather than setting an under or overflow error. There is often loss of precision in the conversion. See also QCBORDecode_GetDoubleConvert() and QCBORDecode_GetDoubleConvert(). */ void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pCtx, uint32_t uConvertTypes, double *pdValue); void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint32_t uConvertTypes, double *pdValue); void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint32_t uConvertTypes, double *pdValue); #endif /* USEFULBUF_DISABLE_ALL_FLOAT */ /** @brief Enter an array for decoding in bounded mode. @param[in] pCtx The decode context. @param[out] pItem The optionally returned QCBORItem that has the label and tags for the array. May be @c NULL (and usually is). This enters an array for decoding in bounded mode. The items in array are decoded in order the same as when not in bounded mode, but the decoding will not proceed past the end or the array. The error @ref QCBOR_ERR_NO_MORE_ITEMS will be set when the end of the array is encountered. To decode past the end of the array, QCBORDecode_ExitArray() must be called. Also, QCBORDecode_Finish() will return an error if all arrays that were enetered are not exited. This works the same for definite and indefinite length arrays. Please see @ref Decode-Errors-Overview "Decode Errors Overview". If attempting to enter a data item that is not an array @ref QCBOR_ERR_UNEXPECTED_TYPE wil be set. Nested arrays and maps may be entered to a depth of @ref QCBOR_MAX_ARRAY_NESTING. See also QCBORDecode_ExitArray(), QCBORDecode_EnterMap() and QCBORDecode_EnterBstrWrapped(). */ static void QCBORDecode_EnterArray(QCBORDecodeContext *pCtx, QCBORItem *pItem); void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t uLabel); void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel); /** @brief Exit an array that has been enetered. @param[in] pCtx The decode context. An array must have been entered for this to succeed. The items in the array that was entered do not have to have been consumed for this to succeed. This sets the pre-order traversal cursor to the item after the array that was exited. This will result in an error if any item in the array is not well formed (since all items in the array must be decoded to find its end), or there are not enough items in the array. */ static void QCBORDecode_ExitArray(QCBORDecodeContext *pCtx); /** @brief Enter a map for decoding and searching. @param[in] pCtx The decode context. @param[out] pItem The optionally returned QCBORItem that has the label and tags for the map. May be @c NULL (and usually is). The next item in the CBOR input must be map or this sets an error. This puts the decoder in bounded mode which narrows decoding to the map entered and enables getting items by label. All items in the map must be well-formed to be able to search it by label because a full traversal is done for each search. If not, the search will retun an error for the item that is not well-formed. This will be the first non-well-formed item which may not be the item with the label that is the target of the search. Nested maps can be decoded like this by entering each map in turn. Call QCBORDecode_ExitMap() to exit the current map decoding level. When all map decoding layers are exited then bounded mode is fully exited. While in bounded mode, QCBORDecode_GetNext() works as usual on the map and the in-order traversal cursor is maintained. It starts out at the first item in the map just entered. Attempts to get items off the end of the map will give error @ref QCBOR_ERR_NO_MORE_ITEMS rather going to the next item after the map as it would when not in bounded mode. Exiting leaves the pre-order cursor at the data item following the last entry in the map or at the end of the input CBOR if there nothing after the map. Entering and Exiting a map is a way to skip over an entire map and its contents. After QCBORDecode_ExitMap(), the pre-order traversal cursor will be at the first item after the map. Please see @ref Decode-Errors-Overview "Decode Errors Overview". See also QCBORDecode_EnterArray() and QCBORDecode_EnterBstrWrapped(). Entering and exiting any nested combination of maps, arrays and bstr-wrapped CBOR is supported up to the maximum of @ref QCBOR_MAX_ARRAY_NESTING. */ static void QCBORDecode_EnterMap(QCBORDecodeContext *pCtx, QCBORItem *pItem); void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pCtx, int64_t nLabel); void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pCtx, const char *szLabel); /** @brief Exit a map that has been enetered. @param[in] pCtx The decode context. A map must have been entered for this to succeed. The items in the map that was entered do not have to have been consumed for this to succeed. This sets the pre-order traversal cursor to the item after the map that was exited. This will result in an error if any item in the map is not well formed (since all items in the map must be decoded to find its end), or there are not enough items in the map. */ static void QCBORDecode_ExitMap(QCBORDecodeContext *pCtx); /** @brief Reset traversal cursor to start of map, array, byte-string wrapped CBOR or start of input. @param[in] pCtx The decode context. If an array, map or wrapping byte string has been entered this sets the traversal cursor to its beginning. If several arrays, maps or byte strings have been entered, this sets the traversal cursor to the beginning of the one most recently entered. If no map or array has been entered, this resets the traversal cursor to the beginning of the input CBOR. This also resets the error state. */ void QCBORDecode_Rewind(QCBORDecodeContext *pCtx); /** @brief Get an item in map by label and type. @param[in] pCtx The decode context. @param[in] nLabel The integer label. @param[in] uQcborType The QCBOR type. One of @c QCBOR_TYPE_XXX. @param[out] pItem The returned item. A map must have been entered to use this. If not @ref QCBOR_ERR_MAP_NOT_ENTERED is set. The map is searched for an item of the requested label and type. @ref QCBOR_TYPE_ANY can be given to search for the label without matching the type. This will always search the entire map. This will always perform duplicate label detection, setting @ref QCBOR_ERR_DUPLICATE_LABEL if there is more than one occurance of the label being searched for. Duplicate label detection is performed for the item being sought, but only for the item being sought. This performs a full decode of every item in the map being searched, which involves a full traversal of every item. For maps with little nesting, this is of little consequence, but may be of consequence for large deeply nested CBOR structures on slow CPUs. The position of the pre-order traversal cursor is not changed. Please see @ref Decode-Errors-Overview "Decode Errors Overview". See also QCBORDecode_GetItemsInMap() for error discussion. */ void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint8_t uQcborType, QCBORItem *pItem); void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint8_t uQcborType, QCBORItem *pItem); /** @brief Get a group of labeled items all at once from a map @param[in] pCtx The decode context. @param[in,out] pItemList On input the items to search for. On output the returned items. This gets several labeled items out of a map. @c pItemList is an array of items terminated by an item with @c uLabelType @ref QCBOR_TYPE_NONE. On input the labels to search for are in the @c uLabelType and label fields in the items in @c pItemList. Also on input are the requested QCBOR types in the field @c uDataType. To match any type, searching just by label, @c uDataType can be @ref QCBOR_TYPE_ANY. This is a CPU-efficient way to decode a bunch of items in a map. It is more efficient than scanning each individually because the map only needs to be traversed once. This will return maps and arrays that are in the map, but provides no way to descend into and decode them. Use QCBORDecode_EnterMapinMapN(), QCBORDecode_EnterArrayInMapN() and such to descend into and process maps and arrays. The position of the pre-order traversal cursor is not changed. Please see @ref Decode-Errors-Overview "Decode Errors Overview". The following errors are set: @ref QCBOR_ERR_MAP_NOT_ENTERED when calling this without previousl calling QCBORDecode_EnterMap() or other methods to enter a map. @ref QCBOR_ERR_DUPLICATE_LABEL when one of the labels being searched for is duplicate. @ref QCBOR_ERR_HIT_END or other errors classifed as not-well-formed by QCBORDecode_IsNotWellFormed() as it is not possible to traverse maps that have any non-well formed items. @ref QCBOR_ERR_UNEXPECTED_TYPE when the type of an item found by matching a label is not the type requested. @ref QCBOR_ERR_ARRAY_NESTING_TOO_DEEP and other implementation limit errors as it is not possible to travere a map beyond the limits of the implementation. The error may occur on items that are not being searched for. For example, it is impossible to traverse over a map that has an array in it that is not closed or over array and map nesting deeper than this implementation can track. See also QCBORDecode_GetItemInMapN(). */ void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList); /** @brief Per-item callback for map searching. @param[in] pCallbackCtx Pointer to the caller-defined context for the callback @param[in] pItem The item from the map. The error set is intended for QCBOR errors, not general protocol decoding errors. If this sets other than @ref QCBOR_SUCCESS, the search will stop and the value it returns will be set in QCBORDecode_GetItemsInMapWithCallback(). The special error, @ref QCBOR_ERR_CALLBACK_FAIL, can be returned to indicate some protocol processing error that is not a CBOR error. The specific details of the protocol processing error can be returned the call back context. */ typedef QCBORError (*QCBORItemCallback)(void *pCallbackCtx, const QCBORItem *pItem); /** @brief Get a group of labeled items all at once from a map with a callback @param[in] pCtx The decode context. @param[in,out] pItemList On input the items to search for. On output the returned items. @param[in,out] pCallbackCtx Pointer to a context structure for @ref QCBORItemCallback @param[in] pfCB pointer to function of type @ref QCBORItemCallback that is called on unmatched items. This searchs a map like QCBORDecode_GetItemsInMap(), but calls a callback on items not matched rather than ignoring them. If @c pItemList is empty, the call back will be called on every item in the map. Like QCBORDecode_GetItemsInMap(), this only matches and calls back on the items at the top level of the map entered. Items in nested maps and arrays are skipped over and not candidate for matching or the callback. See QCBORItemCallback() for error handling. */ void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx, QCBORItem *pItemList, void *pCallbackCtx, QCBORItemCallback pfCB); /** @brief Decode the next item as a Boolean. @param[in] pCtx The decode context. @param[out] pbBool The decoded byte string. The CBOR item to decode must be either the CBOR simple value (CBOR type 7) @c true or @c false. Please see @ref Decode-Errors-Overview "Decode Errors Overview". If the CBOR item to decode is not true or false the @ref QCBOR_ERR_UNEXPECTED_TYPE error is set. */ void QCBORDecode_GetBool(QCBORDecodeContext *pCtx, bool *pbBool); void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, bool *pbBool); void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, bool *pbBool); /** @brief Decode the next item as a null. @param[in] pCtx The decode context. The CBOR item to decode must be the CBOR simple value (CBOR type 7) @c null. The reason to call this is to see if an error is returned or not indicating whether the item is a CBOR null. If it is not then the @ref QCBOR_ERR_UNEXPECTED_TYPE error is set. */ static void QCBORDecode_GetNull(QCBORDecodeContext *pCtx); static void QCBORDecode_GetNullInMapN(QCBORDecodeContext *pCtx, int64_t nLabel); static void QCBORDecode_GetNullInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel); /** @brief Decode the next item as a CBOR "undefined" item. @param[in] pCtx The decode context. The CBOR item to decode must be the CBOR simple value (CBOR type 7) @c undefined. The reason to call this is to see if an error is returned or not indicating whether the item is a CBOR undefed item. If it is not then the @ref QCBOR_ERR_UNEXPECTED_TYPE error is set. */ static void QCBORDecode_GetUndefined(QCBORDecodeContext *pCtx); static void QCBORDecode_GetUndefinedInMapN(QCBORDecodeContext *pCtx, int64_t nLabel); static void QCBORDecode_GetUndefinedInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel); /** @brief Decode the next item as a date string. @param[in] pCtx The decode context. @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX. @param[out] pDateString The decoded date. This decodes the standard CBOR date/time string tag, integer tag number of 0, or encoded CBOR that is not a tag, but borrows the date string content format. Please see @ref Decode-Errors-Overview "Decode Errors Overview". See @ref Tag-Usage for discussion on tag requirements. See also @ref CBOR_TAG_DATE_STRING, QCBOREncode_AddDateString() and @ref QCBOR_TYPE_DATE_STRING. */ static void QCBORDecode_GetDateString(QCBORDecodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC *pDateString); static void QCBORDecode_GetDateStringInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pDateString); static void QCBORDecode_GetDateStringInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pDateString); /** @brief Decode the next item as a date-only string. @param[in] pCtx The decode context. @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX. @param[out] pDateString The decoded date. This decodes the CBOR date-only string tag, integer tag number of 1004, or encoded CBOR that is not a tag, but borrows the date-only string content format. An example of the format is "1985-04-12". Please see @ref Decode-Errors-Overview "Decode Errors Overview". See @ref Tag-Usage for discussion on tag requirements. See also @ref CBOR_TAG_DAYS_STRING, QCBOREncode_AddDaysString() and @ref QCBOR_TYPE_DAYS_STRING. */ static void QCBORDecode_GetDaysString(QCBORDecodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC *pDateString); static void QCBORDecode_GetDaysStringInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pDateString); static void QCBORDecode_GetDaysStringInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pDateString); /** @brief Decode the next item as an epoch date. @param[in] pCtx The decode context. @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX. @param[out] pnTime The decoded epoch date. This decodes the standard CBOR epoch date/time tag, integer tag number of 1. This will also decode any integer or floating-point number as an epoch date (a tag 1 epoch date is just an integer or floating-point number). This will set @ref QCBOR_ERR_DATE_OVERFLOW if the input integer will not fit in an @c int64_t. Note that an @c int64_t can represent a range of over 500 billion years with one second resolution. Floating-point dates are always returned as an @c int64_t. The fractional part is discarded. If the input is a floating-point date and the QCBOR library is compiled with some or all floating-point features disabled, the following errors will be set. If the input is half-precision and half-precision is disabled @ref QCBOR_ERR_HALF_PRECISION_DISABLED is set. This function needs hardware floating-point to convert the floating-point value to an integer so if HW floating point is disabled QCBOR_ERR_HW_FLOAT_DISABLED is set. If all floating-point is disabled then @ref QCBOR_ERR_ALL_FLOAT_DISABLED is set. A previous version of this function would return @ref QCBOR_ERR_FLOAT_DATE_DISABLED in some, but not all, cases when floating-point decoding was disabled. Floating-point dates that are plus infinity, minus infinity or NaN (not-a-number) will result in the @ref QCBOR_ERR_DATE_OVERFLOW error. Please see @ref Decode-Errors-Overview "Decode Errors Overview". See @ref Tag-Usage for discussion on tag requirements. See also @ref CBOR_TAG_DATE_EPOCH, QCBOREncode_AddDateEpoch() and @ref QCBOR_TYPE_DATE_EPOCH. */ void QCBORDecode_GetEpochDate(QCBORDecodeContext *pCtx, uint8_t uTagRequirement, int64_t *pnTime); void QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, int64_t *pnTime); void QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint8_t uTagRequirement, int64_t *pnTime); /** @brief Decode the next item as an days-count epoch date. @param[in] pCtx The decode context. @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX. @param[out] pnDays The decoded epoch date. This decodes the CBOR epoch date tag, integer tag number of 100, or encoded CBOR that is not a tag, but borrows the content format. The date is the number of days (not number of seconds) before or after Jan 1, 1970. Please see @ref Decode-Errors-Overview "Decode Errors Overview". See @ref Tag-Usage for discussion on tag requirements. See also @ref CBOR_TAG_DAYS_EPOCH, QCBOREncode_AddTDaysEpoch() and @ref QCBOR_TYPE_DAYS_EPOCH. */ void QCBORDecode_GetEpochDays(QCBORDecodeContext *pCtx, uint8_t uTagRequirement, int64_t *pnDays); void QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, int64_t *pnDays); void QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint8_t uTagRequirement, int64_t *pnDays); /** @brief Decode the next item as a big number. @param[in] pCtx The decode context. @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX. @param[out] pValue The returned big number. @param[out] pbIsNegative Is @c true if the big number is negative. This is only valid when @c uTagRequirement is @ref QCBOR_TAG_REQUIREMENT_TAG. This decodes a standard CBOR big number, integer tag number of 2 or 3, or encoded CBOR that is not a tag, but borrows the content format. Please see @ref Decode-Errors-Overview "Decode Errors Overview". The big number is in network byte order. The first byte in @c pValue is the most significant byte. There may be leading zeros. The negative value is computed as -1 - n, where n is the postive big number in @c pValue. There is no standard representation for big numbers, positive or negative in C, so this implementation leaves it up to the caller to apply this computation for negative big numbers. See @ref Tag-Usage for discussion on tag requirements. Determination of the sign of the big number depends on the tag requirement of the protocol using the big number. If the protocol requires tagging, @ref QCBOR_TAG_REQUIREMENT_TAG, then the sign indication is in the protocol and @c pbIsNegative indicates the sign. If the protocol doesn't use a tag, @ref QCBOR_TAG_REQUIREMENT_NOT_A_TAG, then the protocol design must have some way of indicating the sign. See also QCBORDecode_GetInt64ConvertAll(), QCBORDecode_GetUInt64ConvertAll() and QCBORDecode_GetDoubleConvertAll() which can convert big numbers. See also @ref CBOR_TAG_POS_BIGNUM, @ref CBOR_TAG_NEG_BIGNUM, QCBOREncode_AddPositiveBignum(), QCBOREncode_AddNegativeBignum(), @ref QCBOR_TYPE_POSBIGNUM and @ref QCBOR_TYPE_NEGBIGNUM. */ // Improvement: Add function that converts integers and other to big nums void QCBORDecode_GetBignum(QCBORDecodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative); void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative); void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pValue, bool *pbIsNegative); #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA /** @brief Decode the next item as a decimal fraction. @param[in] pCtx The decode context. @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX. @param[out] pnMantissa The mantissa. @param[out] pnExponent The base 10 exponent. This decodes a standard CBOR decimal fraction, integer tag number of 4, or encoded CBOR that is not a tag, but borrows the content format. Please see @ref Decode-Errors-Overview "Decode Errors Overview". The value of this is computed by: mantissa * ( 10 ** exponent ) In the encoded CBOR, the mantissa and exponent may be of CBOR type 0 (positive integer), type 1 (negative integer), type 2 tag 2 (positive big number) or type 2 tag 3 (negative big number). This implementation will attempt to convert all of these to an @c int64_t. If the value won't fit, @ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW or QCBOR_ERR_BAD_EXP_AND_MANTISSA will be set. This implementation limits the exponent to between @c INT64_MIN and @c INT64_MAX while CBOR allows the range of @c -UINT64_MAX to @c UINT64_MAX. Various format and type issues will result in @ref QCBOR_ERR_BAD_EXP_AND_MANTISSA being set. See @ref Tag-Usage for discussion on tag requirements. See also QCBORDecode_GetInt64ConvertAll(), QCBORDecode_GetUInt64ConvertAll() and QCBORDecode_GetDoubleConvertAll() which can convert big numbers. See also @ref CBOR_TAG_DECIMAL_FRACTION, QCBOREncode_AddDecimalFraction(), @ref QCBOR_TYPE_DECIMAL_FRACTION and QCBORDecode_GetDecimalFractionBig(). */ void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pCtx, uint8_t uTagRequirement, int64_t *pnMantissa, int64_t *pnExponent); void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, int64_t *pnMantissa, int64_t *pnExponent); void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, int64_t *pnMantissa, int64_t *pnExponent); /** @brief Decode the next item as a decimal fraction with a big number mantissa. @param[in] pCtx The decode context. @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX. @param[in] MantissaBuffer The buffer in which to put the mantissa. @param[out] pMantissa The big num mantissa. @param[out] pbMantissaIsNegative Is @c true if @c pMantissa is negative. @param[out] pnExponent The base 10 exponent. This is the same as QCBORDecode_GetDecimalFraction() except the mantissa is returned as a big number. In the encoded CBOR, the mantissa may be a type 0 (positive integer), type 1 (negative integer), type 2 tag 2 (positive big number) or type 2 tag 3 (negative big number). This implementation will convert all these to a big number. The limit to this conversion is the size of @c MantissaBuffer. See also QCBORDecode_GetInt64ConvertAll(), QCBORDecode_GetUInt64ConvertAll() and QCBORDecode_GetDoubleConvertAll() which can convert decimal fractions. See also @ref CBOR_TAG_DECIMAL_FRACTION, QCBOREncode_AddDecimalFraction(), @ref QCBOR_TYPE_DECIMAL_FRACTION and QCBORDecode_GetDecimalFraction(). */ void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pCtx, uint8_t uTagRequirement, UsefulBuf MantissaBuffer, UsefulBufC *pMantissa, bool *pbMantissaIsNegative, int64_t *pnExponent); void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, UsefulBuf MantissaBuffer, UsefulBufC *pbMantissaIsNegative, bool *pbIsNegative, int64_t *pnExponent); void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint8_t uTagRequirement, UsefulBuf MantissaBuffer, UsefulBufC *pMantissa, bool *pbMantissaIsNegative, int64_t *pnExponent); /** @brief Decode the next item as a big float. @param[in] pCtx The decode context. @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX. @param[out] pnMantissa The mantissa. @param[out] pnExponent The base 2 exponent. This decodes a standard CBOR big float, integer tag number of 5, or encoded CBOR that is not a tag, but borrows the content format. This is the same as QCBORDecode_GetDecimalFraction() with the important distinction that the value is computed by: mantissa * ( 2 ** exponent ) See also QCBORDecode_GetInt64ConvertAll(), QCBORDecode_GetUInt64ConvertAll() and QCBORDecode_GetDoubleConvertAll() which can convert big floats. See also @ref CBOR_TAG_BIGFLOAT, QCBOREncode_AddBigFloat(), @ref QCBOR_TYPE_BIGFLOAT and QCBORDecode_GetBigFloatBig(). */ void QCBORDecode_GetBigFloat(QCBORDecodeContext *pCtx, uint8_t uTagRequirement, int64_t *pnMantissa, int64_t *pnExponent); void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, int64_t *pnMantissa, int64_t *pnExponent); void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint8_t uTagRequirement, int64_t *pnMantissa, int64_t *pnExponent); /** @brief Decode the next item as a big float with a big number mantissa. @param[in] pCtx The decode context. @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX. @param[in] MantissaBuffer The buffer in which to put the mantissa. @param[out] pMantissa The big num mantissa. @param[out] pbMantissaIsNegative Is @c true if @c pMantissa is negative. @param[out] pnExponent The base 2 exponent. This is the same as QCBORDecode_GetDecimalFractionBig() with the important distinction that the value is computed by: mantissa * ( 2 ** exponent ) See also QCBORDecode_GetInt64ConvertAll(), QCBORDecode_GetUInt64ConvertAll() and QCBORDecode_GetDoubleConvertAll() which can convert big floats. See also @ref CBOR_TAG_BIGFLOAT, QCBOREncode_AddBigFloat(), @ref QCBOR_TYPE_BIGFLOAT and QCBORDecode_GetBigFloat(). */ void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pCtx, uint8_t uTagRequirement, UsefulBuf MantissaBuffer, UsefulBufC *pMantissa, bool *pbMantissaIsNegative, int64_t *pnExponent); void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, UsefulBuf MantissaBuffer, UsefulBufC *pMantissa, bool *pbMantissaIsNegative, int64_t *pnExponent); void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint8_t uTagRequirement, UsefulBuf MantissaBuffer, UsefulBufC *pMantissa, bool *pbMantissaIsNegative, int64_t *pnExponent); #endif /* #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA */ /** @brief Decode the next item as a URI. @param[in] pCtx The decode context. @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX. @param[out] pURI The decoded URI. This decodes a standard CBOR URI tag, integer tag number of 32, or encoded CBOR that is not a tag, that is a URI encoded in a text string. Please see @ref Decode-Errors-Overview "Decode Errors Overview". See @ref Tag-Usage for discussion on tag requirements. See also @ref CBOR_TAG_URI, QCBOREncode_AddURI() and @ref QCBOR_TYPE_URI. */ static void QCBORDecode_GetURI(QCBORDecodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC *pURI); static void QCBORDecode_GetURIInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pURI); static void QCBORDecode_GetURIInMapSZ(QCBORDecodeContext *pCtx, const char * szLabel, uint8_t uTagRequirement, UsefulBufC *pURI); /** @brief Decode the next item as base64 encoded text. @param[in] pCtx The decode context. @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX. @param[out] pB64Text The decoded base64 text. This decodes a standard CBOR base64 tag, integer tag number of 34, or encoded CBOR that is not a tag, that is base64 encoded bytes encoded in a text string. Please see @ref Decode-Errors-Overview "Decode Errors Overview". See @ref Tag-Usage for discussion on tag requirements. Note that this does not actually remove the base64 encoding. See also @ref CBOR_TAG_B64, QCBOREncode_AddB64Text() and @ref QCBOR_TYPE_BASE64. */ static void QCBORDecode_GetB64(QCBORDecodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC *pB64Text); static void QCBORDecode_GetB64InMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pB64Text); static void QCBORDecode_GetB64InMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pB64Text); /** @brief Decode the next item as base64URL encoded text. @param[in] pCtx The decode context. @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX. @param[out] pB64Text The decoded base64 text. This decodes a standard CBOR base64url tag, integer tag number of 33, or encoded CBOR that is not a tag, that is base64url encoded bytes encoded in a text string. Please see @ref Decode-Errors-Overview "Decode Errors Overview". See @ref Tag-Usage for discussion on tag requirements. Note that this does not actually remove the base64url encoding. See also @ref CBOR_TAG_B64URL, QCBOREncode_AddB64URLText() and @ref QCBOR_TYPE_BASE64URL. */ static void QCBORDecode_GetB64URL(QCBORDecodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC *pB64Text); static void QCBORDecode_GetB64URLInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pB64Text); static void QCBORDecode_GetB64URLInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pB64Text); /** @brief Decode the next item as a regular expression. @param[in] pCtx The decode context. @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX. @param[out] pRegex The decoded regular expression. This decodes a standard CBOR regex tag, integer tag number of 35, or encoded CBOR that is not a tag, that is a PERL-compatible regular expression encoded in a text string. Please see @ref Decode-Errors-Overview "Decode Errors Overview". See @ref Tag-Usage for discussion on tag requirements. See also @ref CBOR_TAG_REGEX, QCBOREncode_AddRegex() and @ref QCBOR_TYPE_REGEX. */ static void QCBORDecode_GetRegex(QCBORDecodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC *pRegex); static void QCBORDecode_GetRegexInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pRegex); static void QCBORDecode_GetRegexInMapSZ(QCBORDecodeContext *pCtx, const char * szLabel, uint8_t uTagRequirement, UsefulBufC *pRegex); /** @brief Decode the next item as a MIME message. @param[in] pCtx The decode context. @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX. @param[out] pMessage The decoded regular expression. @param[out] pbIsTag257 @c true if tag was 257. May be @c NULL. This decodes the standard CBOR MIME and binary MIME tags, integer tag numbers of 36 or 257, or encoded CBOR that is not a tag, that is a MIME message encoded in a text or binary string. Please see @ref Decode-Errors-Overview "Decode Errors Overview". See @ref Tag-Usage for discussion on tag requirements. The MIME message itself is not parsed. This decodes both tag 36 and 257. If it is tag 257, pbIsTag257 is @c true. The difference between the two is that tag 36 is utf8 and tag 257 is a byte string that can carry binary MIME. QCBOR processes them exactly the same. Possibly the difference can be ignored. NULL can be passed to have no value returned. See also @ref CBOR_TAG_MIME, @ref CBOR_TAG_BINARY_MIME, QCBOREncode_AddTMIMEData(), @ref QCBOR_TYPE_MIME 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 QCBORDecode_GetMIMEMessage(QCBORDecodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC *pMessage, bool *pbIsTag257); static void QCBORDecode_GetMIMEMessageInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pMessage, bool *pbIsTag257); static void QCBORDecode_GetMIMEMessageInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pMessage, bool *pbIsTag257); /** @brief Decode the next item as a UUID @param[in] pCtx The decode context. @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX. @param[out] pUUID The decoded UUID This decodes a standard CBOR UUID tag, integer tag number of 37, or encoded CBOR that is not a tag, that is a UUID encoded in a byte string. Please see @ref Decode-Errors-Overview "Decode Errors Overview". See @ref Tag-Usage for discussion on tag requirements. See also @ref CBOR_TAG_BIN_UUID, QCBOREncode_AddBinaryUUID() and @ref QCBOR_TYPE_UUID. */ static inline void QCBORDecode_GetBinaryUUID(QCBORDecodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC *pUUID); inline static void QCBORDecode_GetBinaryUUIDInMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pUUID); inline static void QCBORDecode_GetBinaryUUIDInMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pUUID); /** @brief Decode some byte-string wrapped CBOR. @param[in] pCtx The decode context. @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX. @param[out] pBstr Pointer and length of byte-string wrapped CBOR (optional). This is for use on some CBOR that has been wrapped in a byte string. There are several ways that this can occur. First is tag 24 and tag 63. Tag 24 wraps a single CBOR data item and 63 a CBOR sequence. This implementation doesn't distinguish between the two (it would be more code and doesn't seem important). The @ref Tag-Usage discussion on the tag requirement applies here just the same as any other tag. In other cases, CBOR is wrapped in a byte string, but it is identified as CBOR by other means. The contents of a COSE payload are one example of that. They can be identified by the COSE content type, or they can be identified as CBOR indirectly by the protocol that uses COSE. for example, if a blob of CBOR is identified as a CWT, then the COSE payload is CBOR. To enter into CBOR of this type use the @ref QCBOR_TAG_REQUIREMENT_NOT_A_TAG as the \c uTagRequirement argument. Note that byte string wrapped CBOR can also be decoded by getting the byte string with QCBORDecode_GetItem() or QCBORDecode_GetByteString() and feeding it into another instance of QCBORDecode. Doing it with this function has the advantage of using less memory as another instance of QCBORDecode is not necessary. When the wrapped CBOR is entered with this function, the pre-order traversal and such are bounded to the wrapped CBOR. QCBORDecode_ExitBstrWrapped() must be called to resume processing CBOR outside the wrapped CBOR. This does not (currently) work on indefinite-length strings. The (confusing) error @ref QCBOR_ERR_INPUT_TOO_LARGE will be set. If @c pBstr is not @c NULL the pointer and length of the wrapped CBOR will be returned. This is usually not needed, but sometimes useful, particularly in the case of verifying signed data like the COSE payload. This is usually the pointer and length of the data is that is hashed or MACed. Please see @ref Decode-Errors-Overview "Decode Errors Overview". See also QCBORDecode_ExitBstrWrapped(), QCBORDecode_EnterMap() and QCBORDecode_EnterArray(). */ void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pCtx, uint8_t uTagRequirement, UsefulBufC *pBstr); void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pCtx, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pBstr); void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pCtx, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pBstr); /** @brief Exit some bstr-wrapped CBOR has been enetered. @param[in] pCtx The decode context. Bstr-wrapped CBOR must have been entered for this to succeed. The items in the wrapped CBOR that was entered do not have to have been consumed for this to succeed. The this sets the pre-order traversal cursor to the item after the byte string that was exited. */ void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pCtx); /* =========================================================================== BEGINNING OF PRIVATE INLINE IMPLEMENTATION ========================================================================== */ // Semi-private void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue, QCBORItem *pItem); // Semi-private void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, uint64_t *puValue, QCBORItem *pItem); // Semi-private void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, uint64_t *puValue, QCBORItem *pItem); void QCBORDecode_GetUInt64Convert(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue) { QCBORItem Item; QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item); } inline static void QCBORDecode_GetUInt64ConvertInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, uint64_t *puValue) { QCBORItem Item; QCBORDecode_GetUInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, puValue, &Item); } inline static void QCBORDecode_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, uint64_t *puValue) { QCBORItem Item; QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, puValue, &Item); } static inline void QCBORDecode_GetUInt64(QCBORDecodeContext *pMe, uint64_t *puValue) { QCBORDecode_GetUInt64Convert(pMe, QCBOR_CONVERT_TYPE_XINT64, puValue); } inline static void QCBORDecode_GetUInt64InMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint64_t *puValue) { QCBORDecode_GetUInt64ConvertInMapN(pMe, nLabel, QCBOR_CONVERT_TYPE_XINT64, puValue); } inline static void QCBORDecode_GetUInt64InMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint64_t *puValue) { QCBORDecode_GetUInt64ConvertInMapSZ(pMe, szLabel, QCBOR_CONVERT_TYPE_XINT64, puValue); } // Semi-private void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem); // Semi-private inline static void QCBORDecode_EnterMap(QCBORDecodeContext *pMe, QCBORItem *pItem) { QCBORDecode_EnterBoundedMapOrArray(pMe, QCBOR_TYPE_MAP, pItem); } // Semi-private inline static void QCBORDecode_EnterArray(QCBORDecodeContext *pMe, QCBORItem *pItem) { QCBORDecode_EnterBoundedMapOrArray(pMe, QCBOR_TYPE_ARRAY, pItem); } // Semi-private void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType); static inline void QCBORDecode_ExitArray(QCBORDecodeContext *pMe) { QCBORDecode_ExitBoundedMapOrArray(pMe, QCBOR_TYPE_ARRAY); } static inline void QCBORDecode_ExitMap(QCBORDecodeContext *pMe) { QCBORDecode_ExitBoundedMapOrArray(pMe, QCBOR_TYPE_MAP); } // Semi-private void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue, QCBORItem *pItem); // Semi-private void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, int64_t *pnValue, QCBORItem *pItem); // Semi-private void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, int64_t *pnValue, QCBORItem *pItem); inline static void QCBORDecode_GetInt64Convert(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue) { QCBORItem Item; QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item); } inline static void QCBORDecode_GetInt64ConvertInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, int64_t *pnValue) { QCBORItem Item; QCBORDecode_GetInt64ConvertInternalInMapN(pMe, nLabel, uConvertTypes, pnValue, &Item); } inline static void QCBORDecode_GetInt64ConvertInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, int64_t *pnValue) { QCBORItem Item; QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pnValue, &Item); } inline static void QCBORDecode_GetInt64(QCBORDecodeContext *pMe, int64_t *pnValue) { QCBORDecode_GetInt64Convert(pMe, QCBOR_CONVERT_TYPE_XINT64, pnValue); } inline static void QCBORDecode_GetInt64InMapN(QCBORDecodeContext *pMe, int64_t nLabel, int64_t *pnValue) { QCBORDecode_GetInt64ConvertInMapN(pMe, nLabel, QCBOR_CONVERT_TYPE_XINT64, pnValue); } inline static void QCBORDecode_GetInt64InMapSZ(QCBORDecodeContext *pMe, const char *szLabel, int64_t *pnValue) { QCBORDecode_GetInt64ConvertInMapSZ(pMe, szLabel, QCBOR_CONVERT_TYPE_XINT64, pnValue); } #ifndef USEFULBUF_DISABLE_ALL_FLOAT // Semi-private void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe, uint32_t uConvertTypes, double *pValue, QCBORItem *pItem); // Semi-private void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, double *pdValue, QCBORItem *pItem); // Semi-private void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, double *pdValue, QCBORItem *pItem); inline static void QCBORDecode_GetDoubleConvert(QCBORDecodeContext *pMe, uint32_t uConvertTypes, double *pdValue) { QCBORItem Item; QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item); } inline static void QCBORDecode_GetDoubleConvertInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint32_t uConvertTypes, double *pdValue) { QCBORItem Item; QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item); } inline static void QCBORDecode_GetDoubleConvertInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint32_t uConvertTypes, double *pdValue) { QCBORItem Item; QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item); } inline static void QCBORDecode_GetDouble(QCBORDecodeContext *pMe, double *pValue) { QCBORDecode_GetDoubleConvert(pMe, QCBOR_CONVERT_TYPE_FLOAT, pValue); } inline static void QCBORDecode_GetDoubleInMapN(QCBORDecodeContext *pMe, int64_t nLabel, double *pdValue) { QCBORDecode_GetDoubleConvertInMapN(pMe, nLabel, QCBOR_CONVERT_TYPE_FLOAT, pdValue); } inline static void QCBORDecode_GetDoubleInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, double *pdValue) { QCBORDecode_GetDoubleConvertInMapSZ(pMe, szLabel, QCBOR_CONVERT_TYPE_FLOAT, pdValue); } #endif /* USEFULBUF_DISABLE_ALL_FLOAT */ // Semi private (this may change in the future) #define QCBOR_TAGSPEC_NUM_TYPES 4 /* Improvement: Carefully understand what compilers do with this, particularly initialization and see if it can be optimized so there is less code and maybe so it can be smaller. */ typedef struct { /* One of QCBOR_TAGSPEC_MATCH_xxx */ uint8_t uTagRequirement; /* The tagged type translated into QCBOR_TYPE_XXX. Used to match explicit tagging */ uint8_t uTaggedTypes[QCBOR_TAGSPEC_NUM_TYPES]; /* The types of the content, which are used to match implicit tagging */ uint8_t uAllowedContentTypes[QCBOR_TAGSPEC_NUM_TYPES]; } TagSpecification; // Semi private void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe, TagSpecification TagSpec, UsefulBufC *pBstr); // Semi private void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe, int64_t nLabel, TagSpecification TagSpec, UsefulBufC *pString); // Semi private void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe, const char * szLabel, TagSpecification TagSpec, UsefulBufC *pString); // Semi private QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement, const QCBORItem *pItem, UsefulBufC *pMessage, bool *pbIsTag257); static inline void QCBORDecode_GetByteString(QCBORDecodeContext *pMe, UsefulBufC *pValue) { // Complier should make this just a 64-bit integer parameter const TagSpecification TagSpec = { QCBOR_TAG_REQUIREMENT_NOT_A_TAG, {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInternal(pMe, TagSpec, pValue); } inline static void QCBORDecode_GetByteStringInMapN(QCBORDecodeContext *pMe, int64_t nLabel, UsefulBufC *pBstr) { const TagSpecification TagSpec = { QCBOR_TAG_REQUIREMENT_NOT_A_TAG, {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pBstr); } inline static void QCBORDecode_GetByteStringInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pBstr) { const TagSpecification TagSpec = { QCBOR_TAG_REQUIREMENT_NOT_A_TAG, {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pBstr); } static inline void QCBORDecode_GetTextString(QCBORDecodeContext *pMe, UsefulBufC *pValue) { // Complier should make this just 64-bit integer parameter const TagSpecification TagSpec = { QCBOR_TAG_REQUIREMENT_NOT_A_TAG, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInternal(pMe, TagSpec, pValue); } inline static void QCBORDecode_GetTextStringInMapN(QCBORDecodeContext *pMe, int64_t nLabel, UsefulBufC *pText) { // This TagSpec only matches text strings; it also should optimize down // to passing a 64-bit integer const TagSpecification TagSpec = { QCBOR_TAG_REQUIREMENT_NOT_A_TAG, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pText); } inline static void QCBORDecode_GetTextStringInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, UsefulBufC *pText) { const TagSpecification TagSpec = { QCBOR_TAG_REQUIREMENT_NOT_A_TAG, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pText); } static inline void QCBORDecode_GetNull(QCBORDecodeContext *pMe) { QCBORItem item; QCBORDecode_VGetNext(pMe, &item); if(pMe->uLastError == QCBOR_SUCCESS && item.uDataType != QCBOR_TYPE_NULL) { pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE; } } static inline void QCBORDecode_GetNullInMapN(QCBORDecodeContext *pMe, int64_t nLabel) { QCBORItem Item; QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_NULL, &Item); } static inline void QCBORDecode_GetNullInMapSZ(QCBORDecodeContext *pMe, const char * szLabel) { QCBORItem Item; QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_NULL, &Item); } static inline void QCBORDecode_GetUndefined(QCBORDecodeContext *pMe) { QCBORItem item; QCBORDecode_VGetNext(pMe, &item); if(pMe->uLastError == QCBOR_SUCCESS && item.uDataType != QCBOR_TYPE_UNDEF) { pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE; } } static inline void QCBORDecode_GetUndefinedInMapN(QCBORDecodeContext *pMe, int64_t nLabel) { QCBORItem Item; QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_UNDEF, &Item); } static inline void QCBORDecode_GetUndefinedInMapSZ(QCBORDecodeContext *pMe, const char * szLabel) { QCBORItem Item; QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_UNDEF, &Item); } static inline void QCBORDecode_GetDateString(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pValue) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_DATE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInternal(pMe, TagSpec, pValue); } inline static void QCBORDecode_GetDateStringInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pText) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_DATE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pText); } inline static void QCBORDecode_GetDateStringInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pText) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_DATE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pText); } static inline void QCBORDecode_GetDaysString(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pValue) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_DAYS_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInternal(pMe, TagSpec, pValue); } inline static void QCBORDecode_GetDaysStringInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pText) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_DAYS_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pText); } inline static void QCBORDecode_GetDaysStringInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pText) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_DAYS_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pText); } static inline void QCBORDecode_GetURI(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pUUID) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_URI, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInternal(pMe, TagSpec, pUUID); } inline static void QCBORDecode_GetURIInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pUUID) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_URI, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pUUID); } inline static void QCBORDecode_GetURIInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pUUID) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_URI, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pUUID); } static inline void QCBORDecode_GetB64(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pB64Text) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_BASE64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInternal(pMe, TagSpec, pB64Text); } inline static void QCBORDecode_GetB64InMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pB64Text) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_BASE64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pB64Text); } inline static void QCBORDecode_GetB64InMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pB64Text) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_BASE64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pB64Text); } static inline void QCBORDecode_GetB64URL(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pB64Text) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_BASE64URL, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInternal(pMe, TagSpec, pB64Text); } inline static void QCBORDecode_GetB64URLInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pB64Text) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_BASE64URL, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pB64Text); } inline static void QCBORDecode_GetB64URLInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pB64Text) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_BASE64URL, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pB64Text); } static inline void QCBORDecode_GetRegex(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pRegex) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_REGEX, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInternal(pMe, TagSpec, pRegex); } static inline void QCBORDecode_GetRegexInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pRegex) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_REGEX, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pRegex); } static inline void QCBORDecode_GetRegexInMapSZ(QCBORDecodeContext *pMe, const char * szLabel, uint8_t uTagRequirement, UsefulBufC *pRegex) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_REGEX, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pRegex); } static inline void QCBORDecode_GetMIMEMessage(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pMessage, bool *pbIsTag257) { if(pMe->uLastError != QCBOR_SUCCESS) { // Already in error state, do nothing return; } QCBORItem Item; QCBORError uError = QCBORDecode_GetNext(pMe, &Item); if(uError != QCBOR_SUCCESS) { pMe->uLastError = (uint8_t)uError; return; } pMe->uLastError = (uint8_t)QCBORDecode_GetMIMEInternal(uTagRequirement, &Item, pMessage, pbIsTag257); } static inline void QCBORDecode_GetMIMEMessageInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pMessage, bool *pbIsTag257) { QCBORItem Item; QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item); if(pMe->uLastError == QCBOR_SUCCESS) { pMe->uLastError = (uint8_t)QCBORDecode_GetMIMEInternal(uTagRequirement, &Item, pMessage, pbIsTag257); } } static inline void QCBORDecode_GetMIMEMessageInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pMessage, bool *pbIsTag257) { QCBORItem Item; QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item); if(pMe->uLastError == QCBOR_SUCCESS) { pMe->uLastError = (uint8_t)QCBORDecode_GetMIMEInternal(uTagRequirement, &Item, pMessage, pbIsTag257); } } static inline void QCBORDecode_GetBinaryUUID(QCBORDecodeContext *pMe, uint8_t uTagRequirement, UsefulBufC *pUUID) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_UUID, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInternal(pMe, TagSpec, pUUID); } inline static void QCBORDecode_GetBinaryUUIDInMapN(QCBORDecodeContext *pMe, int64_t nLabel, uint8_t uTagRequirement, UsefulBufC *pUUID) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_UUID, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pUUID); } inline static void QCBORDecode_GetBinaryUUIDInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, uint8_t uTagRequirement, UsefulBufC *pUUID) { const TagSpecification TagSpec = { uTagRequirement, {QCBOR_TYPE_UUID, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}, {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE} }; QCBORDecode_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pUUID); } #ifdef __cplusplus } #endif #endif /* qcbor_spiffy_decode_h */