Merge from master
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4ec0628..1e233d2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -17,6 +17,10 @@
 
         - os-image: ubuntu-latest
           container: ubuntu:22.04
+          dis-xxx: '-DQCBOR_DISABLE_NON_INTEGER_LABELS'
+
+        - os-image: ubuntu-latest
+          container: ubuntu:22.04
           dis-xxx: '-DQCBOR_DISABLE_TAGS'
 
         - os-image: ubuntu-latest
diff --git a/QCBOR.xcodeproj/project.pbxproj b/QCBOR.xcodeproj/project.pbxproj
index d7ebc4c..34bdfc7 100644
--- a/QCBOR.xcodeproj/project.pbxproj
+++ b/QCBOR.xcodeproj/project.pbxproj
@@ -173,7 +173,7 @@
 		E776E094214AE09700E67947 /* UsefulBuf.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = UsefulBuf.h; path = inc/UsefulBuf.h; sourceTree = "<group>"; tabWidth = 3; };
 		E776E096214AE0C700E67947 /* cmd_line_main.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; path = cmd_line_main.c; sourceTree = "<group>"; tabWidth = 3; };
 		E776E161214EE19C00E67947 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
-		E7864765252CE63100A0C11B /* qcbor_err_to_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = qcbor_err_to_str.c; path = src/qcbor_err_to_str.c; sourceTree = "<group>"; };
+		E7864765252CE63100A0C11B /* qcbor_err_to_str.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = qcbor_err_to_str.c; path = src/qcbor_err_to_str.c; sourceTree = "<group>"; tabWidth = 3; };
 		E78C91DE240C90C100F4CECE /* qcbor_decode.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_decode.h; path = inc/qcbor/qcbor_decode.h; sourceTree = "<group>"; tabWidth = 3; };
 		E78C91DF240C90C100F4CECE /* qcbor_common.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_common.h; path = inc/qcbor/qcbor_common.h; sourceTree = "<group>"; tabWidth = 3; };
 		E78C91E0240C90C100F4CECE /* qcbor_private.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_private.h; path = inc/qcbor/qcbor_private.h; sourceTree = "<group>"; tabWidth = 3; };
diff --git a/README.md b/README.md
index 2f2deef..9adfefe 100644
--- a/README.md
+++ b/README.md
@@ -458,6 +458,7 @@
     | QCBOR_DISABLE_PREFERRED_FLOAT           |   900 |
     | QCBOR_DISABLE_FLOAT_HW_USE              |    50 |
     | QCBOR_DISABLE_TAGS                      |   400 |
+    | QCBOR_DISABLE_NON_INTEGER_LABELS        |   140 |
     | USEFULBUF_DISABLE_ALL_FLOAT             |   950 |
 
 QCBOR_DISABLE_ENCODE_USAGE_GUARDS affects encoding only.  It doesn't
@@ -497,6 +498,12 @@
 have no tags. "Borrowed" tag content formats (e.g. an epoch-based date
 without the tag number), can still be processed.
 
+QCBOR_DISABLE_NON_INTEGER_LABELS causes any label that doesn't
+fit in an int64_t to result in a QCBOR_ERR_MAP_LABEL_TYPE error.
+This also disables QCBOR_DECODE_MODE_MAP_AS_ARRAY and
+QCBOR_DECODE_MODE_MAP_STRINGS_ONLY. It is fairly common for CBOR-based
+protocols to use only small integers as labels.
+
 See the discussion above on floating-point.
 
  ### Size of spiffy decode
diff --git a/inc/qcbor/qcbor_common.h b/inc/qcbor/qcbor_common.h
index 652cf01..d64e973 100644
--- a/inc/qcbor/qcbor_common.h
+++ b/inc/qcbor/qcbor_common.h
@@ -555,12 +555,17 @@
 /**
  * @brief Get string describing an error code.
  *
- * @param[in] err   The error code.
+ * @param[in] uErr   The error code.
  *
  * @return  NULL-terminated string describing error or "Unidentified
  *          error" if the error is not known.
+ *
+ * This is not thread-safe because it uses a static buffer
+ * for formatting, but this is only a diagnostic and the only
+ * consequence is the wrong description.
  */
-const char *qcbor_err_to_str(QCBORError err);
+const char *
+qcbor_err_to_str(QCBORError uErr);
 
 
 
diff --git a/inc/qcbor/qcbor_decode.h b/inc/qcbor/qcbor_decode.h
index 2f55ac4..c1f37cf 100644
--- a/inc/qcbor/qcbor_decode.h
+++ b/inc/qcbor/qcbor_decode.h
@@ -520,13 +520,15 @@
 
    /** Union holding the different label types selected based on @c uLabelType */
    union {
+      /** The label for @c uLabelType for @ref QCBOR_TYPE_INT64 */
+      int64_t     int64;
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+      /** The label for @c uLabelType for @ref QCBOR_TYPE_UINT64 */
+      uint64_t    uint64;
       /** The label for @c uLabelType @ref QCBOR_TYPE_BYTE_STRING and
        *  @ref QCBOR_TYPE_TEXT_STRING */
       UsefulBufC  string;
-      /** The label for @c uLabelType for @ref QCBOR_TYPE_INT64 */
-      int64_t     int64;
-      /** The label for @c uLabelType for @ref QCBOR_TYPE_UINT64 */
-      uint64_t    uint64;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
    } label;
 
 #ifndef QCBOR_DISABLE_TAGS
@@ -1107,7 +1109,7 @@
  * in the QCBORItem.
  *
  * Tags nest. Here the tag with index 0 has the data item as its content. The
- *  tag with index 1 has the tag at index 0 has its content and so forth.
+ * tag with index 1 has the tag at index 0 has its content and so forth.
  *
  * Deep tag nesting is rare so this implementation imposes a limit of
  * @ref QCBOR_MAX_TAGS_PER_ITEM on nesting and returns @ref
diff --git a/inc/qcbor/qcbor_encode.h b/inc/qcbor/qcbor_encode.h
index 86402ee..c72f4d9 100644
--- a/inc/qcbor/qcbor_encode.h
+++ b/inc/qcbor/qcbor_encode.h
@@ -1990,15 +1990,20 @@
  * @param[in] pMe    The encode context.
  * @param[in] uNum   The simple value.
  *
- * Use QCBOREncode_AddBool(), QCBOREncode_AddUndef()... instead of this.
+ * QCBOREncode_AddBool(), QCBOREncode_AddUndef() and
+ * QCBOREncode_AddNull() are preferred to this for the simple values
+ * defined in RFC 8949, but this can be used for them too.
  *
- * Use this to add simple values beyond those in defined RFC
- * 8949. Simple values must be registered with IANA. There is no range
- * of values for proprietary use.
+ * The main purpose of this is to add simple values beyond those in
+ * defined RFC 8949. Note that simple values must be registered with
+ * IANA. Those in the range of 0 to 19 must be standardized.  Those in
+ * the range of 32 to 255 do not require a standard, but must be
+ * publically specified. There is no range of values for proprietary
+ * use. See
  * https://www.iana.org/assignments/cbor-simple-values/cbor-simple-values.xhtml
  */
 static void
