Bug fixes for spiffy decode corner cases (#57)

* Bug fix for decoding empty maps and arrays with spiffy decode
* Bug fix for entering and exiting the same map multiple times
* Add a lot of tests for spiffy decoding of nested maps and arrays

Co-authored-by: Laurence Lundblade <lgl@securitytheory.com>
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index afc3651..7b41ff3 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -227,7 +227,8 @@
       return false;
    }
    // Works for both definite and indefinite length maps/arrays
-   if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0) {
+   if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
+      pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
       // Count is not zero, still unconsumed item
       return false;
    }
@@ -432,6 +433,13 @@
 
 
 static inline void
+DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
+{
+   pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
+}
+
+
+static inline void
 DecodeNesting_Init(QCBORDecodeNesting *pNesting)
 {
    /* Assumes that *pNesting has been zero'd before this call. */
@@ -445,7 +453,7 @@
 {
    *pSave = *pNesting;
    pNesting->pCurrent = pNesting->pCurrentBounded;
-   pNesting->pCurrent->u.ma.uCountCursor = pNesting->pCurrent->u.ma.uCountTotal;
+   DecodeNesting_ResetMapOrArrayCount(pNesting);
 }
 
 
@@ -2964,13 +2972,25 @@
 }
 
 
+/**
+ * @brief Search for a map/array by label and enter it
+ *
+ * @param[in] pMe  The decode context.
+ * @param[in] pSearch The map/array to search for.
+ *
+ * @c pSearch is expected to contain one item of type map or array
+ * with the label specified. The current bounded map will be searched for
+ * this and if found  will be entered.
+ *
+ * If the label is not found, or the item found is not a map or array,
+ * the error state is set.
+ */
 static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
 {
    // The first item in pSearch is the one that is to be
    // entered. It should be the only one filled in. Any other
    // will be ignored unless it causes an error.
    if(pMe->uLastError != QCBOR_SUCCESS) {
-      // Already in error state; do nothing.
       return;
    }
 
@@ -2985,23 +3005,28 @@
       return;
    }
 
-   /* Need to get the current pre-order nesting level and cursor to be
-      at the map/array about to be entered.
-
-    Also need the current map nesting level and start cursor to
-    be at the right place.
-
-    The UsefulInBuf offset could be anywhere, so no assumption is
-    made about it.
-
-    No assumption is made about the pre-order nesting level either.
-
-    However the bounded mode nesting level is assumed to be one above
-    the map level that is being entered.
+   /*
+    * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
+    * next item for the pre-order traversal cursor to be the map/array
+    * found by MapSearch(). The next few lines of code force the
+    * cursor to that.
+    *
+    * There is no need to retain the old cursor because
+    * QCBORDecode_EnterBoundedMapOrArray() will set it to the
+    * beginning of the map/array being entered.
+    *
+    * The cursor is forced by: 1) setting the input buffer position to
+    * the item offset found by MapSearch(), 2) setting the map/array
+    * counter to the total in the map/array, 3) setting the nesting
+    * level. Setting the map/array counter to the total is not
+    * strictly correct, but this is OK because this cursor only needs
+    * to be used to get one item and MapSearch() has already found it
+    * confirming it exists.
     */
-   /* Seek to the data item that is the map or array */
    UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
 
+   DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
+
    DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
 
    QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);