Merge master (what will be 1.4.2) into dev
diff --git a/src/UsefulBuf.c b/src/UsefulBuf.c
index 4177010..25a92f4 100644
--- a/src/UsefulBuf.c
+++ b/src/UsefulBuf.c
@@ -44,8 +44,9 @@
 
  when        who          what, where, why
  --------    ----         ---------------------------------------------------
- 1/7/2024    llundblade   Add UsefulInputBuf_Compare().
+ 08/08/2024  llundblade   Add UsefulOutBuf_SubString().
  21/05/2024  llundblade   Comment formatting and some code tidiness.
+ 1/7/2024    llundblade   Add UsefulInputBuf_Compare().
  28/02/2022  llundblade   Rearrange UsefulOutBuf_Compare().
  19/11/2023  llundblade   Add UsefulOutBuf_GetOutput().
  19/11/2023  llundblade   Add UsefulOutBuf_Swap().
@@ -418,6 +419,35 @@
 }
 
 
+/*
+ * Public function -- see UsefulBuf.h
+ *
+ * Code Reviewers: THIS FUNCTION DOES POINTER MATH
+ */
+UsefulBufC UsefulOutBuf_SubString(UsefulOutBuf *pMe,
+                                  const size_t  uStart,
+                                  const size_t  uLen)
+{
+   const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
+
+   if(UsefulBuf_IsNULLC(Tmp)) {
+      return NULLUsefulBufC;
+   }
+
+   if(uStart > Tmp.len) {
+      return NULLUsefulBufC;
+   }
+
+   if(Tmp.len - uStart < uLen) {
+      return NULLUsefulBufC;
+   }
+
+   UsefulBufC SubString;
+   SubString.ptr = (const uint8_t *)Tmp.ptr + uStart;
+   SubString.len = uLen;
+
+   return SubString;
+}
 
 
 /*
diff --git a/src/ieee754.c b/src/ieee754.c
index 40421ad..506d5e8 100644
--- a/src/ieee754.c
+++ b/src/ieee754.c
@@ -6,7 +6,7 @@
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
- * See BSD-3-Clause license in README.md
+ * See BSD-3-Clause license in file named "LICENSE"
  *
  * Created on 7/23/18
  * ========================================================================== */
diff --git a/src/ieee754.h b/src/ieee754.h
index fed28f1..9d3a8f3 100644
--- a/src/ieee754.h
+++ b/src/ieee754.h
@@ -5,7 +5,7 @@
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
- * See BSD-3-Clause license in README.md
+ * See BSD-3-Clause license in file named "LICENSE"
  *
  * Created on 7/23/18
  * ========================================================================== */
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 41e6b21..21845f4 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -461,8 +461,8 @@
 
 static QCBORError
 DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
-                                uint8_t             uQCBORType,
-                                uint64_t            uCount)
+                                const uint8_t       uQCBORType,
+                                const uint16_t      uCount)
 {
    QCBORError uError = QCBOR_SUCCESS;
 
@@ -474,21 +474,16 @@
       /* Empty indefinite-length maps and arrays are handled elsewhere */
    }
 
-   /* Error out if arrays is too long to handle */
-   if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
-      uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
-      uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
-      goto Done;
-   }
+   /* 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;
    }
 
-   /* Fill in the new map/array level. Check above makes casts OK. */
-   pNesting->pCurrent->u.ma.uCountCursor  = (uint16_t)uCount;
-   pNesting->pCurrent->u.ma.uCountTotal   = (uint16_t)uCount;
+   pNesting->pCurrent->u.ma.uCountCursor = uCount;
+   pNesting->pCurrent->u.ma.uCountTotal  = uCount;
 
    DecodeNesting_ClearBoundedMode(pNesting);
 
@@ -1075,7 +1070,7 @@
 static QCBORError
 QCBOR_Private_DecodeArrayOrMap(const uint8_t  uMode,
                                const int      nMajorType,
-                               const uint64_t uItemCount,
+                               uint64_t       uItemCount,
                                const int      nAdditionalInfo,
                                QCBORItem     *pDecodedItem)
 {
@@ -1108,28 +1103,20 @@
       uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
 #endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
    } else {
+      /* ----- Definite-length array/map ----- */
+      if(uItemCount > (nMajorType == QCBOR_TYPE_MAP ? QCBOR_MAX_ITEMS_IN_MAP : QCBOR_MAX_ITEMS_IN_ARRAY)) {
+         uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
 
+      } else {
 #ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
-      if(uMode == QCBOR_DECODE_MODE_MAP_AS_ARRAY && nMajorType == QCBOR_TYPE_MAP) {
-         /* ------ Definite-length map as array ------ */
-
-         if(uItemCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
-            uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
-         } else {
-            /* cast OK because of check above */
-            pDecodedItem->val.uCount = (uint16_t)uItemCount*2;
+         if(uMode == QCBOR_DECODE_MODE_MAP_AS_ARRAY && nMajorType == QCBOR_TYPE_MAP) {
+            /* ------ Map as array ------ */
+            uItemCount *= 2;
          }
-
-      } else
 #endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
-      {
-         /* ------ Definite-length array/map ------ */
-         if(uItemCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
-            uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
-         } else {
-            /* cast OK because of check above */
-            pDecodedItem->val.uCount = (uint16_t)uItemCount;
-         }
+
+         /* cast OK because of check above */
+         pDecodedItem->val.uCount = (uint16_t)uItemCount;
       }
    }
 
@@ -1528,9 +1515,9 @@
                                    QCBORItem           *pDecodedItem)
 {
    QCBORError uReturn;
-   int      nMajorType = 0;
-   uint64_t uArgument = 0;
-   int      nAdditionalInfo = 0;
+   int       nMajorType = 0;
+   uint64_t  uArgument = 0;
+   int       nAdditionalInfo = 0;
 
    memset(pDecodedItem, 0, sizeof(QCBORItem));
 
@@ -2311,8 +2298,8 @@
        */
       QCBORError uDescendErr;
       uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
-                                                pDecodedItem->uDataType,
-                                                pDecodedItem->val.uCount);
+                                                    pDecodedItem->uDataType,
+                                                    pDecodedItem->val.uCount);
       if(uDescendErr != QCBOR_SUCCESS) {
          /* This error is probably a traversal error and it overrides
           * the non-traversal error.
diff --git a/src/qcbor_encode.c b/src/qcbor_encode.c
index fa7f485..50ed8a3 100644
--- a/src/qcbor_encode.c
+++ b/src/qcbor_encode.c
@@ -1,35 +1,35 @@
-/*==============================================================================
- Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2024, Laurence Lundblade.
- Copyright (c) 2021, Arm Limited.
- All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-    * Neither the name of The Linux Foundation nor the names of its
-      contributors, nor the name "Laurence Lundblade" may be used to
-      endorse or promote products derived from this software without
-      specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- =============================================================================*/
+/* ===========================================================================
+ * Copyright (c) 2016-2018, The Linux Foundation.
+ * Copyright (c) 2018-2024, Laurence Lundblade.
+ * Copyright (c) 2021, Arm Limited.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors, nor the name "Laurence Lundblade" may be used to
+ *       endorse or promote products derived from this software without
+ *       specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ========================================================================= */
 
 
 #include "qcbor/qcbor_encode.h"
@@ -115,10 +115,10 @@
 Nesting_Increment(QCBORTrackNesting *pNesting)
 {
 #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
-   if(1 >= QCBOR_MAX_ITEMS_IN_ARRAY - pNesting->pCurrentNesting->uCount) {
+   if(pNesting->pCurrentNesting->uCount >= QCBOR_MAX_ITEMS_IN_ARRAY) {
       return QCBOR_ERR_ARRAY_TOO_LONG;
    }
-#endif /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
 
    pNesting->pCurrentNesting->uCount++;
 
@@ -170,7 +170,7 @@
 {
    return pNesting->pCurrentNesting == &pNesting->pArrays[0] ? false : true;
 }
-#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
 
 
 
@@ -227,7 +227,7 @@
  *
  * QCBOR_DISABLE_ENCODE_USAGE_GUARDS also disables the check for more
  * than QCBOR_MAX_ITEMS_IN_ARRAY in an array. Since
- * QCBOR_MAX_ITEMS_IN_ARRAY is very large (65,535) it is very unlikely
+ * QCBOR_MAX_ITEMS_IN_ARRAY is very large (65,534) it is very unlikely
  * to be reached. If it is reached, the count will wrap around to zero
  * and CBOR that is not well formed will be produced, but there will
  * be no buffers overrun and new security issues in the code.
@@ -450,7 +450,7 @@
       nAdditionalInfo = CBOR_SIMPLE_BREAK;
 
    } else
-#endif /* !QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
       if (uArgument < CBOR_TWENTY_FOUR && uMinLen == 0) {
       /* Simple case where argument is < 24 */
       nAdditionalInfo = (int)uArgument;
@@ -529,7 +529,7 @@
    }
 #else
    (void)Nesting_Increment(&(pMe->nesting));
-#endif /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
 }
 
 
@@ -580,7 +580,7 @@
 
 
 /*
- * Public functions for adding signed integers. See qcbor/qcbor_encode.h
+ * Public function for adding signed integers. See qcbor/qcbor_encode.h
  */
 void
 QCBOREncode_AddInt64(QCBOREncodeContext *pMe, const int64_t nNum)
@@ -630,7 +630,7 @@
 
 
 /*
- * Public functions for adding raw encoded CBOR. See qcbor/qcbor_encode.h
+ * Public function for adding raw encoded CBOR. See qcbor/qcbor_encode.h
  */
 void
 QCBOREncode_AddEncoded(QCBOREncodeContext *pMe, const UsefulBufC Encoded)
@@ -759,7 +759,7 @@
 
    QCBOREncode_Private_AddType7(pMe, (uint8_t)FloatResult.uSize, FloatResult.uValue);
 }