-QCBOREncode_AddSimple(QCBOREncodeContext *pMe, const uint64_t uNum);
+QCBOREncode_AddSimple(QCBOREncodeContext *pMe, const uint8_t uNum);
 
 static void
 QCBOREncode_AddSimpleToMap(QCBOREncodeContext *pMe,
@@ -3954,7 +3959,7 @@
 
 
 static inline void
-QCBOREncode_AddSimple(QCBOREncodeContext *pMe, const uint64_t uNum)
+QCBOREncode_AddSimple(QCBOREncodeContext *pMe, const uint8_t uNum)
 {
 #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
    if(pMe->uMode >= QCBOR_ENCODE_MODE_DCBOR) {
@@ -3976,8 +3981,8 @@
 
 static inline void
 QCBOREncode_AddSimpleToMap(QCBOREncodeContext *pMe,
-                                   const char         *szLabel,
-                                   const uint8_t       uSimple)
+                           const char         *szLabel,
+                           const uint8_t       uSimple)
 {
    QCBOREncode_AddSZString(pMe, szLabel);
    QCBOREncode_AddSimple(pMe, uSimple);
@@ -3985,8 +3990,8 @@
 
 static inline void
 QCBOREncode_AddSimpleToMapN(QCBOREncodeContext *pMe,
-                                    const int64_t       nLabel,
-                                    const uint8_t       uSimple)
+                            const int64_t       nLabel,
+                            const uint8_t       uSimple)
 {
    QCBOREncode_AddInt64(pMe, nLabel);
    QCBOREncode_AddSimple(pMe, uSimple);
diff --git a/inc/qcbor/qcbor_spiffy_decode.h b/inc/qcbor/qcbor_spiffy_decode.h
index 6169a90..d1e5d20 100644
--- a/inc/qcbor/qcbor_spiffy_decode.h
+++ b/inc/qcbor/qcbor_spiffy_decode.h
@@ -1218,6 +1218,37 @@
 
 
 /**
+ * @brief Decode the next item as a CBOR simple value.
+ *
+ * @param[in] pCtx            The decode context.
+ * @param[out] puSimpleValue  The simplle value returned.
+ *
+ * The purpose of this is to get a CBOR simple value other than a
+ * Boolean, NULL or "undefined", but this works on all simple
+ * values. See QCBOREncode_AddSimple() for more details on simple
+ * values in general.
+ *
+ * See QCBORDecode_GetBool(), QCBORDecode_GetNull(),
+ * QCBORDecode_GetUndefined() for the preferred way of getting those
+ * simple values.
+ */
+void
+QCBORDecode_GetSimple(QCBORDecodeContext *pCtx, uint8_t *puSimpleValue);
+
+void
+QCBORDecode_GetSimpleInMapN(QCBORDecodeContext *pCtx,
+                            int64_t             nLabel,
+                            uint8_t            *puSimpleValue);
+
+void
+QCBORDecode_GetSimpleInMapSZ(QCBORDecodeContext *pCtx,
+                             const char         *szLabel,
+                             uint8_t            *puSimpleValue);
+
+
+
+
+/**
  * @brief Decode the next item as a date string.
  *
  * @param[in] pCtx             The decode context.
@@ -2284,6 +2315,7 @@
                               QCBORItem          *pItem,
                               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);
@@ -2291,6 +2323,12 @@
    OneItemSeach[1].uLabelType   = QCBOR_TYPE_NONE;
 
    QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSeach, pItem, pEncodedCBOR);
+#else
+   (void)szLabel;
+   (void)pItem;
+   (void)pEncodedCBOR;
+   pMe->uLastError =  QCBOR_ERR_MAP_LABEL_TYPE;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
 }
 
 static inline void
@@ -2324,6 +2362,7 @@
                             QCBORItem          *pItem,
                             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);
@@ -2331,6 +2370,12 @@
    OneItemSeach[1].uLabelType   = QCBOR_TYPE_NONE;
 
    QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSeach, pItem, pEncodedCBOR);
+#else
+   (void)szLabel;
+   (void)pItem;
+   (void)pEncodedCBOR;
+   pMe->uLastError =  QCBOR_ERR_MAP_LABEL_TYPE;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
 }
 
 
@@ -2620,6 +2665,7 @@
 }
 
 
+
 static inline void
 QCBORDecode_GetDateString(QCBORDecodeContext *pMe,
                           const uint8_t       uTagRequirement,
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 645f6a8..13a728d 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -105,8 +105,10 @@
 {
    const uint8_t uDataType = Item.uDataType;
    return uDataType == QCBOR_TYPE_MAP ||
-          uDataType == QCBOR_TYPE_ARRAY ||
-          uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+          uDataType == QCBOR_TYPE_MAP_AS_ARRAY ||
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+          uDataType == QCBOR_TYPE_ARRAY;
 }
 
 static bool
@@ -150,6 +152,7 @@
       if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
          return true;
       }
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
    } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
       if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
          return true;
@@ -162,6 +165,7 @@
       if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
          return true;
       }
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
    }
 
    /* Other label types are never matched */
@@ -373,9 +377,11 @@
    }
 
    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;
@@ -845,11 +851,13 @@
 /**
  * @brief Decode integer types, major types 0 and 1.
  *
- * @param[in] nMajorType     The CBOR major type (0 or 1).
- * @param[in] uArgument      The argument from the head.
- * @param[out] pDecodedItem  The filled in decoded item.
+ * @param[in] nMajorType       The CBOR major type (0 or 1).
+ * @param[in] uArgument        The argument from the head.
+ * @param[in] nAdditionalInfo  So it can be error-checked.
+ * @param[out] pDecodedItem    The filled in decoded item.
  *
- * @retval QCBOR_ERR_INT_OVERFLOW Too-large negative encountered
+ * @retval QCBOR_ERR_INT_OVERFLOW  Too-large negative encountered.
+ * @retval QCBOR_ERR_BAD_INT       nAdditionalInfo indicated indefinte.
  *
  * Must only be called when major type is 0 or 1.
  *
@@ -865,10 +873,16 @@
 static QCBORError
 QCBOR_Private_DecodeInteger(const int      nMajorType,
                             const uint64_t uArgument,
+                            const int      nAdditionalInfo,
                             QCBORItem     *pDecodedItem)
 {
    QCBORError uReturn = QCBOR_SUCCESS;
 
+   if(nAdditionalInfo == LEN_IS_INDEFINITE) {
+      uReturn = QCBOR_ERR_BAD_INT;
+      goto Done;
+   }
+
    if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
       if (uArgument <= INT64_MAX) {
          pDecodedItem->val.int64 = (int64_t)uArgument;
@@ -895,10 +909,234 @@
       }
    }
 
+Done:
    return uReturn;
 }
 
 
+/**
+ * @brief Decode text and byte strings
+ *
+ * @param[in] pMe              Decoder context.
+ * @param[in] bAllocate        Whether to allocate and copy string.
+ * @param[in] nMajorType       Whether it is a byte or text string.
+ * @param[in] uStrLen          The length of the string.
+ * @param[in] nAdditionalInfo  Whether it is an indefinite-length string.
+ * @param[out] pDecodedItem    The filled-in decoded item.
+ *
+ * @retval QCBOR_ERR_HIT_END          Unexpected end of input.
+ * @retval QCBOR_ERR_STRING_ALLOCATE  Out of memory.
+ * @retval QCBOR_ERR_STRING_TOO_LONG  String longer than SIZE_MAX - 4.
+ * @retval QCBOR_ERR_NO_STRING_ALLOCATOR  Allocation requested, but no allocator
+ *
+ * This reads @c uStrlen bytes from the input and fills in @c
+ * pDecodedItem. If @c bAllocate is true, then memory for the string
+ * is allocated.
+ */
+static QCBORError
+QCBOR_Private_DecodeString(QCBORDecodeContext  *pMe,
+                           const bool           bAllocate,
+                           const int            nMajorType,
+                           const uint64_t       uStrLen,
+                           const int            nAdditionalInfo,
+                           QCBORItem           *pDecodedItem)
+{
+   QCBORError uReturn = QCBOR_SUCCESS;
+
+   /* ---- Figure out the major type ---- */
+   #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
+   #error QCBOR_TYPE_BYTE_STRING not lined up with major type
+   #endif
+
+   #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
+   #error QCBOR_TYPE_TEXT_STRING not lined up with major type
+   #endif
+   pDecodedItem->uDataType = (uint8_t)(nMajorType + 4);
+
+   if(nAdditionalInfo == LEN_IS_INDEFINITE) {
+      /* --- Just the head of an indefinite-length string --- */
+      pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
+
+   } else {
+      /* --- A definite-length string --- */
+      /* --- (which might be a chunk of an indefinte-length string) --- */
+
+      /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
+       * CPUs.  This check makes the casts to size_t below safe.
+       *
+       * The max is 4 bytes less than the largest sizeof() so this can be
+       * tested by putting a SIZE_MAX length in the CBOR test input (no
+       * one will care the limit on strings is 4 bytes shorter).
+       */
+      if(uStrLen > SIZE_MAX-4) {
+         uReturn = QCBOR_ERR_STRING_TOO_LONG;
+         goto Done;
+      }
+
+      const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(&(pMe->InBuf), (size_t)uStrLen);
+      if(UsefulBuf_IsNULLC(Bytes)) {
+         /* Failed to get the bytes for this string item */
+         uReturn = QCBOR_ERR_HIT_END;
+         goto Done;
+      }
+
+      if(bAllocate) {
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
+         /* --- Put string in allocated memory --- */
+
+         /* Note that this is not where allocation to coalesce
+          * indefinite-length strings is done. This is for when the
+          * caller has requested all strings be allocated. Disabling
+          * indefinite length strings also disables this allocate-all
+          * option.
+          */
+
+         if(pMe->StringAllocator.pfAllocator == NULL) {
+            uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
+            goto Done;
+         }
+         UsefulBuf NewMem = StringAllocator_Allocate(&(pMe->StringAllocator), (size_t)uStrLen);
+         if(UsefulBuf_IsNULL(NewMem)) {
+            uReturn = QCBOR_ERR_STRING_ALLOCATE;
+            goto Done;
+         }
+         pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
+         pDecodedItem->uDataAlloc = 1;
+#else
+         uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
+#endif /*  ! QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
+      } else {
+         /* --- Normal case with no string allocator --- */
+         pDecodedItem->val.string = Bytes;
+      }
+   }
+
+Done:
+   return uReturn;
+}
+
+
+/**
+ * @brief Decode array or map.
+ *
+ * @param[in] uMode            Decoder mode.
+ * @param[in] nMajorType       Whether it is a byte or text string.
+ * @param[in] uItemCount       The length of the string.
+ * @param[in] nAdditionalInfo  Whether it is an indefinite-length.
+ * @param[out] pDecodedItem    The filled-in decoded item.
+ *
+ * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinites disabled.
+ * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG     Too many items in array/map.
+ *
+ * Not much to do for arrays and maps. Just the type item count (but a
+ * little messy because of ifdefs for indefinite-lengths and
+ * map-as-array decoding).
+ *
+ * This also does the bulk of the work for @ref
+ * QCBOR_DECODE_MODE_MAP_AS_ARRAY, a special mode to handle
+ * arbitrarily complex map labels. This ifdefs out with
+ * QCBOR_DISABLE_NON_INTEGER_LABELS.
+ */
+static QCBORError
+QCBOR_Private_DecodeArrayOrMap(const uint8_t  uMode,
+                               const int      nMajorType,
+                               const uint64_t uItemCount,
+                               const int      nAdditionalInfo,
+                               QCBORItem     *pDecodedItem)
+{
+   QCBORError uReturn;
+
+   /* ------ Sort out the data type ------ */
+   #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
+   #error QCBOR_TYPE_ARRAY value not lined up with major type
+   #endif
+
+   #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
+   #error QCBOR_TYPE_MAP value not lined up with major type
+   #endif
+   pDecodedItem->uDataType = (uint8_t)nMajorType;
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+   if(uMode == QCBOR_DECODE_MODE_MAP_AS_ARRAY && nMajorType == QCBOR_TYPE_MAP) {
+      pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
+   }
+#else
+   (void)uMode;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+   uReturn = QCBOR_SUCCESS;
+
+   if(nAdditionalInfo == LEN_IS_INDEFINITE) {
+      /* ------ Indefinite-length array/map ----- */
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+      pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
+#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+      uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
+#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+   } 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;
+         }
+
+      } 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;
+         }
+      }
+   }
+
+   return uReturn;
+}
+
+
+/**
+ * @brief Decode a tag number.
+ *
+ * @param[in] uTagNumber       The length of the string.
+ * @param[in] nAdditionalInfo  So this can be error-checked.
+ * @param[out] pDecodedItem    The filled-in decoded item.
+ *
+ * @retval QCBOR_ERR_BAD_INT        nAdditionalInfo is LEN_IS_INDEFINITE.
+ * @retval QCBOR_ERR_TAGS_DISABLED  QCBOR_DISABLE_TAGS is defined.
+ *
+ * Not much to do for tags, but fill in pDecodedItem and check for
+ * error in nAdditionalInfo.
+ */
+static QCBORError
+QCBOR_Private_DecodeTag(const uint64_t uTagNumber,
+                        const int      nAdditionalInfo,
+                        QCBORItem     *pDecodedItem)
+{
+#ifndef QCBOR_DISABLE_TAGS
+   if(nAdditionalInfo == LEN_IS_INDEFINITE) {
+      return QCBOR_ERR_BAD_INT;
+   } else {
+      pDecodedItem->val.uTagV = uTagNumber;
+      pDecodedItem->uDataType = QCBOR_TYPE_TAG;
+      return QCBOR_SUCCESS;
+   }
+#else /* QCBOR_DISABLE_TAGS */
+   (void)nAdditionalInfo;
+   (void)uTagNumber;
+   (void)pDecodedItem;
+   return QCBOR_ERR_TAGS_DISABLED;
+#endif /* QCBOR_DISABLE_TAGS */
+}
+
+
 /* Make sure #define value line up as DecodeSimple counts on this. */
 #if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
 #error QCBOR_TYPE_FALSE macro value wrong
