| /* =========================================================================== |
| * Copyright (c) 2016-2018, The Linux Foundation. |
| * Copyright (c) 2018-2024, Laurence Lundblade. |
| * Copyright (c) 2021, Arm Limited. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * * Neither the name of The Linux Foundation nor the names of its |
| * contributors, nor the name "Laurence Lundblade" may be used to |
| * endorse or promote products derived from this software without |
| * specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * ========================================================================= */ |
| |
| |
| #ifndef qcbor_decode_h |
| #define qcbor_decode_h |
| |
| |
| #include "qcbor/qcbor_common.h" |
| #include "qcbor/qcbor_private.h" |
| #include <stdbool.h> |
| |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #if 0 |
| } /* Keep editor indention formatting happy */ |
| #endif |
| #endif |
| |
| |
| /** |
| * @file qcbor_decode.h |
| * |
| * @anchor BasicDecode |
| * # QCBOR Basic Decode |
| * |
| * This section discusses decoding assuming familiarity with the |
| * general description of this encoder-decoder in section @ref |
| * Overview. |
| * |
| * Encoded CBOR has 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, CBOR decoding is a |
| * pre-order traversal of this tree with CBOR sequences a minor |
| * exception. Calling QCBORDecode_GetNext() repeatedly will perform |
| * this. QCBOR maintains an internal traversal cursor. It is possible |
| * to decode any CBOR by only calling QCBORDecode_GetNext(), though |
| * this doesn't take advantage of many QCBOR features. |
| * |
| * QCBORDecode_GetNext() returns a 56 byte structure called |
| * @ref QCBORItem that describes the decoded item including: |
| * - The data itself, integer, string, floating-point number... |
| * - The label if present |
| * - Unprocessed tags |
| * - Nesting level |
| * - Allocation type (primarily of interest for indefinite length strings) |
| * |
| * For strings, this structure contains a pointer and length back into |
| * the original data. |
| * |
| * Most of the tags that QCBOR supports directly are decoded into a |
| * representation in @ref QCBORItem. |
| * |
| * A string allocator must be used when decoding indefinite length |
| * strings. See QCBORDecode_SetMemPool() or |
| * QCBORDecode_SetUpAllocator(). @ref QCBORItem indicates if a string |
| * was allocated with the string allocator. |
| * |
| * This pre-order traversal gives natural decoding of arrays where the |
| * array members are taken in order. Maps can be decoded this way too, |
| * but the @ref SpiffyDecode APIs that allow searching maps by label |
| * are often more convenient. |
| * |
| * @anchor Decode-Errors-Overview |
| * # Decode Errors Overview |
| * |
| * The simplest way to handle decoding errors is to make use of the |
| * internal error tracking. The only error code check necessary is |
| * at the end when QCBORDecode_Finish() is called. To do this: |
| * |
| * - Use QCBORDecode_VGetNext(), QCBORDecode_VPeekNext() |
| * and any or all of the functions in qcbor_spiffy_decode.h. Don't use |
| * QCBORDecode_GetNext() or QCBORDecode_PeekNext(). |
| * - Call QCBORDecode_Finish() and check its return code. |
| * - Do not reference any decoded data until after |
| * QCBORDecode_Finish() returns success. |
| * |
| * Once an encoding error has been encountered, the error state is |
| * entered and further decoding function calls will do nothing. It is |
| * safe to continue calling decoding functions after an error. No |
| * error checking is necessary making the code to decode a protocol |
| * simpler. The two exceptions are QCBORDecode_GetNext() and |
| * QCBORDecode_PeekNext() which will try to decode even if the decoder |
| * is in the error state. Use QCBORDecode_VGetNext() and |
| * QCBORDecode_VPeekNext() instead. |
| * |
| * While some protocols are simple enough to be decoded this way, many |
| * aren’t because the data items earlier in the protocol determine how |
| * later data items are to be decoded. In that case it is necessary to |
| * call QCBORDecode_GetError() to know the earlier items were |
| * successfully decoded before examining their value or type. |
| * |
| * The internal decode error state can be reset by reinitializing the |
| * decoder or calling QCBORDecode_GetAndResetError(). Code calling |
| * QCBOR may take advantage of the internal error state to halt |
| * futher decoding and propagate errors it detects using |
| * QCBORDecode_SetError(). |
| * |
| * It is only useful to reset the error state by calling |
| * QCBORDecode_GetAndResetError() on recoverable errors. Examples of |
| * recoverable errors are a map entry not being found or integer |
| * overflow or underflow during conversion. Examples of unrecoverable |
| * errors are hitting the end of the input and array or map nesting |
| * beyond the limits of the implementation. See |
| * QCBORDecode_IsUnrecoverableError().Trying to reset and decode after |
| * an unrecoverable error will usually just lead to another error. |
| * |
| * It is possible to use QCBORDecode_GetNext() and |
| * QCBORDecode_PeekNext() to decode an entire protocol. However, that is |
| * usually more work, more code and less convenient than using spiffy |
| * decode functions. |
| * |
| * It is also possible to mix the use of QCBORDecode_GetNext() with |
| * QCBORDecode_VGetNext() and the spiffy decode functions, but |
| * QCBORDecode_GetError() must be called and return QCBOR_SUCCESS before |
| * QCBORDecode_GetNext() is called. |
| * |
| * The effect of a decoding error on the traversal cursor position |
| * varies by the decoding method called. It is unaffected by spiffy |
| * decode methods that get items by map label. |
| * QCBORDecode_GetInt64InMapN() is an example of this. The traversal |
| * cursor will be advanced by most other decode methods even when |
| * there is a decode error, often leaving it in an indeterminate |
| * position. If it is necessary to continue to decoding after an |
| * error, QCBORDecode_Rewind() can be used to reset it to a known-good |
| * position. |
| * |
| * When using spiffy decode methods to get an item by label from a map |
| * the whole map is internally traversed including nested arrays and |
| * maps. If there is any unrecoverable error during that traversal, |
| * the retrieval by label will fail. The unrecoverable error will be |
| * returned even if it is not because the item being sought is in |
| * error. Recoverable errors will be ignored unless they are on the |
| * item being sought, in which case the unrecoverable error will be |
| * returned. Unrecoverable errors are those indicated by |
| * QCBORDecode_IsUnrecoverableError(). |
| * |
| * @anchor Disabilng-Tag-Decoding |
| * # Disabilng Tag Decoding |
| * |
| * If QCBOR_DISABLE_TAGS is defined, all code for decoding tags will |
| * be omitted reducing the core decoder, QCBORDecode_VGetNext(), by |
| * about 400 bytes. If a tag number is encountered in the decoder |
| * input the unrecoverable error @ref QCBOR_ERR_TAGS_DISABLED will be |
| * returned. No input with tags can be decoded. |
| * |
| * Decode functions like QCBORDecode_GetEpochDate() and |
| * QCBORDecode_GetDecimalFraction() that can decode the tag content |
| * even if the tag number is absent are still available. Typically |
| * they won't be linked in because of dead stripping. The |
| * @c uTagRequirement parameter has no effect, but if it is |
| * @ref QCBOR_TAG_REQUIREMENT_TAG, @ref QCBOR_ERR_TAGS_DISABLED |
| * will be set. |
| */ |
| |
| /** |
| * The decode mode options. |
| */ |
| typedef enum { |
| /** See QCBORDecode_Init() */ |
| QCBOR_DECODE_MODE_NORMAL = 0, |
| /** See QCBORDecode_Init() */ |
| QCBOR_DECODE_MODE_MAP_STRINGS_ONLY = 1, |
| /** See QCBORDecode_Init() */ |
| QCBOR_DECODE_MODE_MAP_AS_ARRAY = 2 |
| /* This is stored in uint8_t in places; never add values > 255 */ |
| } QCBORDecodeMode; |
| |
| /** |
| * The maximum size of input to the decoder. Slightly less than |
| * @c UINT32_MAX to make room for some special indicator values. |
| */ |
| #define QCBOR_MAX_DECODE_INPUT_SIZE (UINT32_MAX - 2) |
| |
| /** |
| * The maximum number of tags that may occur on an individual nested |
| * item. Typically 4. |
| */ |
| #define QCBOR_MAX_TAGS_PER_ITEM QCBOR_MAX_TAGS_PER_ITEM1 |
| |
| |
| |
| /* Do not renumber these. Code depends on some of these values. */ |
| /** The data type is unknown, unset or invalid. */ |
| #define QCBOR_TYPE_NONE 0 |
| |
| /** Never used in QCBORItem. Used by functions that match QCBOR types. */ |
| #define QCBOR_TYPE_ANY 1 |
| |
| /** Type for an integer that decoded either between @c INT64_MIN and |
| * @c INT32_MIN or @c INT32_MAX and @c INT64_MAX. Data is in member |
| * @c val.int64. */ |
| #define QCBOR_TYPE_INT64 2 |
| |
| /** Type for an integer that decoded to a more than @c INT64_MAX and |
| * @c UINT64_MAX. Data is in member @c val.uint64. */ |
| #define QCBOR_TYPE_UINT64 3 |
| |
| /** Type for an array. See comments on @c val.uCount. */ |
| #define QCBOR_TYPE_ARRAY 4 |
| |
| /** Type for a map. See comments on @c val.uCount. */ |
| #define QCBOR_TYPE_MAP 5 |
| |
| /** Type for a buffer full of bytes. Data is in @c val.string. */ |
| #define QCBOR_TYPE_BYTE_STRING 6 |
| |
| /** Type for a UTF-8 string. It is not NULL-terminated. See |
| * QCBOREncode_AddText() for a discussion of line endings in CBOR. Data |
| * is in @c val.string. */ |
| #define QCBOR_TYPE_TEXT_STRING 7 |
| |
| /** Type for a positive big number. Data is in @c val.bignum, a |
| * pointer and a length. */ |
| #define QCBOR_TYPE_POSBIGNUM 9 |
| |
| /** Type for a negative big number. Data is in @c val.bignum, a |
| * pointer and a length. */ |
| #define QCBOR_TYPE_NEGBIGNUM 10 |
| |
| /** Type for [RFC 3339] (https://tools.ietf.org/html/rfc3339) date |
| * string, possibly with time zone. Data is in @c val.string . Note this |
| * was previously in @c val.dateString, however this is the same as |
| * val.string being the same type in same union. val.dateString will |
| * be deprecated.. */ |
| #define QCBOR_TYPE_DATE_STRING 11 |
| |
| /** Type for integer seconds since Jan 1970 + floating-point |
| * fraction. Data is in @c val.epochDate */ |
| #define QCBOR_TYPE_DATE_EPOCH 12 |
| |
| /** The CBOR major type "simple" has a small integer value indicating |
| * what it is. The standard CBOR simples are true, false, null, undef |
| * (values 20-23) and float-point numbers (values 25-27). The values |
| * 0-19 and 32-255 are unassigned and may be used if registered with |
| * in the IANA Simple Values Registry. If these unassigned simple |
| * values occur in the input they will be decoded as this. The value |
| * is in @c val.uSimple. */ |
| #define QCBOR_TYPE_UKNOWN_SIMPLE 13 |
| |
| /** A decimal fraction made of decimal exponent and integer mantissa. |
| * See @ref expAndMantissa and QCBOREncode_AddTDecimalFraction(). */ |
| #define QCBOR_TYPE_DECIMAL_FRACTION 14 |
| |
| /** A decimal fraction made of decimal exponent and positive big |
| * number mantissa. See @ref expAndMantissa and |
| * QCBOREncode_AddTDecimalFractionBigNum(). */ |
| #define QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM 15 |
| |
| /** A decimal fraction made of decimal exponent and negative big |
| * number mantissa. See @ref expAndMantissa and |
| * QCBOREncode_AddTDecimalFractionBigNum(). */ |
| #define QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM 16 |
| |
| /** A floating-point number made of base-2 exponent and integer |
| * mantissa. See @ref expAndMantissa and |
| * QCBOREncode_AddTBigFloat(). */ |
| #define QCBOR_TYPE_BIGFLOAT 17 |
| |
| /** A floating-point number made of base-2 exponent and positive big |
| * number mantissa. See @ref expAndMantissa and |
| * QCBOREncode_AddTBigFloatBigNum(). */ |
| #define QCBOR_TYPE_BIGFLOAT_POS_BIGNUM 18 |
| |
| /** A floating-point number made of base-2 exponent and negative big |
| * number mantissa. See @ref expAndMantissa and |
| * QCBOREncode_AddTBigFloatBigNum(). */ |
| #define QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM 19 |
| |
| /** Type for the simple value false. */ |
| #define QCBOR_TYPE_FALSE 20 |
| |
| /** Type for the simple value true. */ |
| #define QCBOR_TYPE_TRUE 21 |
| |
| /** Type for the simple value null. */ |
| #define QCBOR_TYPE_NULL 22 |
| |
| /** Type for the simple value undef. */ |
| #define QCBOR_TYPE_UNDEF 23 |
| |
| /** Type for a floating-point number. Data is in @c val.fnum. */ |
| #define QCBOR_TYPE_FLOAT 26 |
| |
| /** Type for a double floating-point number. Data is in @c val.dfnum. */ |
| #define QCBOR_TYPE_DOUBLE 27 |
| |
| #define QCBOR_TYPE_BREAK 31 /* Used internally; never returned */ |
| |
| /** For @ref QCBOR_DECODE_MODE_MAP_AS_ARRAY decode mode, a map that is |
| * being traversed as an array. See QCBORDecode_Init() */ |
| #define QCBOR_TYPE_MAP_AS_ARRAY 32 |
| |
| /** Encoded CBOR that is wrapped in a byte string. Often used when the |
| * CBOR is to be hashed for signing or HMAC. See also @ref |
| * QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE. Data is in @c val.string. */ |
| #define QBCOR_TYPE_WRAPPED_CBOR 36 |
| |
| /** A URI as defined in RFC 3986. Data is in @c val.string. */ |
| #define QCBOR_TYPE_URI 44 |
| |
| /** Text is base64 URL encoded in RFC 4648. The base64 encoding is |
| * NOT removed. Data is in @c val.string. */ |
| #define QCBOR_TYPE_BASE64URL 45 |
| |
| /** Text is base64 encoded in RFC 4648. The base64 encoding is NOT |
| * removed. Data is in @c val.string. */ |
| #define QCBOR_TYPE_BASE64 46 |
| |
| /** PERL-compatible regular expression. Data is in @c val.string. */ |
| #define QCBOR_TYPE_REGEX 47 |
| |
| /** Non-binary MIME per RFC 2045. See also @ref |
| * QCBOR_TYPE_BINARY_MIME. Data is in @c val.string. */ |
| #define QCBOR_TYPE_MIME 48 |
| |
| /** Binary UUID per RFC 4122. Data is in @c val.string. */ |
| #define QCBOR_TYPE_UUID 49 |
| |
| /** A CBOR sequence per RFC 8742. See also @ ref |
| * QBCOR_TYPE_WRAPPED_CBOR. Data is in @c val.string. */ |
| #define QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE 75 |
| |
| /** Binary MIME per RFC 2045. See also @ref QCBOR_TYPE_MIME. Data is |
| * in @c val.string. */ |
| #define QCBOR_TYPE_BINARY_MIME 76 |
| |
| /** Type for [RFC 8943](https://tools.ietf.org/html/rfc8943) date |
| * string, a date with no time or time zone info. Data is in |
| * @c val.string */ |
| #define QCBOR_TYPE_DAYS_STRING 77 |
| |
| /** Type for integer days since Jan 1 1970 described in |
| * [RFC 8943](https://tools.ietf.org/html/rfc8943). Data is in |
| * @c val.epochDays */ |
| #define QCBOR_TYPE_DAYS_EPOCH 78 |
| |
| #define QCBOR_TYPE_TAG 254 /* Used internally; never returned */ |
| |
| #define QCBOR_TYPE_OPTTAG QCBOR_TYPE_TAG /* Depricated. See QCBOR_TYPE_TAG */ |
| |
| |
| |
| /** |
| * The largest value in @c utags that is unmapped and can be used without |
| * mapping it through QCBORDecode_GetNthTag(). |
| */ |
| #define QCBOR_LAST_UNMAPPED_TAG (CBOR_TAG_INVALID16 - QCBOR_NUM_MAPPED_TAGS - 1) |
| |
| |
| /** |
| * @anchor expAndMantissa |
| * |
| * This holds the value for big floats and decimal fractions, as an |
| * exponent and mantissa. For big floats the base for exponentiation |
| * is 2. For decimal fractions it is 10. Whether an instance is a big |
| * float or decimal fraction is known by context, usually by @c uDataType |
| * in @ref QCBORItem which might be @ref QCBOR_TYPE_DECIMAL_FRACTION, |
| * @ref QCBOR_TYPE_BIGFLOAT, ... |
| * |
| * The mantissa may be an @c int64_t or a big number. This is again |
| * determined by context, usually @c uDataType in @ref QCBORItem which |
| * might be @ref QCBOR_TYPE_DECIMAL_FRACTION, |
| * @ref QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, ... The sign of the |
| * big number also comes from the context |
| * (@ref QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, |
| * @ref QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM,...). |
| * |
| * @c bigNum is big endian or network byte order. The most significant |
| * byte is first. |
| * |
| * When @c Mantissa is @c int64_t, it represents the true value of the |
| * mantissa with the offset of 1 for CBOR negative values |
| * applied. When it is a negative big number |
| * (@ref QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM or |
| * @ref QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM), the offset of 1 has NOT been |
| * applied (doing so requires somewhat complex big number arithmetic |
| * and may increase the length of the big number). To get the correct |
| * value @c bigNum must be incremented by one before use. |
| * |
| * Also see QCBOREncode_AddTDecimalFraction(), |
| * QCBOREncode_AddTBigFloat(), QCBOREncode_AddTDecimalFractionBigNum() |
| * and QCBOREncode_AddTBigFloatBigNum(). |
| */ |
| typedef struct { |
| int64_t nExponent; |
| union { |
| int64_t nInt; |
| UsefulBufC bigNum; |
| } Mantissa; |
| } QCBORExpAndMantissa; |
| |
| |
| /** |
| * This holds a decoded data item. It is returned by the |
| * QCBORDecode_GetNext(), the principle decoding function. |
| * It holds the type, value, label, tags and other details |
| * of the decoded data item. |
| * |
| * This is typically 56 bytes on 64-bit CPUs and 52 bytes on 32-bit |
| * CPUs (the CPU and the system's ABI determine this size). |
| */ |
| typedef struct _QCBORItem { |
| /** Tells what element of the @c val union to use. One of @ref |
| * QCBOR_TYPE_INT64, @ref QCBOR_TYPE_ARRAY, ...*/ |
| uint8_t uDataType; |
| |
| /** Tells what element of the @c label union to use. One of |
| * @ref QCBOR_TYPE_INT64, @ref QCBOR_TYPE_BYTE_STRING, ...*/ |
| uint8_t uLabelType; |
| |
| /** Holds the nesting depth for arrays and map. 0 is the top level |
| * with no arrays or maps entered. */ |
| uint8_t uNestingLevel; |
| |
| /** Holds the nesting level of the next item after this one. If |
| * less than @c uNestingLevel, this item was the last one in an |
| * arry or map and it closed out at least one nesting level. */ |
| uint8_t uNextNestLevel; |
| |
| /** 1 if a @c val that is a string is allocated with string |
| * allocator, 0 if not. Always 0 unless an allocator has been set |
| * up by calling QCBORDecode_SetMemPool() or |
| * QCBORDecode_SetUpAllocator(). */ |
| uint8_t uDataAlloc; |
| |
| /** 1 if a @c label that is a string is allocated with string |
| * allocator, 0 if not. Always 0 unless an allocator has been set |
| * up by calling QCBORDecode_SetMemPool() or |
| * QCBORDecode_SetUpAllocator(). */ |
| uint8_t uLabelAlloc; |
| |
| /** The union holding the item's value. Select union member based |
| * on @c uDataType. */ |
| union { |
| /** The value for @c uDataType @ref QCBOR_TYPE_INT64. */ |
| int64_t int64; |
| /** The value for @c uDataType @ref QCBOR_TYPE_UINT64. */ |
| uint64_t uint64; |
| /** The value for @c uDataType @ref QCBOR_TYPE_BYTE_STRING and |
| * @ref QCBOR_TYPE_TEXT_STRING. Also |
| * for many tags whose content is a string such @ref QCBOR_TYPE_DAYS_STRING |
| * and @ref QCBOR_TYPE_URI. */ |
| UsefulBufC string; |
| /** The "value" for @c uDataType @ref QCBOR_TYPE_ARRAY or @ref |
| * QCBOR_TYPE_MAP, the number of items in the array or map. It |
| * is @c UINT16_MAX when decoding indefinite-lengths maps and |
| * arrays. Detection of the end of a map or array is best done |
| * with @c uNestLevel and @c uNextNestLevel so as to work for |
| * both definite and indefinite length maps and arrays. */ |
| uint16_t uCount; |
| #ifndef USEFULBUF_DISABLE_ALL_FLOAT |
| /** The value for @c uDataType @ref QCBOR_TYPE_DOUBLE. */ |
| double dfnum; |
| /** The value for @c uDataType @ref QCBOR_TYPE_FLOAT. */ |
| float fnum; |
| #endif /* USEFULBUF_DISABLE_ALL_FLOAT */ |
| /** The value for @c uDataType @ref QCBOR_TYPE_DATE_EPOCH, the |
| * number of seconds after or before Jan 1, 1970. This has a |
| * range of 500 billion years. Floating-point dates are |
| * converted to this integer + fractional value. If the input |
| * value is beyond the 500 billion-year range (e.g., +/i |
| * infinity, large floating point values, NaN) |
| * @ref QCBOR_ERR_DATE_OVERFLOW will be returned. If the input |
| * is floating-point and QCBOR has been compiled with |
| * floating-point disabled, one of the various floating-point |
| * disabled errors will be returned. */ |
| struct { |
| int64_t nSeconds; |
| #ifndef USEFULBUF_DISABLE_ALL_FLOAT |
| double fSecondsFraction; |
| #endif /* USEFULBUF_DISABLE_ALL_FLOAT */ |
| } epochDate; |
| |
| /** The value for @c uDataType @ref QCBOR_TYPE_DAYS_EPOCH -- the |
| * number of days before or after Jan 1, 1970. */ |
| int64_t epochDays; |
| /** No longer used. Was the value for @ref QCBOR_TYPE_DATE_STRING, |
| * but now that value is in @c string. This will be removed in QCBOR 2.0. */ |
| UsefulBufC dateString; |
| /** The value for @c uDataType @ref QCBOR_TYPE_POSBIGNUM and |
| * @ref QCBOR_TYPE_NEGBIGNUM. */ |
| UsefulBufC bigNum; |
| /** See @ref QCBOR_TYPE_UKNOWN_SIMPLE */ |
| uint8_t uSimple; |
| #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA |
| QCBORExpAndMantissa expAndMantissa; |
| #endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */ |
| uint64_t uTagV; /* Used internally during decoding */ |
| |
| } val; |
| |
| /** Union holding the different label types selected based on @c uLabelType */ |
| union { |
| /** The label for @c uLabelType for @ref QCBOR_TYPE_INT64 */ |
| int64_t int64; |
| #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS |
| /** The label for @c uLabelType for @ref QCBOR_TYPE_UINT64 */ |
| uint64_t uint64; |
| /** The label for @c uLabelType @ref QCBOR_TYPE_BYTE_STRING and |
| * @ref QCBOR_TYPE_TEXT_STRING */ |
| UsefulBufC string; |
| #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */ |
| } label; |
| |
| #ifndef QCBOR_DISABLE_TAGS |
| /** |
| * The tags numbers for which the item is the tag content. Tags |
| * nest, so index 0 in the array is the tag on the data item |
| * itself, index 1 is the tag that applies to the tag in index |
| * 0. The end of the list is indicated by @ref CBOR_TAG_INVALID16 |
| * |
| * Tag nesting is uncommon and rarely deep. This implementation |
| * only allows nesting to a depth of @ref QCBOR_MAX_TAGS_PER_ITEM, |
| * usually 4. |
| * |
| * Tag numbers in the array below and equal to @ref |
| * QCBOR_LAST_UNMAPPED_TAG are unmapped and can be used |
| * directly. Tag numbers above this must be translated through |
| * QCBORDecode_GetNthTag(). |
| * |
| * See also the large number of functions like |
| * QCBORDecode_GetEpochDate() and QCBORDecode_GetBignum() in |
| * qcbor_spiffy_decode.h for a way to decode tagged types without |
| * having to reference this array. Also see @ref Tags-Overview. |
| */ |
| uint16_t uTags[QCBOR_MAX_TAGS_PER_ITEM]; |
| #endif |
| |
| } QCBORItem; |
| |
| /** |
| * An array or map's length is indefinite when it has this value. |
| */ |
| #define QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH UINT16_MAX |
| |
| |
| |
| |
| /** |
| * @brief Prototype for the implementation of a string allocator. |
| * |
| * @param[in] pAllocateCxt Pointer to context for the particular |
| * allocator implementation. Its contents |
| * depend on how a particular string allocator |
| * works. Typically, it will contain a pointer |
| * to the memory pool and some booking keeping |
| * data. |
| * |
| * @param[in] pOldMem Points to some memory previously allocated |
| * that is either to be freed or to be |
| * reallocated to be larger. It is @c NULL for |
| * new allocations and when called as the |
| * destructor. |
| * |
| * @param[in] uNewSize Size of memory to be allocated or new size |
| * for a chunk being reallocated. Zero when |
| * called to free memory or when called as the |
| * destructor. |
| * |
| * @return Either the allocated buffer is returned, or |
| * @ref NULLUsefulBufC. @ref NULLUsefulBufC is returned on a |
| * failed allocation and in the two cases where there is |
| * nothing to return. |
| * |
| * This function must be implemented for a custom string |
| * allocator. See QCBORDecode_SetUpAllocator(). |
| * |
| * This is not needed if the built-in string allocator available |
| * through QCBORDecode_SetMemPool() is used. |
| * |
| * After being set up by a call to QCBORDecode_SetUpAllocator(), |
| * this is called back in four modes: |
| * |
| * - allocate: @c uNewSize is the amount to allocate. @c pOldMem is |
| * @c NULL. |
| * |
| * - free: @c uNewSize is 0. @c pOldMem points to the memory to be |
| * freed. When the decoder calls this, it will always be for the most |
| * recent block that was either allocated or reallocated. |
| * |
| * - reallocate: @c pOldMem is the block to reallocate. @c uNewSize is |
| * its new size. When the decoder calls this, it will always be for the |
| * most recent block that was either allocated or reallocated. |
| * |
| * - destruct: @c pOldMem is @c NULL and @c uNewSize is 0. This is |
| * called when the decoding is complete by |
| * QCBORDecode_Finish(). Usually, the strings allocated by a string |
| * allocator are in use after the decoding is completed so this |
| * usually will not free those strings. Many string allocators will |
| * not need to do anything in this mode. |
| * |
| * The strings allocated by this will have @c uDataAlloc set to true |
| * in the @ref QCBORItem when they are returned. The user of the |
| * strings will have to free them. How they free them, depends on the |
| * design of the string allocator. |
| */ |
| typedef UsefulBuf (* QCBORStringAllocate)(void *pAllocateCxt, |
| void *pOldMem, |
| size_t uNewSize); |
| |
| |
| /** |
| * For the built-in string allocator available via |
| * QCBORDecode_SetMemPool(), this is the size overhead needed |
| * internally. The amount of memory available for decoded strings is |
| * the size of the buffer given to QCBORDecode_SetMemPool() less this |
| * amount. |
| * |
| * This doesn't apply to custom string allocators, only to the one |
| * available via QCBORDecode_SetMemPool(). |
| */ |
| #define QCBOR_DECODE_MIN_MEM_POOL_SIZE 8 |
| |
| |
| |
| |
| /** |
| * QCBORDecodeContext holds the context for decoding CBOR. It is |
| * about 300 bytes, so it can go on the stack. The contents are |
| * opaque, and the caller should not access any internal items. A |
| * context may be re-used serially as long as it is re initialized. |
| */ |
| typedef struct _QCBORDecodeContext QCBORDecodeContext; |
| |
| |
| /** |
| * Initialize the CBOR decoder context. |
| * |
| * @param[in] pCtx The context to initialize. |
| * @param[in] EncodedCBOR The buffer with CBOR encoded bytes to be decoded. |
| * @param[in] nMode See below and @ref QCBORDecodeMode. |
| * |
| * Initialize context for a pre-order traversal of the encoded CBOR |
| * tree. |
| * |
| * Most CBOR decoding can be completed by calling this function to |
| * start and QCBORDecode_GetNext() in a loop. |
| * |
| * If indefinite-length strings are to be decoded, then |
| * QCBORDecode_SetMemPool() or QCBORDecode_SetUpAllocator() must be |
| * called to set up a string allocator. |
| * |
| * Three decoding modes are supported. In normal mode, @ref |
| * QCBOR_DECODE_MODE_NORMAL, maps are decoded and strings and integers |
| * are accepted as map labels. If a label is other than these, the |
| * error @ref QCBOR_ERR_MAP_LABEL_TYPE is returned by |
| * QCBORDecode_GetNext(). |
| * |
| * In strings-only mode, @ref QCBOR_DECODE_MODE_MAP_STRINGS_ONLY, only |
| * text strings are accepted for map labels. This lines up with CBOR |
| * that converts to JSON. The error @ref QCBOR_ERR_MAP_LABEL_TYPE is |
| * returned by QCBORDecode_GetNext() if anything but a text string |
| * label is encountered. |
| * |
| * In @ref QCBOR_DECODE_MODE_MAP_AS_ARRAY maps are treated as special |
| * arrays. They will be returned with special @c uDataType @ref |
| * QCBOR_TYPE_MAP_AS_ARRAY and @c uCount, the number of items, will be |
| * double what it would be for a normal map because the labels are |
| * also counted. This mode is useful for decoding CBOR that has labels |
| * that are not integers or text strings, but the caller must manage |
| * much of the map decoding. |
| */ |
| void |
| QCBORDecode_Init(QCBORDecodeContext *pCtx, UsefulBufC EncodedCBOR, QCBORDecodeMode nMode); |
| |
| |
| /** |
| * @brief Set up the MemPool string allocator for indefinite-length strings. |
| * |
| * @param[in] pCtx The decode context. |
| * @param[in] MemPool The pointer and length of the memory pool. |
| * @param[in] bAllStrings If true, all strings, even of definite |
| * length, will be allocated with the string |
| * allocator. |
| * |
| * @return Error if the MemPool was greater than @c UINT32_MAX |
| * or less than @ref QCBOR_DECODE_MIN_MEM_POOL_SIZE. |
| * |
| * Indefinite-length strings (text and byte) cannot be decoded unless |
| * there is a string allocator configured. MemPool is a simple |
| * built-in string allocator that allocates bytes from a memory pool |
| * handed to it by calling this function. The memory pool is just a |
| * pointer and length for some block of memory that is to be used for |
| * string allocation. It can come from the stack, heap or other. |
| * |
| * The memory pool must be @ref QCBOR_DECODE_MIN_MEM_POOL_SIZE plus |
| * space for all the strings allocated. There is no overhead per |
| * string allocated. A conservative way to size this buffer is to make |
| * it the same size as the CBOR being decoded plus @ref |
| * QCBOR_DECODE_MIN_MEM_POOL_SIZE. |
| * |
| * This memory pool is used for all indefinite-length strings that are |
| * text strings or byte strings, including strings used as labels. |
| * |
| * The pointers to strings in @ref QCBORItem will point into the |
| * memory pool set here. They do not need to be individually |
| * freed. Just discard the buffer when they are no longer needed. |
| * |
| * If @c bAllStrings is set, then the size will be the overhead plus |
| * the space to hold **all** strings, definite and indefinite-length, |
| * value or label. The advantage of this is that after the decode is |
| * complete, the original memory holding the encoded CBOR does not |
| * need to remain valid. |
| * |
| * This simple allocator is not hard linked to the QCBOR decoder. |
| * Assuming dead-stripping of unused symbols is being performed, this |
| * simple allocator will not be linked in unless |
| * QCBORDecode_SetMemPool() is called. |
| * |
| * See also QCBORDecode_SetUpAllocator() to set up a custom allocator |
| * if this one isn't sufficient. |
| */ |
| QCBORError |
| QCBORDecode_SetMemPool(QCBORDecodeContext *pCtx, |
| UsefulBuf MemPool, |
| bool bAllStrings); |
| |
| |
| /** |
| * @brief Sets up a custom string allocator for indefinite-length strings |
| * |
| * @param[in] pCtx The decoder context to set up an |
| * allocator for. |
| * @param[in] pfAllocateFunction Pointer to function that will be |
| * called by QCBOR for allocations and |
| * frees. |
| * @param[in] pAllocateContext Context passed to @c |
| * pfAllocateFunction. |
| * @param[in] bAllStrings If true, all strings, even of definite |
| * length, will be allocated with the |
| * string allocator. |
| * |
| * Indefinite-length strings (text and byte) cannot be decoded unless |
| * a string allocator is configured. QCBORDecode_SetUpAllocator() |
| * allows the caller to configure an external string allocator |
| * implementation if the internal string allocator is |
| * unsuitable. See QCBORDecode_SetMemPool() to configure the internal |
| * allocator. |
| * |
| * The string allocator configured here is a custom one designed |
| * and implemented by the caller. See @ref QCBORStringAllocate for |
| * the requirements for a string allocator implementation. |
| * |
| * A malloc-based string external allocator can be obtained by calling |
| * @c QCBORDecode_MakeMallocStringAllocator(). It will return a |
| * function and pointer that can be given here as @c pAllocatorFunction |
| * and @c pAllocatorContext. It uses standard @c malloc() so @c free() |
| * must be called on all strings marked by @c uDataAlloc @c == @c 1 or |
| * @c uLabelAlloc @c == @c 1 in @ref QCBORItem. Note this is in a |
| * separate GitHub repository. |
| */ |
| void |
| QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx, |
| QCBORStringAllocate pfAllocateFunction, |
| void *pAllocateContext, |
| bool bAllStrings); |
| |
| |
| /** |
| * @brief Get the next item (integer, byte string, array...) in the |
| * preorder traversal of the CBOR tree. |
| * |
| * @param[in] pCtx The decoder context. |
| * @param[out] pDecodedItem The decoded CBOR item. |
| * |
| * @c pDecodedItem is filled from the decoded item. Generally, the |
| * following data is returned in the structure: |
| * |
| * - @c uDataType which indicates which member of the @c val union the |
| * data is in. This decoder figures out the type based on the CBOR |
| * major type, the CBOR "additionalInfo", the CBOR optional tags and |
| * the value of the integer. |
| * |
| * - The value of the item, which might be an integer, a pointer and a |
| * length, the count of items in an array, a floating-point number or |
| * other. |
| * |
| * - The nesting level for maps and arrays. |
| * |
| * - The label for an item in a map, which may be a text or byte string |
| * or an integer. |
| * |
| * - The unprocessed tag numbers for which the item is the tag content. |
| * |
| * See @ref QCBORItem for all the details about what is returned. |
| * |
| * This function handles arrays and maps. When an array or map is |
| * first encountered a @ref QCBORItem will be returned with major type |
| * @ref QCBOR_TYPE_ARRAY or @ref QCBOR_TYPE_MAP. @c |
| * QCBORItem.val.uNestLevel gives the nesting level of the opening of |
| * the array or map. When the next item is fetched, it will be the |
| * first one in the array or map and its @c QCBORItem.val.uNestLevel |
| * will be one more than that of the opening of the array or map. |
| * |
| * Nesting level 0 is the top-most nesting level. The first item |
| * decoded always has nesting level 0. A map or array at the top level |
| * has nesting level 0 and the members of the array or map have |
| * nesting level 1. |
| * |
| * Here is an example of how the nesting level is reported for a CBOR |
| * sequence with no arrays or maps at all. |
| * |
| * @code |
| * Data Item Nesting Level |
| * integer 0 |
| * byte string 0 |
| * @endcode |
| * |
| * Here is an example of how the nesting level is reported for a CBOR |
| * sequence with a simple array and some top-level items. |
| * |
| * @code |
| * Data Item Nesting Level |
| * integer 0 |
| * array with 2 items 0 |
| * byte string 1 |
| * byte string 1 |
| * integer 0 |
| * @endcode |
| * |
| * Here's a more complex example that is not a CBOR sequence |
| * |
| * @code |
| * Data Item Nesting Level |
| * map with 4 items 0 |
| * text string 1 |
| * array with 3 integers 1 |
| * integer 2 |
| * integer 2 |
| * integer 2 |
| * text string 1 |
| * byte string 1 |
| * @endcode |
| * |
| * In @ref QCBORItem, @c uNextNestLevel is the nesting level for the |
| * next call to QCBORDecode_VGetNext(). It indicates if any maps or |
| * arrays were closed out during the processing of the just-fetched |
| * @ref QCBORItem. This processing includes a look-ahead for any |
| * breaks that close out indefinite-length arrays or maps. This value |
| * is needed to be able to understand the hierarchical structure. If |
| * @c uNextNestLevel is not equal to @c uNestLevel the end of the |
| * current map or array has been encountered. This works for both |
| * definite and indefinite-length arrays so it is the best way to find the |
| * end of a map or array. Alternatively, for definite-length arrays, |
| * @c QCBORItem.val.uCount contains the number of items in the |
| * array. For indefinite-length arrays, @c QCBORItem.val.uCount |
| * is @c UINT16_MAX. |
| * |
| * All tags defined in RFC 8949 are automatically fully decoded. There |
| * are QCBOR_TYPES and members in @ref QCBORItem for them. For |
| * example, the tag 9 will show up in the @ref QCBORItem as type |
| * @ref QCBOR_TYPE_POSBIGNUM with the value in |
| * @c QCBORItem.val.bignum. There is also support for |
| * some of the tags in the IANA tag registry. |
| * |
| * Most tags with a CBOR_TAG_XXX define in qcbor_common.h like @ref |
| * CBOR_TAG_DATE_STRING are automaticlly decoded by QCBOR. Those that |
| * are defined but not decoded are so noted. |
| * |
| * Tags that are not decoded by QCBOR will be identified and recorded |
| * in @ref QCBORItem. Use QCBORDecode_GetNthTag() to get them. Only |
| * @ref QCBOR_MAX_TAGS_PER_ITEM tags are recorded per item and an |
| * error is returned if there are more than that. |
| * |
| * Previous versions of QCBOR handled tags in a more complex way using |
| * QCBORDecode_SetCallerConfiguredTagList() and |
| * QCBORDecode_GetNextWithTags(). This version is largely compatible, but |
| * imposes the limit of @ref QCBOR_MAX_TAGS_PER_ITEM tags per item. |
| * |
| * See @ref Tags-Overview for a description of how to go about |
| * creating custom tags. |
| * |
| * This tag decoding design is to be open-ended and flexible to be |
| * able to handle newly defined tags, while using very little memory, |
| * in particular keeping @ref QCBORItem as small as possible. |
| * |
| * See [Decode Error Overview](#Decode-Errors-Overview). |
| * |
| * If a decoding error occurs or previously occured, @c uDataType and |
| * @c uLabelType will be set to @ref QCBOR_TYPE_NONE. If there is no |
| * need to know the specific error, it is sufficient to check for @ref |
| * QCBOR_TYPE_NONE. |
| * |
| * Errors fall in several categories: |
| * |
| * - Not well-formed errors are those where there is something |
| * syntactically and fundamentally wrong with the CBOR being |
| * decoded. Decoding should stop completely. |
| * |
| * - Invalid CBOR is well-formed, but still not correct. It is |
| * probably best to stop decoding, but not necessary. |
| * |
| * - This implementation has some size limits. They should rarely be |
| * encountered. If they are it may because something is wrong with |
| * the CBOR, for example an array size is incorrect. |
| * |
| * - There are a few CBOR constructs that are not handled without some |
| * extra configuration. These are indefinite length strings and maps |
| * with labels that are not strings or integers. See |
| * QCBORDecode_Init(). Also, the QCBOR library may have been |
| * compiled with some features disabled to reduce code size and this |
| * can result in some errors. |
| * |
| * - Resource exhaustion. This only occurs when a string allocator is |
| * configured to handle indefinite-length strings as other than |
| * that, this implementation does no dynamic memory allocation. |
| * |
| * | Error | Description | |
| * | ---- | ---- | |
| * | __Not well-formed errors__ || |
| * | @ref QCBOR_ERR_HIT_END | Partial data item; need more input bytes to complete decoding | |
| * | @ref QCBOR_ERR_UNSUPPORTED | Input contains CBOR with reserved additional info values | |
| * | @ref QCBOR_ERR_BAD_TYPE_7 | Simple value encoded as two-byte integer rather than one | |
| * | @ref QCBOR_ERR_BAD_BREAK | Break occured outside an indefinite-length map or such | |
| * | @ref QCBOR_ERR_BAD_INT | Length of integer is bad | |
| * | @ref QCBOR_ERR_INDEFINITE_STRING_CHUNK | One of the chunks in indefinite-length string is the wrong type | |
| * | __Invalid CBOR__ || |
| * | @ref QCBOR_ERR_NO_MORE_ITEMS | Need more input data items to decode | |
| * | @ref QCBOR_ERR_BAD_EXP_AND_MANTISSA | The structure of a big float or big number is invalid | |
| * | @ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT | The content of a tag is of the wrong type | |
| * | __Implementation Limits__ || |
| * | @ref QCBOR_ERR_INT_OVERFLOW | Input integer smaller than INT64_MIN | |
| * | @ref QCBOR_ERR_ARRAY_DECODE_TOO_LONG | Array or map has more elements than can be handled | |
| * | @ref QCBOR_ERR_DATE_OVERFLOW | Date larger than can be handled | |
| * | @ref QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP | Nesting deeper than can be handled | |
| * | @ref QCBOR_ERR_STRING_TOO_LONG | Encountered a string longer than size_t can hold less 4 bytes | |
| * | @ref QCBOR_ERR_TOO_MANY_TAGS | Tag nesting deeper than limit, typically 4 | |
| * | __Configuration errors__ || |
| * | @ref QCBOR_ERR_NO_STRING_ALLOCATOR | Encountered indefinite-length string with no allocator configured | |
| * | @ref QCBOR_ERR_MAP_LABEL_TYPE | A map label that is not a string on an integer | |
| * | @ref QCBOR_ERR_HALF_PRECISION_DISABLED | Half-precision input, but disabled in QCBOR library | |
| * | @ref QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED | Indefinite-length input, but disabled in QCBOR library | |
| * | @ref QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED | Indefinite-length input, but disabled in QCBOR library | |
| * | @ref QCBOR_ERR_ALL_FLOAT_DISABLED | Library compiled with floating-point support turned off. | |
| * | __Resource exhaustion errors__ || |
| * | @ref QCBOR_ERR_STRING_ALLOCATE | The string allocator is unable to allocate more memory | |
| */ |
| void |
| QCBORDecode_VGetNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem); |
| |
| |
| /** |
| * @brief Preorder traversal like QCBORDecode_VGetNext() without use |
| * of internal error state. |
| * |
| * @param[in] pCtx The decoder context. |
| * @param[out] pDecodedItem The decoded CBOR item. |
| * |
| * @return See error table of decoding errors set by QCBORDecode_VGetNext(). |
| * |
| * This is the same as QCBORDecode_VGetNext() except it |
| * doesn't set the internal decoding error and will attempt to decode |
| * even if the decoder is in the error state. |
| */ |
| QCBORError |
| QCBORDecode_GetNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem); |
| |
| |
| /** |
| * @brief Get the next item, fully consuming it if it is a map or array. |
| * |
| * @param[in] pCtx The decoder context. |
| * @param[out] pDecodedItem The decoded CBOR item. |
| * |
| * @c pItem returned is the same as QCBORDecode_VGetNext(). If the |
| * item is an array or map, the entire contents of the array or map |
| * will be consumed leaving the cursor after the array or map. |
| * |
| * If an array or map is being consumed by this, an error will occur |
| * if any of the items in the array or map are in error. |
| * |
| * If the item is a tag the contents of which is an array or map, like |
| * a big float, @c pItem will identify it as such and the contents |
| * will be consumed, but the validity of the tag won't be checked |
| * other than for being well-formed. |
| * |
| * In order to go back to decode the contents of an array or map |
| * consumed by this, the decoder must be rewound using |
| * QCBORDecode_Rewind(). |
| */ |
| void |
| QCBORDecode_VGetNextConsume(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem); |
| |
| |
| /** |
| * @brief Get the next data item without consuming it. |
| * |
| * @param[in] pCtx The decoder context. |
| * @param[out] pDecodedItem The decoded CBOR item. |
| * |
| * This is the same as QCBORDecode_VGetNext() but does not consume the |
| * data item. This only looks ahead one item. Calling it repeatedly |
| * will just return the same item over and over. |
| * |
| * This uses about 200 bytes of stack, far more than anything else |
| * here in qcbor_decode.h because it saves a copy of most of the |
| * decode context temporarily. |
| * |
| * This is useful for looking ahead to determine the type of a data |
| * item to know which type-specific spiffy decode function to call or |
| * decoding protocols where the types of later data items |
| * depending on type of earlier ones. |
| * |
| * The error must be retrieved with QCBORDecode_GetError() and checked |
| * to know the peek was successful before referencing the contents of |
| * @c pDecodedItem. |
| */ |
| void |
| QCBORDecode_VPeekNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem); |
| |
| |
| /** |
| * @brief Get the next data item without consuming it without use |
| * of internal error state. |
| * |
| * @param[in] pCtx The decoder context. |
| * @param[out] pDecodedItem The decoded CBOR item. |
| * |
| * This is the same as QCBORDecode_VPeekNext() except it doesn't set |
| * the internal decoding error and will attempt to decode even if the |
| * decoder is in the error state. |
| */ |
| QCBORError |
| QCBORDecode_PeekNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem); |
| |
| |
| /** |
| * @brief Get the current traversal cursort offset in the input CBOR. |
| * |
| * @param[in] pCtx The decoder context. |
| * |
| * @returns The traversal cursor offset or @c UINT32_MAX. |
| |
| * The position returned is always the start of the next item that |
| * would be next decoded with QCBORDecode_VGetNext(). The cursor |
| * returned may be at the end of the input in which case the next call |
| * to QCBORDecode_VGetNext() will result in the @ref |
| * QCBOR_ERR_NO_MORE_ITEMS. See also QCBORDecode_AtEnd(). |
| * |
| * If the decoder is in error state from previous decoding, |
| * @c UINT32_MAX is returned. |
| * |
| * When decoding map items, the position returned is always of the |
| * label, never the value. |
| * |
| * For indefinite-length arrays and maps, the break byte is consumed |
| * when the last item in the array or map is consumed so the cursor is |
| * at the next item to be decoded as expected. |
| * |
| * There are some special rules for the traversal cursor when fetching |
| * map items by label. See the description of @SpiffyDecode. |
| * |
| * When traversal is bounded because an array or map has been entered |
| * (e.g., QCBORDecode_EnterMap()) and all items in the array or map |
| * have been consumed, the position returned will be of the item |
| * outside of the array or map. The array or map must be exited before |
| * QCBORDecode_VGetNext() will decode it. |
| * |
| * In many cases the position returned will be in the middle of |
| * an array or map. It will not be possible to start decoding at |
| * that location with another instance of the decoder and go to |
| * the end. It is not valid CBOR. If the input is a CBOR sequence |
| * and the position is not in the moddle of an array or map |
| * then it is possible to decode to the end. |
| * |
| * There is no corresponding seek method because it is too complicated |
| * to restore the internal decoder state that tracks nesting. |
| */ |
| static uint32_t |
| QCBORDecode_Tell(QCBORDecodeContext *pCtx); |
| |
| |
| /** |
| * @brief Tell whether cursor is at end of the input. |
| * |
| * @param[in] pCtx The decoder context. |
| * |
| * @returns Error code possibly indicating end of input. |
| * |
| * This returns the same as QCBORDecode_GetError() except that @ref |
| * QCBOR_ERR_NO_MORE_ITEMS is returned if the travseral cursor is at |
| * the end of the CBOR input bytes (not the end of an entered array or |
| * map). |
| */ |
| QCBORError |
| QCBORDecode_EndCheck(QCBORDecodeContext *pCtx); |
| |
| |
| /** |
| * @brief Returns the tag numbers for an item. |
| * |
| * @param[in] pCtx The decoder context. |
| * @param[in] pItem The CBOR item to get the tag for. |
| * @param[in] uIndex The index of the tag to get. |
| * |
| * @returns The nth tag number or CBOR_TAG_INVALID64. |
| * |
| * When QCBOR decodes an item that is a tag, it will fully decode tags |
| * it is able to. Tags that it is unable to process are put in a list |
| * in the QCBORItem. |
| * |
| * Tags nest. Here the tag with index 0 has the data item as its content. The |
| * tag with index 1 has the tag at index 0 has its content and so forth. |
| * |
| * Deep tag nesting is rare so this implementation imposes a limit of |
| * @ref QCBOR_MAX_TAGS_PER_ITEM on nesting and returns @ref |
| * QCBOR_ERR_TOO_MANY_TAGS if there are more. This is a limit of this |
| * implementation, not of CBOR. (To be able to handle deeper |
| * nesting, the constant can be increased and the library |
| * recompiled. It will use more memory). |
| * |
| * See also @ref CBORTags, @ref Tag-Usage and @ref Tags-Overview. |
| * |
| * To reduce memory used by a QCBORItem, tag numbers larger than |
| * @c UINT16_MAX are mapped so the tag numbers in @c uTags should be |
| * accessed with this function rather than directly. |
| * |
| * This returns @ref CBOR_TAG_INVALID64 if any error occurred when |
| * getting the item. This is also returned if there are no tags on the |
| * item or no tag at @c uIndex. |
| */ |
| uint64_t |
| QCBORDecode_GetNthTag(QCBORDecodeContext *pCtx, const QCBORItem *pItem, uint32_t uIndex); |
| |
| |
| /** |
| * @brief Returns the tag numbers for last-decoded item. |
| * |
| * @param[in] pCtx The decoder context. |
| * @param[in] uIndex The index of the tag to get. |
| * |
| * @returns The nth tag number or CBOR_TAG_INVALID64. |
| * |
| * This returns tags of the most recently decoded item. See |
| * QCBORDecode_GetNthTag(). This is particularly of use for spiffy |
| * decode functions that don't return a @ref QCBORItem. |
| * |
| * This does not work for QCBORDecode_GetNext(), |
| * QCBORDecode_PeekNext(), QCBORDecode_VPeekNext() or |
| * QCBORDecode_VGetNextConsume() but these all return a |
| * @ref QCBORItem, so it is not necessary. |
| * |
| * If a decoding error is set, then this returns CBOR_TAG_INVALID64. |
| */ |
| uint64_t |
| QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pCtx, uint32_t uIndex); |
| |
| |
| /** |
| * @brief Check that a decode completed successfully. |
| * |
| * @param[in] pCtx The context to check. |
| * |
| * @returns The internal tracked decode error or @ref QCBOR_SUCCESS. |
| * |
| * Please see @ref Decode-Errors-Overview "Decode Errors Overview". |
| * |
| * This should always be called at the end of a decode to determine if |
| * it completed successfully. For some protocols, checking the return |
| * value here may be the only error check necessary. |
| * |
| * This returns the internal tracked error if the decoder is in the |
| * error state, the same one returned by QCBORDecode_GetError(). This |
| * performs final checks at the end of the decode, and may also return |
| * @ref QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN |
| * or @ref QCBOR_ERR_EXTRA_BYTES. |
| * |
| * This calls the destructor for the string allocator, if one is in |
| * use. Because of this, It can't be called multiple times like |
| * QCBORDecode_PartialFinish(). |
| * |
| * Some CBOR protocols use a CBOR sequence defined in [RFC 8742] |
| * (https://tools.ietf.org/html/rfc8742). A CBOR sequence typically |
| * doesn't start out with a map or an array. The end of the CBOR is |
| * determined in some other way, perhaps by external framing, or by |
| * the occurrence of some particular CBOR data item or such. The |
| * buffer given to decode must start out with valid CBOR, but it can |
| * have extra bytes at the end that are not CBOR or CBOR that is to be |
| * ignored. |
| * |
| * QCBORDecode_Finish() should still be called when decoding CBOR |
| * sequences to check that the input decoded was well-formed. If the |
| * input was well-formed and there are extra bytes at the end @ref |
| * QCBOR_ERR_EXTRA_BYTES will be returned. This can be considered a |
| * successful decode. See also QCBORDecode_PartialFinish(). |
| */ |
| QCBORError |
| QCBORDecode_Finish(QCBORDecodeContext *pCtx); |
| |
| |
| /** |
| * @brief Return number of bytes consumed so far. |
| * |
| * @param[in] pCtx The context to check. |
| * @param[out] puConsumed The number of bytes consumed so far. |
| * May be @c NULL. |
| * |
| * @returns The same as QCBORDecode_Finish(); |
| * |
| * This is primarily for partially decoding CBOR sequences. It is the |
| * same as QCBORDecode_Finish() except it returns the number of bytes |
| * consumed and doesn't call the destructor for the string allocator |
| * (See @ref QCBORDecode_SetMemPool()). |
| * |
| * When this is called before all input bytes are consumed, @ref |
| * QCBOR_ERR_EXTRA_BYTES will be returned as QCBORDecode_Finish() |
| * does. For typical use of this, that particular error is disregarded. |
| * |
| * Decoding with the same @ref QCBORDecodeContext can continue after |
| * calling this and this may be called many times. |
| * |
| * Another way to resume decoding is to call QCBORDecode_Init() with the |
| * bytes not decoded, but this only works on CBOR sequences when the |
| * decoding stopped with no open arrays, maps or byte strings. |
| */ |
| QCBORError |
| QCBORDecode_PartialFinish(QCBORDecodeContext *pCtx, size_t *puConsumed); |
| |
| |
| /** |
| * @brief Retrieve the undecoded input buffer. |
| * |
| * @param[in] pCtx The decode context. |
| * |
| * @return The input that was given to QCBORDecode_Init(). |
| * |
| * A simple convenience method, should it be useful to get the original input back. |
| */ |
| static UsefulBufC |
| QCBORDecode_RetrieveUndecodedInput(QCBORDecodeContext *pCtx); |
| |
| |
| /** |
| * @brief Get the decoding error. |
| * |
| * @param[in] pCtx The decoder context. |
| * @return The decoding error. |
| * |
| * Please see @ref Decode-Errors-Overview "Decode Errors Overview". |
| * |
| * The returns the tracked internal error code. All decoding functions |
| * set the internal error except QCBORDecode_GetNext() and |
| * QCBORDecode_PeekNext(). |
| * |
| * For many protocols it is only necessary to check the return code |
| * from QCBORDecode_Finish() at the end of all the decoding. It is |
| * unnecessary to call this. |
| * |
| * For some protocols, the decoding sequence depends on the types, |
| * values or labels of data items. If so, this must be called before |
| * using decoded values to know the decode was a success and the |
| * type, value and label is valid. |
| * |
| * Some errors, like integer conversion overflow, date string format |
| * may not affect the flow of a protocol. The protocol decoder may |
| * wish to proceed even if they occur. In that case |
| * QCBORDecode_GetAndResetError() may be called after these data items |
| * are fetched. |
| */ |
| static QCBORError |
| QCBORDecode_GetError(QCBORDecodeContext *pCtx); |
| |
| |
| /** |
| * @brief Get and reset the decoding error. |
| * |
| * @param[in] pCtx The decoder context. |
| * @returns The decoding error. |
| * |
| * This returns the same as QCBORDecode_GetError() and also resets the |
| * error state to @ref QCBOR_SUCCESS. |
| */ |
| static QCBORError |
| QCBORDecode_GetAndResetError(QCBORDecodeContext *pCtx); |
| |
| |
| /** |
| * @brief Whether an error indicates non-well-formed CBOR. |
| * |
| * @param[in] uErr The QCBOR error code. |
| * @return @c true if the error code indicates non-well-formed CBOR. |
| */ |
| static bool |
| QCBORDecode_IsNotWellFormedError(QCBORError uErr); |
| |
| |
| /** |
| * @brief Whether a decoding error is recoverable. |
| * |
| * @param[in] uErr The QCBOR error code. |
| * @return @c true if the error code indicates and uncrecoverable error. |
| * |
| * When an error is unrecoverable, no further decoding of the input is |
| * possible. CBOR is a compact format with almost no redundancy so |
| * errors like incorrect lengths or array counts are |
| * unrecoverable. Unrecoverable errors also occur when implementation |
| * limits such as the limit on array and map nesting are encountered. |
| * When the built-in decoding of a tag like an epoch date encounters |
| * an error such as a data item of an unexpected type, this is also an |
| * unrecoverable error because the internal decoding doesn't try to |
| * decode everything in the tag. |
| * |
| * The unrecoverable errors are a range of the errors in |
| * @ref QCBORError. |
| */ |
| static bool |
| QCBORDecode_IsUnrecoverableError(QCBORError uErr); |
| |
| |
| /** |
| * @brief Manually set error condition, or set user-defined error. |
| * |
| * @param[in] pCtx The decoder context. |
| * @param[in] uError The error code to set. |
| * |
| * Once set, none of the QCBORDecode methods will do anything and the |
| * error code set will stay until cleared with |
| * QCBORDecode_GetAndResetError(). A user-defined error can be set |
| * deep in some decoding layers to short-circuit further decoding |
| * and propagate up. |
| * |
| * When the error condition is set, QCBORDecode_VGetNext() will always |
| * return an item with data and label type as @ref QCBOR_TYPE_NONE. |
| * |
| * The main intent of this is to set a user-defined error code in the |
| * range of @ref QCBOR_ERR_FIRST_USER_DEFINED to |
| * @ref QCBOR_ERR_LAST_USER_DEFINED, but it is OK to set QCBOR-defined |
| * error codes too. |
| */ |
| static void |
| QCBORDecode_SetError(QCBORDecodeContext *pCtx, QCBORError uError); |
| |
| |
| |
| |
| /** |
| * @brief Convert int64_t to smaller integers safely. |
| * |
| * @param [in] src An @c int64_t. |
| * @param [out] dest A smaller sized integer to convert to. |
| * |
| * @return 0 on success -1 if not |
| * |
| * When decoding an integer, the CBOR decoder will return the value as |
| * an int64_t unless the integer is in the range of @c INT64_MAX and |
| * @c UINT64_MAX. That is, unless the value is so large that it can only be |
| * represented as a @c uint64_t, it will be an @c int64_t. |
| * |
| * CBOR itself doesn't size the individual integers it carries at |
| * all. The only limits it puts on the major integer types is that they |
| * are 8 bytes or less in length. Then encoders like this one use the |
| * smallest number of 1, 2, 4 or 8 bytes to represent the integer based |
| * on its value. There is thus no notion that one data item in CBOR is |
| * a 1-byte integer and another is a 4-byte integer. |
| * |
| * The interface to this CBOR encoder only uses 64-bit integers. Some |
| * CBOR protocols or implementations of CBOR protocols may not want to |
| * work with something smaller than a 64-bit integer. Perhaps an array |
| * of 1,000 integers needs to be sent and none has a value larger than |
| * 50,000 and are represented as @c uint16_t. |
| * |
| * The sending / encoding side is easy. Integers are temporarily widened |
| * to 64-bits as a parameter passing through QCBOREncode_AddInt64() and |
| * encoded in the smallest way possible for their value, possibly in |
| * less than an @c uint16_t. |
| * |
| * On the decoding side the integers will be returned at @c int64_t even if |
| * they are small and were represented by only 1 or 2 bytes in the |
| * encoded CBOR. The functions here will convert integers to a small |
| * representation with an overflow check. |
| * |
| * (The decoder could have support 8 different integer types and |
| * represented the integer with the smallest type automatically, but |
| * this would have made the decoder more complex and code calling the |
| * decoder more complex in most use cases. In most use cases on 64-bit |
| * machines it is no burden to carry around even small integers as |
| * 64-bit values). |
| */ |
| static inline int |
| QCBOR_Int64ToInt32(int64_t src, int32_t *dest) |
| { |
| if(src > INT32_MAX || src < INT32_MIN) { |
| return -1; |
| } else { |
| *dest = (int32_t) src; |
| } |
| return 0; |
| } |
| |
| static inline int |
| QCBOR_Int64ToInt16(int64_t src, int16_t *dest) |
| { |
| if(src > INT16_MAX || src < INT16_MIN) { |
| return -1; |
| } else { |
| *dest = (int16_t) src; |
| } |
| return 0; |
| } |
| |
| static inline int |
| QCBOR_Int64ToInt8(int64_t src, int8_t *dest) |
| { |
| if(src > INT8_MAX || src < INT8_MIN) { |
| return -1; |
| } else { |
| *dest = (int8_t) src; |
| } |
| return 0; |
| } |
| |
| static inline int |
| QCBOR_Int64ToUInt32(int64_t src, uint32_t *dest) |
| { |
| if(src > UINT32_MAX || src < 0) { |
| return -1; |
| } else { |
| *dest = (uint32_t) src; |
| } |
| return 0; |
| } |
| |
| /** |
| * https://github.com/laurencelundblade/QCBOR/pull/243 |
| * For backwards compatibility |
| */ |
| #define QCBOR_Int64UToInt16 QCBOR_Int64ToUInt16 |
| |
| static inline int |
| QCBOR_Int64ToUInt16(int64_t src, uint16_t *dest) |
| { |
| if(src > UINT16_MAX || src < 0) { |
| return -1; |
| } else { |
| *dest = (uint16_t) src; |
| } |
| return 0; |
| } |
| |
| static inline int |
| QCBOR_Int64ToUInt8(int64_t src, uint8_t *dest) |
| { |
| if(src > UINT8_MAX || src < 0) { |
| return -1; |
| } else { |
| *dest = (uint8_t) src; |
| } |
| return 0; |
| } |
| |
| static inline int |
| QCBOR_Int64ToUInt64(int64_t src, uint64_t *dest) |
| { |
| if(src < 0) { |
| return -1; |
| } else { |
| *dest = (uint64_t) src; |
| } |
| return 0; |
| } |
| |
| |
| |
| |
| /* ========================================================================= * |
| * BEGINNING OF DEPRECATED FUNCTIONS * |
| * * |
| * There is no plan to remove these in future versions. * |
| * They just have been replaced by something better. * |
| * ========================================================================= */ |
| |
| /** |
| * Deprecated -- Tag handling has been revised and this is no longer |
| * used. See QCBORDecode_GetNthTag() for new tag handling. |
| */ |
| typedef struct { |
| uint8_t uNumTags; |
| const uint64_t *puTags; |
| } QCBORTagListIn; |
| |
| |
| /** |
| * Deprecated -- this is retained only for backwards compatibility. |
| * Use QCBORDecode_GetNthTag() instead. |
| * |
| * This is for QCBORDecode_GetNextWithTags() to be able to return the |
| * full list of tags on an item. |
| * |
| * On input, @c puTags points to a buffer to be filled in and |
| * uNumAllocated is the number of @c uint64_t values in the buffer. |
| * |
| * On output the buffer contains the tags for the item. @c uNumUsed |
| * tells how many there are. |
| */ |
| typedef struct { |
| uint8_t uNumUsed; |
| uint8_t uNumAllocated; |
| uint64_t *puTags; |
| } QCBORTagListOut; |
| |
| |
| /** |
| * @brief Deprecated -- Configure list of caller-selected tags to be recognized. |
| * |
| * @param[in] pCtx The decode context. |
| * @param[out] pTagList Structure holding the list of tags to configure. |
| * |
| * Tag handling has been revised and it is no longer ncessary to use |
| * this. See QCBORDecode_GetNthTag(). |
| */ |
| void |
| QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pCtx, |
| const QCBORTagListIn *pTagList); |
| |
| |
| /** |
| * @brief Deprecated -- Determine if a CBOR item is a particular tag. |
| * |
| * @param[in] pCtx The decoder context. |
| * @param[in] pItem The CBOR item to check. |
| * @param[in] uTag The tag to check, one of @c CBOR_TAG_XXX, |
| * for example, @ref CBOR_TAG_DATE_STRING. |
| * |
| * @return true if it was tagged, false if not. |
| * |
| * See QCBORDecode_GetNext() for the main description of tag |
| * handling. For tags that are not fully decoded a bit corresponding |
| * to the tag is set in in @c uTagBits in the @ref QCBORItem. The |
| * particular bit depends on an internal mapping table. This function |
| * checks for set bits against the mapping table. |
| * |
| * Typically, a protocol implementation just wants to know if a |
| * particular tag is present. That is what this provides. To get the |
| * full list of tags on a data item, see |
| * QCBORDecode_GetNextWithTags(). |
| * |
| * Also see QCBORDecode_SetCallerConfiguredTagList() for the means to |
| * add new tags to the internal list so they can be checked for with |
| * this function. |
| */ |
| bool |
| QCBORDecode_IsTagged(QCBORDecodeContext *pCtx, |
| const QCBORItem *pItem, |
| uint64_t uTag); |
| |
| |
| /** |
| * @brief Deprecated -- Gets the next item including full list of tags for item. |
| * |
| * @param[in] pCtx The decoder context. |
| * @param[out] pDecodedItem Holds the CBOR item just decoded. |
| * @param[in,out] pTagList On input array to put tags in; on output |
| * the tags on this item. See |
| * @ref QCBORTagListOut. |
| * |
| * @return See return values for QCBORDecode_GetNext(). |
| * |
| * @retval QCBOR_ERR_TOO_MANY_TAGS The size of @c pTagList is too small. |
| * |
| * This is retained for backwards compatibility. It is replaced by |
| * QCBORDecode_GetNthTag() which also returns all the tags that have |
| * been decoded. |
| * |
| * This is not backwards compatibile in two ways. First, it is limited |
| * to @ref QCBOR_MAX_TAGS_PER_ITEM items whereas previously it was |
| * unlimited. Second, it will not inlucde the tags that QCBOR decodes |
| * internally. |
| * |
| * This works the same as QCBORDecode_GetNext() except that it also |
| * returns the list of tags for the data item in @c pTagList. |
| * |
| * The 0th tag returned here is the one furthest from the data |
| * item. This is opposite the order for QCBORDecode_GetNthTag(). |
| * |
| * CBOR has no upper bound or limit on the number of tags that can be |
| * associated with a data item but in practice the number of tags on |
| * an item will usually be small. This will return @ref |
| * QCBOR_ERR_TOO_MANY_TAGS if the array in @c pTagList is too small to |
| * hold all the tags for the item. |
| */ |
| QCBORError |
| QCBORDecode_GetNextWithTags(QCBORDecodeContext *pCtx, |
| QCBORItem *pDecodedItem, |
| QCBORTagListOut *pTagList); |
| |
| |
| /* ========================================================================= * |
| * END OF DEPRECATED FUNCTIONS * |
| * ========================================================================= */ |
| |
| |
| |
| |
| /* ========================================================================= * |
| * BEGINNING OF PRIVATE INLINE IMPLEMENTATION * |
| * ========================================================================= */ |
| |
| static inline uint32_t |
| QCBORDecode_Tell(QCBORDecodeContext *pMe) |
| { |
| if(pMe->uLastError) { |
| return UINT32_MAX; |
| } |
| |
| /* Cast is safe because decoder input size is restricted. */ |
| return (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf)); |
| } |
| |
| static inline UsefulBufC |
| QCBORDecode_RetrieveUndecodedInput(QCBORDecodeContext *pMe) |
| { |
| return UsefulInputBuf_RetrieveUndecodedInput(&(pMe->InBuf)); |
| } |
| |
| static inline QCBORError |
| QCBORDecode_GetError(QCBORDecodeContext *pMe) |
| { |
| return (QCBORError)pMe->uLastError; |
| } |
| |
| static inline QCBORError |
| QCBORDecode_GetAndResetError(QCBORDecodeContext *pMe) |
| { |
| const QCBORError uReturn = (QCBORError)pMe->uLastError; |
| pMe->uLastError = QCBOR_SUCCESS; |
| return uReturn; |
| } |
| |
| static inline bool |
| QCBORDecode_IsNotWellFormedError(const QCBORError uErr) |
| { |
| if(uErr >= QCBOR_START_OF_NOT_WELL_FORMED_ERRORS && |
| uErr <= QCBOR_END_OF_NOT_WELL_FORMED_ERRORS) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| static inline bool |
| QCBORDecode_IsUnrecoverableError(const QCBORError uErr) |
| { |
| if(uErr >= QCBOR_START_OF_UNRECOVERABLE_DECODE_ERRORS && |
| uErr <= QCBOR_END_OF_UNRECOVERABLE_DECODE_ERRORS) { |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| |
| static inline void |
| QCBORDecode_SetError(QCBORDecodeContext *pMe, QCBORError uError) |
| { |
| pMe->uLastError = (uint8_t)uError; |
| } |
| |
| /* ======================================================================== * |
| * END OF PRIVATE INLINE IMPLEMENTATION * |
| * ======================================================================== */ |
| |
| |
| /* A few cross checks on size constants and special value lengths */ |
| #if QCBOR_MAP_OFFSET_CACHE_INVALID < QCBOR_MAX_DECODE_INPUT_SIZE |
| #error QCBOR_MAP_OFFSET_CACHE_INVALID is too large |
| #endif |
| |
| #if QCBOR_NON_BOUNDED_OFFSET < QCBOR_MAX_DECODE_INPUT_SIZE |
| #error QCBOR_NON_BOUNDED_OFFSET is too large |
| #endif |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* qcbor_decode_h */ |