-#endif /* !QCBOR_DISABLE_PREFERRED_FLOAT */
+#endif /* ! QCBOR_DISABLE_PREFERRED_FLOAT */
 
 
 
@@ -1120,7 +1120,7 @@
    }
    QCBOREncode_CloseArray(pMe);
 }
-#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
+#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
 
 
 /**
@@ -1196,7 +1196,7 @@
     */
    QCBOREncode_Private_OpenMapOrArray(pMe, uMajorType);
 }
-#endif
+#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
 
 
 /**
@@ -1231,7 +1231,7 @@
       return true;
    }
 
-#else /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+#else /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
    /* None of these checks are performed if the encode guards are
     * turned off as they all relate to correct calling.
     *
@@ -1241,14 +1241,14 @@
 
    (void)uMajorType;
    (void)pMe;
-#endif /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
 
    return false;
 }
 
 
 /**
- * @brief Insert the CBOR head for a map, array or wrapped bstr
+ * @brief Insert the CBOR head for a map, array or wrapped bstr.
  *
  * @param pMe         QCBOR encoding context.
  * @param uMajorType  One of CBOR_MAJOR_TYPE_XXXX.
@@ -1643,7 +1643,7 @@
 
 
 /*
- * Public functions for closing bstr wrapping. See qcbor/qcbor_encode.h
+ * Public function for closing bstr wrapping. See qcbor/qcbor_encode.h
  */
 void
 QCBOREncode_CloseBstrWrap2(QCBOREncodeContext *pMe,
@@ -1707,7 +1707,7 @@
     * security hole, so no extra code or state is added to handle this
     * condition.
     */
-#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
 
    Nesting_Decrease(&(pMe->nesting));
    Nesting_Decrement(&(pMe->nesting));
@@ -1729,7 +1729,7 @@
       pMe->uError = QCBOR_ERR_OPEN_BYTE_STRING;
       return;
    }
-#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
 
    QCBOREncode_Private_OpenMapOrArray(pMe, CBOR_MAJOR_NONE_TYPE_OPEN_BSTR);
 }
@@ -1752,7 +1752,6 @@
 
 
 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
-
 /**
  * @brief Semi-private method to close a map, array with indefinite length
  *
@@ -1774,7 +1773,7 @@
    QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_NONE_TYPE_SIMPLE_BREAK, CBOR_SIMPLE_BREAK, 0);
    Nesting_Decrease(&(pMe->nesting));
 }
-#endif
+#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
 
 
 /*
@@ -1792,7 +1791,7 @@
       pMe->uError = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
       goto Done;
    }
-#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
 
    *pEncodedCBOR = UsefulOutBuf_OutUBuf(&(pMe->OutBuf));
 
@@ -1802,7 +1801,7 @@
 
 
 /*
- * Public functions to get size of the encoded result. See qcbor/qcbor_encode.h
+ * Public function to get size of the encoded result. See qcbor/qcbor_encode.h
  */
 QCBORError
 QCBOREncode_FinishGetSize(QCBOREncodeContext *pMe, size_t *puEncodedLen)
@@ -1817,3 +1816,28 @@
 
    return nReturn;
 }
+
+
+/*
+ * Public function to get substring of encoded-so-far. See qcbor/qcbor_encode.h
+ */
+UsefulBufC
+QCBOREncode_SubString(QCBOREncodeContext *pMe, const size_t uStart)
+{
+   if(pMe->uError) {
+      return NULLUsefulBufC;
+   }
+
+   /* An attempt was made to detect usage errors by comparing uStart
+    * to offsets of open arrays and maps in pMe->nesting, but it is
+    * not possible because there's not enough information in just
+    * the offset. It's not possible to known if Tell() was called before
+    * or after an Open(). To detect this error, the nesting level
+    * would also need to be known. This is not frequently used, so
+    * it is not worth adding this complexity.
+    */
+
+   const size_t uEnd = QCBOREncode_Tell(pMe);
+
+   return UsefulOutBuf_SubString(&(pMe->OutBuf), uStart, uEnd - uStart);
+}
diff --git a/src/qcbor_err_to_str.c b/src/qcbor_err_to_str.c
index 87c2b28..f9588e5 100644
--- a/src/qcbor_err_to_str.c
+++ b/src/qcbor_err_to_str.c
@@ -7,7 +7,7 @@
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
- * See BSD-3-Clause license in README.md
+ * See BSD-3-Clause license in file named "LICENSE"
  *
  * Created on 3/21/20
  * ========================================================================== */