@@ -1048,129 +1286,11 @@
 
 
 /**
- * @brief Decode text and byte strings
- *
- * @param[in] pAllocator     The string allocator or NULL.
- * @param[in] uStrLen        The length of the string.
- * @param[in] pUInBuf        The surce from which to read the string's bytes.
- * @param[out] pDecodedItem  The filled in decoded item.
- *
- * @retval QCBOR_ERR_HIT_END          Unexpected end of input.
- * @retval QCBOR_ERR_STRING_ALLOCATE  Out of memory.
- * @retval QCBOR_ERR_STRING_TOO_LONG  String longer than SIZE_MAX - 4.
- *
- * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
- * pDecodedItem. If @c pAllocator is not NULL then memory for the
- * string is allocated.
- */
-static QCBORError
-QCBOR_Private_DecodeBytes(const QCBORInternalAllocator *pAllocator,
-                          const uint64_t                uStrLen,
-                          UsefulInputBuf               *pUInBuf,
-                          QCBORItem                    *pDecodedItem)
-{
-   QCBORError uReturn = QCBOR_SUCCESS;
-
-   /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
-    * CPUs.  This check makes the casts to size_t below safe.
-    *
-    * The max is 4 bytes less than the largest sizeof() so this can be
-    * tested by putting a SIZE_MAX length in the CBOR test input (no
-    * one will care the limit on strings is 4 bytes shorter).
-    */
-   if(uStrLen > SIZE_MAX-4) {
-      uReturn = QCBOR_ERR_STRING_TOO_LONG;
-      goto Done;
-   }
-
-   const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
-   if(UsefulBuf_IsNULLC(Bytes)) {
-      /* Failed to get the bytes for this string item */
-      uReturn = QCBOR_ERR_HIT_END;
-      goto Done;
-   }
-
-#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
-   /* Note that this is not where allocation to coalesce
-    * indefinite-length strings is done. This is for when the caller
-    * has requested all strings be allocated. Disabling indefinite
-    * length strings also disables this allocate-all option.
-    */
-   if(pAllocator) {
-      /* request to use the string allocator to make a copy */
-      UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
-      if(UsefulBuf_IsNULL(NewMem)) {
-         uReturn = QCBOR_ERR_STRING_ALLOCATE;
-         goto Done;
-      }
-      pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
-      pDecodedItem->uDataAlloc = 1;
-      goto Done;
-   }
-#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
-   (void)pAllocator;
-#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
-
-   /* Normal case with no string allocator */
-   pDecodedItem->val.string = Bytes;
-
-Done:
-   return uReturn;
-}
-
-
-/**
- * @brief Map the CBOR major types for strings to the QCBOR types.
- *
- * @param[in] nCBORMajorType  The CBOR major type to convert.
- * @retturns QCBOR type number.
- *
- * This only works for the two string types.
- */
-static uint8_t
-QCBOR_Private_ConvertStringMajorTypes(int nCBORMajorType)
-{
-   #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
-   #error QCBOR_TYPE_BYTE_STRING no lined up with major type
-   #endif
-
-   #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
-   #error QCBOR_TYPE_TEXT_STRING no lined up with major type
-   #endif
-
-   return (uint8_t)(nCBORMajorType + 4);
-}
-
-
-/**
- * @brief Map the CBOR major types  for arrays/maps  to the QCBOR types.
- *
- * @param[in] nCBORMajorType  The CBOR major type to convert.
- * @retturns QCBOR type number.
- *
- * This only works for the two aggregate types.
- */
-static uint8_t
-QCBORDecode_Private_ConvertArrayOrMapType(int nCBORMajorType)
-{
-   #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
-   #error QCBOR_TYPE_ARRAY value not lined up with major type
-   #endif
-
-   #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
-   #error QCBOR_TYPE_MAP value not lined up with major type
-   #endif
-
-   return (uint8_t)(nCBORMajorType);
-}
-
-
-/**
  * @brief Decode a single primitive data item (decode layer 6).
  *
- * @param[in] pUInBuf       Input buffer to read data item from.
- * @param[out] pDecodedItem  The filled-in decoded item.
- * @param[in] pAllocator    The allocator to use for strings or NULL.
+ * @param[in] pMe                Decoder context.
+ * @param[in] bAllocateStrings   If true, use allocator for strings.
+ * @param[out] pDecodedItem      The filled-in decoded item.
  *
  * @retval QCBOR_ERR_UNSUPPORTED             Encountered unsupported/reserved
  *                                           features
@@ -1178,6 +1298,7 @@
  * @retval QCBOR_ERR_INT_OVERFLOW            Too-large negative encountered
  * @retval QCBOR_ERR_STRING_ALLOCATE         Out of memory.
  * @retval QCBOR_ERR_STRING_TOO_LONG         String longer than SIZE_MAX - 4.
+ * @retval QCBOR_ERR_NO_STRING_ALLOCATOR     Allocation requested, but no allocator
  * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
  *                                           of half-precision disabled
  * @retval QCBOR_ERR_ALL_FLOAT_DISABLED      Float-point in input, but all
@@ -1187,104 +1308,67 @@
  * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED  Indefinite length map/array
  *                                              in input, but indefinite
  *                                              lengths disabled.
+ * @retval QCBOR_ERR_BAD_INT                 nAdditionalInfo indicated indefinte.
+ * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG   Too many items in array/map.
+ * @retval QCBOR_ERR_TAGS_DISABLED           QCBOR_DISABLE_TAGS is defined.
  *
- * This decodes the most primitive / atomic data item. It does
- * no combing of data items.
+ * This decodes the most primitive/atomic data item. It does no
+ * combining of data items.
  */
 static QCBORError
-QCBOR_Private_DecodeAtomicDataItem(UsefulInputBuf               *pUInBuf,
-                                   QCBORItem                    *pDecodedItem,
-                                   const QCBORInternalAllocator *pAllocator)
+QCBOR_Private_DecodeAtomicDataItem(QCBORDecodeContext  *pMe,
+                                   const bool           bAllocateStrings,
+                                   QCBORItem           *pDecodedItem)
 {
    QCBORError uReturn;
-
-   /* Get the major type and the argument. The argument could be
-    * length of more bytes or the value depending on the major
-    * type. nAdditionalInfo is an encoding of the length of the
-    * uNumber and is needed to decode floats and doubles.
-    */
    int      nMajorType = 0;
    uint64_t uArgument = 0;
    int      nAdditionalInfo = 0;
 
-   memset(pDecodedItem, 0, sizeof(QCBORItem));
-
-   uReturn = QCBOR_Private_DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
-   if(uReturn) {
-      goto Done;
+   /* Decode the "head" that every CBOR item has into the major type,
+    * argument and the additional info.
+    */
+   uReturn = QCBOR_Private_DecodeHead(&(pMe->InBuf), &nMajorType, &uArgument, &nAdditionalInfo);
+   if(uReturn != QCBOR_SUCCESS) {
+      return uReturn;
    }
 
-   /* At this point the major type and the argument are valid. We've
-    * got the type and the argument that starts every CBOR data item.
+   memset(pDecodedItem, 0, sizeof(QCBORItem));
+
+   /* All the functions below get inlined by the optimizer. This code
+    * is easier to read with them all being similar functions, even if
+    * some functions don't do much.
     */
    switch (nMajorType) {
       case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
       case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
-         if(nAdditionalInfo == LEN_IS_INDEFINITE) {
-            uReturn = QCBOR_ERR_BAD_INT;
-         } else {
-            uReturn = QCBOR_Private_DecodeInteger(nMajorType, uArgument, pDecodedItem);
-         }
+         return QCBOR_Private_DecodeInteger(nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
          break;
 
       case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
       case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
-         pDecodedItem->uDataType = QCBOR_Private_ConvertStringMajorTypes(nMajorType);
-         if(nAdditionalInfo == LEN_IS_INDEFINITE) {
-            pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
-         } else {
-            uReturn = QCBOR_Private_DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
-         }
+         return QCBOR_Private_DecodeString(pMe, bAllocateStrings, nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
          break;
 
       case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
       case CBOR_MAJOR_TYPE_MAP:   /* Major type 5 */
-         if(nAdditionalInfo == LEN_IS_INDEFINITE) {
-            /* Indefinite-length string. */
-#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
-            pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
-#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
-            uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
-            break;
-#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
-         } else {
-            /* Definite-length string. */
-            if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
-                uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
-                goto Done;
-             }
-            /* cast OK because of check above */
-            pDecodedItem->val.uCount = (uint16_t)uArgument;
-         }
-         pDecodedItem->uDataType = QCBORDecode_Private_ConvertArrayOrMapType(nMajorType);
+         return QCBOR_Private_DecodeArrayOrMap(pMe->uDecodeMode, nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
          break;
 
       case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
-#ifndef QCBOR_DISABLE_TAGS
-         if(nAdditionalInfo == LEN_IS_INDEFINITE) {
-            uReturn = QCBOR_ERR_BAD_INT;
-         } else {
-            pDecodedItem->val.uTagV = uArgument;
-            pDecodedItem->uDataType = QCBOR_TYPE_TAG;
-         }
-#else /* QCBOR_DISABLE_TAGS */
-         uReturn = QCBOR_ERR_TAGS_DISABLED;
-#endif /* QCBOR_DISABLE_TAGS */
+         return QCBOR_Private_DecodeTag(uArgument, nAdditionalInfo, pDecodedItem);
          break;
 
       case CBOR_MAJOR_TYPE_SIMPLE:
          /* Major type 7: float, double, true, false, null... */
-         uReturn = QCBOR_Private_DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
+         return QCBOR_Private_DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
          break;
 
       default:
          /* Never happens because DecodeHead() should never return > 7 */
-         uReturn = QCBOR_ERR_UNSUPPORTED;
+         return QCBOR_ERR_UNSUPPORTED;
          break;
    }
-
-Done:
-   return uReturn;
 }
 
 
@@ -1336,57 +1420,53 @@
     *   QCBORItem                                     56          52
     *   TOTAL                                        120          74
     */
-
-   /* The string allocator is used here for two purposes: 1)
-    * coalescing the chunks of an indefinite-length string, 2)
-    * allocating storage for every string returned when requested.
-    *
-    * The first use is below in this function. Indefinite-length
-    * strings cannot be processed at all without a string allocator.
-    *
-    * The second used is in DecodeBytes() which is called by
-    * GetNext_Item() below. This second use unneccessary for most use
-    * and only happens when requested in the call to
-    * QCBORDecode_SetMemPool(). If the second use not requested then
-    * NULL is passed for the string allocator to GetNext_Item().
-    *
-    * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
-    * allocator altogether and thus both of these uses. It reduced the
-    * decoder object code by about 400 bytes.
-    */
-   const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
-
-#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
-   const QCBORInternalAllocator *pAllocator = NULL;
-
-   if(pMe->StringAllocator.pfAllocator) {
-      pAllocator = &(pMe->StringAllocator);
-      if(pMe->bStringAllocateAll) {
-         pAllocatorForGetNext = pAllocator;
-      }
-   }
-#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
-
    QCBORError uReturn;
-   uReturn = QCBOR_Private_DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
+
+   /* A note about string allocation -- Memory for strings is
+    * allocated either because 1) indefinte-length string chunks are
+    * being coalecsed or 2) caller has requested all strings be
+    * allocated.  The first case is handed below here. The second case
+    * is handled in DecodeString if the bAllocate is true. That
+    * boolean originates here with pMe->bStringAllocateAll immediately
+    * below. That is, QCBOR_Private_DecodeAtomicDataItem() is called
+    * in two different contexts here 1) main-line processing which is
+    * where definite-length strings need to be allocated if
+    * bStringAllocateAll is true and 2) processing chunks of
+    * indefinite-lengths strings in in which case there must be no
+    * allocation.
+    */
+
+
+   uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, pMe->bStringAllocateAll, pDecodedItem);
    if(uReturn != QCBOR_SUCCESS) {
       goto Done;
    }
 
-   /* Only do indefinite-length processing on strings */
-   const uint8_t uStringType = pDecodedItem->uDataType;
-   if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
+
+   /* This is where out-of-place break is detected for the whole
+    * decoding stack. Break is an error for everything that calls
+    * QCBORDecode_Private_GetNextFullString(), so the check is
+    * centralized here.
+    */
+   if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
+      uReturn = QCBOR_ERR_BAD_BREAK;
       goto Done;
    }
 
-   /* Is this a string with an indefinite length? */
+
+   /* Skip out if not an indefinite-length string */
+   const uint8_t uStringType = pDecodedItem->uDataType;
+   if(uStringType != QCBOR_TYPE_BYTE_STRING &&
+      uStringType != QCBOR_TYPE_TEXT_STRING) {
+      goto Done;
+   }
    if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
       goto Done;
    }
 
 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
    /* Can't decode indefinite-length strings without a string allocator */
-   if(pAllocator == NULL) {
+   if(!pMe->StringAllocator.pfAllocator) {
       uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
       goto Done;
    }
@@ -1397,12 +1477,12 @@
    for(;;) {
       /* Get QCBORItem for next chunk */
       QCBORItem StringChunkItem;
-      /* Pass a NULL string allocator to GetNext_Item() because the
-       * individual string chunks in an indefinite-length should not
-       * be allocated. They are always copied in the the contiguous
-       * buffer allocated here.
+      /* Pass false to DecodeAtomicDataItem() because the individual
+       * string chunks in an indefinite-length must not be
+       * allocated. They are always copied into the allocated
+       * contiguous buffer allocated here.
        */
-      uReturn = QCBOR_Private_DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
+      uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, false, &StringChunkItem);
       if(uReturn) {
          break;
       }
@@ -1431,10 +1511,9 @@
           * equivalent to StringAllocator_Allocate(). Subsequently it is
           * not NULL and a reallocation happens.
           */
-         UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
+         UsefulBuf NewMem = StringAllocator_Reallocate(&(pMe->StringAllocator),
                                                        FullString.ptr,
                                                        FullString.len + StringChunkItem.val.string.len);
-
          if(UsefulBuf_IsNULL(NewMem)) {
             uReturn = QCBOR_ERR_STRING_ALLOCATE;
             break;
@@ -1447,7 +1526,7 @@
 
    if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
       /* Getting the item failed, clean up the allocated memory */
-      StringAllocator_Free(pAllocator, FullString.ptr);
+      StringAllocator_Free(&(pMe->StringAllocator), FullString.ptr);
    }
 #else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
    uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
@@ -1675,96 +1754,83 @@
  * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG   Too many items in array.
  * @retval QCBOR_ERR_MAP_LABEL_TYPE          Map label not string or integer.
  *
- * If a the current nesting level is a map, then this
- * combines pairs of items into one data item with a label
- * and value.
+ * If the current nesting level is a map, then this combines pairs of
+ * items into one data item with a label and value.
  *
- * This is passthrough if the current nesting level is
- * not a map.
+ * This is passthrough if the current nesting level is not a map.
  *
- * This also implements maps-as-array mode where a map
- * is treated like an array to allow caller to do their
- * own label processing.
+ * This also implements maps-as-array mode where a map is treated like
+ * an array to allow caller to do their own label processing.
  */
+
 static QCBORError
 QCBORDecode_Private_GetNextMapEntry(QCBORDecodeContext *pMe,
                                     QCBORItem          *pDecodedItem)
 {
-   QCBORError uReturn = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
-   if(uReturn != QCBOR_SUCCESS) {
+   QCBORItem  LabelItem;
+   QCBORError uErr;
+
+   uErr = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
+   if(QCBORDecode_IsUnrecoverableError(uErr)) {
       goto Done;
    }
 
-   if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
-      /* Break can't be a map entry */
+   if(!DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
+      /* Not decoding a map. Nothing to do. */
+      /* When decoding maps-as-arrays, the type will be
+       * QCBOR_TYPE_MAP_AS_ARRAY and this function will exit
+       * here. This is now map processing for maps-as-arrays is not
+       * done. */
       goto Done;
    }
 
-   if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
-      /* Normal decoding of maps -- combine label and value into one item. */
+   /* Decoding a map entry, so the item decoded above was the label */
+   LabelItem = *pDecodedItem;
 
-      if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
-         /* Save label in pDecodedItem and get the next which will
-          * be the real data item.
-          */
-         QCBORItem LabelItem = *pDecodedItem;
-         uReturn = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
-         if(QCBORDecode_IsUnrecoverableError(uReturn)) {
-            goto Done;
-         }
+   /* Get the value of the map item */
+   uErr = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
+   if(QCBORDecode_IsUnrecoverableError(uErr)) {
+      goto Done;
+   }
 
-         pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
+   /* Combine the label item and value item into one */
+   pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
+   pDecodedItem->uLabelType  = LabelItem.uDataType;
 
-         if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
-            /* strings are always good labels */
-            pDecodedItem->label.string = LabelItem.val.string;
-            pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
-         } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
-            /* It's not a string and we only want strings */
-            uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
-            goto Done;
-         } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
-            pDecodedItem->label.int64 = LabelItem.val.int64;
-            pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
-         } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
-            pDecodedItem->label.uint64 = LabelItem.val.uint64;
-            pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
-         } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
-            pDecodedItem->label.string = LabelItem.val.string;
-            pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
-            pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
-         } else {
-            /* label is not an int or a string. It is an arrray
-             * or a float or such and this implementation doesn't handle that.
-             * Also, tags on labels are ignored.
-             */
-            uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
-            goto Done;
-         }
-      }
-   } else {
-      /* Decoding of maps as arrays to let the caller decide what to do
-       * about labels, particularly lables that are not integers or
-       * strings.
-       */
-      if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
-         pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
-         if(pDecodedItem->val.uCount != UINT16_MAX) {
-            /* Adjust definite-length map item count */
-            if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
-               uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
-               goto Done;
-            }
-            /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
-             * Cast is needed because of integer promotion.
-             */
-            pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
-         }
-      }
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+   /* QCBOR_DECODE_MODE_MAP_STRINGS_ONLY might have been a bad idea. Maybe
+    * get rid of it in QCBOR 2.0
+    */
+   if(pMe->uDecodeMode == QCBOR_DECODE_MODE_MAP_STRINGS_ONLY &&
+      LabelItem.uDataType != QCBOR_TYPE_TEXT_STRING) {
+      uErr = QCBOR_ERR_MAP_LABEL_TYPE;
+      goto Done;
+   }
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+   switch(LabelItem.uDataType) {
+      case QCBOR_TYPE_INT64:
+         pDecodedItem->label.int64 = LabelItem.val.int64;
+         break;
+
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+      case QCBOR_TYPE_UINT64:
+         pDecodedItem->label.uint64 = LabelItem.val.uint64;
+         break;
+
+      case QCBOR_TYPE_TEXT_STRING:
+      case QCBOR_TYPE_BYTE_STRING:
+         pDecodedItem->label.string = LabelItem.val.string;
+         break;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+      default:
+         uErr = QCBOR_ERR_MAP_LABEL_TYPE;
+         goto Done;
    }
 
 Done:
-   return uReturn;
+   return uErr;
 }
 
 
@@ -1772,7 +1838,7 @@
 /**
  * @brief Peek and see if next data item is a break;
  *
- * @param[in]  pUIB            UsefulInputBuf to read from.
+ * param[in]  pUIB            UsefulInputBuf to read from.
  * @param[out] pbNextIsBreak   Indicate if next was a break or not.
  *
  * @return  Any decoding error.
@@ -1781,19 +1847,19 @@
  * if not it is not consumed.
 */
 static QCBORError
-QCBOR_Private_NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
+QCBOR_Private_NextIsBreak(QCBORDecodeContext *pMe, bool *pbNextIsBreak)
 {
    *pbNextIsBreak = false;
-   if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
+   if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) != 0) {
       QCBORItem Peek;
-      size_t uPeek = UsefulInputBuf_Tell(pUIB);
-      QCBORError uReturn = QCBOR_Private_DecodeAtomicDataItem(pUIB, &Peek, NULL);
+      size_t uPeek = UsefulInputBuf_Tell(&(pMe->InBuf));
+      QCBORError uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, false, &Peek);
       if(uReturn != QCBOR_SUCCESS) {
          return uReturn;
       }
       if(Peek.uDataType != QCBOR_TYPE_BREAK) {
          /* It is not a break, rewind so it can be processed normally. */
-         UsefulInputBuf_Seek(pUIB, uPeek);
+         UsefulInputBuf_Seek(&(pMe->InBuf), uPeek);
       } else {
          *pbNextIsBreak = true;
       }
@@ -1861,7 +1927,7 @@
 
          /* Check for a break which is what ends indefinite-length arrays/maps */
          bool bIsBreak = false;
-         uReturn = QCBOR_Private_NextIsBreak(&(pMe->InBuf), &bIsBreak);
+         uReturn = QCBOR_Private_NextIsBreak(pMe, &bIsBreak);
          if(uReturn != QCBOR_SUCCESS) {
             goto Done;
          }
@@ -1992,14 +2058,6 @@
       goto Done;
    }
 
-   /* Breaks ending arrays/maps are processed later in the call to
-    * QCBORDecode_NestLevelAscender(). They should never show up here.
-    */
-   if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
-      uReturn = QCBOR_ERR_BAD_BREAK;
-      goto Done;
-   }
-
    /* Record the nesting level for this data item before processing
     * any of decrementing and descending.
     */
@@ -3509,6 +3567,7 @@
       return;
    }
 
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
    QCBORItem OneItemSeach[2];
    OneItemSeach[0].uLabelType   = QCBOR_TYPE_TEXT_STRING;
    OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
@@ -3526,8 +3585,16 @@
    }
 
    *pItem = OneItemSeach[0];
-
 Done:
+
+#else
+   (void)pMe;
+   (void)szLabel;
+   (void)uQcborType;
+   (void)pItem;
+   QCBORError uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
    pMe->uLastError = (uint8_t)uReturn;
 }
 
@@ -3578,9 +3645,11 @@
    }
 
    uint8_t uItemDataType = pItem->uDataType;
+#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) {
       pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
@@ -3997,6 +4066,7 @@
 void
 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);
@@ -4004,6 +4074,10 @@
    OneItemSeach[1].uLabelType   = QCBOR_TYPE_NONE;
 
    QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
