more improvements and tests working
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index f58c6c3..6ccef67 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -207,6 +207,16 @@
return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
}
+inline static bool
+DecodeNesting_BoundedIsType(const QCBORDecodeNesting *pNesting, uint8_t uType)
+{
+ if(pNesting->pCurrentMap->uMajorType == uType) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
// return 1 if closed out an array or map
inline static void
@@ -1844,7 +1854,9 @@
/*
Public function, see header qcbor/qcbor_decode.h file
*/
-uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe, const QCBORItem *pItem, unsigned int uIndex)
+uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
+ const QCBORItem *pItem,
+ unsigned int uIndex)
{
if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
return CBOR_TAG_INVALID16;
@@ -2072,6 +2084,8 @@
return QCBOR_SUCCESS;
}
+
+
#include <stdio.h>
void printdecode(QCBORDecodeContext *pMe, const char *szName)
{
@@ -2101,7 +2115,8 @@
/*
- *
+ Consume an entire map or array (and do next to
+ nothing for non-aggregate types).
*/
static inline QCBORError
ConsumeItem(QCBORDecodeContext *pMe,
@@ -2173,6 +2188,11 @@
return false;
}
+
+/*
+ Returns true if Item1 and Item2 are the same type
+ or if either are of QCBOR_TYPE_ANY.
+ */
static inline bool
MatchType(QCBORItem Item1, QCBORItem Item2)
{
@@ -2188,7 +2208,7 @@
/**
- \brief Search a map for a set of items
+ \brief Search a map for a set of items.
@param[in] pMe The decode context to search.
@param[in,out] pItemArray The items to search for and the items found.
@@ -2216,7 +2236,6 @@
MapSearch(QCBORDecodeContext *pMe,
QCBORItem *pItemArray,
size_t *puOffset,
- size_t *puEndOffset,
void *pCBContext,
QCBORItemCallback pfCallback)
{
@@ -2306,10 +2325,6 @@
const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
// Cast OK because encoded CBOR is limited to UINT32_MAX
pMe->uMapEndOffset = (uint32_t)uEndOffset;
- // TODO: is zero *puOffset OK?
- if(puEndOffset) {
- *puEndOffset = uEndOffset;
- }
/* For all items not found, set the data type to QCBOR_TYPE_NONE */
int i;
@@ -2345,7 +2360,7 @@
OneItemSeach[0].uDataType = uQcborType;
OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
- QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL, NULL);
+ QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
if(nReturn) {
pMe->uLastError = (uint8_t)nReturn;
}
@@ -2376,7 +2391,7 @@
OneItemSeach[0].uDataType = uQcborType;
OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
- QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL, NULL);
+ QCBORError nReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
if(nReturn) {
pMe->uLastError = (uint8_t)nReturn;
}
@@ -2486,7 +2501,7 @@
*/
QCBORError QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList)
{
- return MapSearch(pCtx, pItemList, NULL, NULL, NULL, NULL);
+ return MapSearch(pCtx, pItemList, NULL, NULL, NULL);
}
/*
@@ -2497,7 +2512,7 @@
void *pCallbackCtx,
QCBORItemCallback pfCB)
{
- return MapSearch(pCtx, pItemList, NULL, NULL, pCallbackCtx, pfCB);
+ return MapSearch(pCtx, pItemList, NULL, pCallbackCtx, pfCB);
}
@@ -2509,7 +2524,7 @@
}
size_t uOffset;
- pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL, NULL);
+ pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
if(pMe->uLastError != QCBOR_SUCCESS) {
return;
}
@@ -2620,47 +2635,55 @@
DecodeNesting_EnterBoundedMode(&(pMe->nesting), UsefulInputBuf_Tell(&(pMe->InBuf)));
+ // TODO: restrict input to less than this or some other invalidation strategy.
+ pMe->uMapEndOffset = 0xffffffff; // Invalidate the cached map end.
+
printdecode(pMe, "EnterMapModeDone");
}
+
+// Semi-private function
void QCBORDecode_ExitBoundedMode(QCBORDecodeContext *pMe, uint8_t uType)
{
- QCBORError uErr;
- size_t uEndOffset;
+ if(pMe->uLastError != QCBOR_SUCCESS) {
+ // Already in error state; do nothing.
+ return;
+ }
- (void)uType; // TODO: error check
-
-/*
- if(pMe->uMapEndOffset) {
- uEndOffset = pMe->uMapEndOffset;
- // It is only valid once.
- pMe->uMapEndOffset = 0;
- } else { */
- // Find offset of the end the bounded array / map
- QCBORItem Dummy;
-
- Dummy.uLabelType = QCBOR_TYPE_NONE;
-
- QCBORError nReturn = MapSearch(pMe, &Dummy, NULL, &uEndOffset, NULL, NULL);
-
- (void)nReturn; // TODO:
-// }
-
printdecode(pMe, "start exit");
-
- /* Before acending mark this level as no longer in bound mode. */
+
+ QCBORError uErr = QCBOR_SUCCESS;
+
+ if(!DecodeNesting_BoundedIsType(&(pMe->nesting), uType)){
+ uErr = QCBOR_ERR_CLOSE_MISMATCH;
+ goto Done;
+ }
+
+ /* Have to set the offset to the end of the map/array
+ that is being exited. If there is no cached value,
+ from previous map search, then do a dummy search. */
+ if(pMe->uMapEndOffset == 0xffffffff) {
+ QCBORItem Dummy;
+ Dummy.uLabelType = QCBOR_TYPE_NONE;
+ uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
+ if(uErr != QCBOR_SUCCESS) {
+ goto Done;
+ }
+ }
+ UsefulInputBuf_Seek(&(pMe->InBuf), pMe->uMapEndOffset);
+ pMe->uMapEndOffset = 0xffffffff; // Invalidate the cached map end.
+
+ /* Before acending, mark this level as no longer in bound mode. */
pMe->nesting.pCurrentMap->uType &= ~QCBOR_NEST_TYPE_IS_BOUND;
-
- /* Set the pre-order traversal state to just after
- the map or array that was exited. */
- UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
-
// Always go up one level
// Need error check to know level is bounded mode and not at top level
pMe->nesting.pCurrent = pMe->nesting.pCurrentMap - 1; // TODO error check
uErr = Ascender(pMe);
+ if(uErr != QCBOR_SUCCESS) {
+ goto Done;
+ }
/* Also ascend to the next higest bounded mode level if
there is one. */
@@ -2675,7 +2698,9 @@
}
}
+Done:
printdecode(pMe, "end exit");
+ pMe->uLastError = (uint8_t)uErr;
}