Merge some feature adds from QCBOR 1.x into dev
diff --git a/inc/qcbor/UsefulBuf.h b/inc/qcbor/UsefulBuf.h
index 1a4a3bf..95f0571 100644
--- a/inc/qcbor/UsefulBuf.h
+++ b/inc/qcbor/UsefulBuf.h
@@ -43,7 +43,8 @@
when who what, where, why
-------- ---- --------------------------------------------------
- 28/02/2022 llundblade Rearrange UsefulOutBuf_Compare().
+ 10/05/2024 llundblade Add Xxx_OffsetToPointer.
+ 28/02/2024 llundblade Rearrange UsefulOutBuf_Compare().
19/11/2023 llundblade Add UsefulOutBuf_GetOutput().
19/11/2023 llundblade Add UsefulOutBuf_Swap().
19/11/2023 llundblade Add UsefulOutBuf_Compare().
@@ -651,16 +652,27 @@
/**
- @brief Convert a pointer to an offset with bounds checking.
-
- @param[in] UB Pointer to the UsefulInputBuf.
- @param[in] p Pointer to convert to offset.
-
- @return SIZE_MAX if @c p is out of range, the byte offset if not.
+ * @brief Convert a pointer to an offset with bounds checking.
+ *
+ * @param[in] UB A UsefulBuf.
+ * @param[in] p Pointer to convert to offset.
+ *
+ * @return SIZE_MAX if @c p is out of range, the byte offset if not.
*/
static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
+/**
+ * @brief Convert an offset to a pointer with bounds checking.
+ *
+ * @param[in] UB A UsefulBuf.
+ * @param[in] uOffset Offset in @c pUInBuf.
+ *
+ * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
+ */
+static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset);
+
+
#ifndef USEFULBUF_DISABLE_DEPRECATED
/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
@@ -1589,7 +1601,18 @@
*
* @return SIZE_MAX if @c p is out of range, the byte offset if not.
*/
-static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
+static size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
+
+
+/**
+ * @brief Convert an offset to a pointer with bounds checking.
+ *
+ * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
+ * @param[in] uOffset Offset in @c pUInBuf.
+ *
+ * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
+ */
+static const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset);
/**
@@ -1955,6 +1978,18 @@
}
+static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset)
+{
+ if(UsefulBuf_IsNULLC(UB) || uOffset >= UB.len) {
+ return NULL;
+ }
+
+ return (const uint8_t *)UB.ptr + uOffset;
+}
+
+
+
+
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
{
@@ -2361,6 +2396,12 @@
}
+static inline const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset)
+ {
+ return UsefulBuf_OffsetToPointer(pUInBuf->UB, uOffset);
+ }
+
+
static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
{
const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
diff --git a/inc/qcbor/qcbor_common.h b/inc/qcbor/qcbor_common.h
index 8c6c125..652cf01 100644
--- a/inc/qcbor/qcbor_common.h
+++ b/inc/qcbor/qcbor_common.h
@@ -238,7 +238,7 @@
/**
- * Error codes returned by QCBOR Encoder and Decoder.
+ * Error codes returned by QCBOR Encoder-Decoder.
*
* They are grouped to keep the code size of
* QCBORDecode_IsNotWellFormedError() and
@@ -535,6 +535,10 @@
* negative integer) without allowing it by calling
* QCBOREncode_Allow() */
QCBOR_ERR_NOT_ALLOWED = 80,
+ /** QCBORDecode_EnterBstrWrapped() cannot be used on
+ * indefinite-length strings because they exist in memory pool for
+ * a @ref QCBORStringAllocate. */
+ QCBOR_ERR_CANNOT_ENTER_ALLOCATED_STRING = 81,
/** A range of error codes that can be made use of by the
* caller. QCBOR internally does nothing with these except notice
diff --git a/inc/qcbor/qcbor_decode.h b/inc/qcbor/qcbor_decode.h
index 69dbbc1..d7010d9 100644
--- a/inc/qcbor/qcbor_decode.h
+++ b/inc/qcbor/qcbor_decode.h
@@ -56,7 +56,7 @@
* # QCBOR Basic Decode
*
* This section discusses decoding assuming familiarity with the
- * general description of this encoder / decoder in section @ref
+ * general description of this encoder-decoder in section @ref
* Overview.
*
* Encoded CBOR has a tree structure where the leaf nodes are
@@ -64,9 +64,9 @@
* 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. It is possible to decode any CBOR by only calling
- * QCBORDecode_GetNext(), though this doesn't take advantage of many
- * QCBOR features.
+ * 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:
@@ -198,8 +198,8 @@
} QCBORDecodeMode;
/**
- * The maximum size of input to the decoder. Slightly less than UINT32_MAX
- * to make room for some special indicator values.
+ * 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)
@@ -989,10 +989,19 @@
* @param[in] pCtx The decoder context.
* @param[out] pDecodedItem The decoded CBOR item.
*
- * This is the same as QCBORDecode_VGetNext() but the contents of the
- * entire map or array will be consumed if the item is a map or array.
+ * @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.
*
- * In order to go back to decode the contents of a map or array
+ * 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().
*/
@@ -1043,6 +1052,48 @@
/**
+ * @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(). If the cursor
+ * is at the end of the input or in the error state, @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.
+ */
+uint32_t
+QCBORDecode_Tell(QCBORDecodeContext *pCtx);
+
+
+/**
* @brief Returns the tag numbers for an item.
*
* @param[in] pCtx The decoder context.
@@ -1068,7 +1119,7 @@
* See also @ref CBORTags, @ref Tag-Usage and @ref Tags-Overview.
*
* To reduce memory used by a QCBORItem, tag numbers larger than
- * UINT16_MAX are mapped so the tag numbers in @c uTags should be
+ * @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
@@ -1281,8 +1332,8 @@
* @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
+ * 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
@@ -1494,7 +1545,7 @@
* 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
+ * to @ref QCBOR_MAX_TAGS_PER_ITEM items whereas previously it was
* unlimited. Second, it will not inlucde the tags that QCBOR decodes
* internally.
*
diff --git a/inc/qcbor/qcbor_encode.h b/inc/qcbor/qcbor_encode.h
index 694c2a3..008ee91 100644
--- a/inc/qcbor/qcbor_encode.h
+++ b/inc/qcbor/qcbor_encode.h
@@ -341,7 +341,7 @@
* float type as 32-bits and a C double type as 64-bits. Floating-point
* epoch dates will be unsupported.
*
- * If USEFULBUF_DISABLE_ALL_FLOATis defined, then floating point
+ * If USEFULBUF_DISABLE_ALL_FLOAT is defined, then floating point
* support is completely disabled. Decoding functions return
* @ref QCBOR_ERR_ALL_FLOAT_DISABLED if a floating point value is
* encountered during decoding. Functions that are encoding floating
@@ -349,31 +349,33 @@
*
* ## Limitations
*
- * Summary Limits of this implementation:
+ * Summary limitations:
* - The entire encoded CBOR must fit into contiguous memory.
- * - Max size of encoded / decoded CBOR data is a few bytes less than @c UINT32_MAX (4GB).
- * - Max array / map nesting level when encoding / decoding is
+ * - Max size of encoded CBOR data is a few bytes less than
+ * @c UINT32_MAX (4GB).
+ * - Max array / map nesting level when encoding or decoding is
* @ref QCBOR_MAX_ARRAY_NESTING (this is typically 15).
- * - Max items in an array or map when encoding / decoding is
+ * - Max items in an array or map when encoding or decoding is
* @ref QCBOR_MAX_ITEMS_IN_ARRAY (typically 65,536).
* - Does not directly support labels in maps other than text strings & integers.
- * - Does not directly support integer labels greater than @c INT64_MAX.
+ * - Does not directly support integer labels beyond whats fits in @c int64_t
+ * or @c uint64_t.
* - Epoch dates limited to @c INT64_MAX (+/- 292 billion years).
- * - Exponents for bigfloats and decimal integers are limited to @c INT64_MAX.
+ * - Exponents for bigfloats and decimal integers are limited to whats fits in
+ * @c int64_t.
* - Tags on labels are ignored during decoding.
* - The maximum tag nesting is @c QCBOR_MAX_TAGS_PER_ITEM (typically 4).
- * - Works only on 32- and 64-bit CPUs (modifications could make it work
- * on 16-bit CPUs).
+ * - Works only on 32- and 64-bit CPUs.
+ * - QCBORDecode_EnterBstrWrapped() doesn't work on indefinite-length strings.
*
* The public interface uses @c size_t for all lengths. Internally the
* implementation uses 32-bit lengths by design to use less memory and
* fit structures on the stack. This limits the encoded CBOR it can
- * work with to size @c UINT32_MAX (4GB) which should be enough.
+ * work with to size @c UINT32_MAX (4GB).
*
- * This implementation assumes two's compliment integer machines.
- * @c <stdint.h> also requires this. It is possible to modify this
- * implementation for another integer representation, but all modern
- * machines seem to be two's compliment.
+ * This implementation requires two's compliment integers. While
+ * C doesn't require two's compliment, <stdint.h> does. Other
+ * parts of this implementation may also require two's compliment.
*/
@@ -4116,15 +4118,17 @@
QCBOREncode_GetErrorState(QCBOREncodeContext *pMe)
{
if(UsefulOutBuf_GetError(&(pMe->OutBuf))) {
- // Items didn't fit in the buffer.
- // This check catches this condition for all the appends and inserts
- // so checks aren't needed when the appends and inserts are performed.
- // And of course UsefulBuf will never overrun the input buffer given
- // to it. No complex analysis of the error handling in this file is
- // needed to know that is true. Just read the UsefulBuf code.
+ /* Items didn't fit in the buffer. This check catches this
+ * condition for all the appends and inserts so checks aren't
+ * needed when the appends and inserts are performed. And of
+ * course UsefulBuf will never overrun the input buffer given to
+ * it. No complex analysis of the error handling in this file is
+ * needed to know that is true. Just read the UsefulBuf code.
+ */
pMe->uError = QCBOR_ERR_BUFFER_TOO_SMALL;
- // QCBOR_ERR_BUFFER_TOO_SMALL masks other errors, but that is
- // OK. Once the caller fixes this, they'll be unmasked.
+ /* QCBOR_ERR_BUFFER_TOO_SMALL masks other errors, but that is
+ * OK. Once the caller fixes this, they'll be unmasked.
+ */
}
return (QCBORError)pMe->uError;
diff --git a/inc/qcbor/qcbor_private.h b/inc/qcbor/qcbor_private.h
index ea543b0..20e99ba 100644
--- a/inc/qcbor/qcbor_private.h
+++ b/inc/qcbor/qcbor_private.h
@@ -269,13 +269,13 @@
* 1) Byte count tracking. This is for the top level input CBOR
* which might be a single item or a CBOR sequence and byte
* string wrapped encoded CBOR.
- * 2) Item tracking. This is for maps and arrays.
+ * 2) Item count tracking. This is for maps and arrays.
*
* uLevelType has value QCBOR_TYPE_BYTE_STRING for 1) and
* QCBOR_TYPE_MAP or QCBOR_TYPE_ARRAY or QCBOR_TYPE_MAP_AS_ARRAY
* for 2).
*
- * Item tracking is either for definite or indefinite-length
+ * Item count tracking is either for definite or indefinite-length
* maps/arrays. For definite lengths, the total count and items
* unconsumed are tracked. For indefinite-length, uTotalCount is
* QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH (UINT16_MAX) and
@@ -286,16 +286,16 @@
* uCountCursor is QCBOR_COUNT_INDICATES_ZERO_LENGTH to indicate
* it is empty.
*
- * This also records whether a level is bounded or not. All
+ * This also records whether a level is bounded or not. All
* byte-count tracked levels (the top-level sequence and
- * bstr-wrapped CBOR) are bounded. Maps and arrays may or may
- * not be bounded. They are bounded if they were Entered() and
- * not if they were traversed with GetNext(). They are marked as
- * bounded by uStartOffset not being UINT32_MAX.
+ * bstr-wrapped CBOR) are bounded implicitly. Maps and arrays
+ * may or may not be bounded. They are bounded if they were
+ * Entered() and not if they were traversed with GetNext(). They
+ * are marked as bounded by uStartOffset not being @c UINT32_MAX.
*/
/*
* If uLevelType can put in a separately indexed array, the
- * union/ struct will be 8 bytes rather than 9 and a lot of
+ * union/struct will be 8 bytes rather than 9 and a lot of
* wasted padding for alignment will be saved.
*/
uint8_t uLevelType;
@@ -306,6 +306,8 @@
uint16_t uCountTotal;
uint16_t uCountCursor;
#define QCBOR_NON_BOUNDED_OFFSET UINT32_MAX
+ /* The start of the array or map in bounded mode so
+ * the input can be rewound for GetInMapXx() by label. */
uint32_t uStartOffset;
} ma; /* for maps and arrays */
struct {
diff --git a/inc/qcbor/qcbor_spiffy_decode.h b/inc/qcbor/qcbor_spiffy_decode.h
index 1370ada..6169a90 100644
--- a/inc/qcbor/qcbor_spiffy_decode.h
+++ b/inc/qcbor/qcbor_spiffy_decode.h
@@ -91,9 +91,6 @@
* QCBORDecode_EnterArray() can be used to narrow the traversal to the
* extent of the array.
*
- * QCBORDecode_EnterArray() can be used to narrow the traversal to the
- * extent of the array.
- *
* All the QCBORDecode_GetXxxxInMapX() methods support duplicate label
* detection and will result in an error if the map has duplicate
* labels.
@@ -726,8 +723,8 @@
* 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().
+ * See also QCBORDecode_ExitArray(), QCBORDecode_EnterMap(),
+ * QCBORDecode_EnterBstrWrapped() and QCBORDecode_GetArray().
*/
static void
QCBORDecode_EnterArray(QCBORDecodeContext *pCtx, QCBORItem *pItem);
@@ -749,7 +746,7 @@
* 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
+ * This sets the 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
@@ -761,6 +758,65 @@
+/**
+ * @brief Get the encoded bytes that make up an array.
+ *
+ * @param[in] pCtx The decode context.
+ * @param[out] pItem Place to return the item.
+ * @param[out] pEncodedCBOR Place to return pointer and length of the array.
+ *
+ * The next item to decode must be an array.
+ *
+ * The encoded bytes of the array will be returned. They can be
+ * decoded by another decoder instance.
+ *
+ * @c pItem will have the label and tags for the array. It is filled
+ * in the same as if QCBORDecode_GetNext() were called on the array item. In
+ * particular, the array count will be filled in for definite-length
+ * arrays and set to @c UINT16_MAX for indefinite-length arrays.
+ *
+ * This works on both definite and indefinite length arrays (unless
+ * indefinite length array decoding has been disabled).
+ *
+ * The pointer returned is to the data item that opens the array. The
+ * length in bytes includes it and all the member data items. If the array
+ * occurs in another map and thus has a label, the label is not included
+ * in what is returned.
+ *
+ * If the array is preceeded by tags, those encoded tags are included
+ * in the encoded CBOR that is returned.
+ *
+ * QCBORDecode_GetArray() consumes the entire array and leaves the
+ * traversal cursor at the item after the array.
+ * QCBORDecode_GetArrayFromMapN() and QCBORDecode_GetArrayFromMapSZ()
+ * don't affect the traversal cursor.
+ *
+ * This traverses the whole array and every subordinate array or map in
+ * it. This is necessary to determine the length of the array.
+ *
+ * This will fail if any item in the array is not well-formed.
+ *
+ * This uses a few hundred bytes of stack, more than most methods.
+ *
+ * See also QCBORDecode_EnterArray().
+ */
+static void
+QCBORDecode_GetArray(QCBORDecodeContext *pCtx,
+ QCBORItem *pItem,
+ UsefulBufC *pEncodedCBOR);
+
+static void
+QCBORDecode_GetArrayFromMapN(QCBORDecodeContext *pCtx,
+ int64_t nLabel,
+ QCBORItem *pItem,
+ UsefulBufC *pEncodedCBOR);
+
+static void
+QCBORDecode_GetArrayFromMapSZ(QCBORDecodeContext *pCtx,
+ const char *szLabel,
+ QCBORItem *pItem,
+ UsefulBufC *pEncodedCBOR);
+
/**
* @brief Enter a map for decoding and searching.
@@ -788,7 +844,7 @@
* fully exited.
*
* While in bounded mode, QCBORDecode_GetNext() works as usual on the
- * map and the pre-order traversal cursor is maintained. It starts out
+ * map and the 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
@@ -799,12 +855,12 @@
* non-aggregate items by label behaves differently from entering subordinate
* aggregate items by label. See dicussion in @ref SpiffyDecode.
*
- * Exiting leaves the pre-order cursor at the data item following the
+ * Exiting leaves the traversal 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
+ * its contents. After QCBORDecode_ExitMap(), the traversal
* cursor will be at the first item after the map.
*
* Please see @ref Decode-Errors-Overview "Decode Errors Overview".
@@ -813,6 +869,8 @@
* 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.
+ *
+ * See also QCBORDecode_GetMap().
*/
static void
QCBORDecode_EnterMap(QCBORDecodeContext *pCtx, QCBORItem *pItem);
@@ -834,7 +892,7 @@
* 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
+ * This sets the 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
@@ -846,6 +904,67 @@
/**
+ * @brief Get the bytes that make up a map.
+ *
+ * @param[in] pCtx The decode context.
+ * @param[out] pItem Place to return the item.
+ * @param[out] pEncodedCBOR Place to return pointer and length of the map.
+ *
+ * The next item to decode must be a map.
+ *
+ * The encoded bytes of the map will be returned. They can be
+ * decoded by another decoder instance.
+ *
+ * @c pItem will have the label and tags for the array. It is filled
+ * in the same as if QCBORDecode_GetNext() were called on the map item. In
+ * particular, the map count will be filled in for definite-length
+ * maps and set to @c UINT16_MAX for indefinite-length maps.
+ *
+ * This works on both definite and indefinite length maps (unless
+ * indefinite length map decoding has been disabled).
+ *
+ * The pointer returned is to the data item that opens the map. The
+ * length in bytes includes it and all the member data items. If the map
+ * occurs in another map and thus has a label, the label is not included
+ * in what is returned.
+ *
+ * If the map is preceeded by tags, those encoded tags are included in
+ * the encoded CBOR that is returned.
+ *
+ * QCBORDecode_GetMap() consumes the entire array and leaves the
+ * traversal cursor at the item after the map.
+ * QCBORDecode_GetMapFromMapN() and QCBORDecode_GetMapFromMapSZ()
+ * don't affect the traversal cursor.
+ *
+ * This traverses the whole map and every subordinate array or map in
+ * it. This is necessary to determine the length of the map. The
+ * traversal cursor is left at the first item after the map.
+ *
+ * This will fail if any item in the map is not well-formed.
+ *
+ * This uses a few hundred bytes of stack, more than most methods.
+ *
+ * See also QCBORDecode_EnterMap().
+ */
+static void
+QCBORDecode_GetMap(QCBORDecodeContext *pCtx,
+ QCBORItem *pItem,
+ UsefulBufC *pEncodedCBOR);
+
+static void
+QCBORDecode_GetMapFromMapN(QCBORDecodeContext *pCtx,
+ int64_t nLabel,
+ QCBORItem *pItem,
+ UsefulBufC *pEncodedCBOR);
+
+static void
+QCBORDecode_GetMapFromMapSZ(QCBORDecodeContext *pCtx,
+ const char *szLabel,
+ QCBORItem *pItem,
+ UsefulBufC *pEncodedCBOR);
+
+
+/**
* @brief Reset traversal cursor to start of map, array, byte-string
* wrapped CBOR or start of input.
*
@@ -893,7 +1012,7 @@
* 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.
+ * The position of the traversal cursor is not changed.
*
* Please see @ref Decode-Errors-Overview "Decode Errors Overview".
*
@@ -940,7 +1059,7 @@
* 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.
+ * The position of the traversal cursor is not changed.
*
* Please see @ref Decode-Errors-Overview "Decode Errors Overview".
*
@@ -1831,8 +1950,8 @@
* 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.
+ * This does not work on indefinite-length strings. The
+ * error @ref QCBOR_ERR_CANNOT_ENTER_ALLOCATED_STRING 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
@@ -1873,7 +1992,7 @@
* 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
+ * The this sets the traversal cursor to the item after the
* byte string that was exited.
*/
void
@@ -2118,6 +2237,103 @@
}
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_GetArrayOrMap(QCBORDecodeContext *pCtx,
+ uint8_t uType,
+ QCBORItem *pItem,
+ UsefulBufC *pEncodedCBOR);
+
+
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_SearchAndGetArrayOrMap(QCBORDecodeContext *pCtx,
+ QCBORItem *pTarget,
+ QCBORItem *pItem,
+ UsefulBufC *pEncodedCBOR);
+
+
+static inline void
+QCBORDecode_GetArray(QCBORDecodeContext *pMe,
+ QCBORItem *pItem,
+ UsefulBufC *pEncodedCBOR)
+{
+ QCBORDecode_Private_GetArrayOrMap(pMe, QCBOR_TYPE_ARRAY, pItem, pEncodedCBOR);
+}
+
+
+static inline void
+QCBORDecode_GetArrayFromMapN(QCBORDecodeContext *pMe,
+ int64_t nLabel,
+ QCBORItem *pItem,
+ UsefulBufC *pEncodedCBOR)
+{
+ QCBORItem OneItemSeach[2];
+ OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
+ OneItemSeach[0].label.int64 = nLabel;
+ OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
+ OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
+
+ QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSeach, pItem, pEncodedCBOR);
+}
+
+
+static inline void
+QCBORDecode_GetArrayFromMapSZ(QCBORDecodeContext *pMe,
+ const char *szLabel,
+ QCBORItem *pItem,
+ UsefulBufC *pEncodedCBOR)
+{
+ QCBORItem OneItemSeach[2];
+ OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
+ OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
+ OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
+ OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
+
+ QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSeach, pItem, pEncodedCBOR);
+}
+
+static inline void
+QCBORDecode_GetMap(QCBORDecodeContext *pMe,
+ QCBORItem *pItem,
+ UsefulBufC *pEncodedCBOR)
+{
+ QCBORDecode_Private_GetArrayOrMap(pMe, QCBOR_TYPE_MAP, pItem, pEncodedCBOR);
+}
+
+
+static inline void
+QCBORDecode_GetMapFromMapN(QCBORDecodeContext *pMe,
+ int64_t nLabel,
+ QCBORItem *pItem,
+ UsefulBufC *pEncodedCBOR)
+{
+ QCBORItem OneItemSeach[2];
+ OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
+ OneItemSeach[0].label.int64 = nLabel;
+ OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
+ OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
+
+ QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSeach, pItem, pEncodedCBOR);
+}
+
+
+static inline void
+QCBORDecode_GetMapFromMapSZ(QCBORDecodeContext *pMe,
+ const char *szLabel,
+ QCBORItem *pItem,
+ UsefulBufC *pEncodedCBOR)
+{
+ QCBORItem OneItemSeach[2];
+ OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
+ OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
+ OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
+ OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
+
+ QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSeach, pItem, pEncodedCBOR);
+}
+
+
static inline void
QCBORDecode_GetInt64Convert(QCBORDecodeContext *pMe,