+#else
+   (void)szLabel;
+   pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
 }
 
 /*
@@ -4027,6 +4101,7 @@
 void
 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);
@@ -4034,6 +4109,10 @@
    OneItemSeach[1].uLabelType   = QCBOR_TYPE_NONE;
 
    QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
+#else
+   (void)szLabel;
+   pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
 }
 
 
@@ -4069,9 +4148,13 @@
    }
 
    uint8_t uItemDataType = Item.uDataType;
+
+#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) {
       uErr = QCBOR_ERR_UNEXPECTED_TYPE;
       goto Done;
@@ -4499,6 +4582,97 @@
 }
 
 
+/**
+ * @brief Process simple values.
+ *
+ * @param[in] pMe     The decode context.
+ * @param[in] pItem   The item with the simple value.
+ * @param[out] puSimple  The simple value output.
+ *
+ * Sets the internal error if the item isn't a true or a false. Also
+ * records any tag numbers as the tag numbers of the last item.
+ */
+static void
+QCBORDecode_Private_ProcessSimple(QCBORDecodeContext *pMe,
+                                  const QCBORItem    *pItem,
+                                  uint8_t            *puSimple)
+{
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   /* It's kind of lame to remap true...undef back to simple values, but
+    * this function isn't used much and to not do it would require
+    * changing GetNext() behavior in an incompatible way.
+    */
+   switch(pItem->uDataType) {
+      case QCBOR_TYPE_UKNOWN_SIMPLE:
+         *puSimple = pItem->val.uSimple;
+         break;
+
+      case QCBOR_TYPE_TRUE:
+         *puSimple = CBOR_SIMPLEV_TRUE;
+         break;
+
+      case QCBOR_TYPE_FALSE:
+         *puSimple = CBOR_SIMPLEV_FALSE;
+         break;
+
+      case QCBOR_TYPE_NULL:
+         *puSimple = CBOR_SIMPLEV_NULL;
+         break;
+
+      case QCBOR_TYPE_UNDEF:
+         *puSimple = CBOR_SIMPLEV_UNDEF;
+         break;
+
+      default:
+         pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+         return;
+   }
+   QCBORDecode_Private_CopyTags(pMe, pItem);
+}
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetSimple(QCBORDecodeContext *pMe, uint8_t *puSimple)
+{
+   QCBORItem Item;
+
+   QCBORDecode_VGetNext(pMe, &Item);
+   QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimple);
+}
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetSimpleInMapN(QCBORDecodeContext *pMe,
+                            int64_t             nLabel,
+                            uint8_t            *puSimpleValue)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
+
+   QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimpleValue);
+}
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetSimpleInMapSZ(QCBORDecodeContext *pMe,
+                             const char         *szLabel,
+                             uint8_t            *puSimpleValue)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+
+   QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimpleValue);
+}
+
 
 
 /**
diff --git a/src/qcbor_err_to_str.c b/src/qcbor_err_to_str.c
index 4879f91..87c2b28 100644
--- a/src/qcbor_err_to_str.c
+++ b/src/qcbor_err_to_str.c
@@ -1,69 +1,92 @@
-/*==============================================================================
- err_to_str.c -- strings names for errors
-
- Copyright (c) 2020, Patrick Uiterwijk. All rights reserved.
- Copyright (c) 2020, Laurence Lundblade.
- Copyright (c) 2021, Arm Limited. All rights reserved.
-
- SPDX-License-Identifier: BSD-3-Clause
-
- See BSD-3-Clause license in README.md
-
- Created on 3/21/20
- =============================================================================*/
+/* ==========================================================================
+ * err_to_str.c -- strings names for errors
+ *
+ * Copyright (c) 2020, Patrick Uiterwijk. All rights reserved.
+ * Copyright (c) 2020,2024, Laurence Lundblade.
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * See BSD-3-Clause license in README.md
+ *
+ * Created on 3/21/20
+ * ========================================================================== */
 
 #include "qcbor/qcbor_common.h"
+#include <string.h>
 
-#define _ERR_TO_STR(errpart) case QCBOR_##errpart: return "QCBOR_" #errpart;
+#define ERR_TO_STR_CASE(errpart) case errpart: return #errpart;
 
-const char *qcbor_err_to_str(QCBORError err) {
-    switch (err) {
-    _ERR_TO_STR(SUCCESS)
-    _ERR_TO_STR(ERR_BUFFER_TOO_SMALL)
-    _ERR_TO_STR(ERR_ENCODE_UNSUPPORTED)
-    _ERR_TO_STR(ERR_BUFFER_TOO_LARGE)
-    _ERR_TO_STR(ERR_ARRAY_NESTING_TOO_DEEP)
-    _ERR_TO_STR(ERR_CLOSE_MISMATCH)
-    _ERR_TO_STR(ERR_ARRAY_TOO_LONG)
-    _ERR_TO_STR(ERR_TOO_MANY_CLOSES)
-    _ERR_TO_STR(ERR_ARRAY_OR_MAP_STILL_OPEN)
-    _ERR_TO_STR(ERR_BAD_TYPE_7)
-    _ERR_TO_STR(ERR_EXTRA_BYTES)
-    _ERR_TO_STR(ERR_UNSUPPORTED)
-    _ERR_TO_STR(ERR_ARRAY_OR_MAP_UNCONSUMED)
-    _ERR_TO_STR(ERR_BAD_INT)
-    _ERR_TO_STR(ERR_INDEFINITE_STRING_CHUNK)
-    _ERR_TO_STR(ERR_HIT_END)
-    _ERR_TO_STR(ERR_BAD_BREAK)
-    _ERR_TO_STR(ERR_INPUT_TOO_LARGE)
-    _ERR_TO_STR(ERR_ARRAY_DECODE_NESTING_TOO_DEEP)
-    _ERR_TO_STR(ERR_ARRAY_DECODE_TOO_LONG)
-    _ERR_TO_STR(ERR_STRING_TOO_LONG)
-    _ERR_TO_STR(ERR_BAD_EXP_AND_MANTISSA)
-    _ERR_TO_STR(ERR_NO_STRING_ALLOCATOR)
-    _ERR_TO_STR(ERR_STRING_ALLOCATE)
-    _ERR_TO_STR(ERR_TOO_MANY_TAGS)
-    _ERR_TO_STR(ERR_MAP_LABEL_TYPE)
-    _ERR_TO_STR(ERR_UNEXPECTED_TYPE)
-    _ERR_TO_STR(ERR_BAD_OPT_TAG)
-    _ERR_TO_STR(ERR_DUPLICATE_LABEL)
-    _ERR_TO_STR(ERR_MEM_POOL_SIZE)
-    _ERR_TO_STR(ERR_INT_OVERFLOW)
-    _ERR_TO_STR(ERR_DATE_OVERFLOW)
-    _ERR_TO_STR(ERR_EXIT_MISMATCH)
-    _ERR_TO_STR(ERR_NO_MORE_ITEMS)
-    _ERR_TO_STR(ERR_LABEL_NOT_FOUND)
-    _ERR_TO_STR(ERR_NUMBER_SIGN_CONVERSION)
-    _ERR_TO_STR(ERR_CONVERSION_UNDER_OVER_FLOW)
-    _ERR_TO_STR(ERR_MAP_NOT_ENTERED)
-    _ERR_TO_STR(ERR_CALLBACK_FAIL)
-    _ERR_TO_STR(ERR_FLOAT_DATE_DISABLED)
-    _ERR_TO_STR(ERR_HALF_PRECISION_DISABLED)
-    _ERR_TO_STR(ERR_HW_FLOAT_DISABLED)
-    _ERR_TO_STR(ERR_FLOAT_EXCEPTION)
-    _ERR_TO_STR(ERR_ALL_FLOAT_DISABLED)
 
-    default:
-        return "Unidentified error";
-    }
+const char *
+qcbor_err_to_str(const QCBORError uErr) {
+   switch (uErr) {
+   ERR_TO_STR_CASE(QCBOR_SUCCESS)
+   ERR_TO_STR_CASE(QCBOR_ERR_BUFFER_TOO_SMALL)
+   ERR_TO_STR_CASE(QCBOR_ERR_ENCODE_UNSUPPORTED)
+   ERR_TO_STR_CASE(QCBOR_ERR_BUFFER_TOO_LARGE)
+   ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_NESTING_TOO_DEEP)
+   ERR_TO_STR_CASE(QCBOR_ERR_CLOSE_MISMATCH)
+   ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_TOO_LONG)
+   ERR_TO_STR_CASE(QCBOR_ERR_TOO_MANY_CLOSES)
+   ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN)
+   ERR_TO_STR_CASE(QCBOR_ERR_OPEN_BYTE_STRING)
+   ERR_TO_STR_CASE(QCBOR_ERR_CANNOT_CANCEL)
+   ERR_TO_STR_CASE(QCBOR_ERR_BAD_TYPE_7)
+   ERR_TO_STR_CASE(QCBOR_ERR_EXTRA_BYTES)
+   ERR_TO_STR_CASE(QCBOR_ERR_UNSUPPORTED)
+   ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED)
+   ERR_TO_STR_CASE(QCBOR_ERR_BAD_INT)
+   ERR_TO_STR_CASE(QCBOR_ERR_INDEFINITE_STRING_CHUNK)
+   ERR_TO_STR_CASE(QCBOR_ERR_HIT_END)
+   ERR_TO_STR_CASE(QCBOR_ERR_BAD_BREAK)
+   ERR_TO_STR_CASE(QCBOR_ERR_INPUT_TOO_LARGE)
+   ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP)
+   ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_DECODE_TOO_LONG)
+   ERR_TO_STR_CASE(QCBOR_ERR_STRING_TOO_LONG)
+   ERR_TO_STR_CASE(QCBOR_ERR_BAD_EXP_AND_MANTISSA)
+   ERR_TO_STR_CASE(QCBOR_ERR_NO_STRING_ALLOCATOR)
+   ERR_TO_STR_CASE(QCBOR_ERR_STRING_ALLOCATE)
+   ERR_TO_STR_CASE(QCBOR_ERR_MAP_LABEL_TYPE)
+   ERR_TO_STR_CASE(QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT)
+   ERR_TO_STR_CASE(QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED)
+   ERR_TO_STR_CASE(QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED)
+   ERR_TO_STR_CASE(QCBOR_ERR_TAGS_DISABLED)
+   ERR_TO_STR_CASE(QCBOR_ERR_TOO_MANY_TAGS)
+   ERR_TO_STR_CASE(QCBOR_ERR_UNEXPECTED_TYPE)
+   ERR_TO_STR_CASE(QCBOR_ERR_DUPLICATE_LABEL)
+   ERR_TO_STR_CASE(QCBOR_ERR_MEM_POOL_SIZE)
+   ERR_TO_STR_CASE(QCBOR_ERR_INT_OVERFLOW)
+   ERR_TO_STR_CASE(QCBOR_ERR_DATE_OVERFLOW)
+   ERR_TO_STR_CASE(QCBOR_ERR_EXIT_MISMATCH)
+   ERR_TO_STR_CASE(QCBOR_ERR_NO_MORE_ITEMS)
+   ERR_TO_STR_CASE(QCBOR_ERR_LABEL_NOT_FOUND)
+   ERR_TO_STR_CASE(QCBOR_ERR_NUMBER_SIGN_CONVERSION)
+   ERR_TO_STR_CASE(QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW)
+   ERR_TO_STR_CASE(QCBOR_ERR_MAP_NOT_ENTERED)
+   ERR_TO_STR_CASE(QCBOR_ERR_CALLBACK_FAIL)
+   ERR_TO_STR_CASE(QCBOR_ERR_FLOAT_DATE_DISABLED)
+   ERR_TO_STR_CASE(QCBOR_ERR_HALF_PRECISION_DISABLED)
+   ERR_TO_STR_CASE(QCBOR_ERR_HW_FLOAT_DISABLED)
+   ERR_TO_STR_CASE(QCBOR_ERR_FLOAT_EXCEPTION)
+   ERR_TO_STR_CASE(QCBOR_ERR_ALL_FLOAT_DISABLED)
+   ERR_TO_STR_CASE(QCBOR_ERR_RECOVERABLE_BAD_TAG_CONTENT)
+   ERR_TO_STR_CASE(QCBOR_ERR_CANNOT_ENTER_ALLOCATED_STRING)
+
+   default:
+      if(uErr >= QCBOR_ERR_FIRST_USER_DEFINED && uErr <= QCBOR_ERR_LAST_USER_DEFINED) {
+         /* Static buffer is not thread safe, but this is only a diagnostic */
+         static char buf[20];
+         strcpy(buf, "USER_DEFINED_");
+         size_t uEndOffset = strlen(buf);
+         buf[uEndOffset]   = (char)(uErr/100 + '0');
+         buf[uEndOffset+1] = (char)(((uErr/10) % 10) + '0');
+         buf[uEndOffset+2] = (char)((uErr % 10 )+ '0');
+         buf[uEndOffset+3] = '\0';
+         return buf;
+
+      } else {
+         return "Unidentified QCBOR error";
+      }
+   }
 }
diff --git a/test/UsefulBuf_Tests.c b/test/UsefulBuf_Tests.c
index 0524b4d..0235466 100644
--- a/test/UsefulBuf_Tests.c
+++ b/test/UsefulBuf_Tests.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 "UsefulBuf.h"
 
