Fix GetArray() and GetMap() on empty maps
diff --git a/QCBOR.xcodeproj/project.pbxproj b/QCBOR.xcodeproj/project.pbxproj
index a580e4d..3e0e614 100644
--- a/QCBOR.xcodeproj/project.pbxproj
+++ b/QCBOR.xcodeproj/project.pbxproj
@@ -161,7 +161,7 @@
0FA9BEBC216DE31700BA646B /* UsefulBuf_Tests.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = UsefulBuf_Tests.c; path = test/UsefulBuf_Tests.c; sourceTree = "<group>"; tabWidth = 3; };
E7180F222CF1657A00513186 /* qcbor_number_decode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = qcbor_number_decode.c; path = src/qcbor_number_decode.c; sourceTree = "<group>"; };
E7180F242CF2390100513186 /* qcbor_number_decode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = qcbor_number_decode.h; path = inc/qcbor/qcbor_number_decode.h; sourceTree = "<group>"; };
- E7180F252CF8F2EB00513186 /* qcbor_spiffy_decode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = qcbor_spiffy_decode.c; path = src/qcbor_spiffy_decode.c; sourceTree = "<group>"; };
+ E7180F252CF8F2EB00513186 /* qcbor_spiffy_decode.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = qcbor_spiffy_decode.c; path = src/qcbor_spiffy_decode.c; sourceTree = "<group>"; tabWidth = 3; };
E7180F272CF917D200513186 /* decode_nesting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = decode_nesting.h; path = src/decode_nesting.h; sourceTree = "<group>"; };
E7180F282CFCE9B000513186 /* qcbor_main_decode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = qcbor_main_decode.h; path = inc/qcbor/qcbor_main_decode.h; sourceTree = "<group>"; };
E7180F292CFCE9F800513186 /* qcbor_decode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = qcbor_decode.h; path = inc/qcbor/qcbor_decode.h; sourceTree = "<group>"; };
diff --git a/doc/Overview.md b/doc/Overview.md
index 1b4c589..c49709e 100644
--- a/doc/Overview.md
+++ b/doc/Overview.md
@@ -109,6 +109,8 @@
map. It is possible to use this API to construct and parse such
labels, but it is not explicitly supported.
+@anchor Limitations
+
## Limitations
Summary limitations:
diff --git a/inc/qcbor/qcbor_spiffy_decode.h b/inc/qcbor/qcbor_spiffy_decode.h
index dced4d9..7e67687 100644
--- a/inc/qcbor/qcbor_spiffy_decode.h
+++ b/inc/qcbor/qcbor_spiffy_decode.h
@@ -546,34 +546,23 @@
*
* @param[in] pCtx The decode context.
* @param[in] nLabel The integer label.
- * @param[in] uQcborType The QCBOR type. One of @c QCBOR_TYPE_XXX.
+ * @param[in] uQcborType A QCBOR type like @ref QCBOR_TYPE_INT64.
* @param[out] pItem The returned item.
*
- * A map must have been entered to use this. If not
- * @ref QCBOR_ERR_MAP_NOT_ENTERED is set.
- *
* The map is searched for an item of the requested label and type.
* @ref QCBOR_TYPE_ANY can be given to search for the label without
* matching the type.
*
- * This will always search the entire map. This will always perform
- * duplicate label detection, setting @ref QCBOR_ERR_DUPLICATE_LABEL
- * if there is more than one occurance of the label being searched
- * for.
+ * The decoder’s cursor position is preserved and is not advanced by
+ * this function.
*
- * Duplicate label detection is performed for the item being sought
- * and only for the item being sought.
+ * Because the entire map is traversed, errors can occur on unrelated
+ * items—not just the one being searched for.
*
- * This performs a full decode of every item in the map being
- * searched which involves a full traversal of every item. For maps
- * with little nesting, this is of little consequence, but may be of
- * consequence for large deeply nested CBOR structures on slow CPUs.
+ * This performs duplicate label detection for the label being
+ * searched for, but no others.
*
- * The position of the traversal cursor is not changed.
- *
- * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
- *
- * See also QCBORDecode_GetItemsInMap() for error discussion.
+ * @sa QCBORDecode_GetItemsInMap() for error discussion.
*/
void
QCBORDecode_GetItemInMapN(QCBORDecodeContext *pCtx,
@@ -590,27 +579,28 @@
/**
- * @brief Get a group of labeled items all at once from a map
+ * @brief Get multiple labeled items from a CBOR map efficiently.
*
* @param[in] pCtx The decode context.
* @param[in,out] pItemList On input, the items to search for. On output,
- * the returne *d items.
+ * the returned items.
*
- * This gets several labeled items out of a map.
+ * @c pItemList is an array of items, terminated by an item with
+ * @c uLabelType == @ref QCBOR_TYPE_NONE.
*
- * @c pItemList is an array of items terminated by an item with @c
- * uLabelType @ref QCBOR_TYPE_NONE.
+ * On input, each item in @c pItemList specifies:
+ * - A label to search for (@c uLabelType and @c label fields).
+ * - An expected CBOR type (@c uDataType).
+ * - To match any type regardless of its CBOR type, set @c uDataType to
+ * @ref QCBOR_TYPE_ANY.
*
- * On input the labels to search for are in the @c uLabelType and
- * label fields in the items in @c pItemList.
+ * On output, each item in @c pItemList may contain a found item:
+ * - @c uDataType is the data type for found items or @ref QCBOR_TYPE_NONE
+ * if the label was not matched.
+ * - @c value is the value of the found item.
*
- * Also on input are the requested QCBOR types in the field
- * @c uDataType. To match any type, searching just by label,
- * @c uDataType can be @ref QCBOR_TYPE_ANY.
- *
- * This is a CPU-efficient way to decode a bunch of items in a map. It
- * is more efficient than scanning each individually because the map
- * only needs to be traversed once.
+ * This is CPU-efficient because the map is traversed only once,
+ * rather than scanning for each label individually.
*
* Warning, this does not check that the tag numbers have been
* consumed or checked. This can be remedied by checking that
@@ -622,42 +612,41 @@
* This function works well with tag content decoders as described in
* QCBORDecode_InstallTagDecoders().
*
- * This will return maps and arrays that are in the map, but provides
- * no way to descend into and decode them. Use
- * QCBORDecode_EnterMapinMapN(), QCBORDecode_EnterArrayInMapN() and
- * such to descend into and process maps and arrays.
+ * This function returns maps and arrays contained within the map, but
+ * does not provide a way to descend into or decode them. To process
+ * nested maps and arrays, use functions like
+ * QCBORDecode_EnterMapFromMapN(), QCBORDecode_EnterArrayFromMapN(),
+ * and similar.
*
- * The position of the traversal cursor is not changed.
+ * The decoder’s cursor position is preserved and is not advanced by
+ * this function.
*
* Please see @ref Decode-Errors-Overview "Decode Errors Overview".
*
- * The following errors are set:
+ * This function may set the following errors:
*
- * @ref QCBOR_ERR_MAP_NOT_ENTERED when calling this without previousl
- * calling QCBORDecode_EnterMap() or other methods to enter a map.
+ * - @ref QCBOR_ERR_MAP_NOT_ENTERED --- called before entering a map
+ * with QCBORDecode_EnterMap() or similar.
*
- * @ref QCBOR_ERR_DUPLICATE_LABEL when one of the labels being searched
- * for is duplicate.
+ * - @ref QCBOR_ERR_DUPLICATE_LABEL --- One of the labels being
+ * searched for is duplicated in the input CBOR.
*
- * @ref QCBOR_ERR_HIT_END or other errors classifed as not-well-formed
- * by QCBORDecode_IsNotWellFormed() as it is not possible to traverse
- * maps that have any non-well formed items.
+ * - @ref QCBOR_ERR_HIT_END --- and other well-formedness errors as
+ * per QCBORDecode_IsNotWellFormedError().
*
- * @ref QCBOR_ERR_UNEXPECTED_TYPE when the type of an item found by
- * matching a label is not the type requested.
+ * - @ref QCBOR_ERR_UNEXPECTED_TYPE --- The type of a found item does
+ * not match the expected @c uDataType.
*
- * @ref QCBOR_ERR_ARRAY_NESTING_TOO_DEEP and other implementation
- * limit errors as it is not possible to travere a map beyond the
- * limits of the implementation.
+ * - @ref QCBOR_ERR_ARRAY_NESTING_TOO_DEEP --- and other QCBOR implementation
+ * @ref Limitations errors.
*
- * The error may occur on items that are not being searched for. For
- * example, it is impossible to traverse over a map that has an array in
- * it that is not closed or over array and map nesting deeper than this
- * implementation can track.
+ * Because the entire map is traversed, these errors can occur on
+ * unrelated items—not just those being searched for.
*
- * See also QCBORDecode_GetItemInMapN().
+ * @sa QCBORDecode_GetItemInMapN(), QCBORDecode_GetItemInMapSZ() and
+ * QCBORDecode_GetItemsInMapWithCallback().
*/
-void
+static void
QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList);
@@ -704,7 +693,7 @@
*
* See QCBORItemCallback() for error handling.
*/
-void
+static void
QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
QCBORItem *pItemList,
void *pCallbackCtx,
@@ -936,13 +925,13 @@
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;
+ QCBORItem OneItemSearch[2];
+ OneItemSearch[0].uLabelType = QCBOR_TYPE_INT64;
+ OneItemSearch[0].label.int64 = nLabel;
+ OneItemSearch[0].uDataType = QCBOR_TYPE_ARRAY;
+ OneItemSearch[1].uLabelType = QCBOR_TYPE_NONE;
- QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSeach, pItem, pEncodedCBOR);
+ QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSearch, pItem, pEncodedCBOR);
}
@@ -953,13 +942,13 @@
UsefulBufC *pEncodedCBOR)
{
#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
- 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;
+ QCBORItem OneItemSearch[2];
+ OneItemSearch[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
+ OneItemSearch[0].label.string = UsefulBuf_FromSZ(szLabel);
+ OneItemSearch[0].uDataType = QCBOR_TYPE_ARRAY;
+ OneItemSearch[1].uLabelType = QCBOR_TYPE_NONE;
- QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSeach, pItem, pEncodedCBOR);
+ QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSearch, pItem, pEncodedCBOR);
#else
(void)szLabel;
(void)pItem;
@@ -983,13 +972,13 @@
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;
+ QCBORItem OneItemSearch[2];
+ OneItemSearch[0].uLabelType = QCBOR_TYPE_INT64;
+ OneItemSearch[0].label.int64 = nLabel;
+ OneItemSearch[0].uDataType = QCBOR_TYPE_MAP;
+ OneItemSearch[1].uLabelType = QCBOR_TYPE_NONE;
- QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSeach, pItem, pEncodedCBOR);
+ QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSearch, pItem, pEncodedCBOR);
}
@@ -1000,13 +989,13 @@
UsefulBufC *pEncodedCBOR)
{
#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
- 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;
+ QCBORItem OneItemSearch[2];
+ OneItemSearch[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
+ OneItemSearch[0].label.string = UsefulBuf_FromSZ(szLabel);
+ OneItemSearch[0].uDataType = QCBOR_TYPE_MAP;
+ OneItemSearch[1].uLabelType = QCBOR_TYPE_NONE;
- QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSeach, pItem, pEncodedCBOR);
+ QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSearch, pItem, pEncodedCBOR);
#else
(void)szLabel;
(void)pItem;
@@ -1017,6 +1006,27 @@
static inline void
+QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
+{
+ pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, NULL);
+}
+
+static inline void
+QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
+ QCBORItem *pItemList,
+ void *pCallbackCtx,
+ QCBORItemCallback pfCB)
+{
+ MapSearchCallBack CallBack;
+
+ CallBack.pCBContext = pCallbackCtx;
+ CallBack.pfCallback = pfCB;
+
+ pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, &CallBack);
+}
+
+
+static inline void
QCBORDecode_GetByteString(QCBORDecodeContext *pMe, UsefulBufC *pBytes)
{
QCBORDecode_Private_GetString(pMe, QCBOR_TYPE_BYTE_STRING, pBytes);
diff --git a/src/qcbor_spiffy_decode.c b/src/qcbor_spiffy_decode.c
index ee373f3..762dd2c 100644
--- a/src/qcbor_spiffy_decode.c
+++ b/src/qcbor_spiffy_decode.c
@@ -238,7 +238,15 @@
MapSearchCallBack *pCallBack)
{
QCBORError uReturn;
- uint64_t uFoundItemBitMap = 0;
+ uint64_t uFoundItemBitMap;
+ uint8_t uNextNestLevel;
+
+ if(pInfo != NULL) {
+ pInfo->uItemCount = 0;
+ pInfo->uStartOffset = UINT32_MAX;
+ }
+
+ uFoundItemBitMap = 0;
if(pMe->uLastError != QCBOR_SUCCESS) {
uReturn = pMe->uLastError;
@@ -247,8 +255,8 @@
if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
pItemArray->uLabelType != QCBOR_TYPE_NONE) {
- /* QCBOR_TYPE_NONE as first item indicates just looking
- for the end of an array, so don't give error. */
+ /* QCBOR_TYPE_NONE as first item indicates just looking for the
+ * end of an array, so don't give error. */
uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
goto Done2;
}
@@ -260,8 +268,8 @@
pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
uReturn = QCBOR_SUCCESS;
} else {
- // Nothing is ever found in an empty array or map. All items
- // are marked as not found below.
+ /* Nothing is ever found in an empty array or map. All items
+ * are marked as not found below. */
uReturn = QCBOR_SUCCESS;
}
goto Done2;
@@ -274,38 +282,35 @@
/* Reposition to search from the start of the map / array */
QCBORDecode_Private_RewindMapOrArray(pMe);
- /*
- Loop over all the items in the map or array. Each item
- could be a map or array, but label matching is only at
- the main level. This handles definite- and indefinite-
- length maps and arrays. The only reason this is ever
- called on arrays is to find their end position.
-
- This will always run over all items in order to do
- duplicate detection.
-
- This will exit with failure if it encounters an
- unrecoverable error, but continue on for recoverable
- errors.
-
- If a recoverable error occurs on a matched item, then
- that error code is returned.
+ /* Loop over all the items in the map or array. Each item could be
+ * a map or array, but label matching is only at the main
+ * level. This handles definite- and indefinite- length maps and
+ * arrays. The only reason this is ever called on arrays is to find
+ * their end position.
+ *
+ * This will always run over all items in order to do duplicate
+ * detection.
+ *
+ * This will exit with failure if it encounters an unrecoverable
+ * error, but continue on for recoverable errors.
+ *
+ * If a recoverable error occurs on a matched item, then that error
+ * code is returned.
*/
const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
- if(pInfo) {
- pInfo->uItemCount = 0;
- }
- uint8_t uNextNestLevel;
do {
+ QCBORItem Item;
+ bool bMatched;
+ QCBORError uResult;
+
/* Remember offset of the item because sometimes it has to be returned */
const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
/* Get the item */
- QCBORItem Item;
/* QCBORDecode_Private_GetNextTagContent() rather than GetNext()
* because a label match is performed on recoverable errors to
* be able to return the the error code for the found item. */
- QCBORError uResult = QCBORDecode_Private_GetNextTagContent(pMe, &Item);
+ uResult = QCBORDecode_Private_GetNextTagContent(pMe, &Item);
if(QCBORDecode_IsUnrecoverableError(uResult)) {
/* The map/array can't be decoded when unrecoverable errors occur */
uReturn = uResult;
@@ -318,7 +323,7 @@
}
/* See if item has one of the labels that are of interest */
- bool bMatched = false;
+ bMatched = false;
for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
if(QCBORItem_MatchLabel(Item, pItemArray[nIndex])) {
/* A label match has been found */
@@ -342,7 +347,7 @@
/* Successful match. Return the item. */
pItemArray[nIndex] = Item;
uFoundItemBitMap |= 0x01ULL << nIndex;
- if(pInfo) {
+ if(pInfo != NULL) {
pInfo->uStartOffset = uOffset;
}
bMatched = true;
@@ -351,31 +356,26 @@
if(!bMatched && pCallBack != NULL) {
- /*
- Call the callback on unmatched labels.
- (It is tempting to do duplicate detection here, but that would
- require dynamic memory allocation because the number of labels
- that might be encountered is unbounded.)
- */
+ /* Call the callback on unmatched labels.
+ * (It is tempting to do duplicate detection here, but that
+ * would require dynamic memory allocation because the number
+ * of labels that might be encountered is unbounded.) */
uReturn = (*(pCallBack->pfCallback))(pCallBack->pCBContext, &Item);
if(uReturn != QCBOR_SUCCESS) {
goto Done;
}
}
- /*
- Consume the item whether matched or not. This
- does the work of traversing maps and array and
- everything in them. In this loop only the
- items at the current nesting level are examined
- to match the labels.
- */
+ /* Consume the item whether matched or not. This does the work
+ * of traversing maps and array and everything in them. In this
+ * loop only the items at the current nesting level are examined
+ * to match the labels. */
uReturn = QCBORDecode_Private_ConsumeItem(pMe, &Item, NULL, &uNextNestLevel);
if(uReturn != QCBOR_SUCCESS) {
goto Done;
}
- if(pInfo) {
+ if(pInfo != NULL) {
pInfo->uItemCount++;
}
@@ -385,10 +385,12 @@
const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
- // Check here makes sure that this won't accidentally be
- // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
- // QCBOR_MAX_SIZE.
- // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
+ /* Check here makes sure that this won't accidentally be
+ * QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
+ * QCBOR_MAX_DECODE_INPUT_SIZE. Cast to uint32_t to possibly
+ * address cases where SIZE_MAX < UINT32_MAX. It is near-impossible
+ * to test this, so test coverage of this function is not 100%,
+ * but it is 100% when this is commented out. */
if((uint32_t)uEndOffset >= QCBOR_MAX_SIZE) {
uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
goto Done;
@@ -418,18 +420,18 @@
QCBORDecode_SeekToLabelN(QCBORDecodeContext *pMe, int64_t nLabel)
{
MapSearchInfo Info;
- QCBORItem OneItemSeach[2];
+ QCBORItem OneItemSearch[2];
if(pMe->uLastError != QCBOR_SUCCESS) {
return;
}
- OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
- OneItemSeach[0].label.int64 = nLabel;
- OneItemSeach[0].uDataType = QCBOR_TYPE_ANY;
- OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
+ OneItemSearch[0].uLabelType = QCBOR_TYPE_INT64;
+ OneItemSearch[0].label.int64 = nLabel;
+ OneItemSearch[0].uDataType = QCBOR_TYPE_ANY;
+ OneItemSearch[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
- pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, OneItemSeach, &Info, NULL);
+ pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, OneItemSearch, &Info, NULL);
if(pMe->uLastError == QCBOR_SUCCESS) {
UsefulInputBuf_Seek(&(pMe->InBuf), Info.uStartOffset);
}
@@ -441,18 +443,18 @@
{
#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
MapSearchInfo Info;
- QCBORItem OneItemSeach[2];
+ QCBORItem OneItemSearch[2];
if(pMe->uLastError != QCBOR_SUCCESS) {
return;
}
- OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
- OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
- OneItemSeach[0].uDataType = QCBOR_TYPE_ANY;
- OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
+ OneItemSearch[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
+ OneItemSearch[0].label.string = UsefulBuf_FromSZ(szLabel);
+ OneItemSearch[0].uDataType = QCBOR_TYPE_ANY;
+ OneItemSearch[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
- pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, OneItemSeach, &Info, NULL);
+ pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, OneItemSearch, &Info, NULL);
if(pMe->uLastError == QCBOR_SUCCESS) {
UsefulInputBuf_Seek(&(pMe->InBuf), Info.uStartOffset);
}
@@ -466,7 +468,7 @@
void
QCBORDecode_Private_GetItemInMapNoCheck(QCBORDecodeContext *pMe,
- QCBORItem *OneItemSeach,
+ QCBORItem *OneItemSearch,
QCBORItem *pItem,
size_t *puOffset)
{
@@ -477,12 +479,12 @@
return;
}
- uErr = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, &SearchInfo, NULL);
+ uErr = QCBORDecode_Private_MapSearch(pMe, OneItemSearch, &SearchInfo, NULL);
- if(uErr == QCBOR_SUCCESS && OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
+ if(uErr == QCBOR_SUCCESS && OneItemSearch[0].uDataType == QCBOR_TYPE_NONE) {
uErr = QCBOR_ERR_LABEL_NOT_FOUND;
}
- *pItem = OneItemSeach[0];
+ *pItem = OneItemSearch[0];
*puOffset = SearchInfo.uStartOffset;
if(uErr == QCBOR_SUCCESS) {
@@ -494,12 +496,12 @@
static void
-QCBORDecode_Private_GetItemInMap(QCBORDecodeContext *pMe, QCBORItem *OneItemSeach, QCBORItem *pItem)
+QCBORDecode_Private_GetItemInMap(QCBORDecodeContext *pMe, QCBORItem *OneItemSearch, QCBORItem *pItem)
{
QCBORError uErr;
size_t uOffset;
- QCBORDecode_Private_GetItemInMapNoCheck(pMe, OneItemSeach, pItem, &uOffset);
+ QCBORDecode_Private_GetItemInMapNoCheck(pMe, OneItemSearch, pItem, &uOffset);
uErr = QCBORDecode_Private_GetItemChecks(pMe, pMe->uLastError, uOffset, pItem);
if(uErr != QCBOR_SUCCESS) {
@@ -520,14 +522,14 @@
const uint8_t uQcborType,
QCBORItem *pItem)
{
- QCBORItem OneItemSeach[2];
+ QCBORItem OneItemSearch[2];
- OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
- OneItemSeach[0].label.int64 = nLabel;
- OneItemSeach[0].uDataType = uQcborType;
- OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
+ OneItemSearch[0].uLabelType = QCBOR_TYPE_INT64;
+ OneItemSearch[0].label.int64 = nLabel;
+ OneItemSearch[0].uDataType = uQcborType;
+ OneItemSearch[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
- QCBORDecode_Private_GetItemInMap(pMe, OneItemSeach, pItem);
+ QCBORDecode_Private_GetItemInMap(pMe, OneItemSearch, pItem);
}
@@ -551,14 +553,14 @@
QCBORItem *pItem,
size_t *puOffset)
{
- QCBORItem OneItemSeach[2];
+ QCBORItem OneItemSearch[2];
- OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
- OneItemSeach[0].label.int64 = nLabel;
- OneItemSeach[0].uDataType = uQcborType;
- OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
+ OneItemSearch[0].uLabelType = QCBOR_TYPE_INT64;
+ OneItemSearch[0].label.int64 = nLabel;
+ OneItemSearch[0].uDataType = uQcborType;
+ OneItemSearch[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
- QCBORDecode_Private_GetItemInMapNoCheck(pMe, OneItemSeach, pItem, puOffset);
+ QCBORDecode_Private_GetItemInMapNoCheck(pMe, OneItemSearch, pItem, puOffset);
}
@@ -570,14 +572,14 @@
QCBORItem *pItem)
{
#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
- QCBORItem OneItemSeach[2];
+ QCBORItem OneItemSearch[2];
- OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
- OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
- OneItemSeach[0].uDataType = uQcborType;
- OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
+ OneItemSearch[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
+ OneItemSearch[0].label.string = UsefulBuf_FromSZ(szLabel);
+ OneItemSearch[0].uDataType = uQcborType;
+ OneItemSearch[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
- QCBORDecode_Private_GetItemInMap(pMe, OneItemSeach, pItem);
+ QCBORDecode_Private_GetItemInMap(pMe, OneItemSearch, pItem);
#else
(void)pMe;
@@ -609,14 +611,14 @@
size_t *puOffset)
{
#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
- QCBORItem OneItemSeach[2];
+ QCBORItem OneItemSearch[2];
- OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
- OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
- OneItemSeach[0].uDataType = uQcborType;
- OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
+ OneItemSearch[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
+ OneItemSearch[0].label.string = UsefulBuf_FromSZ(szLabel);
+ OneItemSearch[0].uDataType = uQcborType;
+ OneItemSearch[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
- QCBORDecode_Private_GetItemInMapNoCheck(pMe, OneItemSeach, pItem, puOffset);
+ QCBORDecode_Private_GetItemInMapNoCheck(pMe, OneItemSearch, pItem, puOffset);
#else
(void)pMe;
@@ -642,65 +644,50 @@
* The next item to be decoded must be a map or array as specified by @c uType.
*
* When this is complete, the traversal cursor is unchanged.
- */void
+ */
+void
QCBORDecode_Private_SearchAndGetArrayOrMap(QCBORDecodeContext *pMe,
QCBORItem *pTarget,
QCBORItem *pItem,
UsefulBufC *pEncodedCBOR)
{
+ /* Heavy stack use, but it's only for a few QCBOR public methods */
MapSearchInfo Info;
QCBORDecodeNesting SaveNesting;
size_t uSaveCursor;
+ /* Find the array or map of interest */
pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pTarget, &Info, NULL);
if(pMe->uLastError != QCBOR_SUCCESS) {
return;
}
+
+ if(pTarget->uDataType == QCBOR_TYPE_NONE) {
+ pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
+ return;
+ }
+
pMe->uLastError = (uint8_t)QCBORDecode_Private_GetItemChecks(pMe, pMe->uLastError, Info.uStartOffset, pItem);
if(pMe->uLastError != QCBOR_SUCCESS) {
return;
}
- /* Save the whole position of things so they can be restored.
- * so the cursor position is unchanged by this operation, like
- * all the other GetXxxxInMap() operations. */
+ /* Save the traversal cursor and related */
DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
uSaveCursor = UsefulInputBuf_Tell(&(pMe->InBuf));
+ /* Get the array or map of interest */
DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
UsefulInputBuf_Seek(&(pMe->InBuf), Info.uStartOffset);
QCBORDecode_Private_GetArrayOrMap(pMe, pTarget[0].uDataType, pItem, pEncodedCBOR);
+ /* Restore the traversal cursor */
UsefulInputBuf_Seek(&(pMe->InBuf), uSaveCursor);
DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
}
-/* Public function, see qcbor/qcbor_spiffy_decode.h */
-void
-QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
-{
- pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, NULL);
-}
-
-/* Public function, see qcbor/qcbor_spiffy_decode.h */
-void
-QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
- QCBORItem *pItemList,
- void *pCallbackCtx,
- QCBORItemCallback pfCB)
-{
- MapSearchCallBack CallBack;
-
- CallBack.pCBContext = pCallbackCtx;
- CallBack.pfCallback = pfCB;
-
- pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, &CallBack);
-}
-
-
-
/**
* @brief Search for a map/array by label and enter it
@@ -775,14 +762,14 @@
void
QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
{
- 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;
+ QCBORItem OneItemSearch[2];
+ OneItemSearch[0].uLabelType = QCBOR_TYPE_INT64;
+ OneItemSearch[0].label.int64 = nLabel;
+ OneItemSearch[0].uDataType = QCBOR_TYPE_MAP;
+ OneItemSearch[1].uLabelType = QCBOR_TYPE_NONE;
/* The map to enter was found, now finish off entering it. */
- QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
+ QCBORDecode_Private_SearchAndEnter(pMe, OneItemSearch);
}
@@ -791,13 +778,13 @@
QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
{
#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
- 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;
+ QCBORItem OneItemSearch[2];
+ OneItemSearch[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
+ OneItemSearch[0].label.string = UsefulBuf_FromSZ(szLabel);
+ OneItemSearch[0].uDataType = QCBOR_TYPE_MAP;
+ OneItemSearch[1].uLabelType = QCBOR_TYPE_NONE;
- QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
+ QCBORDecode_Private_SearchAndEnter(pMe, OneItemSearch);
#else
(void)szLabel;
pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
@@ -808,13 +795,13 @@
void
QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
{
- 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;
+ QCBORItem OneItemSearch[2];
+ OneItemSearch[0].uLabelType = QCBOR_TYPE_INT64;
+ OneItemSearch[0].label.int64 = nLabel;
+ OneItemSearch[0].uDataType = QCBOR_TYPE_ARRAY;
+ OneItemSearch[1].uLabelType = QCBOR_TYPE_NONE;
- QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
+ QCBORDecode_Private_SearchAndEnter(pMe, OneItemSearch);
}
/* Public function, see qcbor/qcbor_spiffy_decode.h */
@@ -822,13 +809,13 @@
QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
{
#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
- 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;
+ QCBORItem OneItemSearch[2];
+ OneItemSearch[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
+ OneItemSearch[0].label.string = UsefulBuf_FromSZ(szLabel);
+ OneItemSearch[0].uDataType = QCBOR_TYPE_ARRAY;
+ OneItemSearch[1].uLabelType = QCBOR_TYPE_NONE;
- QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
+ QCBORDecode_Private_SearchAndEnter(pMe, OneItemSearch);
#else
(void)szLabel;
pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
diff --git a/src/qcbor_tag_decode.c b/src/qcbor_tag_decode.c
index 132aa0a..f694568 100644
--- a/src/qcbor_tag_decode.c
+++ b/src/qcbor_tag_decode.c
@@ -74,19 +74,19 @@
{
size_t uOffset;
MapSearchInfo Info;
- QCBORItem OneItemSeach[2];
+ QCBORItem OneItemSearch[2];
QCBORError uReturn;
if(pMe->uLastError != QCBOR_SUCCESS) {
return pMe->uLastError;
}
- OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
- OneItemSeach[0].label.int64 = nLabel;
- OneItemSeach[0].uDataType = QCBOR_TYPE_ANY;
- OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
+ OneItemSearch[0].uLabelType = QCBOR_TYPE_INT64;
+ OneItemSearch[0].label.int64 = nLabel;
+ OneItemSearch[0].uDataType = QCBOR_TYPE_ANY;
+ OneItemSearch[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
- uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, &Info, NULL);
+ uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSearch, &Info, NULL);
uOffset = Info.uStartOffset;
if(uOffset == pMe->uTagNumberCheckOffset) {
@@ -98,10 +98,10 @@
*puTagNumber = CBOR_TAG_INVALID64;
*puTagNumber = QCBORDecode_GetNthTagNumber(pMe,
- &OneItemSeach[0],
+ &OneItemSearch[0],
pMe->uTagNumberIndex);
if(*puTagNumber == CBOR_TAG_INVALID64 ||
- QCBORDecode_GetNthTagNumber(pMe, &OneItemSeach[0], pMe->uTagNumberIndex+1) == CBOR_TAG_INVALID64 ) {
+ QCBORDecode_GetNthTagNumber(pMe, &OneItemSearch[0], pMe->uTagNumberIndex+1) == CBOR_TAG_INVALID64 ) {
pMe->uTagNumberIndex = QCBOR_ALL_TAGS_PROCESSED;
}
pMe->uTagNumberCheckOffset = uOffset;
@@ -117,19 +117,19 @@
#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
size_t uOffset;
MapSearchInfo Info;
- QCBORItem OneItemSeach[2];
+ QCBORItem OneItemSearch[2];
if(pMe->uLastError != QCBOR_SUCCESS) {
return pMe->uLastError;
}
- OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
- OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
- OneItemSeach[0].uDataType = QCBOR_TYPE_ANY;
- OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
+ OneItemSearch[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
+ OneItemSearch[0].label.string = UsefulBuf_FromSZ(szLabel);
+ OneItemSearch[0].uDataType = QCBOR_TYPE_ANY;
+ OneItemSearch[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe,
- OneItemSeach,
+ OneItemSearch,
&Info,
NULL);
@@ -144,10 +144,10 @@
*puTagNumber = CBOR_TAG_INVALID64;
*puTagNumber = QCBORDecode_GetNthTagNumber(pMe,
- &OneItemSeach[0],
+ &OneItemSearch[0],
pMe->uTagNumberIndex);
if(*puTagNumber == CBOR_TAG_INVALID64 ||
- QCBORDecode_GetNthTagNumber(pMe, &OneItemSeach[0], pMe->uTagNumberIndex+1) == CBOR_TAG_INVALID64 ) {
+ QCBORDecode_GetNthTagNumber(pMe, &OneItemSearch[0], pMe->uTagNumberIndex+1) == CBOR_TAG_INVALID64 ) {
pMe->uTagNumberIndex = 255; /* All tags clear for this item */
}
pMe->uTagNumberCheckOffset = uOffset;
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 8ae0e3d..0883bef 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -7478,6 +7478,53 @@
}
+QCBORError CBTest(void *pCallbackCtx, const QCBORItem *pItem)
+{
+ (void)pCallbackCtx;
+ (void)pItem;
+ return QCBOR_SUCCESS;
+}
+
+
+struct CbTest2Ctx {
+ bool found2;
+ bool found4;
+ bool error;
+};
+
+QCBORError CBTest2(void *pCallbackCtx, const QCBORItem *pItem)
+{
+ struct CbTest2Ctx *pCtx;
+
+ pCtx = (struct CbTest2Ctx *)pCallbackCtx;
+
+ if(pItem->uLabelType != QCBOR_TYPE_INT64) {
+ pCtx->error = true;
+ return QCBOR_SUCCESS;
+ }
+
+ switch(pItem->label.int64) {
+
+ case 2:
+ pCtx->found2 = true;
+ break;
+
+ case 4:
+ pCtx->found4 = true;
+ break;
+
+ case 3:
+ /* To test error return out of callback */
+ return QCBOR_ERR_CALLBACK_FAIL;
+
+ default:
+ pCtx->error = true;
+
+ }
+ return QCBOR_SUCCESS;
+}
+
+
int32_t EnterMapTest(void)
{
QCBORItem Item1;
@@ -7856,6 +7903,141 @@
return 3000;
}
+ QCBORItem SearchItems[4];
+
+ /* GetItems on an empty map */
+ QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEmptyMap), 0);
+ QCBORDecode_EnterMap(&DCtx, NULL);
+
+ SearchItems[0].uLabelType = QCBOR_TYPE_INT64;
+ SearchItems[0].label.int64 = 0;
+ SearchItems[0].uDataType = QCBOR_TYPE_ANY;
+ SearchItems[1].uLabelType = QCBOR_TYPE_NONE;
+ QCBORDecode_GetItemsInMap(&DCtx, SearchItems);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
+ return 4000;
+ }
+ if(SearchItems[0].uDataType != QCBOR_TYPE_NONE) {
+ return 4001;
+ }
+
+ /* Get Items with call back on empty map */
+ SearchItems[0].uLabelType = QCBOR_TYPE_INT64;
+ SearchItems[0].label.int64 = 0;
+ SearchItems[0].uDataType = QCBOR_TYPE_ANY;
+ SearchItems[1].uLabelType = QCBOR_TYPE_NONE;
+ QCBORDecode_GetItemsInMapWithCallback(&DCtx, SearchItems, NULL, CBTest);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
+ return 4002;
+ }
+ if(SearchItems[0].uDataType != QCBOR_TYPE_NONE) {
+ return 4003;
+ }
+
+ /* Test exiting an empty map */
+ QCBORDecode_ExitMap(&DCtx);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
+ return 4702;
+ }
+
+ QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spNested), 0);
+ QCBORDecode_EnterMap(&DCtx, NULL);
+
+ /* GetItems test */
+ SearchItems[0].uLabelType = QCBOR_TYPE_INT64;
+ SearchItems[0].label.int64 = 3;
+ SearchItems[0].uDataType = QCBOR_TYPE_ANY;
+ SearchItems[1].uLabelType = QCBOR_TYPE_INT64;
+ SearchItems[1].label.int64 = 1;
+ SearchItems[1].uDataType = QCBOR_TYPE_ANY;
+ SearchItems[2].uLabelType = QCBOR_TYPE_INT64;
+ SearchItems[2].label.int64 = 99;
+ SearchItems[2].uDataType = QCBOR_TYPE_ANY;
+ SearchItems[3].uLabelType = QCBOR_TYPE_NONE;
+ QCBORDecode_GetItemsInMap(&DCtx, SearchItems);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
+ return 4104;
+ }
+ if(SearchItems[0].uDataType != QCBOR_TYPE_INT64 ||
+ SearchItems[1].uDataType != QCBOR_TYPE_INT64 ||
+ SearchItems[0].val.int64 != 3 ||
+ SearchItems[1].val.int64 != 1 ||
+ SearchItems[2].uDataType != QCBOR_TYPE_NONE) {
+ return 4103;
+ }
+
+
+ /* Test callback */
+ SearchItems[0].uLabelType = QCBOR_TYPE_INT64;
+ SearchItems[0].label.int64 = 3;
+ SearchItems[0].uDataType = QCBOR_TYPE_ANY;
+ SearchItems[1].uLabelType = QCBOR_TYPE_INT64;
+ SearchItems[1].label.int64 = 1;
+ SearchItems[1].uDataType = QCBOR_TYPE_ANY;
+ SearchItems[2].uLabelType = QCBOR_TYPE_NONE;
+
+ struct CbTest2Ctx CTX;
+ CTX.error = false;
+ CTX.found2 = false;
+ CTX.found4 = false;
+ QCBORDecode_GetItemsInMapWithCallback(&DCtx, SearchItems, &CTX, CBTest2);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
+ return 4204;
+ }
+ if(!CTX.found2 || !CTX.found4) {
+ return 4201;
+ }
+
+ if(SearchItems[0].uDataType != QCBOR_TYPE_INT64 || SearchItems[1].uDataType != QCBOR_TYPE_INT64) {
+ return 4203;
+ }
+
+ /* Test error-exit from callback */
+ SearchItems[0].uLabelType = QCBOR_TYPE_INT64;
+ SearchItems[0].label.int64 = 2;
+ SearchItems[0].uDataType = QCBOR_TYPE_ANY;
+ SearchItems[1].uLabelType = QCBOR_TYPE_INT64;
+ SearchItems[1].label.int64 = 1;
+ SearchItems[1].uDataType = QCBOR_TYPE_ANY;
+ SearchItems[2].uLabelType = QCBOR_TYPE_NONE;
+
+ CTX.error = false;
+ CTX.found2 = false;
+ CTX.found4 = false;
+ QCBORDecode_GetItemsInMapWithCallback(&DCtx, SearchItems, &CTX, CBTest2);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_CALLBACK_FAIL) {
+ return 4306;
+ }
+
+ /* Test while in error condition */
+ QCBORDecode_GetItemsInMap(&DCtx, SearchItems);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_CALLBACK_FAIL) {
+ return 4309;
+ }
+
+ /* Test QCBORDecode_GetItemInMapN (covered indireclty by many other tests) */
+ QCBORItem Item;
+ (void)QCBORDecode_GetAndResetError(&DCtx);
+ QCBORDecode_GetItemInMapN(&DCtx, 1, QCBOR_TYPE_ANY, &Item);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
+ return 4704;
+ }
+ if(Item.uDataType != QCBOR_TYPE_INT64 || Item.val.int64 != 1) {
+ return 4707;
+ }
+
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+ QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), 0);
+ QCBORDecode_EnterMap(&DCtx, NULL);
+ QCBORDecode_GetItemInMapSZ(&DCtx, "map in a map", QCBOR_TYPE_ANY, &Item);
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_SUCCESS) {
+ return 4804;
+ }
+ if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 4) {
+ return 4807;
+ }
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
nReturn = EnterMapCursorTest();
return nReturn;
@@ -11392,6 +11574,17 @@
}
#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+ /* ------ */
+ QCBORDecode_Init(&DCtx,
+ UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEmptyMap),
+ 0);
+ QCBORDecode_EnterMap(&DCtx, NULL);
+ QCBORDecode_GetArrayFromMapSZ(&DCtx, "xx", &Item, &ReturnedEncodedCBOR);
+
+ if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_LABEL_NOT_FOUND) {
+ return 106;
+ }
+
return 0;
}
#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */