Move tag-related and spiffy-related code to their own source files

qcbor_decode.c was just too big

* Move all tag-related code into qcbor_tag_decode.[ch]

* split out spiffy decode source and DecodeNesting

---------

Co-authored-by: Laurence Lundblade <lgl@securitytheory.com>
diff --git a/src/decode_nesting.h b/src/decode_nesting.h
new file mode 100644
index 0000000..0e1c3a1
--- /dev/null
+++ b/src/decode_nesting.h
@@ -0,0 +1,419 @@
+/* ==========================================================================
+ * decode_nesting.c -- All inline implementation of QCBORDecodeNesting
+ *
+ * Copyright (c) 2016-2018, The Linux Foundation.
+ * Copyright (c) 2018-2024, Laurence Lundblade.
+ * Copyright (c) 2021, Arm Limited.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Forked from qcbor_decode.c on 11/28/24
+ * ========================================================================== */
+
+#ifndef decode_nesting_h
+#define decode_nesting_h
+
+#include "qcbor/qcbor_private.h"
+
+
+/* When this was not all explicitly inline, the compiler decided to
+ * inline everything on its own, so we know there's no loss by
+ * making it all inline.
+ */
+
+static inline void
+DecodeNesting_Init(QCBORDecodeNesting *pNesting)
+{
+   /* Assumes that *pNesting has been zero'd before this call. */
+   pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
+   pNesting->pCurrent = &(pNesting->pLevels[0]);
+}
+
+
+static inline bool
+DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
+{
+   if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
+      /* Not a map or array */
+      return false;
+   }
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+   if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
+      /* Is indefinite */
+      return false;
+   }
+
+#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+
+   /* All checks passed; is a definte length map or array */
+   return true;
+}
+
+
+static inline bool
+DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
+{
+   if(pNesting->pCurrentBounded == NULL) {
+      return false;
+   }
+
+   uint8_t uItemDataType = pNesting->pCurrentBounded->uLevelType;
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+   if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY) {
+      uItemDataType = QCBOR_TYPE_ARRAY;
+   }
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+   if(uItemDataType != uType) {
+      return false;
+   }
+
+   return true;
+}
+
+
+static inline bool
+DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
+{
+   if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
+      return true;
+   }
+   if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
+      return true;
+   }
+   return false;
+}
+
+
+static inline bool
+DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
+{
+   if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
+      return true;
+   } else {
+      return false;
+   }
+}
+
+
+static inline bool
+DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
+{
+   if(pNesting->pCurrentBounded == NULL) {
+      /* No bounded map or array set up */
+      return false;
+   }
+   if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
+      /* Not a map or array; end of those is by byte count */
+      return false;
+   }
+   if(!DecodeNesting_IsCurrentBounded(pNesting)) {
+      /* In a traveral at a level deeper than the bounded level */
+      return false;
+   }
+   /* Works for both definite- and indefinitelength maps/arrays */
+   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;
+   }
+   /* All checks passed, got to the end of an array or map*/
+   return true;
+}
+
+
+static inline bool
+DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
+{
+   /* Must only be called on map / array */
+   if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
+      return true;
+   } else {
+      return false;
+   }
+}
+
+
+static inline bool
+DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
+{
+   if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
+      return true;
+   } else {
+      return false;
+   }
+}
+
+
+static inline bool
+DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
+{
+   if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
+      return true;
+   } else {
+      return false;
+   }
+}
+
+
+static inline bool
+DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
+{
+   if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
+      /* is a byte string */
+      return true;
+   }
+   return false;
+}
+
+
+static inline uint8_t
+DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
+{
+   const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
+   /* Limit in DecodeNesting_Descend against more than
+    * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
+    */
+   return (uint8_t)nLevel;
+}
+
+
+
+
+static inline void
+DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
+{
+   /* Only call on a definite-length array / map */
+   pNesting->pCurrent->u.ma.uCountCursor--;
+}
+
+
+static inline void
+DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
+{
+   pNesting->pCurrent->u.ma.uCountCursor = 0;
+}
+
+static inline void
+DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
+{
+   if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
+      pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
+   }
+}
+
+static inline void
+DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
+{
+   /* Only call on a definite-length array / map */
+   pNesting->pCurrent->u.ma.uCountCursor++;
+}
+
+
+
+
+static inline void
+DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
+{
+   pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
+}
+
+
+static inline QCBORError
+DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
+{
+   /* Error out if nesting is too deep */
+   if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
+      return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
+   }
+
+   /* The actual descend */
+   pNesting->pCurrent++;
+
+   pNesting->pCurrent->uLevelType = uType;
+
+   return QCBOR_SUCCESS;
+}
+
+static inline QCBORError
+DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
+                                const uint8_t       uQCBORType,
+                                const uint16_t      uCount)
+{
+   QCBORError uError = QCBOR_SUCCESS;
+
+   if(uCount == 0) {
+      /* Nothing to do for empty definite-length arrays. They are just are
+       * effectively the same as an item that is not a map or array.
+       */
+      goto Done;
+      /* Empty indefinite-length maps and arrays are handled elsewhere */
+   }
+
+   /* Rely on check in QCBOR_Private_DecodeArrayOrMap() for definite-length
+    * arrays and maps that are too long */
+
+   uError = DecodeNesting_Descend(pNesting, uQCBORType);
+   if(uError != QCBOR_SUCCESS) {
+      goto Done;
+   }
+
+   pNesting->pCurrent->u.ma.uCountCursor = uCount;
+   pNesting->pCurrent->u.ma.uCountTotal  = uCount;
+
+   DecodeNesting_ClearBoundedMode(pNesting);
+
+Done:
+   return uError;;
+}
+
+
+static inline QCBORError
+DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
+                                     uint32_t            uEndOffset,
+                                     uint32_t            uStartOffset)
+{
+   QCBORError uError;
+
+   uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
+   if(uError != QCBOR_SUCCESS) {
+      goto Done;
+   }
+
+   /* Fill in the new byte string level */
+   pNesting->pCurrent->u.bs.uSavedEndOffset  = uEndOffset;
+   pNesting->pCurrent->u.bs.uBstrStartOffset = uStartOffset;
+
+   /* Bstr wrapped levels are always bounded */
+   pNesting->pCurrentBounded = pNesting->pCurrent;
+
+Done:
+   return uError;;
+}
+
+
+static inline void
+DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
+{
+   pNesting->pCurrent--;
+}
+
+
+
+
+static inline void
+DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
+{
+   pNesting->pCurrent = pNesting->pCurrentBounded;
+}
+
+static inline void
+DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
+{
+   /* Should be only called on maps and arrays */
+   /*
+    * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
+    * larger than DecodeNesting_EnterBoundedMode which keeps it less than
+    * uin32_t so the cast is safe.
+    */
+   pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
+
+   if(bIsEmpty) {
+      pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
+   }
+}
+
+static inline QCBORError
+DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
+                                     bool                bIsEmpty,
+                                     size_t              uOffset)
+{
+   /*
+    * Should only be called on map/array.
+    *
+    * Have descended into this before this is called. The job here is
+    * just to mark it in bounded mode.
+    *
+    * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
+    * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
+    *
+    * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
+    */
+   if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
+      return QCBOR_ERR_INPUT_TOO_LARGE;
+   }
+
+   pNesting->pCurrentBounded = pNesting->pCurrent;
+
+   DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
+
+   return QCBOR_SUCCESS;
+}
+
+
+static inline uint32_t
+DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
+{
+   return pMe->pCurrentBounded->u.bs.uSavedEndOffset;
+}
+
+
+static inline uint8_t
+DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
+{
+   const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
+   /* Limit in DecodeNesting_Descend against more than
+    * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
+    */
+   return (uint8_t)nLevel;
+}
+
+
+
+
+static inline uint32_t
+DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
+{
+   return pNesting->pCurrentBounded->u.ma.uStartOffset;
+}
+
+
+static inline void
+DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
+{
+   pNesting->pCurrent = pNesting->pCurrentBounded - 1;
+}
+
+
+static inline void
+DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
+{
+   while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
+      pNesting->pCurrentBounded--;
+      if(DecodeNesting_IsCurrentBounded(pNesting)) {
+         break;
+      }
+   }
+}
+
+
+
+
+static inline void
+DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
+                                  QCBORDecodeNesting *pSave)
+{
+   *pSave = *pNesting;
+}
+
+
+static inline void
+DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
+                                   const QCBORDecodeNesting *pSave)
+{
+   *pNesting = *pSave;
+}
+
+#endif /* decode_nesting_h */