@@ -146,13 +146,12 @@
 
 
 /*
-  Append test utility.
-    pUOB is the buffer to append too
-    num is the amount to append
-    expected is the expected return code, 0 or 1
-
- returns 0 if test passed
-
+ * Append test utility.
+ *   pUOB is the buffer to append too
+ *   num is the amount to append
+ *   expected is the expected return code, 0 or 1
+ *
+ * returns 0 if test passed
  */
 static int AppendTest(UsefulOutBuf *pUOB, size_t num, int expected)
 {
@@ -175,7 +174,7 @@
 
 
 /*
- Same as append, but takes a position param too
+ * Same as append, but takes a position param too
  */
 static int InsertTest(UsefulOutBuf *pUOB,  size_t num, size_t pos, int expected)
 {
@@ -196,15 +195,14 @@
 
 
 /*
- Boundary conditions to test
-   - around 0
-   - around the buffer size
-   - around MAX size_t
-
-
- Test these for the buffer size and the cursor, the insert amount, the
- append amount and the insert position
-
+ * Boundary conditions to test
+ *  - around 0
+ *  - around the buffer size
+ *  - around MAX size_t
+ *
+ *
+ * Test these for the buffer size and the cursor, the insert amount, the
+ * append amount and the insert position
  */
 
 const char *UOBTest_BoundaryConditionsTest(void)
@@ -280,19 +278,34 @@
    if(!UsefulOutBuf_GetError(&UOB)) {
       return "lengths near max size";
    }
+   UsefulBufC O = UsefulOutBuf_OutUBuf(&UOB);
+   if(!UsefulBuf_IsNULLC(O)) {
+      return "OutUBuf in error should have returned NULL";
+   }
 
    UsefulOutBuf_Init(&UOB, (UsefulBuf){NULL, 100});
    if(!UsefulOutBuf_IsBufferNULL(&UOB)) {
       return "NULL check failed";
    }
 
+   UsefulOutBuf_Init(&UOB, outbuf);
+   UOB.magic = 99; // corrupt the UOB
+   O = UsefulOutBuf_OutUBuf(&UOB);
+   if(!UsefulBuf_IsNULLC(O)) {
+      return "OutUBuf on corrupted should have returned NULL";
+   }
+
+   MakeUsefulBufOnStack(Tmp, 20);
+   O = UsefulOutBuf_CopyOut(&UOB, Tmp);
+   if(!UsefulBuf_IsNULLC(O)) {
+      return "CopyOut on corrupted should have returned NULL";
+   }
+
    return NULL;
 }
 
 
 
-
-
 // Test function to get size and magic number check
 
 const char *TestBasicSanity(void)
@@ -640,6 +653,10 @@
       return "Failed to find 3";
    }
 
+   if(SIZE_MAX != UsefulBuf_FindBytes(Expected, ExpectedLonger)) {
+      return "Failed to find 4";
+   }
+
 
    const uint8_t pB[] = {0x01, 0x02, 0x03};
    UsefulBufC Boo = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pB);
@@ -704,7 +721,7 @@
 #ifndef USEFULBUF_DISABLE_ALL_FLOAT
    const float    f  = (float)314.15;
    const double   d  = 2.1e10;
-#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT */
 
 
    UsefulOutBuf_AppendUint32(&UOB, u32); // Also tests UsefulOutBuf_InsertUint64 and UsefulOutBuf_GetEndPosition
@@ -714,7 +731,7 @@
 #ifndef USEFULBUF_DISABLE_ALL_FLOAT
    UsefulOutBuf_AppendFloat(&UOB, f); // Also tests UsefulOutBuf_InsertFloat
    UsefulOutBuf_AppendDouble(&UOB, d); // Also tests UsefulOutBuf_InsertDouble
-#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT */
 
    const UsefulBufC O = UsefulOutBuf_OutUBuf(&UOB);
    if(UsefulBuf_IsNULLC(O))
@@ -755,6 +772,16 @@
    }
 #endif /* USEFULBUF_DISABLE_ALL_FLOAT */
 
+   if(UsefulInputBuf_GetUint16(&UIB) != 0) {
+      return "Didn't catch off end with GetUint16";
+   }
+   if(UsefulInputBuf_GetUint32(&UIB) !=0 ) {
+      return "Didn't catch off end with GetUint32";
+   }
+   if(UsefulInputBuf_GetUint64(&UIB) !=0 ) {
+      return "Didn't catch off end with GetUint64";
+   }
+
    // Reset and go again for a few more tests
    UsefulInputBuf_Init(&UIB, O);
 
@@ -789,7 +816,7 @@
    if(UsefulInputBuf_BytesAvailable(&UIB, 12)){
       return "Wrong number of bytes available II";
    }
-#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT */
 
    UsefulInputBuf_Seek(&UIB, 0);
 
@@ -830,6 +857,37 @@
       return "OffsetToPointer SIZE_MAX fail";
    }
 
+   UsefulInputBuf_Init(&UIB, Boo);
+   UIB.magic = 88;
+   size_t uUnc = UsefulInputBuf_BytesUnconsumed(&UIB);
+   if(uUnc != 0) {
+      return "Didn't detect corrupted UsefulInputBuf";
+   }
+
+   UsefulInputBuf_Init(&UIB, Boo);
+   UIB.cursor = 500;
+   uUnc = UsefulInputBuf_BytesUnconsumed(&UIB);
+   if(uUnc != 0) {
+      return "Didn't detect bad UsefulInputBuf cursor";
+   }
+
+   if(!UsefulBuf_IsNULLC(UsefulInputBuf_GetUsefulBuf(&UIB, 5000))) {
+      return "Didn't detect off-end request of UsefulInputBuf";
+   }
+
+   if(!UsefulInputBuf_GetError(&UIB)) {
+      return "UIB Error state not reported";
+   }
+
+   UsefulInputBuf_Init(&UIB, Boo);
+   if(UsefulInputBuf_GetBufferLength(&UIB) != Boo.len) {
+      return "UIB length wrong";
+   }
+   UsefulInputBuf_SetBufferLength(&UIB, 1);
+   if(UsefulInputBuf_GetBufferLength(&UIB) != 1) {
+      return "UIB SetBufferLength failed";
+   }
+
    return NULL;
 }
 
@@ -855,7 +913,7 @@
 
    return NULL;
 }
-#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT */
 
 
 const char *UBAdvanceTest(void)
@@ -901,6 +959,34 @@
       return "Advance off end didn't set error";
    }
 
+   // Try to advance in error state
+   UsefulOutBuf_Reset(&UOB);
+   UsefulOutBuf_Advance(&UOB, 1);
+   Place = UsefulOutBuf_GetOutPlace(&UOB);
+   UsefulOutBuf_Advance(&UOB, 1000);
+   UsefulOutBuf_Advance(&UOB, 1);
+   UsefulBuf Place2;
+   Place2 = UsefulOutBuf_GetOutPlace(&UOB);
+   if(memcmp(&Place, &Place2, sizeof(Place))) {
+      return "Advance didn't noop in error state";
+   }
+
+   UsefulOutBuf_Reset(&UOB);
+   UOB.data_len = UOB.UB.len + 1; // React in and corrupt
+   UsefulOutBuf_Advance(&UOB, 1);
+   if(!UsefulOutBuf_GetError(&UOB)) {
+      return "didn't detect corrupted UOB";
+   }
+
+   UsefulOutBuf BadUOB;
+   memset(&BadUOB, 'x', sizeof(BadUOB));
+   BadUOB.err = 0;
+   UsefulOutBuf_Advance(&BadUOB, 1);
+   if(!UsefulOutBuf_GetError(&BadUOB)) {
+      return "didn't detect bad UOB";
+   }
+
+
    return NULL;
 }
 
diff --git a/test/UsefulBuf_Tests.h b/test/UsefulBuf_Tests.h
index e00aa37..c0317e8 100644
--- a/test/UsefulBuf_Tests.h
+++ b/test/UsefulBuf_Tests.h
@@ -1,35 +1,35 @@
-/*==============================================================================
- Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2023, 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, 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.
+ * ========================================================================= */
 
 #ifndef UsefulBuf_UsefulBuf_Tests_h
 #define UsefulBuf_UsefulBuf_Tests_h
@@ -48,7 +48,7 @@
 
 #ifndef USEFULBUF_DISABLE_ALL_FLOAT
 const char *  UBUTest_CopyUtil(void);
-#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+#endif /* ! USEFULBUF_DISABLE_ALL_FLOAT */
 
 const char * UBAdvanceTest(void);
 
diff --git a/test/not_well_formed_cbor.h b/test/not_well_formed_cbor.h
index e505887..5a213ef 100644
--- a/test/not_well_formed_cbor.h
+++ b/test/not_well_formed_cbor.h
@@ -159,9 +159,10 @@
     {(uint8_t[]){0xa1, 0xff, 0x00}, 3},
     // Array of length 1 with 2nd member value replaced by a break
     {(uint8_t[]){0xa1, 0x00, 0xff}, 3},
-    // Map of length 2 with 2nd member replaced by a break
-    {(uint8_t[]){0xa2, 0x00, 0x00, 0xff}, 4},
-
+    // Map of length 2 with 2nd entry label replaced by a break
+    {(uint8_t[]){0xa2, 0x00, 0x00, 0xff, 0x00}, 5},
+    // Map of length 2 with 2nd entry value replaced by a break
+    {(uint8_t[]){0xa2, 0x00, 0x00, 0x00, 0xff}, 5},
 
     // Breaks must not occur on their own out of an indefinite length
     // data item
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 3108fcb..6b97768 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -1135,6 +1135,7 @@
 #endif
 
 
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
 /*
  Decode and thoroughly check a moderately complex
  set of maps. Can be run in QCBOR_DECODE_MODE_NORMAL or in
@@ -1262,7 +1263,7 @@
 
    return 0;
 }
-
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
 
 /* This test requires indef strings, HW float and preferred float,... */
 #if !defined(QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS) && \
@@ -2085,6 +2086,7 @@
 
 
 
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
 
 /*
  Fully or partially decode pValidMapEncoded. When
@@ -2292,7 +2294,6 @@
 
 
 
-
 int32_t ParseMapTest(void)
 {
    // Parse a moderatly complex map structure very thoroughly
@@ -2320,6 +2321,7 @@
 
    return nResult;
 }
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
 
 
 /* The simple-values including some not well formed */
@@ -2328,79 +2330,156 @@
    0xf8, 0x00, 0xf8, 0x13, 0xf8, 0x1f, 0xf8, 0x20,
    0xf8, 0xff};
 
-int32_t ParseSimpleTest(void)
+/* A map of good simple values, plus one well-formed integer */
+static const uint8_t spGoodSimpleValues[] = {
+   0xa9, 0x01, 0xf4, 0x02, 0xf5, 0x03, 0xf6, 0x04, 0xf7,
+   0x05, 0xe0, 0x06, 0xf3, 0x07, 0xf8, 0x20, 0x61, 0x40,
+   0xf8, 0xff, 0x0f, 0x0f};
+
+int32_t SimpleValueDecodeTests(void)
 {
    QCBORDecodeContext DCtx;
-   QCBORItem Item;
-   QCBORError nCBORError;
-
+   QCBORItem          Item;
+   QCBORError         uErr;
 
    QCBORDecode_Init(&DCtx,
                     UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSimpleValues),
                     QCBOR_DECODE_MODE_NORMAL);
 
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+      return (int32_t)uErr;
    if(Item.uDataType != QCBOR_TYPE_ARRAY ||
       Item.val.uCount != 10)
-      return -1;
+      return 1;
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+      return (int32_t)uErr;
    if(Item.uDataType != QCBOR_TYPE_FALSE)
-      return -1;
+      return 2;
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+      return (int32_t)uErr;
    if(Item.uDataType != QCBOR_TYPE_TRUE)
-      return -1;
+      return 3;
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+      return (int32_t)uErr;
    if(Item.uDataType != QCBOR_TYPE_NULL)
-      return -1;
+      return 4;
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+      return (int32_t)uErr;
    if(Item.uDataType != QCBOR_TYPE_UNDEF)
-      return -1;
+      return 5;
 
    // A break
    if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_BAD_BREAK)
-      return -1;
+      return 6;
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+      return (int32_t)uErr;
    if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 0)
-      return -1;
+      return 7;
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+      return (int32_t)uErr;
    if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 19)
-      return -1;
+      return 8;
 
    if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_BAD_TYPE_7)
-      return -1;
+      return 9;
 
    if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_BAD_TYPE_7)
-      return -1;
+      return 10;
 
    if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_BAD_TYPE_7)
-      return -1;
+      return 11;
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+      return (int32_t)uErr;
    if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 32)
-      return -1;
+      return 12;
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item)))
+      return (int32_t)uErr;
    if(Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE || Item.val.uSimple != 255)
-      return -1;
+      return 13;
+
+
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spGoodSimpleValues),
+                    QCBOR_DECODE_MODE_NORMAL);
+
+   uint8_t uSimple;
+
+   QCBORDecode_EnterMap(&DCtx, &Item);
+   QCBORDecode_GetSimple(&DCtx, &uSimple);
+   if(QCBORDecode_GetError(&DCtx) || uSimple != CBOR_SIMPLEV_FALSE) {
+      return 20;
+   }
+   QCBORDecode_GetSimple(&DCtx, &uSimple);
+   if(QCBORDecode_GetError(&DCtx) || uSimple != CBOR_SIMPLEV_TRUE) {
+      return 21;
+   }
+   QCBORDecode_GetSimple(&DCtx, &uSimple);
+   if(QCBORDecode_GetError(&DCtx) || uSimple != CBOR_SIMPLEV_NULL) {
+      return 22;
+   }
+   QCBORDecode_GetSimple(&DCtx, &uSimple);
+   if(QCBORDecode_GetError(&DCtx) || uSimple != CBOR_SIMPLEV_UNDEF) {
+      return 23;
+   }
+   QCBORDecode_GetSimple(&DCtx, &uSimple);
+   if(QCBORDecode_GetError(&DCtx) || uSimple != 0) {
+      return 24;
+   }
+   QCBORDecode_GetSimple(&DCtx, &uSimple);
+   if(QCBORDecode_GetError(&DCtx) || uSimple != 19) {
+      return 25;
+   }
+   QCBORDecode_GetSimple(&DCtx, &uSimple);
+   if(QCBORDecode_GetError(&DCtx) || uSimple != 32) {
+      return 26;
+   }
+   QCBORDecode_GetSimple(&DCtx, &uSimple);
+   if(QCBORDecode_GetError(&DCtx) || uSimple != 255) {
+      return 27;
+   }
+   QCBORDecode_VGetNext(&DCtx, &Item);
+   QCBORDecode_GetSimple(&DCtx, &uSimple);
+   if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_NO_MORE_ITEMS) {
+      return 28;
+   }
+
+   QCBORDecode_Rewind(&DCtx);
+
+   QCBORDecode_GetSimpleInMapN(&DCtx, 6, &uSimple);
+   if(QCBORDecode_GetError(&DCtx) || uSimple != 19) {
+      return 30;
+   }
+
+   QCBORDecode_GetSimpleInMapSZ(&DCtx, "@", &uSimple);
+   if(QCBORDecode_GetError(&DCtx) || uSimple != 255) {
+      return 31;
+   }
+
+   QCBORDecode_GetSimpleInMapN(&DCtx, 99, &uSimple);
+   if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_LABEL_NOT_FOUND) {
+      return 32;
+   }
+
+   QCBORDecode_GetSimpleInMapSZ(&DCtx, "xx", &uSimple);
+   if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_LABEL_NOT_FOUND) {
+      return 33;
+   }
+
+   QCBORDecode_GetSimpleInMapN(&DCtx, 15, &uSimple);
+   if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) {
+      return 34;
+   }
 
    return 0;
-
 }
 
 
@@ -2414,10 +2493,6 @@
       const struct someBinaryBytes *pBytes = &paNotWellFormedCBOR[nIterate];
       const UsefulBufC Input = (UsefulBufC){pBytes->p, pBytes->n};
 
-      if(nIterate == 86) {
-         nIterate = 86;
-      }
-
       // Set up decoder context. String allocator needed for indefinite
       // string test cases
       QCBORDecodeContext DCtx;
@@ -2844,9 +2919,14 @@
       {"\xa1\x00\xff", 3},
       QCBOR_ERR_BAD_BREAK
    },
-   { "Map of length 2 with 2nd member replaced by a break",
+   { "Map of length 2 with 2nd entry label replaced by a break",
       QCBOR_DECODE_MODE_NORMAL,
-      {"\xa2\x00\x00\xff", 4},
+      {"\xa2\x00\x00\xff\x00", 5},
+      QCBOR_ERR_BAD_BREAK
+   },
+   { "Map of length 2 with 2nd entry value replaced by a break",
+      QCBOR_DECODE_MODE_NORMAL,
+      {"\xa2\x00\x00\x01\xff", 5},
       QCBOR_ERR_BAD_BREAK
    },
 
@@ -4455,12 +4535,14 @@
  * These are showing the big numbers converted to integers.
  * The tag numbers are not shown.
  *
- * [ 18446744073709551616,
- *   -18446744073709551617,
- *   {"BN+": 18446744073709551616,
- *     64: 18446744073709551616,
- *     "BN-": -18446744073709551617,
- *     -64: -18446744073709551617
+ * [
+ *   18446744073709551616,
+ *  -18446744073709551617,
+ *   {
+ *     -64: -18446744073709551617,
+ *      64: 18446744073709551616,
+ *     "BN+": 18446744073709551616,
+ *     "BN-": -18446744073709551617
  *   }
  * ]
  */
@@ -4470,14 +4552,15 @@
    0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xA4,
-     0x63, 0x42, 0x4E, 0x2B,
-       0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x38, 0x3F,
+      0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x18, 0x40,
        0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x63, 0x42, 0x4E, 0x2D,
-       0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x38, 0x3F,
-       0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+     0x63, 0x42, 0x4E, 0x2B,
+       0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x63, 0x42, 0x4E, 0x2D,
+       0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
 
 #ifndef QCBOR_DISABLE_TAGS
 /* The expected big num */
@@ -4530,11 +4613,12 @@
    }
 
    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
-      return -9;
-   if(Item.uDataType != QCBOR_TYPE_POSBIGNUM ||
-      Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
+      return -15;
+   if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM ||
+      Item.uLabelType != QCBOR_TYPE_INT64 ||
+      Item.label.int64 != -64 ||
       UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){
-      return -10;
+      return -16;
    }
 
    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
@@ -4546,6 +4630,15 @@
       return -12;
    }
 
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
+      return -9;
+   if(Item.uDataType != QCBOR_TYPE_POSBIGNUM ||
+      Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
+      UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){
+      return -10;
+   }
+
    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
       return -13;
    if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM ||
@@ -4554,14 +4647,9 @@
       return -14;
    }
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
-      return -15;
-   if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM ||
-      Item.uLabelType != QCBOR_TYPE_INT64 ||
-      Item.label.int64 != -64 ||
-      UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){
-      return -16;
-   }
+
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
 #else
 
    if(QCBORDecode_GetNext(&DCtx, &Item) != QCBOR_ERR_TAGS_DISABLED) {
@@ -4573,7 +4661,6 @@
 }
 
 
-
 static int32_t CheckItemWithIntLabel(QCBORDecodeContext *pCtx,
                                  uint8_t uDataType,
                                  uint8_t uNestingLevel,
@@ -4587,15 +4674,13 @@
    if((nCBORError = QCBORDecode_GetNext(pCtx, &Item))) return -1;
    if(Item.uDataType != uDataType) return -1;
    if(uNestingLevel > 0) {
-      if(Item.uLabelType != QCBOR_TYPE_INT64 &&
-         Item.uLabelType != QCBOR_TYPE_UINT64) {
+      if(Item.uLabelType != QCBOR_TYPE_INT64) {
          return -1;
       }
-      if(Item.uLabelType == QCBOR_TYPE_INT64) {
-         if(Item.label.int64 != nLabel) return -1;
-      } else  {
-         if(Item.label.uint64 != (uint64_t)nLabel) return -1;
+      if(Item.label.int64 != nLabel) {
+         return -1;
       }
+
    }
    if(Item.uNestingLevel != uNestingLevel) return -1;
    if(Item.uNextNestLevel != uNextNest) return -1;
@@ -4606,7 +4691,6 @@
    return 0;
 }
 
-
 // Same code checks definite and indefinite length versions of the map
 static int32_t CheckCSRMaps(QCBORDecodeContext *pDC)
 {
@@ -5009,6 +5093,7 @@
    // missing end of string
 };
 
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
 static const uint8_t spIndefiniteLenStringLabel[] = {
    0xa1, // Array of length one
    0x7f, // text string marked with indefinite length
@@ -5017,6 +5102,7 @@
    0xff, // ending break
    0x01 // integer being labeled.
 };
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
 
 /**
  Make an indefinite length string
@@ -5225,6 +5311,7 @@
       return -29;
    }
 
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
    // --- label is an indefinite length string ------
    QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringLabel), QCBOR_DECODE_MODE_NORMAL);
 
@@ -5250,6 +5337,7 @@
    if(QCBORDecode_Finish(&DC)) {
       return -34;
    }
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
 
    return 0;
 }
@@ -5277,6 +5365,7 @@
       return -2;
    }
 
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
    // Next parse, save pointers to a few strings, destroy original and
    // see all is OK.
    UsefulBuf_MAKE_STACK_UB(CopyOfStorage, sizeof(pValidMapEncoded) + QCBOR_DECODE_MIN_MEM_POOL_SIZE);
@@ -5308,7 +5397,9 @@
       Item1.val.int64 != 42 ||
       Item1.uDataAlloc != 0 ||
       Item1.uLabelAlloc == 0 ||
-      UsefulBufCompareToSZ(Item1.label.string, "first integer")) {
+      UsefulBufCompareToSZ(Item1.label.string, "first integer") ||
+      Item1.label.string.ptr < Pool.ptr ||
+      Item1.label.string.ptr > (const void *)((const uint8_t *)Pool.ptr + Pool.len)) {
       return -4;
    }
 
@@ -5357,6 +5448,7 @@
    if(nCBORError != QCBOR_ERR_STRING_ALLOCATE) {
       return -10;
    }
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
 
    return 0;
 }
@@ -6731,7 +6823,6 @@
 int32_t EnterMapTest(void)
 {
    QCBORItem          Item1;
-   QCBORItem          ArrayItem;
    QCBORDecodeContext DCtx;
    int32_t            nReturn;
    QCBORError         uErr;
@@ -6780,13 +6871,17 @@
       return 3011;
    }
 
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
    (void)pValidMapIndefEncoded;
    nReturn = SpiffyDecodeBasicMap(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapIndefEncoded));
    if(nReturn) {
       return nReturn + 20000;
    }
-#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
 
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+   QCBORItem          ArrayItem;
 
    nReturn = SpiffyDecodeBasicMap(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded));
    if(nReturn) {
@@ -6868,20 +6963,25 @@
    if(QCBORDecode_GetNext(&DCtx, &Item1) != QCBOR_ERR_NO_MORE_ITEMS) {
       return 2007;
    }
+#endif /* !QCBOR_DISABLE_NON_INTEGER_LABELS */
 
    QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSimpleArray), 0);
    QCBORDecode_EnterArray(&DCtx, NULL);
    int64_t nDecodedInt2;
+
+   UsefulBufC String;
+   QCBORDecode_GetTextStringInMapN(&DCtx, 88, &String);
+   uErr = QCBORDecode_GetAndResetError(&DCtx);
+   if(uErr != QCBOR_ERR_MAP_NOT_ENTERED){
+      return 2009;
+   }
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
    QCBORDecode_GetInt64InMapSZ(&DCtx, "another int",  &nDecodedInt2);
    uErr = QCBORDecode_GetAndResetError(&DCtx);
    if(uErr != QCBOR_ERR_MAP_NOT_ENTERED){
       return 2008;
    }
-   UsefulBufC String;
-   QCBORDecode_GetTextStringInMapN(&DCtx, 88, &String);
-   if(uErr != QCBOR_ERR_MAP_NOT_ENTERED){
-      return 2009;
-   }
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
 
 
    QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEmptyMap), 0);
@@ -7002,6 +7102,7 @@
    }
 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
 
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
    QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), 0);
    QCBORDecode_VGetNextConsume(&DCtx, &Item1);
    if(Item1.uDataType != QCBOR_TYPE_MAP) {
@@ -7050,6 +7151,7 @@
    if(QCBORDecode_GetError(&DCtx)) {
       return 2410;
    }
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
 
    nReturn = DecodeNestedIterate();
 
@@ -8611,6 +8713,7 @@
 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
 
 
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
 /*
  * An array of an integer and an array. The second array contains
  * a bstr-wrapped map.
@@ -8671,11 +8774,11 @@
    0x73,
    0xff, 0xff
 };
-#endif
-
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
 
 static const uint8_t pWithEmptyMap[] = {0x82, 0x18, 0x64, 0xa0};
 
+
 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
 static const uint8_t pWithEmptyMapInDef[] = {0x9f, 0x18, 0x64, 0xbf, 0xff, 0xff};
 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
@@ -8701,13 +8804,17 @@
 };
 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
 
+#endif
 
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
 int32_t PeekAndRewindTest(void)
 {
    QCBORItem          Item;
    QCBORError         nCBORError;
    QCBORDecodeContext DCtx;
 
+   // Improvement: rework this test to use only integer labels.
+
    QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), 0);
 
    if((nCBORError = QCBORDecode_PeekNext(&DCtx, &Item))) {
@@ -9316,7 +9423,7 @@
    }
     */
 
-#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
+#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
 
 
    // Rewind an indefnite length byte-string wrapped sequence
@@ -9324,7 +9431,7 @@
    return 0;
 }
 
-
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
 
 
 static const uint8_t spBooleansInMap[] =
@@ -9704,6 +9811,7 @@
 
 
 
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
 static const uint8_t spExpectedArray2s[] = {
    0x82, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
    0x31, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
@@ -9753,13 +9861,13 @@
 };
 #endif /* !QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
 
-
 #ifndef QCBOR_DISABLE_TAGS
 /* An exp / mant tag in two nested arrays */
 static const uint8_t spExpMant[] = {0x81, 0x81, 0xC4, 0x82, 0x20, 0x03};
 #endif /* !QCBOR_DISABLE_TAGS */
+#endif
 
-
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
 int32_t GetMapAndArrayTest(void)
 {
    QCBORDecodeContext DCtx;
@@ -9767,7 +9875,7 @@
    QCBORItem          Item;
    UsefulBufC         ReturnedEncodedCBOR;
 
-
+   // Improvement: rework so it can run with QCBOR_DISABLE_NON_INTEGER_LABELS
    QCBORDecode_Init(&DCtx,
                     UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded),
                     0);
@@ -10024,10 +10132,11 @@
    if(uPosition != QCBORDecode_Tell(&DCtx)) {
       return 102;
    }
-#endif /* !QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
 
    return 0;
 }
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
 
    
 int32_t
@@ -10108,6 +10217,41 @@
       return -23;
    }
 
+   /* Test error strings */
+   const char *szErrString;
+
+   szErrString = qcbor_err_to_str(QCBOR_ERR_ARRAY_DECODE_TOO_LONG);
+   if(szErrString == NULL) {
+      return -100;
+   }
+   if(strcmp(szErrString, "QCBOR_ERR_ARRAY_DECODE_TOO_LONG")) {
+      return -101;
+   }
+
+   szErrString = qcbor_err_to_str(QCBOR_SUCCESS);
+   if(szErrString == NULL) {
+      return -102;
+   }
+   if(strcmp(szErrString, "QCBOR_SUCCESS")) {
+      return -103;
+   }
+
+   szErrString = qcbor_err_to_str(100);
+   if(szErrString == NULL) {
+      return -104;
+   }
+   if(strcmp(szErrString, "Unidentified QCBOR error")) {
+      return -105;
+   }
+
+   szErrString = qcbor_err_to_str(200);
+   if(szErrString == NULL) {
+      return -106;
+   }
+   if(strcmp(szErrString, "USER_DEFINED_200")) {
+      return -107;
+   }
+
    return 0;
 }
 
@@ -10120,6 +10264,7 @@
    int                nIndex;
    int64_t            nDecodedInt;
 
+   // Improvement: rewrite so this can run with only integer labels
    static const uint32_t aPos[] =
        {0, 1, 17, 42, 50, 58, 72, 85, 98, 112, UINT32_MAX};
    QCBORDecode_Init(&DCtx,
diff --git a/test/qcbor_decode_tests.h b/test/qcbor_decode_tests.h
index e3fe1b6..4c4c0a6 100644
--- a/test/qcbor_decode_tests.h
+++ b/test/qcbor_decode_tests.h
@@ -126,7 +126,7 @@
 /*
  Test parsing of some simple values like true, false, null...
  */
-int32_t ParseSimpleTest(void);
+int32_t SimpleValueDecodeTests(void);
 
 
 /*
diff --git a/test/run_tests.c b/test/run_tests.c
index a94aa47..e24506a 100644
--- a/test/run_tests.c
+++ b/test/run_tests.c
@@ -67,48 +67,58 @@
 
 
 static test_entry s_tests[] = {
-   TEST_ENTRY(ErrorHandlingTests),
-   TEST_ENTRY(OpenCloseBytesTest),
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
    TEST_ENTRY(GetMapAndArrayTest),
    TEST_ENTRY(TellTests),
+   TEST_ENTRY(ParseMapAsArrayTest),
+   TEST_ENTRY(SpiffyDateDecodeTest),
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+   TEST_ENTRY(ErrorHandlingTests),
+   TEST_ENTRY(OpenCloseBytesTest),
    TEST_ENTRY(EnterBstrTest),
    TEST_ENTRY(IntegerConvertTest),
    TEST_ENTRY(EnterMapTest),
    TEST_ENTRY(QCBORHeadTest),
    TEST_ENTRY(EmptyMapsAndArraysTest),
    TEST_ENTRY(NotWellFormedTests),
-   TEST_ENTRY(ParseMapAsArrayTest),
+
 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
    TEST_ENTRY(IndefiniteLengthNestTest),
    TEST_ENTRY(IndefiniteLengthArrayMapTest),
    TEST_ENTRY(NestedMapTestIndefLen),
 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
-   TEST_ENTRY(ParseSimpleTest),
+
+   TEST_ENTRY(SimpleValueDecodeTests),
    TEST_ENTRY(DecodeFailureTests),
    TEST_ENTRY(EncodeRawTest),
    TEST_ENTRY(RTICResultsTest),
    TEST_ENTRY(MapEncodeTest),
    TEST_ENTRY(ArrayNestingTest1),
    TEST_ENTRY(ArrayNestingTest2),
+
 #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
    TEST_ENTRY(ArrayNestingTest3),
 #endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+
    TEST_ENTRY(EncodeDateTest),
    TEST_ENTRY(SimpleValuesTest1),
    TEST_ENTRY(IntegerValuesTest1),
    TEST_ENTRY(AllAddMethodsTest),
    TEST_ENTRY(ParseTooDeepArrayTest),
    TEST_ENTRY(ComprehensiveInputTest),
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
    TEST_ENTRY(ParseMapTest),
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
    TEST_ENTRY(BasicEncodeTest),
    TEST_ENTRY(NestedMapTest),
    TEST_ENTRY(BignumParseTest),
+
 #ifndef QCBOR_DISABLE_TAGS
    TEST_ENTRY(OptTagParseTest),
    TEST_ENTRY(DateParseTest),
    TEST_ENTRY(DecodeTaggedTypeTests),
 #endif /* QCBOR_DISABLE_TAGS */
-   TEST_ENTRY(SpiffyDateDecodeTest),
+
    TEST_ENTRY(ShortBufferParseTest2),
    TEST_ENTRY(ShortBufferParseTest),
    TEST_ENTRY(ParseDeepArrayTest),
@@ -118,9 +128,12 @@
    TEST_ENTRY(AllocAllStringsTest),
    TEST_ENTRY(MemPoolTest),
    TEST_ENTRY(IndefiniteLengthStringTest),
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
    TEST_ENTRY(SpiffyIndefiniteLengthStringsTests),
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
    TEST_ENTRY(SetUpAllocatorTest),
    TEST_ENTRY(CBORTestIssue134),
+
 #endif /* #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
 #ifndef USEFULBUF_DISABLE_ALL_FLOAT
 #ifndef QCBOR_DISABLE_PREFERRED_FLOAT
@@ -131,19 +144,29 @@
    TEST_ENTRY(GeneralFloatEncodeTests),
    TEST_ENTRY(GeneralFloatDecodeTests),
 #endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
    TEST_ENTRY(BstrWrapTest),
    TEST_ENTRY(BstrWrapErrorTest),
    TEST_ENTRY(BstrWrapNestTest),
    TEST_ENTRY(CoseSign1TBSTest),
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
    TEST_ENTRY(StringDecoderModeFailTest),
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
    TEST_ENTRY_DISABLED(BigComprehensiveInputTest),
    TEST_ENTRY_DISABLED(TooLargeInputTest),
    TEST_ENTRY(EncodeErrorTests),
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
    TEST_ENTRY(SimpleValuesIndefiniteLengthTest1),
+#endif
    TEST_ENTRY(EncodeLengthThirtyoneTest),
    TEST_ENTRY(CBORSequenceDecodeTests),
    TEST_ENTRY(IntToTests),
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
    TEST_ENTRY(PeekAndRewindTest),
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+
+
 #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
    TEST_ENTRY(ExponentAndMantissaDecodeTests),
 #ifndef QCBOR_DISABLE_TAGS