Merge recent changes from master
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 486946c..e4aa83f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -72,6 +72,25 @@
     )
 endif()
 
+set(HEADERS
+    inc/qcbor/qcbor.h
+    inc/qcbor/qcbor_common.h
+    inc/qcbor/qcbor_private.h
+    inc/qcbor/qcbor_encode.h
+    inc/qcbor/qcbor_decode.h
+    inc/qcbor/qcbor_spiffy_decode.h
+    inc/qcbor/UsefulBuf.h
+)
+set_target_properties(
+    qcbor PROPERTIES
+    PUBLIC_HEADER "${HEADERS}"
+)
+include(GNUInstallDirs)
+install(
+    TARGETS qcbor
+    PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/qcbor"
+)
+
 if (NOT BUILD_QCBOR_TEST STREQUAL "OFF")
     add_subdirectory(test)
 endif()
diff --git a/README.md b/README.md
index 08ab1f5..2f2deef 100644
--- a/README.md
+++ b/README.md
@@ -393,17 +393,21 @@
 ## Code Size
 
 These are approximate sizes on a 64-bit x86 CPU with the -Os optimization.
+All QCBOR_DISABLE_XXX are set and compiler stack frame checking is disabled
+for smallest but not for largest. Smallest is the library functions for a
+protocol with strings, integers, arrays, maps and Booleans, but not floats
+and standard tag types.
 
     |               | smallest | largest |
     |---------------|----------|---------|
-    | encode only   |      900 |    2100 |
+    | encode only   |      850 |    2200 |
     | decode only   |     1550 |   13300 |
-    | combined      |     2450 |   15500 |
+    | combined      |     2500 |   15500 |
 
  From the table above, one can see that the amount of code pulled in
  from the QCBOR library varies a lot, ranging from 1KB to 15KB.  The
- main factor is in this is the number of QCBOR functions called and
- which ones they are. QCBOR is constructed with less internal
+ main factor is the number of QCBOR functions called and
+ which ones they are. QCBOR minimizes internal
  interdependency so only code necessary for the called functions is
  brought in.
 
diff --git a/inc/qcbor/UsefulBuf.h b/inc/qcbor/UsefulBuf.h
index 95f0571..218d269 100644
--- a/inc/qcbor/UsefulBuf.h
+++ b/inc/qcbor/UsefulBuf.h
@@ -2371,9 +2371,9 @@
 
    /* The cursor is off the end of the input buffer given.
     * Presuming there are no bugs in this code, this should never happen.
-    * If it so, the struct was corrupted. The check is retained as
+    * If it is so, the struct was corrupted. The check is retained as
     * as a defense in case there is a bug in this code or the struct is
-    * corrupted.
+    * corrupted by an attacker or accidentally.
     */
    if(pMe->cursor > pMe->UB.len) {
       return 0;
diff --git a/inc/qcbor/qcbor_decode.h b/inc/qcbor/qcbor_decode.h
index d7010d9..2f55ac4 100644
--- a/inc/qcbor/qcbor_decode.h
+++ b/inc/qcbor/qcbor_decode.h
@@ -310,10 +310,10 @@
 /** Type for the simple value undef. */
 #define QCBOR_TYPE_UNDEF         23
 
-/** Type for a floating-point number. Data is in @c val.float. */
+/** Type for a floating-point number. Data is in @c val.fnum. */
 #define QCBOR_TYPE_FLOAT         26
 
-/** Type for a double floating-point number. Data is in @c val.double. */
+/** Type for a double floating-point number. Data is in @c val.dfnum. */
 #define QCBOR_TYPE_DOUBLE        27
 
 /** Special type for integers between -2^63 - 1 to -2^64 that
diff --git a/inc/qcbor/qcbor_encode.h b/inc/qcbor/qcbor_encode.h
index 008ee91..cf32f3c 100644
--- a/inc/qcbor/qcbor_encode.h
+++ b/inc/qcbor/qcbor_encode.h
@@ -673,7 +673,7 @@
  *
  * Error handling is the same as for QCBOREncode_AddInt64().
  */
-void
+static void
 QCBOREncode_AddUInt64(QCBOREncodeContext *pCtx, uint64_t uNum);
 
 static void
@@ -839,7 +839,7 @@
  * By default, this will error out on an attempt to encode a NaN with
  * a payload. See QCBOREncode_Allow() and @ref QCBOR_ENCODE_ALLOW_NAN_PAYLOAD.
  */
-void
+static void
 QCBOREncode_AddDouble(QCBOREncodeContext *pCtx, double dNum);
 
 static void
@@ -861,7 +861,7 @@
  * See also QCBOREncode_AddDouble(), QCBOREncode_AddDoubleNoPreferred(),
  * and QCBOREncode_AddFloatNoPreferred() and @ref Floating-Point.
  */
-void
+static void
 QCBOREncode_AddFloat(QCBOREncodeContext *pCtx, float fNum);
 
 static void
@@ -877,18 +877,15 @@
  * @param[in] pCtx  The encoding context to add the double to.
  * @param[in] dNum  The double-precision number to add.
  *
- * This always outputs the number as a 64-bit double-precision.
- * Preferred serialization is not used.
+ * Output a double-precision float straight-through with no checking or
+ * processing for preferred serializtion, dCBOR or other.
  *
  * Error handling is the same as QCBOREncode_AddInt64().
  *
- * By default, this will error out on an attempt to encode a NaN with
- * a payload. See QCBOREncode_Allow() and @ref QCBOR_ENCODE_ALLOW_NAN_PAYLOAD.
- *
  * See also QCBOREncode_AddDouble(), QCBOREncode_AddFloat(), and
  * QCBOREncode_AddFloatNoPreferred() and @ref Floating-Point.
  */
-void
+static void
 QCBOREncode_AddDoubleNoPreferred(QCBOREncodeContext *pCtx, double dNum);
 
 static void
@@ -904,18 +901,15 @@
  * @param[in] pCtx  The encoding context to add the double to.
  * @param[in] fNum  The single-precision number to add.
  *
- * This always outputs the number as a 32-bit single-precision.
- * Preferred serialization is not used.
+ * Output a single-precision float straight-through with no checking or
+ * processing for preferred serializtion, dCBOR or other.
  *
  * Error handling is the same as QCBOREncode_AddInt64().
  *
- * By default, this will error out on an attempt to encode a NaN with
- * a payload. See QCBOREncode_Allow() and @ref QCBOR_ENCODE_ALLOW_NAN_PAYLOAD.
- *
  * See also QCBOREncode_AddDouble(), QCBOREncode_AddFloat(), and
  * QCBOREncode_AddDoubleNoPreferred() and @ref Floating-Point.
  */
-void
+static void
 QCBOREncode_AddFloatNoPreferred(QCBOREncodeContext *pCtx, float fNum);
 
 static void
@@ -949,7 +943,7 @@
  * tags. See QCBORDecode_GetNext() for discussion of decoding custom
  * tags.
  */
-void
+static void
 QCBOREncode_AddTag(QCBOREncodeContext *pCtx, uint64_t uTag);
 
 
@@ -1944,7 +1938,6 @@
 QCBOREncode_AddBoolToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, bool b);
 
 
-
 /**
  * @brief  Add a NULL to the encoded output.
  *
@@ -1992,6 +1985,33 @@
 
 
 /**
+ * @brief Add a simple value.
+ *
+ * @param[in] pMe    The encode context.
+ * @param[in] uNum   The simple value.
+ *
+ * Use QCBOREncode_AddBool(), QCBOREncode_AddUndef()... instead of this.
+ *
+ * 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.
+ * https://www.iana.org/assignments/cbor-simple-values/cbor-simple-values.xhtml
+ */
+static void
+QCBOREncode_AddSimple(QCBOREncodeContext *pMe, const uint64_t uNum);
+
+static void
+QCBOREncode_AddSimpleToMap(QCBOREncodeContext *pMe,
+                           const char         *szLabel,
+                           const uint8_t       uSimple);
+
+static void
+QCBOREncode_AddSimpleToMapN(QCBOREncodeContext *pMe,
+                            const int64_t       nLabel,
+                            const uint8_t       uSimple);
+
+
+/**
  * @brief  Indicates that the next items added are in an array.
  *
  * @param[in] pCtx The encoding context to open the array in.
@@ -2343,7 +2363,7 @@
  * must be enclosed in a map or array. At the top level the raw
  * CBOR must be a single data item.
  */
-static void
+void
 QCBOREncode_AddEncoded(QCBOREncodeContext *pCtx, UsefulBufC Encoded);
 
 static void
@@ -2523,12 +2543,29 @@
    ========================================================================= */
 
 /* Semi-private funcion used by public inline functions. See qcbor_encode.c */
+void QCBOREncode_Private_AppendCBORHead(QCBOREncodeContext *pMe,
+                                        const uint8_t       uMajorType,
+                                        const uint64_t      uArgument,
+                                        const uint8_t       uMinLen);
+
+
+/* Semi-private funcion used by public inline functions. See qcbor_encode.c */
 void
 QCBOREncode_Private_AddBuffer(QCBOREncodeContext *pCtx,
                               uint8_t             uMajorType,
                               UsefulBufC          Bytes);
 
 
+/* Semi-private function for adding a double with preferred encoding. See qcbor_encode.c */
+void
+QCBOREncode_Private_AddPreferredDouble(QCBOREncodeContext *pMe, const double dNum);
+
+
+/* Semi-private function for adding a float with preferred encoding. See qcbor_encode.c */
+void
+QCBOREncode_Private_AddPreferredFloat(QCBOREncodeContext *pMe, const float fNum);
+
+
 /* Semi-private funcion used by public inline functions. See qcbor_encode.c */
 void
 QCBOREncode_Private_OpenMapOrArray(QCBOREncodeContext *pCtx,
@@ -2555,13 +2592,6 @@
 
 /* Semi-private funcion used by public inline functions. See qcbor_encode.c */
 void
-QCBOREncode_Private_AddType7(QCBOREncodeContext *pCtx,
-                             uint8_t             uMinLen,
-                             uint64_t            uNum);
-
-
-/* Semi-private funcion used by public inline functions. See qcbor_encode.c */
-void
 QCBOREncode_Private_AddExpMantissa(QCBOREncodeContext *pCtx,
                                    uint64_t            uTag,
                                    UsefulBufC          BigNumMantissa,
@@ -2571,6 +2601,73 @@
 
 
 
+/**
+ * @brief  Semi-private method to add simple items and floating-point.
+ *
+ * @param[in] pMe        The encoding context.
+ * @param[in] uMinLen    Minimum encoding size for uNum. Usually 0.
+ * @param[in] uArgument  The value to add.
+ *
+ * This is used to add simple types like true and false and float-point
+ * values, both of which are type 7.
+ *
+ * Call QCBOREncode_AddBool(), QCBOREncode_AddNULL(),
+ * QCBOREncode_AddUndef() QCBOREncode_AddDouble() instead of this.
+ *
+ * Error handling is the same as QCBOREncode_AddInt64().
+ */
+static inline void
+QCBOREncode_Private_AddType7(QCBOREncodeContext *pMe,
+                             const uint8_t       uMinLen,
+                             const uint64_t      uArgument)
+{
+   QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_SIMPLE, uArgument, uMinLen);
+}
+
+
+/**
+ * @brief Semi-private method to add only the type and length of a byte string.
+ *
+ * @param[in] pCtx    The context to initialize.
+ * @param[in] Bytes   Pointer and length of the input data.
+ *
+ * This will be removed in QCBOR 2.0. It was never a public function.
+ *
+ * This is the same as QCBOREncode_AddBytes() except it only adds the
+ * CBOR encoding for the type and the length. It doesn't actually add
+ * the bytes. You can't actually produce correct CBOR with this and
+ * the rest of this API. It is only used for a special case where the
+ * valid CBOR is created manually by putting this type and length in
+ * and then adding the actual bytes. In particular, when only a hash
+ * of the encoded CBOR is needed, where the type and header are hashed
+ * separately and then the bytes is hashed. This makes it possible to
+ * implement COSE Sign1 with only one copy of the payload in the
+ * output buffer, rather than two, roughly cutting memory use in half.
+ *
+ * This is only used for this odd case, but this is a supported
+ * tested function for QCBOR 1.0.
+ *
+ * See also QCBOREncode_EncodeHead().
+ */
+static void
+QCBOREncode_AddBytesLenOnly(QCBOREncodeContext *pCtx,
+                            UsefulBufC          Bytes);
+
+static void
+QCBOREncode_AddBytesLenOnlyToMap(QCBOREncodeContext *pCtx,
+                                 const char         *szLabel,
+                                 UsefulBufC          Bytes);
+
+static void
+QCBOREncode_AddBytesLenOnlyToMapN(QCBOREncodeContext *pCtx,
+                                 int64_t              nLabel,
+                                 UsefulBufC           Bytes);
+
+
+/* Forward declaration */
+static void
+QCBOREncode_AddSZString(QCBOREncodeContext *pMe, const char *szString);
+
 
 static inline void
 QCBOREncode_SerializationCDE(QCBOREncodeContext *pMe)
@@ -2616,10 +2713,7 @@
                           const char        *szLabel,
                           const int64_t      uNum)
 {
-   /* Use _AddBuffer() because _AddSZString() is defined below, not above */
-   QCBOREncode_Private_AddBuffer(pMe,
-                                 CBOR_MAJOR_TYPE_TEXT_STRING,
-                                 UsefulBuf_FromSZ(szLabel));
+   QCBOREncode_AddSZString(pMe, szLabel);
    QCBOREncode_AddInt64(pMe, uNum);
 }
 
@@ -2634,14 +2728,18 @@
 
 
 static inline void
+QCBOREncode_AddUInt64(QCBOREncodeContext *pMe, const uint64_t uValue)
+{
+   QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_POSITIVE_INT, uValue, 0);
+}
+
+
+static inline void
 QCBOREncode_AddUInt64ToMap(QCBOREncodeContext *pMe,
                            const char         *szLabel,
                            const uint64_t      uNum)
 {
-   /* Use _AddBuffer() because _AddSZString() is defined below, not above */
-   QCBOREncode_Private_AddBuffer(pMe,
-                                 CBOR_MAJOR_TYPE_TEXT_STRING,
-                                 UsefulBuf_FromSZ(szLabel));
+   QCBOREncode_AddSZString(pMe, szLabel);
    QCBOREncode_AddUInt64(pMe, uNum);
 }
 
@@ -2723,7 +2821,47 @@
 }
 
 
+
+/*
+ * Public functions for adding a tag. See qcbor/qcbor_encode.h
+ */
+static inline void
+QCBOREncode_AddTag(QCBOREncodeContext *pMe, const uint64_t uTag)
+{
+   QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_TAG, uTag, 0);
+}
+
+
+
 #ifndef USEFULBUF_DISABLE_ALL_FLOAT
+
+static inline void
+QCBOREncode_AddDoubleNoPreferred(QCBOREncodeContext *pMe, const double dNum)
+{
+   QCBOREncode_Private_AddType7(pMe,
+                                sizeof(uint64_t),
+                                UsefulBufUtil_CopyDoubleToUint64(dNum));
+}
+
+static inline void
+QCBOREncode_AddFloatNoPreferred(QCBOREncodeContext *pMe, const float fNum)
+{
+   QCBOREncode_Private_AddType7(pMe,
+                                sizeof(uint32_t),
+                                UsefulBufUtil_CopyFloatToUint32(fNum));
+}
+
+
+static inline void
+QCBOREncode_AddDouble(QCBOREncodeContext *pMe, const double dNum)
+{
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+   QCBOREncode_Private_AddPreferredDouble(pMe, dNum);
+#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
+   QCBOREncode_AddDoubleNoPreferred(pMe, dNum);
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+}
+
 static inline void
 QCBOREncode_AddDoubleToMap(QCBOREncodeContext *pMe,
                            const char         *szLabel,
@@ -2742,6 +2880,17 @@
    QCBOREncode_AddDouble(pMe, dNum);
 }
 
+
+static inline void
+QCBOREncode_AddFloat(QCBOREncodeContext *pMe, const float fNum)
+{
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+   QCBOREncode_Private_AddPreferredFloat(pMe, fNum);
+#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
+   QCBOREncode_AddFloatNoPreferred(pMe, fNum);
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+}
+
 static inline void
 QCBOREncode_AddFloatToMap(QCBOREncodeContext *pMe,
                           const char         *szLabel,
@@ -2799,6 +2948,8 @@
 
 
 
+
+
 static inline void
 QCBOREncode_AddTDateEpoch(QCBOREncodeContext *pMe,
                           const uint8_t       uTag,
@@ -2932,6 +3083,35 @@
 }
 
 
+/*
+ * Public functions for adding only a byte string length. See qcbor/qcbor_encode.h
+ */
+static inline void
+QCBOREncode_AddBytesLenOnly(QCBOREncodeContext *pMe, const UsefulBufC Bytes)
+{
+   QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, Bytes.len, 0);
+}
+
+
+static inline void
+QCBOREncode_AddBytesLenOnlyToMap(QCBOREncodeContext *pMe,
+                                 const char         *szLabel,
+                                 const UsefulBufC    Bytes)
+{
+    QCBOREncode_AddSZString(pMe, szLabel);
+    QCBOREncode_AddBytesLenOnly(pMe, Bytes);
+}
+
+static inline void
+QCBOREncode_AddBytesLenOnlyToMapN(QCBOREncodeContext *pMe,
+                                  const int64_t       nLabel,
+                                  const UsefulBufC    Bytes)
+{
+    QCBOREncode_AddInt64(pMe, nLabel);
+    QCBOREncode_AddBytesLenOnly(pMe, Bytes);
+}
+
+
 static inline void
 QCBOREncode_AddTBinaryUUID(QCBOREncodeContext *pMe,
                            const uint8_t       uTagRequirement,
@@ -3841,9 +4021,8 @@
 }
 
 
-
 static inline void
-QCBOREncode_Private_AddSimple(QCBOREncodeContext *pMe, const uint64_t uNum)
+QCBOREncode_AddSimple(QCBOREncodeContext *pMe, const uint64_t uNum)
 {
 #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
    if(pMe->uMode >= QCBOR_ENCODE_MODE_DCBOR) {
@@ -3853,27 +4032,32 @@
          return;
       }
    }
-#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+   /* This check often is optimized out because uNum is known at compile time. */
+   if(uNum >= CBOR_SIMPLEV_RESERVED_START && uNum <= CBOR_SIMPLEV_RESERVED_END) {
+      pMe->uError = QCBOR_ERR_ENCODE_UNSUPPORTED;
+      return;
+   }
+#endif /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
 
    QCBOREncode_Private_AddType7(pMe, 0, uNum);
 }
 
 static inline void
-QCBOREncode_Private_AddSimpleToMap(QCBOREncodeContext *pMe,
+QCBOREncode_AddSimpleToMap(QCBOREncodeContext *pMe,
                                    const char         *szLabel,
                                    const uint8_t       uSimple)
 {
    QCBOREncode_AddSZString(pMe, szLabel);
-   QCBOREncode_Private_AddSimple(pMe, uSimple);
+   QCBOREncode_AddSimple(pMe, uSimple);
 }
 
 static inline void
-QCBOREncode_Private_AddSimpleToMapN(QCBOREncodeContext *pMe,
+QCBOREncode_AddSimpleToMapN(QCBOREncodeContext *pMe,
                                     const int64_t       nLabel,
                                     const uint8_t       uSimple)
 {
    QCBOREncode_AddInt64(pMe, nLabel);
-   QCBOREncode_Private_AddSimple(pMe, uSimple);
+   QCBOREncode_AddSimple(pMe, uSimple);
 }
 
 
@@ -3884,7 +4068,7 @@
    if(b) {
       uSimple = CBOR_SIMPLEV_TRUE;
    }
-   QCBOREncode_Private_AddSimple(pMe, uSimple);
+   QCBOREncode_AddSimple(pMe, uSimple);
 }
 
 static inline void
@@ -3905,7 +4089,7 @@
 static inline void
 QCBOREncode_AddNULL(QCBOREncodeContext *pMe)
 {
-   QCBOREncode_Private_AddSimple(pMe, CBOR_SIMPLEV_NULL);
+   QCBOREncode_AddSimple(pMe, CBOR_SIMPLEV_NULL);
 }
 
 static inline void
@@ -3926,7 +4110,7 @@
 static inline void
 QCBOREncode_AddUndef(QCBOREncodeContext *pMe)
 {
-   QCBOREncode_Private_AddSimple(pMe, CBOR_SIMPLEV_UNDEF);
+   QCBOREncode_AddSimple(pMe, CBOR_SIMPLEV_UNDEF);
 }
 
 static inline void
@@ -4083,11 +4267,6 @@
 }
 
 
-static inline void
-QCBOREncode_AddEncoded(QCBOREncodeContext *pMe, const UsefulBufC Encoded)
-{
-   QCBOREncode_Private_AddBuffer(pMe, CBOR_MAJOR_NONE_TYPE_RAW, Encoded);
-}
 
 static inline void
 QCBOREncode_AddEncodedToMap(QCBOREncodeContext *pMe,
diff --git a/inc/qcbor/qcbor_private.h b/inc/qcbor/qcbor_private.h
index 20e99ba..04d0d11 100644
--- a/inc/qcbor/qcbor_private.h
+++ b/inc/qcbor/qcbor_private.h
@@ -394,7 +394,6 @@
 /* Used internally in the impementation here Must not conflict with
  * any of the official CBOR types
  */
-#define CBOR_MAJOR_NONE_TYPE_RAW            9
 #define CBOR_MAJOR_NONE_TAG_LABEL_REORDER  10
 #define CBOR_MAJOR_NONE_TYPE_OPEN_BSTR     12
 
diff --git a/src/UsefulBuf.c b/src/UsefulBuf.c
index dae4eb1..91ffda1 100644
--- a/src/UsefulBuf.c
+++ b/src/UsefulBuf.c
@@ -1,33 +1,36 @@
 /*==============================================================================
- Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2024, Laurence Lundblade.
+ * Copyright (c) 2016-2018, The Linux Foundation.
+ * Copyright (c) 2018-2024, Laurence Lundblade.
+ * 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.
+ * ========================================================================= */
 
-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.
- =============================================================================*/
 
 /*=============================================================================
  FILE:  UsefulBuf.c
@@ -41,6 +44,7 @@
 
  when        who          what, where, why
  --------    ----         ---------------------------------------------------
+ 21/05/2024  llundblade   Comment formatting and some code tidiness.
  28/02/2022  llundblade   Rearrange UsefulOutBuf_Compare().
  19/11/2023  llundblade   Add UsefulOutBuf_GetOutput().
  19/11/2023  llundblade   Add UsefulOutBuf_Swap().
@@ -65,18 +69,20 @@
 
 #include "UsefulBuf.h"
 
-// used to catch use of uninitialized or corrupted UsefulOutBuf
+/* used to catch use of uninitialized or corrupted UsefulOutBuf */
 #define USEFUL_OUT_BUF_MAGIC  (0x0B0F)
 
 
 /*
- Public function -- see UsefulBuf.h
+ * Public function -- see UsefulBuf.h
  */
 UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
 {
-   // Do this with subtraction so it doesn't give erroneous
-   // result if uOffset + Src.len overflows
-   if(uOffset > Dest.len || Src.len > Dest.len - uOffset) { // uOffset + Src.len > Dest.len
+   /* Do this with subtraction so it doesn't give an erroneous
+    * result if uOffset + Src.len overflows. Right side is equivalent to
+    * uOffset + Src.len > Dest.len
+    */
+   if(uOffset > Dest.len || Src.len > Dest.len - uOffset) {
       return NULLUsefulBufC;
    }
 
@@ -87,24 +93,25 @@
 
 
 /*
-   Public function -- see UsefulBuf.h
+ * Public function -- see UsefulBuf.h
  */
 int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2)
 {
-   // use the comparisons rather than subtracting lengths to
-   // return an int instead of a size_t
+   /* Use comparisons rather than subtracting lengths to
+    * return an int instead of a size_t
+    */
    if(UB1.len < UB2.len) {
       return -1;
    } else if (UB1.len > UB2.len) {
       return 1;
-   } // else UB1.len == UB2.len
+   } /* else UB1.len == UB2.len */
 
    return memcmp(UB1.ptr, UB2.ptr, UB1.len);
 }
 
 
 /*
- Public function -- see UsefulBuf.h
+ * Public function -- see UsefulBuf.h
  */
 size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue)
 {
@@ -117,7 +124,7 @@
    for(const uint8_t *p = UB.ptr; p < pEnd; p++) {
       if(*p != uValue) {
          /* Byte didn't match */
-         /* Cast from signed  to unsigned . Safe because the loop increments.*/
+         /* Cast from signed to unsigned. Safe because the loop increments.*/
          return (size_t)(p - (const uint8_t *)UB.ptr);
       }
    }
@@ -128,7 +135,7 @@
 
 
 /*
- Public function -- see UsefulBuf.h
+ * Public function -- see UsefulBuf.h
  */
 size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
 {
@@ -137,7 +144,11 @@
    }
 
    for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
-      if(!UsefulBuf_Compare((UsefulBufC){((const uint8_t *)BytesToSearch.ptr) + uPos, BytesToFind.len}, BytesToFind)) {
+      UsefulBufC SearchNext;
+
+      SearchNext.ptr = ((const uint8_t *)BytesToSearch.ptr) + uPos;
+      SearchNext.len = BytesToFind.len;
+      if(!UsefulBuf_Compare(SearchNext, BytesToFind)) {
          return uPos;
       }
    }
@@ -147,9 +158,9 @@
 
 
 /*
- Public function -- see UsefulBuf.h
-
- Code Reviewers: THIS FUNCTION DOES POINTER MATH
+ * Public function -- see UsefulBuf.h
+ *
+ * Code Reviewers: THIS FUNCTION DOES POINTER MATH
  */
 void UsefulOutBuf_Init(UsefulOutBuf *pMe, UsefulBuf Storage)
 {
@@ -158,17 +169,18 @@
     pMe->UB     = Storage;
 
 #if 0
-   // This check is off by default.
-
-   // The following check fails on ThreadX
-
-    // Sanity check on the pointer and size to be sure we are not
-    // passed a buffer that goes off the end of the address space.
-    // Given this test, we know that all unsigned lengths less than
-    // me->size are valid and won't wrap in any pointer additions
-    // based off of pStorage in the rest of this code.
+   /* This check is off by default.
+    *
+    * The following check fails on ThreadX
+    *
+    * Sanity check on the pointer and size to be sure we are not
+    * passed a buffer that goes off the end of the address space.
+    * Given this test, we know that all unsigned lengths less than
+    * me->size are valid and won't wrap in any pointer additions
+    * based off of pStorage in the rest of this code.
+    */
     const uintptr_t ptrM = UINTPTR_MAX - Storage.len;
-    if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) // Check #0
+    if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) /* Check #0 */
         me->err = 1;
 #endif
 }
@@ -176,101 +188,107 @@
 
 
 /*
- Public function -- see UsefulBuf.h
-
- The core of UsefulOutBuf -- put some bytes in the buffer without writing off
-                             the end of it.
-
- Code Reviewers: THIS FUNCTION DOES POINTER MATH
-
- This function inserts the source buffer, NewData, into the destination
- buffer, me->UB.ptr.
-
- Destination is represented as:
-   me->UB.ptr -- start of the buffer
-   me->UB.len -- size of the buffer UB.ptr
-   me->data_len -- length of value data in UB
-
- Source is data:
-   NewData.ptr -- start of source buffer
-   NewData.len -- length of source buffer
-
- Insertion point:
-   uInsertionPos.
-
- Steps:
-
- 0. Corruption checks on UsefulOutBuf
-
- 1. Figure out if the new data will fit or not
-
- 2. Is insertion position in the range of valid data?
-
- 3. If insertion point is not at the end, slide data to the right of the
-    insertion point to the right
-
- 4. Put the new data in at the insertion position.
-
+ * Public function -- see UsefulBuf.h
+ *
+ * The core of UsefulOutBuf -- put some bytes in the buffer without writing off
+ *                             the end of it.
+ *
+ * Code Reviewers: THIS FUNCTION DOES POINTER MATH
+ *
+ * This function inserts the source buffer, NewData, into the destination
+ * buffer, me->UB.ptr.
+ *
+ * Destination is represented as:
+ *   me->UB.ptr -- start of the buffer
+ *   me->UB.len -- size of the buffer UB.ptr
+ *   me->data_len -- length of value data in UB
+ *
+ * Source is data:
+ *   NewData.ptr -- start of source buffer
+ *   NewData.len -- length of source buffer
+ *
+ * Insertion point:
+ *   uInsertionPos.
+ *
+ * Steps:
+ *
+ * 0. Corruption checks on UsefulOutBuf
+ *
+ * 1. Figure out if the new data will fit or not
+ *
+ * 2. Is insertion position in the range of valid data?
+ *
+ * 3. If insertion point is not at the end, slide data to the right of the
+ *    insertion point to the right
+ *
+ * 4. Put the new data in at the insertion position.
+ *
  */
 void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pMe, UsefulBufC NewData, size_t uInsertionPos)
 {
    if(pMe->err) {
-      // Already in error state.
+      /* Already in error state. */
       return;
    }
 
-   /* 0. Sanity check the UsefulOutBuf structure */
-   // A "counter measure". If magic number is not the right number it
-   // probably means me was not initialized or it was corrupted. Attackers
-   // can defeat this, but it is a hurdle and does good with very
-   // little code.
+   /* 0. Sanity check the UsefulOutBuf structure
+    * A "counter measure". If magic number is not the right number it
+    * probably means pMe was not initialized or it was corrupted. Attackers
+    * can defeat this, but it is a hurdle and does good with very
+    * little code.
+    */
    if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
       pMe->err = 1;
-      return;  // Magic number is wrong due to uninitalization or corrption
+      return;  /* Magic number is wrong due to uninitalization or corrption */
    }
 
-   // Make sure valid data is less than buffer size. This would only occur
-   // if there was corruption of me, but it is also part of the checks to
-   // be sure there is no pointer arithmatic under/overflow.
-   if(pMe->data_len > pMe->UB.len) {  // Check #1
+   /* Make sure valid data is less than buffer size. This would only occur
+    * if there was corruption of me, but it is also part of the checks to
+    * be sure there is no pointer arithmatic under/overflow.
+    */
+   if(pMe->data_len > pMe->UB.len) {  /* Check #1 */
       pMe->err = 1;
-      // Offset of valid data is off the end of the UsefulOutBuf due to
-      // uninitialization or corruption
+      /* Offset of valid data is off the end of the UsefulOutBuf due to
+       * uninitialization or corruption
+       */
       return;
    }
 
-   /* 1. Will it fit? */
-   // WillItFit() is the same as: NewData.len <= (me->UB.len - me->data_len)
-   // Check #1 makes sure subtraction in RoomLeft will not wrap around
-   if(! UsefulOutBuf_WillItFit(pMe, NewData.len)) { // Check #2
-      // The new data will not fit into the the buffer.
+   /* 1. Will it fit?
+    * WillItFit() is the same as: NewData.len <= (me->UB.len - me->data_len)
+    * Check #1 makes sure subtraction in RoomLeft will not wrap around
+    */
+   if(! UsefulOutBuf_WillItFit(pMe, NewData.len)) { /* Check #2 */
+      /* The new data will not fit into the the buffer. */
       pMe->err = 1;
       return;
    }
 
-   /* 2. Check the Insertion Position */
-   // This, with Check #1, also confirms that uInsertionPos <= me->data_len and
-   // that uInsertionPos + pMe->UB.ptr will not wrap around the end of the
-   // address space.
-   if(uInsertionPos > pMe->data_len) { // Check #3
-      // Off the end of the valid data in the buffer.
+   /* 2. Check the Insertion Position
+    * This, with Check #1, also confirms that uInsertionPos <= me->data_len and
+    * that uInsertionPos + pMe->UB.ptr will not wrap around the end of the
+    * address space.
+    */
+   if(uInsertionPos > pMe->data_len) { /* Check #3 */
+      /* Off the end of the valid data in the buffer. */
       pMe->err = 1;
       return;
    }
 
    /* 3. Slide existing data to the right */
    if (!UsefulOutBuf_IsBufferNULL(pMe)) {
-      uint8_t *pSourceOfMove       = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; // PtrMath #1
-      size_t   uNumBytesToMove     = pMe->data_len - uInsertionPos; // PtrMath #2
-      uint8_t *pDestinationOfMove  = pSourceOfMove + NewData.len; // PtrMath #3
+      uint8_t *pSourceOfMove      = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; /* PtrMath #1 */
+      size_t   uNumBytesToMove    = pMe->data_len - uInsertionPos; /* PtrMath #2 */
+      uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; /* PtrMath #3*/
 
-      // To know memmove won't go off end of destination, see PtrMath #4
-      // Use memove because it handles overlapping buffers
+      /* To know memmove won't go off end of destination, see PtrMath #4.
+       * Use memove because it handles overlapping buffers
+       */
       memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
 
       /* 4. Put the new data in */
       uint8_t *pInsertionPoint = pSourceOfMove;
-      // To know memmove won't go off end of destination, see PtrMath #5
+      /* To know memmove won't go off end of destination, see PtrMath #5 */
       if(NewData.ptr != NULL) {
          memmove(pInsertionPoint, NewData.ptr, NewData.len);
       }
@@ -281,30 +299,30 @@
 
 
 /*
- Rationale that describes why the above pointer math is safe
-
- PtrMath #1 will never wrap around over because
-    Check #0 in UsefulOutBuf_Init makes sure me->UB.ptr + me->UB.len doesn't wrap
-    Check #1 makes sure me->data_len is less than me->UB.len
-    Check #3 makes sure uInsertionPos is less than me->data_len
-
- PtrMath #2 will never wrap around under because
-    Check #3 makes sure uInsertionPos is less than me->data_len
-
- PtrMath #3 will never wrap around over because
-    PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr and me->UB.ptr + me->data_len
-    Check #2 that NewData.len will fit in the unused space left in me->UB
-
- PtrMath #4 will never wrap under because
-    Calculation for extent or memmove is uRoomInDestination  = me->UB.len - (uInsertionPos + NewData.len)
-    Check #3 makes sure uInsertionPos is less than me->data_len
-    Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
-    This algebraically rearranges to me->size > uInsertionPos + NewData.len
-
- PtrMath #5 will never wrap under because
-    Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos;
-    Check #1 makes sure me->data_len is less than me->size
-    Check #3 makes sure uInsertionPos is less than me->data_len
+ * Rationale that describes why the above pointer math is safe
+ *
+ * PtrMath #1 will never wrap around over because
+ *   Check #0 in UsefulOutBuf_Init that me->UB.ptr + me->UB.len doesn't wrap
+ *   Check #1 makes sure me->data_len is less than me->UB.len
+ *   Check #3 makes sure uInsertionPos is less than me->data_len
+ *
+ * PtrMath #2 will never wrap around under because
+ *   Check #3 makes sure uInsertionPos is less than me->data_len
+ *
+ * PtrMath #3 will never wrap around over because
+ *   PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr and me->UB.ptr + me->data_len
+ *   Check #2 that NewData.len will fit in the unused space left in me->UB
+ *
+ * PtrMath #4 will never wrap under because
+ *   Calculation for extent or memmove is uRoomInDestination  = me->UB.len - (uInsertionPos + NewData.len)
+ *   Check #3 makes sure uInsertionPos is less than me->data_len
+ *   Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
+ *   This algebraically rearranges to me->size > uInsertionPos + NewData.len
+ *
+ * PtrMath #5 will never wrap under because
+ *   Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos;
+ *   Check #1 makes sure me->data_len is less than me->size
+ *   Check #3 makes sure uInsertionPos is less than me->data_len
  */
 
 
@@ -342,7 +360,7 @@
     * checks to be sure there is no pointer arithmatic
     * under/overflow.
     */
-   if(pMe->data_len > pMe->UB.len) {  // Check #1
+   if(pMe->data_len > pMe->UB.len) {  /* Check #1 */
       pMe->err = 1;
       /* Offset of valid data is off the end of the UsefulOutBuf due
        * to uninitialization or corruption.
@@ -367,7 +385,7 @@
 
 
 /*
- Public function -- see UsefulBuf.h
+ * Public function -- see UsefulBuf.h
  */
 UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pMe)
 {
@@ -385,9 +403,9 @@
 
 
 /*
- Public function -- see UsefulBuf.h
-
- Copy out the data accumulated in to the output buffer.
+ * Public function -- see UsefulBuf.h
+ *
+ * Copy out the data accumulated in to the output buffer.
  */
 UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pMe, UsefulBuf pDest)
 {
@@ -402,28 +420,28 @@
 
 
 /*
- Public function -- see UsefulBuf.h
-
- The core of UsefulInputBuf -- consume bytes without going off end of buffer.
-
- Code Reviewers: THIS FUNCTION DOES POINTER MATH
+ * Public function -- see UsefulBuf.h
+ *
+ * The core of UsefulInputBuf -- consume bytes without going off end of buffer.
+ *
+ * Code Reviewers: THIS FUNCTION DOES POINTER MATH
  */
 const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pMe, size_t uAmount)
 {
-   // Already in error state. Do nothing.
+   /* Already in error state. Do nothing. */
    if(pMe->err) {
       return NULL;
    }
 
    if(!UsefulInputBuf_BytesAvailable(pMe, uAmount)) {
-      // Number of bytes asked for at current position are more than available
+      /* Number of bytes asked for is more than available */
       pMe->err = 1;
       return NULL;
    }
 
-   // This is going to succeed
+   /* This is going to succeed */
    const void * const result = ((const uint8_t *)pMe->UB.ptr) + pMe->cursor;
-   // Will not overflow because of check using UsefulInputBuf_BytesAvailable()
+   /* Won't overflow because of check using UsefulInputBuf_BytesAvailable() */
    pMe->cursor += uAmount;
    return result;
 }
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index d37aa24..645f6a8 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -372,7 +372,12 @@
       return false;
    }
 
-   if(pNesting->pCurrentBounded->uLevelType != uType) {
+   uint8_t uItemDataType = pNesting->pCurrentBounded->uLevelType;
+   if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY) {
+      uItemDataType = QCBOR_TYPE_ARRAY;
+   }
+
+   if(uItemDataType != uType) {
       return false;
    }
 
@@ -1743,15 +1748,18 @@
        * strings.
        */
       if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
-         if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
-            uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
-            goto Done;
-         }
          pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
-         /* 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);
+         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);
+         }
       }
    }
 
@@ -3569,7 +3577,12 @@
       return;
    }
 
-   if(pItem->uDataType != uType) {
+   uint8_t uItemDataType = pItem->uDataType;
+   if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY) {
+      uItemDataType = QCBOR_TYPE_ARRAY;
+   }
+
+   if(uItemDataType != uType) {
       pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
       return;
    }
@@ -4054,7 +4067,12 @@
    if(uErr != QCBOR_SUCCESS) {
       goto Done;
    }
-   if(Item.uDataType != uType) {
+
+   uint8_t uItemDataType = Item.uDataType;
+   if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY ) {
+      uItemDataType = QCBOR_TYPE_ARRAY;
+   }
+   if(uItemDataType != uType) {
       uErr = QCBOR_ERR_UNEXPECTED_TYPE;
       goto Done;
    }
diff --git a/src/qcbor_encode.c b/src/qcbor_encode.c
index a614eb1..d196149 100644
--- a/src/qcbor_encode.c
+++ b/src/qcbor_encode.c
@@ -118,7 +118,7 @@
    if(1 >= QCBOR_MAX_ITEMS_IN_ARRAY - pNesting->pCurrentNesting->uCount) {
       return QCBOR_ERR_ARRAY_TOO_LONG;
    }
-#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+#endif /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
 
    pNesting->pCurrentNesting->uCount++;
 
@@ -436,6 +436,7 @@
    /* The 5 bits in the initial byte that are not the major type */
    int nAdditionalInfo;
 
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
    if(uMajorType > QCBOR_INDEFINITE_LEN_TYPE_MODIFIER) {
       /* Special case for start & end of indefinite length */
       uMajorType  = uMajorType - QCBOR_INDEFINITE_LEN_TYPE_MODIFIER;
@@ -448,7 +449,9 @@
        #endif
       nAdditionalInfo = CBOR_SIMPLE_BREAK;
 
-   } else if (uArgument < CBOR_TWENTY_FOUR && uMinLen == 0) {
+   } else
+#endif /* !QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+      if (uArgument < CBOR_TWENTY_FOUR && uMinLen == 0) {
       /* Simple case where argument is < 24 */
       nAdditionalInfo = (int)uArgument;
 
@@ -510,16 +513,39 @@
 
 
 /**
+ * @brief Increment item counter for maps and arrays.
+ *
+ * @param pMe          QCBOR encoding context.
+ *
+ * This is mostly a separate function to make code more readable and
+ * to have fewer occurrences of #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+ */
+static void
+QCBOREncode_Private_IncrementMapOrArrayCount(QCBOREncodeContext *pMe)
+{
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   if(pMe->uError == QCBOR_SUCCESS) {
+      pMe->uError = Nesting_Increment(&(pMe->nesting));
+   }
+#else
+   (void)Nesting_Increment(&(pMe->nesting));
+#endif /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+}
+
+
+/**
  * @brief Append the CBOR head, the major type and argument
  *
- * @param pMe          Encoder context.
+ * @param pMe         Encoder context.
  * @param uMajorType  Major type to insert.
  * @param uArgument   The argument (an integer value or a length).
  * @param uMinLen     Minimum number of bytes for encoding the CBOR argument.
  *
  * This formats the CBOR "head" and appends it to the output.
+ *
+ * This also increments the array/map item counter in most cases.
  */
-static void
+void
 QCBOREncode_Private_AppendCBORHead(QCBOREncodeContext *pMe,
                                    const uint8_t       uMajorType,
                                    const uint64_t      uArgument,
@@ -541,136 +567,15 @@
     */
 
    UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), EncodedHead);
-}
 
-
-/**
- * @brief Check for errors when decreasing nesting.
- *
- * @param pMe          QCBOR encoding context.
- * @param uMajorType  The major type of the nesting.
- *
- * Check that there is no previous error, that there is actually some
- * nesting and that the major type of the opening of the nesting
- * matches the major type of the nesting being closed.
- *
- * This is called when closing maps, arrays, byte string wrapping and
- * open/close of byte strings.
- */
-static bool
-QCBOREncode_Private_CheckDecreaseNesting(QCBOREncodeContext *pMe,
-                                         const uint8_t       uMajorType)
-{
-#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
-   if(pMe->uError != QCBOR_SUCCESS) {
-      return true;
+   if(!(uMajorType & QCBOR_INDEFINITE_LEN_TYPE_MODIFIER || uMajorType == CBOR_MAJOR_TYPE_TAG)) {
+      /* Don't increment the map count for tag or break because that is
+       * not needed. Don't do it for indefinite-length arrays and maps
+       * because it is done elsewhere. This is never called for definite-length
+       * arrays and maps.
+       */
+      QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
    }
-
-   if(!Nesting_IsInNest(&(pMe->nesting))) {
-      pMe->uError = QCBOR_ERR_TOO_MANY_CLOSES;
-      return true;
-   }
-
-   if(Nesting_GetMajorType(&(pMe->nesting)) != uMajorType) {
-      pMe->uError = QCBOR_ERR_CLOSE_MISMATCH;
-      return true;
-   }
-
-#else
-   /* None of these checks are performed if the encode guards are
-    * turned off as they all relate to correct calling.
-    *
-    * Turning off all these checks does not turn off any checking for
-    * buffer overflows or pointer issues.
-    */
-
-   (void)uMajorType;
-   (void)pMe;
-#endif
-
-   return false;
-}
-
-
-/**
- * @brief Insert the CBOR head for a map, array or wrapped bstr
- *
- * @param pMe          QCBOR encoding context.
- * @param uMajorType  One of CBOR_MAJOR_TYPE_XXXX.
- * @param uLen        The length of the data item.
- *
- * When an array, map or bstr was opened, nothing was done but note
- * the position. This function goes back to that position and inserts
- * the CBOR Head with the major type and length.
- */
-static void
-QCBOREncode_Private_InsertCBORHead(QCBOREncodeContext *pMe,
-                                   uint8_t             uMajorType,
-                                   size_t              uLen)
-{
-   if(QCBOREncode_Private_CheckDecreaseNesting(pMe, uMajorType)) {
-      return;
-   }
-
-   if(uMajorType == CBOR_MAJOR_NONE_TYPE_OPEN_BSTR) {
-      uMajorType = CBOR_MAJOR_TYPE_BYTE_STRING;
-   }
-
-   /* A stack buffer large enough for a CBOR head (9 bytes) */
-   UsefulBuf_MAKE_STACK_UB(pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
-
-   UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
-                                                   uMajorType,
-                                                   0,
-                                                   uLen);
-
-   /* No check for EncodedHead == NULLUsefulBufC is performed here to
-    * save object code. It is very clear that pBufferForEncodedHead is
-    * the correct size. If EncodedHead == NULLUsefulBufC then
-    * UsefulOutBuf_InsertUsefulBuf() will do nothing so there is no
-    * security hole introduced.
-    */
-   UsefulOutBuf_InsertUsefulBuf(&(pMe->OutBuf),
-                                EncodedHead,
-                                Nesting_GetStartPos(&(pMe->nesting)));
-
-   Nesting_Decrease(&(pMe->nesting));
-}
-
-
-/**
- * @brief Increment item counter for maps and arrays.
- *
- * @param pMe          QCBOR encoding context.
- *
- * This is mostly a separate function to make code more readable and
- * to have fewer occurrences of #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
- */
-static void
-QCBOREncode_Private_IncrementMapOrArrayCount(QCBOREncodeContext *pMe)
-{
-#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
-   if(pMe->uError == QCBOR_SUCCESS) {
-      pMe->uError = Nesting_Increment(&(pMe->nesting));
-   }
-#else
-   (void)Nesting_Increment(&(pMe->nesting));
-#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
-}
-
-
-/*
- * Public functions for adding unsigned integers. See qcbor/qcbor_encode.h
- */
-void
-QCBOREncode_AddUInt64(QCBOREncodeContext *pMe, const uint64_t uValue)
-{
-   QCBOREncode_Private_AppendCBORHead(pMe,
-                                      CBOR_MAJOR_TYPE_POSITIVE_INT,
-                                      uValue,
-                                      0);
-
-   QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
 }
 
 
@@ -694,8 +599,6 @@
 #endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
 
    QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_NEGATIVE_INT, uValue, 0);
-
-   QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
 }
 
 
@@ -722,140 +625,57 @@
       uMajorType = CBOR_MAJOR_TYPE_POSITIVE_INT;
    }
    QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, uValue, 0);
-
-   QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
 }
 
 
 /**
  * @brief Semi-private method to add a buffer full of bytes to encoded output.
  *
- * @param[in] pMe       The encoding context to add the integer to.
+ * @param[in] pMe       The encoding context to add the string to.
  * @param[in] uMajorType The CBOR major type of the bytes.
  * @param[in] Bytes      The bytes to add.
  *
- * Use QCBOREncode_AddText() or QCBOREncode_AddBytes() or
- * QCBOREncode_AddEncoded() instead. They are inline functions that
- * call this and supply the correct major type. This function is
- * public to make the inline functions work to keep the overall code
- * size down and because the C language has no way to make it private.
+ * Called by inline functions to add text and byte strings.
  *
- * If this is called the major type should be @c CBOR_MAJOR_TYPE_TEXT_STRING,
- * @c CBOR_MAJOR_TYPE_BYTE_STRING or @c CBOR_MAJOR_NONE_TYPE_RAW. The
- * last one is special for adding already-encoded CBOR.
- *
- * This does the work of adding actual strings bytes to the CBOR
- * output (as opposed to adding numbers and opening / closing
- * aggregate types).
-
- * There are four use cases:
- *   CBOR_MAJOR_TYPE_BYTE_STRING -- Byte strings
- *   CBOR_MAJOR_TYPE_TEXT_STRING -- Text strings
- *   CBOR_MAJOR_NONE_TYPE_RAW -- Already-encoded CBOR
- *
- * The first two add the head plus the actual bytes. The third just
- * adds the bytes as the heas is presumed to be in the bytes. The
- * fourth just adds the head for the very special case of
- * QCBOREncode_AddBytesLenOnly().
+ * (This used to support QCBOREncode_AddEncoded() and
+ * QCBOREncode_AddBytesLenOnly(), but that was pulled out to make this
+ * smaller. This is one of the most used methods and they are some of
+ * the least used).
  */
 void
 QCBOREncode_Private_AddBuffer(QCBOREncodeContext *pMe,
                               const uint8_t       uMajorType,
                               const UsefulBufC    Bytes)
 {
-   /* If it is not Raw CBOR, add the type and the length */
-   if(uMajorType != CBOR_MAJOR_NONE_TYPE_RAW) {
-      uint8_t uRealMajorType = uMajorType;
-      QCBOREncode_Private_AppendCBORHead(pMe, uRealMajorType, Bytes.len, 0);
-   }
-
-   /* Actually add the bytes */
+   QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, Bytes.len, 0);
    UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), Bytes);
+}
 
+
+/*
+ * Public functions for adding raw encoded CBOR. See qcbor/qcbor_encode.h
+ */
+void
+QCBOREncode_AddEncoded(QCBOREncodeContext *pMe, const UsefulBufC Encoded)
+{
+   UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), Encoded);
    QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
 }
 
 
-/*
- * Public functions for adding a tag. See qcbor/qcbor_encode.h
- */
-void
-QCBOREncode_AddTag(QCBOREncodeContext *pMe, const uint64_t uTag)
-{
-   QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_TAG, uTag, 0);
-}
-
-
-/**
- * @brief  Semi-private method to add simple types.
- *
- * @param[in] pMe     The encoding context to add the simple value to.
- * @param[in] uMinLen  Minimum encoding size for uNum. Usually 0.
- * @param[in] uNum     One of CBOR_SIMPLEV_FALSE through _UNDEF or other.
- *
- * This is used to add simple types like true and false.
- *
- * Call QCBOREncode_AddBool(), QCBOREncode_AddNULL(),
- * QCBOREncode_AddUndef() instead of this.
- *
- * This function can add simple values that are not defined by CBOR
- * yet. This expansion point in CBOR should not be used unless they are
- * standardized.
- *
- * Error handling is the same as QCBOREncode_AddInt64().
- */
-void
-QCBOREncode_Private_AddType7(QCBOREncodeContext *pMe,
-                             const uint8_t       uMinLen,
-                             const uint64_t      uNum)
-{
-#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
-   if(pMe->uError == QCBOR_SUCCESS) {
-      if(uNum >= CBOR_SIMPLEV_RESERVED_START && uNum <= CBOR_SIMPLEV_RESERVED_END) {
-         pMe->uError = QCBOR_ERR_ENCODE_UNSUPPORTED;
-         return;
-      }
-   }
-#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
-
-   /* AppendCBORHead() does endian swapping for the float / double */
-   QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_SIMPLE, uNum, uMinLen);
-
-   QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
-}
-
-
-#ifndef USEFULBUF_DISABLE_ALL_FLOAT
-/*
- * Public functions for adding a double. See qcbor/qcbor_encode.h
- */
-void
-QCBOREncode_AddDoubleNoPreferred(QCBOREncodeContext *pMe, const double dNum)
-{
-#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
-   if(pMe->uMode >= QCBOR_ENCODE_MODE_PREFERRED) {
-      pMe->uError = QCBOR_ERR_NOT_PREFERRED;
-      return;
-   }
-   if(IEEE754_IsNotStandardDoubleNaN(dNum) && !(pMe->uAllow & QCBOR_ENCODE_ALLOW_NAN_PAYLOAD)) {
-      pMe->uError = QCBOR_ERR_NOT_ALLOWED;
-      return;
-   }
-#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
-
-   QCBOREncode_Private_AddType7(pMe,
-                                sizeof(uint64_t),
-                                UsefulBufUtil_CopyDoubleToUint64(dNum));
-}
-
-
-/*
- * Public functions for adding a double. See qcbor/qcbor_encode.h
- */
-void
-QCBOREncode_AddDouble(QCBOREncodeContext *pMe, double dNum)
-{
 #ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+/**
+ * @brief Semi-private method to add a double using preferred encoding.
+ *
+ * @param[in] pMe   The encode context.
+ * @param[in] dNum  The double to add.
+ *
+ * This converts the double to a float or half-precision if it can be done
+ * without a loss of precision. See QCBOREncode_AddDouble().
+ */
+void
+QCBOREncode_Private_AddPreferredDouble(QCBOREncodeContext *pMe, double dNum)
+{
    IEEE754_union        FloatResult;
    bool                 bNoNaNPayload;
    struct IEEE754_ToInt IntResult;
@@ -890,44 +710,21 @@
    FloatResult = IEEE754_DoubleToSmaller(dNum, true, bNoNaNPayload);
 
    QCBOREncode_Private_AddType7(pMe, (uint8_t)FloatResult.uSize, FloatResult.uValue);
-
-#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
-   QCBOREncode_AddDoubleNoPreferred(pMe, dNum);
-#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
 }
 
 
-
-
-/*
- * Public functions for adding a float. See qcbor/qcbor_encode.h
+/**
+ * @brief Semi-private method to add a float using preferred encoding.
+ *
+ * @param[in] pMe   The encode context.
+ * @param[in] fNum  The float to add.
+ *
+ * This converts the float to a half-precision if it can be done
+ * without a loss of precision. See QCBOREncode_AddFloat().
  */
 void
-QCBOREncode_AddFloatNoPreferred(QCBOREncodeContext *pMe, const float fNum)
+QCBOREncode_Private_AddPreferredFloat(QCBOREncodeContext *pMe, float fNum)
 {
-#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
-   if(pMe->uMode >= QCBOR_ENCODE_MODE_PREFERRED) {
-      pMe->uError = QCBOR_ERR_NOT_PREFERRED;
-      return;
-   }
-   if(IEEE754_IsNotStandardSingleNaN(fNum) && !(pMe->uAllow & QCBOR_ENCODE_ALLOW_NAN_PAYLOAD)) {
-      pMe->uError = QCBOR_ERR_NOT_ALLOWED;
-      return;
-   }
-#endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
-   QCBOREncode_Private_AddType7(pMe,
-                                sizeof(uint32_t),
-                                UsefulBufUtil_CopyFloatToUint32(fNum));
-}
-
-
-/*
- * Public functions for adding a float. See qcbor/qcbor_encode.h
- */
-void
-QCBOREncode_AddFloat(QCBOREncodeContext *pMe, float fNum)
-{
-#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
    IEEE754_union        FloatResult;
    bool                 bNoNaNPayload;
    struct IEEE754_ToInt IntResult;
@@ -939,7 +736,6 @@
    }
 #endif /* ! QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
 
-
    if(pMe->uMode == QCBOR_ENCODE_MODE_DCBOR) {
       IntResult = IEEE754_SingleToInt(fNum);
       switch(IntResult.type) {
@@ -963,12 +759,9 @@
    FloatResult = IEEE754_SingleToHalf(fNum, bNoNaNPayload);
 
    QCBOREncode_Private_AddType7(pMe, (uint8_t)FloatResult.uSize, FloatResult.uValue);
-
-#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
-   QCBOREncode_AddFloatNoPreferred(pMe, fNum);
-#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
 }
-#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+#endif /* !QCBOR_DISABLE_PREFERRED_FLOAT */
+
 
 
 #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
@@ -1079,6 +872,7 @@
 }
 
 
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
 /**
  * @brief Semi-private method to open a map, array with indefinite length
  *
@@ -1107,6 +901,101 @@
     */
    QCBOREncode_Private_OpenMapOrArray(pMe, uMajorType);
 }
+#endif
+
+
+/**
+ * @brief Check for errors when decreasing nesting.
+ *
+ * @param pMe          QCBOR encoding context.
+ * @param uMajorType  The major type of the nesting.
+ *
+ * Check that there is no previous error, that there is actually some
+ * nesting and that the major type of the opening of the nesting
+ * matches the major type of the nesting being closed.
+ *
+ * This is called when closing maps, arrays, byte string wrapping and
+ * open/close of byte strings.
+ */
+static bool
+QCBOREncode_Private_CheckDecreaseNesting(QCBOREncodeContext *pMe,
+                                         const uint8_t       uMajorType)
+{
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   if(pMe->uError != QCBOR_SUCCESS) {
+      return true;
+   }
+
+   if(!Nesting_IsInNest(&(pMe->nesting))) {
+      pMe->uError = QCBOR_ERR_TOO_MANY_CLOSES;
+      return true;
+   }
+
+   if(Nesting_GetMajorType(&(pMe->nesting)) != uMajorType) {
+      pMe->uError = QCBOR_ERR_CLOSE_MISMATCH;
+      return true;
+   }
+
+#else /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+   /* None of these checks are performed if the encode guards are
+    * turned off as they all relate to correct calling.
+    *
+    * Turning off all these checks does not turn off any checking for
+    * buffer overflows or pointer issues.
+    */
+
+   (void)uMajorType;
+   (void)pMe;
+#endif /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+
+   return false;
+}
+
+
+/**
+ * @brief Insert the CBOR head for a map, array or wrapped bstr
+ *
+ * @param pMe         QCBOR encoding context.
+ * @param uMajorType  One of CBOR_MAJOR_TYPE_XXXX.
+ * @param uLen        The length of the data item.
+ *
+ * When an array, map or bstr was opened, nothing was done but note
+ * the position. This function goes back to that position and inserts
+ * the CBOR Head with the major type and length.
+ */
+static void
+QCBOREncode_Private_CloseAggregate(QCBOREncodeContext *pMe,
+                                   uint8_t             uMajorType,
+                                   size_t              uLen)
+{
+   if(QCBOREncode_Private_CheckDecreaseNesting(pMe, uMajorType)) {
+      return;
+   }
+
+   if(uMajorType == CBOR_MAJOR_NONE_TYPE_OPEN_BSTR) {
+      uMajorType = CBOR_MAJOR_TYPE_BYTE_STRING;
+   }
+
+   /* A stack buffer large enough for a CBOR head (9 bytes) */
+   UsefulBuf_MAKE_STACK_UB(pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
+
+   UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
+                                                   uMajorType,
+                                                   0,
+                                                   uLen);
+
+   /* No check for EncodedHead == NULLUsefulBufC is performed here to
+    * save object code. It is very clear that pBufferForEncodedHead is
+    * the correct size. If EncodedHead == NULLUsefulBufC then
+    * UsefulOutBuf_InsertUsefulBuf() will do nothing so there is no
+    * security hole introduced.
+    */
+   UsefulOutBuf_InsertUsefulBuf(&(pMe->OutBuf),
+                                EncodedHead,
+                                Nesting_GetStartPos(&(pMe->nesting)));
+
+   Nesting_Decrease(&(pMe->nesting));
+}
 
 
 /**
@@ -1119,7 +1008,7 @@
 QCBOREncode_Private_CloseMapOrArray(QCBOREncodeContext *pMe,
                                     const uint8_t       uMajorType)
 {
-   QCBOREncode_Private_InsertCBORHead(pMe, uMajorType, Nesting_GetCount(&(pMe->nesting)));
+   QCBOREncode_Private_CloseAggregate(pMe, uMajorType, Nesting_GetCount(&(pMe->nesting)));
 }
 
 
@@ -1437,7 +1326,7 @@
    uStart = Nesting_GetStartPos(&(pMe->nesting));
    QCBOREncode_Private_SortMap(pMe, uStart);
 
-   QCBOREncode_Private_InsertCBORHead(pMe, CBOR_MAJOR_TYPE_MAP, Nesting_GetCount(&(pMe->nesting)));
+   QCBOREncode_Private_CloseAggregate(pMe, CBOR_MAJOR_TYPE_MAP, Nesting_GetCount(&(pMe->nesting)));
 }
 
 
@@ -1475,7 +1364,7 @@
    const size_t uBstrLen = uEndPosition - uInsertPosition;
 
    /* Actually insert */
-   QCBOREncode_Private_InsertCBORHead(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, uBstrLen);
+   QCBOREncode_Private_CloseAggregate(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, uBstrLen);
 
    if(pWrappedCBOR) {
       /* Return pointer and length to the enclosed encoded CBOR. The
@@ -1561,10 +1450,12 @@
       return;
    }
 
-   QCBOREncode_Private_InsertCBORHead(pMe, CBOR_MAJOR_NONE_TYPE_OPEN_BSTR, uAmount);
+   QCBOREncode_Private_CloseAggregate(pMe, CBOR_MAJOR_NONE_TYPE_OPEN_BSTR, uAmount);
 }
 
 
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+
 /**
  * @brief Semi-private method to close a map, array with indefinite length
  *
@@ -1586,6 +1477,7 @@
    QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_NONE_TYPE_SIMPLE_BREAK, CBOR_SIMPLE_BREAK, 0);
    Nesting_Decrease(&(pMe->nesting));
 }
+#endif
 
 
 /*
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 5e43823..3108fcb 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -63,6 +63,22 @@
 }
 #endif /* PRINT_FUNCTIONS_FOR_DEBUGGING */
 
+
+/* Make a test results code that includes three components. Return code
+ * is xxxyyyzzz where zz is the error code, yy is the test number and
+ * zz is check being performed
+ */
+static int32_t
+MakeTestResultCode(uint32_t   uTestCase,
+                   uint32_t   uTestNumber,
+                   QCBORError uErrorCode)
+{
+   uint32_t uCode = (uTestCase * 1000000) +
+                    (uTestNumber * 1000) +
+                    (uint32_t)uErrorCode;
+   return (int32_t)uCode;
+}
+
 /*
    [
       -9223372036854775808,
@@ -1077,6 +1093,48 @@
    return(nReturn);
 }
 
+
+/* This test requires indef strings, HW float and preferred float,... */
+#if !defined(QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS) && \
+    !defined(QCBOR_DISABLE_FLOAT_HW_USE) && \
+    !defined(QCBOR_DISABLE_PREFERRED_FLOAT) && \
+    !defined(QCBOR_DISABLE_TAGS) && \
+    !defined(QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS)
+
+static const uint8_t pPerverseLabels[] = {
+   0xae,
+
+   0xf5, 0x61, 0x61,
+
+   0xf6, 0x61, 0x62,
+
+   0xf8, 0xff, 0x61, 0x63,
+
+   0xf9, 0x7e, 0x00, 0x61, 0x64,
+
+   0xfa, 0x7f, 0x7f, 0xff, 0xff, 0x61, 0x65,
+
+   0xfb, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x66,
+
+   0xa1, 0x19, 0x03, 0xe8, 0x10, 0x61, 0x67,
+
+   0x81, 0x81, 0x81, 0x80, 0x61, 0x68,
+
+   0xc1, 0x09, 0x61, 0x69,
+
+   0x82, 0x05, 0xa2, 0x01, 0x02, 0x03, 0x04, 0x61, 0x6a,
+
+   0xbf, 0xff, 0x61, 0x6b,
+
+   0x9f, 0x11, 0x12, 0x13, 0xff, 0x61, 0x6c,
+
+   0x7f, 0x62, 0x41, 0x42, 0x62, 0x43, 0x44, 0xff, 0x61, 0x6d,
+
+   0xd9, 0x01, 0x02, 0xbf, 0x7f, 0x61, 0x4a, 0x61, 0x4b, 0xff, 0x00, 0xf4, 0xd7, 0x80 ,0xff, 0x61, 0x6e
+};
+#endif
+
+
 /*
  Decode and thoroughly check a moderately complex
  set of maps. Can be run in QCBOR_DECODE_MODE_NORMAL or in
@@ -1206,6 +1264,39 @@
 }
 
 
+/* This test requires indef strings, HW float and preferred float,... */
+#if !defined(QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS) && \
+    !defined(QCBOR_DISABLE_FLOAT_HW_USE) && \
+    !defined(QCBOR_DISABLE_PREFERRED_FLOAT) && \
+    !defined(QCBOR_DISABLE_TAGS) && \
+    !defined(QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS)
+
+/* Utility to decode a one byte string and match to letter. */
+static QCBORError
+CheckOneLetterString(QCBORDecodeContext *pDecode, uint8_t letter)
+{
+   UsefulBufC Text;
+   QCBORError uErr;
+
+   QCBORDecode_GetTextString(pDecode, &Text);
+   uErr = QCBORDecode_GetError(pDecode);
+   if(uErr) {
+      return uErr;
+   }
+
+   if(Text.len != 1) {
+      return QCBOR_ERR_FIRST_USER_DEFINED;
+   }
+
+   if(*(const uint8_t *)Text.ptr != letter) {
+      return QCBOR_ERR_FIRST_USER_DEFINED;
+   }
+
+   return QCBOR_SUCCESS;
+}
+#endif
+
+
 /*
  Decode and thoroughly check a moderately complex
  set of maps in the QCBOR_DECODE_MODE_MAP_AS_ARRAY mode.
@@ -1213,23 +1304,23 @@
 int32_t ParseMapAsArrayTest(void)
 {
    QCBORDecodeContext DCtx;
-   QCBORItem Item;
-   QCBORError nCBORError;
+   QCBORItem          Item;
+   QCBORError         uErr;
 
    QCBORDecode_Init(&DCtx,
                     UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded),
                     QCBOR_DECODE_MODE_MAP_AS_ARRAY);
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return MakeTestResultCode(1, 1, uErr);
    }
    if(Item.uDataType != QCBOR_TYPE_MAP_AS_ARRAY ||
       Item.val.uCount != 6) {
       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_TEXT_STRING ||
       Item.uDataAlloc ||
@@ -1239,8 +1330,8 @@
       return -2;
    }
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return (int32_t)uErr;
    }
    if(Item.uLabelType != QCBOR_TYPE_NONE ||
       Item.uDataType != QCBOR_TYPE_INT64 ||
@@ -1250,8 +1341,8 @@
       return -3;
    }
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return (int32_t)uErr;
    }
    if(Item.uLabelType != QCBOR_TYPE_NONE ||
       Item.uDataAlloc ||
@@ -1261,8 +1352,8 @@
       return -4;
    }
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return (int32_t)uErr;
    }
    if(Item.uLabelType != QCBOR_TYPE_NONE ||
       Item.uDataAlloc ||
@@ -1272,8 +1363,8 @@
       return -5;
    }
 
-   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_TEXT_STRING ||
       Item.val.string.len != 7 ||
@@ -1283,8 +1374,8 @@
       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_TEXT_STRING ||
       Item.uDataAlloc ||
@@ -1294,8 +1385,8 @@
    }
 
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return (int32_t)uErr;
    }
    if(Item.uLabelType != QCBOR_TYPE_NONE ||
       Item.uDataAlloc ||
@@ -1304,8 +1395,8 @@
       return -8;
    }
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return (int32_t)uErr;
    }
    if(Item.uLabelType != QCBOR_TYPE_NONE ||
       Item.uDataAlloc ||
@@ -1315,8 +1406,8 @@
       return -9;
    }
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return (int32_t)uErr;
    }
    if(Item.uLabelType != QCBOR_TYPE_NONE ||
       UsefulBufCompareToSZ(Item.val.string, "bytes 1") ||
@@ -1326,8 +1417,8 @@
       return -10;
    }
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return (int32_t)uErr;
    }
    if(Item.uLabelType != QCBOR_TYPE_NONE ||
       Item.uDataType != QCBOR_TYPE_BYTE_STRING ||
@@ -1337,8 +1428,8 @@
       return -11;
    }
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return (int32_t)uErr;
    }
    if(Item.uLabelType != QCBOR_TYPE_NONE ||
       UsefulBufCompareToSZ(Item.val.string, "bytes 2") ||
@@ -1348,8 +1439,8 @@
       return -12;
    }
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return (int32_t)uErr;
    }
    if(Item.uLabelType != QCBOR_TYPE_NONE ||
       Item.uDataType != QCBOR_TYPE_BYTE_STRING ||
@@ -1359,8 +1450,8 @@
       return -13;
    }
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return (int32_t)uErr;
    }
    if(Item.uLabelType != QCBOR_TYPE_NONE ||
       Item.uDataAlloc ||
@@ -1370,8 +1461,8 @@
       return -14;
    }
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return (int32_t)uErr;
    }
    if(Item.uLabelType != QCBOR_TYPE_NONE ||
       Item.uDataAlloc ||
@@ -1381,8 +1472,8 @@
       return -15;
    }
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return (int32_t)uErr;
    }
    if(Item.uLabelType != QCBOR_TYPE_NONE ||
       UsefulBufCompareToSZ(Item.val.string, "text 2") ||
@@ -1392,8 +1483,8 @@
       return -16;
    }
 
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
-      return (int32_t)nCBORError;
+   if((uErr = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return (int32_t)uErr;
    }
    if(Item.uLabelType != QCBOR_TYPE_NONE ||
       Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
@@ -1419,13 +1510,582 @@
       return -50;
    }
 
-   // TODO: test decoding of labels that are arrays or such
-   // TODO: test spiffy decoding of QCBOR_DECODE_MODE_MAP_AS_ARRAY
+   /* This test requires indef strings, HW float and preferred float,... */
+#if !defined(QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS) && \
+    !defined(QCBOR_DISABLE_FLOAT_HW_USE) && \
+    !defined(QCBOR_DISABLE_PREFERRED_FLOAT) && \
+    !defined(QCBOR_DISABLE_TAGS) && \
+    !defined(QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS)
+
+   UsefulBufC         Encoded;
+
+   /* Big decode of a map with a wide variety or labels */
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pPerverseLabels),
+                    QCBOR_DECODE_MODE_MAP_AS_ARRAY);
+      UsefulBuf_MAKE_STACK_UB(Pool, 100);
+      QCBORDecode_SetMemPool(&DCtx, Pool, 0);
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 1, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_MAP_AS_ARRAY) {
+      return MakeTestResultCode(10, 2, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 3, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_TRUE) {
+      return MakeTestResultCode(10, 4, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 5, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      ((const char *)Item.val.string.ptr)[0] != 'a') {
+      return MakeTestResultCode(10, 6, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 7, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_NULL) {
+      return MakeTestResultCode(10, 8, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 9, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      ((const char *)Item.val.string.ptr)[0] != 'b') {
+      return MakeTestResultCode(10, 10, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 11, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_UKNOWN_SIMPLE ||
+      Item.val.int64 != 255) {
+      return MakeTestResultCode(10, 12, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 13, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      ((const char *)Item.val.string.ptr)[0] != 'c') {
+      return MakeTestResultCode(10, 14, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 15, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_DOUBLE ||
+      !isnan(Item.val.dfnum)) {
+      return MakeTestResultCode(10, 16, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 17, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      ((const char *)Item.val.string.ptr)[0] != 'd') {
+      return MakeTestResultCode(10, 18, 0);
+   }
+
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 19, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_DOUBLE ||
+      Item.val.dfnum != 3.4028234663852886E+38) {
+      return MakeTestResultCode(10, 20, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 21, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      ((const char *)Item.val.string.ptr)[0] != 'e') {
+      return MakeTestResultCode(10, 22, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 23, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_DOUBLE ||
+      Item.val.dfnum != -INFINITY) {
+      return MakeTestResultCode(10, 24, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 25, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      ((const char *)Item.val.string.ptr)[0] != 'f') {
+      return MakeTestResultCode(10, 26, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 26, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_MAP_AS_ARRAY ||
+      Item.val.uCount != 2) {
+      return MakeTestResultCode(10, 27, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 28, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_INT64 ||
+      Item.val.int64 != 1000) {
+      return MakeTestResultCode(10, 29, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 30, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_INT64 ||
+      Item.val.int64 != 16) {
+      return MakeTestResultCode(10, 31, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 32, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      ((const char *)Item.val.string.ptr)[0] != 'g') {
+      return MakeTestResultCode(10, 33, 0);
+   }
+
+   for(int i = 0 ; i < 4; i++) {
+      uErr = QCBORDecode_GetNext(&DCtx, &Item);
+      if(uErr) {
+         return MakeTestResultCode(10, 34, uErr);
+      }
+      if(Item.uLabelType != QCBOR_TYPE_NONE ||
+         Item.uDataType != QCBOR_TYPE_ARRAY)  {
+         return MakeTestResultCode(10, 35, 0);
+      }
+      if(i != 3) {
+         if(Item.val.uCount != 1) {
+            return MakeTestResultCode(10, 35, 0);
+         }
+      }
+   }
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 36, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      ((const char *)Item.val.string.ptr)[0] != 'h') {
+      return MakeTestResultCode(10, 37, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 38, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_DATE_EPOCH) {
+      return MakeTestResultCode(10, 39, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 40, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      ((const char *)Item.val.string.ptr)[0] != 'i') {
+      return MakeTestResultCode(10, 41, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 42, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_ARRAY ||
+      Item.val.uCount != 2) {
+      return MakeTestResultCode(10, 31, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 43, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_INT64) {
+      return MakeTestResultCode(10, 31, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 44, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_MAP_AS_ARRAY ||
+      Item.val.uCount != 4) {
+      return MakeTestResultCode(10, 45, 0);
+   }
+
+   for(int i = 0 ; i < 4; i++) {
+      uErr = QCBORDecode_GetNext(&DCtx, &Item);
+      if(uErr) {
+         return MakeTestResultCode(10, 46, uErr);
+      }
+      if(Item.uLabelType != QCBOR_TYPE_NONE ||
+         Item.uDataType != QCBOR_TYPE_INT64) {
+         return MakeTestResultCode(10, 47, 0);
+      }
+   }
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 48, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      ((const char *)Item.val.string.ptr)[0] != 'j') {
+      return MakeTestResultCode(10, 49, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 50, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_MAP_AS_ARRAY ||
+      Item.val.uCount != UINT16_MAX) {
+      return MakeTestResultCode(10, 51, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 52, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      ((const char *)Item.val.string.ptr)[0] != 'k') {
+      return MakeTestResultCode(10, 53, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 54, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_ARRAY ||
+      Item.val.uCount != UINT16_MAX) {
+      return MakeTestResultCode(10, 55, 0);
+   }
+
+   for(int i = 0 ; i < 3; i++) {
+      uErr = QCBORDecode_GetNext(&DCtx, &Item);
+      if(uErr) {
+         return MakeTestResultCode(10, 56, uErr);
+      }
+      if(Item.uLabelType != QCBOR_TYPE_NONE ||
+         Item.uDataType != QCBOR_TYPE_INT64) {
+         return MakeTestResultCode(10, 57, 0);
+      }
+   }
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 58, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      ((const char *)Item.val.string.ptr)[0] != 'l') {
+      return MakeTestResultCode(10, 59, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 60, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      Item.val.string.len != 4) {
+      return MakeTestResultCode(10, 61, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 62, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      ((const char *)Item.val.string.ptr)[0] != 'm') {
+      return MakeTestResultCode(10, 63, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 64, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_MAP_AS_ARRAY ||
+      !QCBORDecode_IsTagged(&DCtx, &Item, 258) ||
+      Item.val.uCount != UINT16_MAX) {
+      return MakeTestResultCode(10, 65, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 66, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      Item.val.string.len != 2) {
+      return MakeTestResultCode(10, 67, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 68, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_INT64 ||
+      Item.val.int64 != 0) {
+      return MakeTestResultCode(10, 69, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 70, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_FALSE) {
+      return MakeTestResultCode(10, 71, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 72, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_ARRAY ||
+      !QCBORDecode_IsTagged(&DCtx, &Item, 23) ||
+      Item.val.uCount != 0) {
+      return MakeTestResultCode(10, 73, 0);
+   }
+
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+   if(uErr) {
+      return MakeTestResultCode(10, 74, uErr);
+   }
+   if(Item.uLabelType != QCBOR_TYPE_NONE ||
+      Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      ((const char *)Item.val.string.ptr)[0] != 'n') {
+      return MakeTestResultCode(10, 75, 0);
+   }
+
+
+   /* Big decode of a map with a wide variety or labels */
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pPerverseLabels),
+                    QCBOR_DECODE_MODE_MAP_AS_ARRAY);
+      QCBORDecode_SetMemPool(&DCtx, Pool, 0);
+
+   QCBORDecode_EnterArray(&DCtx, &Item);
+   bool b;
+   QCBORDecode_GetBool(&DCtx, &b);
+
+   uErr = CheckOneLetterString(&DCtx, 'a');
+   if(uErr) {
+      return MakeTestResultCode(11, 1, uErr);
+   }
+
+   QCBORDecode_GetNull(&DCtx);
+   uErr = CheckOneLetterString(&DCtx, 'b');
+   if(uErr) {
+      return MakeTestResultCode(11, 2, uErr);
+   }
+
+   QCBORDecode_VGetNext(&DCtx,  &Item);
+   uErr = CheckOneLetterString(&DCtx, 'c');
+   if(uErr) {
+      return MakeTestResultCode(11, 3, uErr);
+   }
+
+   double dNum;
+   QCBORDecode_GetDouble(&DCtx, &dNum);
+   if(!isnan(dNum)) {
+      return MakeTestResultCode(11, 4, 0);
+   }
+   uErr = CheckOneLetterString(&DCtx, 'd');
+   if(uErr) {
+      return MakeTestResultCode(11, 5, uErr);
+   }
+
+   QCBORDecode_GetDouble(&DCtx, &dNum);
+   if( dNum != 3.4028234663852886E+38 ) {
+      return MakeTestResultCode(11, 6, 0);
+   }
+   uErr = CheckOneLetterString(&DCtx, 'e');
+   if(uErr) {
+      return MakeTestResultCode(11, 7, uErr);
+   }
+
+   QCBORDecode_GetDouble(&DCtx, &dNum);
+   if(dNum != -INFINITY) {
+      return MakeTestResultCode(11, 8, 0);
+   }
+   uErr = CheckOneLetterString(&DCtx, 'f');
+   if(uErr) {
+      return MakeTestResultCode(11, 9, uErr);
+   }
+
+   int64_t nInt;
+   QCBORDecode_EnterArray(&DCtx, &Item);
+   QCBORDecode_GetInt64(&DCtx, &nInt);
+   QCBORDecode_GetInt64(&DCtx, &nInt);
+   QCBORDecode_ExitArray(&DCtx);
+   uErr = CheckOneLetterString(&DCtx, 'g');
+   if(uErr) {
+      return MakeTestResultCode(11, 10, uErr);
+   }
+
+   QCBORDecode_EnterArray(&DCtx, &Item);
+   QCBORDecode_EnterArray(&DCtx, &Item);
+   QCBORDecode_EnterArray(&DCtx, &Item);
+   QCBORDecode_EnterArray(&DCtx, &Item);
+   QCBORDecode_ExitArray(&DCtx);
+   QCBORDecode_ExitArray(&DCtx);
+   QCBORDecode_ExitArray(&DCtx);
+   QCBORDecode_ExitArray(&DCtx);
+   uErr = CheckOneLetterString(&DCtx, 'h');
+   if(uErr) {
+      return MakeTestResultCode(11, 11, uErr);
+   }
+   QCBORDecode_GetEpochDate(&DCtx, QCBOR_TAG_REQUIREMENT_TAG, &nInt);
+   uErr = CheckOneLetterString(&DCtx, 'i');
+   if(uErr) {
+      return MakeTestResultCode(11, 12, uErr);
+   }
+
+   QCBORDecode_EnterArray(&DCtx, &Item);
+   QCBORDecode_GetInt64(&DCtx, &nInt);
+   QCBORDecode_EnterArray(&DCtx, &Item);
+   QCBORDecode_GetInt64(&DCtx, &nInt);
+   QCBORDecode_GetInt64(&DCtx, &nInt);
+   QCBORDecode_GetInt64(&DCtx, &nInt);
+   QCBORDecode_GetInt64(&DCtx, &nInt);
+   QCBORDecode_ExitArray(&DCtx);
+   QCBORDecode_ExitArray(&DCtx);
+   uErr = CheckOneLetterString(&DCtx, 'j');
+   if(uErr) {
+      return MakeTestResultCode(11, 13, uErr);
+   }
+
+   QCBORDecode_GetArray(&DCtx, &Item, &Encoded);
+   uErr = CheckOneLetterString(&DCtx, 'k');
+   if(uErr) {
+      return MakeTestResultCode(11, 14, uErr);
+   }
+
+   QCBORDecode_EnterArray(&DCtx, &Item);
+   QCBORDecode_GetInt64(&DCtx, &nInt);
+   QCBORDecode_GetInt64(&DCtx, &nInt);
+   QCBORDecode_GetInt64(&DCtx, &nInt);
+   QCBORDecode_ExitArray(&DCtx);
+   uErr = CheckOneLetterString(&DCtx, 'l');
+   if(uErr) {
+      return MakeTestResultCode(11, 15, uErr);
+   }
+
+   QCBORDecode_GetTextString(&DCtx, &Encoded);
+   uErr = CheckOneLetterString(&DCtx, 'm');
+   if(uErr) {
+      return MakeTestResultCode(11, 16, uErr);
+   }
+
+   QCBORDecode_EnterArray(&DCtx, &Item);
+   if(!QCBORDecode_IsTagged(&DCtx, &Item, 258)) {
+      return MakeTestResultCode(11, 17, 0);
+   }
+   if(Item.uDataType != QCBOR_TYPE_MAP_AS_ARRAY) {
+      return MakeTestResultCode(11, 18, 0);
+   }
+   if(Item.val.uCount != UINT16_MAX) {
+      return MakeTestResultCode(11, 19, 0);
+   }
+   QCBORDecode_GetTextString(&DCtx, &Encoded);
+   if(Encoded.len != 2) {
+      return MakeTestResultCode(11, 20, 0);
+   }   QCBORDecode_GetInt64(&DCtx, &nInt);
+   QCBORDecode_GetBool(&DCtx, &b);
+   if(b != false) {
+      return MakeTestResultCode(11, 21, 0);
+   }
+   QCBORDecode_EnterArray(&DCtx, &Item);
+   if(!QCBORDecode_IsTagged(&DCtx, &Item, 23)) {
+      return MakeTestResultCode(11, 22, 0);
+   }
+   if(Item.uDataType != QCBOR_TYPE_ARRAY) {
+      return MakeTestResultCode(11, 23, 0);
+   }
+   if(Item.val.uCount != 0) {
+      return MakeTestResultCode(11, 24, 0);
+   }
+   QCBORDecode_ExitArray(&DCtx);
+   QCBORDecode_ExitArray(&DCtx);
+   uErr = CheckOneLetterString(&DCtx, 'n');
+   if(uErr) {
+      return MakeTestResultCode(11, 25, uErr);
+   }
+
+   QCBORDecode_ExitArray(&DCtx);
+   uErr = QCBORDecode_Finish(&DCtx);
+   if(uErr) {
+      return MakeTestResultCode(11, 26, uErr);
+   }
+#endif /* QCBOR_DISABLE_... */
 
    return 0;
 }
 
 
+
+
 /*
  Fully or partially decode pValidMapEncoded. When
  partially decoding check for the right error code.
diff --git a/test/qcbor_encode_tests.c b/test/qcbor_encode_tests.c
index 6cc9d08..1c0902b 100644
--- a/test/qcbor_encode_tests.c
+++ b/test/qcbor_encode_tests.c
@@ -48,7 +48,7 @@
 
  */
 
-//#define PRINT_FUNCTIONS_FOR_DEBUGGING
+#define PRINT_FUNCTIONS_FOR_DEBUGGING
 
 #ifdef  PRINT_FUNCTIONS_FOR_DEBUGGING
 #include <stdio.h>
@@ -639,17 +639,17 @@
    QCBOREncode_OpenMap(pECtx);
    QCBOREncode_AddSZString(pECtx, "s1");
    QCBOREncode_AddTag(pECtx, 88);
-   QCBOREncode_Private_AddSimple(pECtx, 255);
-   QCBOREncode_Private_AddSimpleToMap(pECtx, "s2", 0);
+   QCBOREncode_AddSimple(pECtx, 255);
+   QCBOREncode_AddSimpleToMap(pECtx, "s2", 0);
    QCBOREncode_AddSZString(pECtx, "s3");
    QCBOREncode_AddTag(pECtx, 88);
-   QCBOREncode_Private_AddSimple(pECtx, 33);
+   QCBOREncode_AddSimple(pECtx, 33);
    QCBOREncode_AddInt64(pECtx, 88378374); // label before tag
    QCBOREncode_AddTag(pECtx, 88);
-   QCBOREncode_Private_AddSimple(pECtx, 255);
+   QCBOREncode_AddSimple(pECtx, 255);
    QCBOREncode_AddInt64(pECtx, 89); // label before tag
    QCBOREncode_AddTag(pECtx, 88);
-   QCBOREncode_Private_AddSimple(pECtx, 19);
+   QCBOREncode_AddSimple(pECtx, 19);
    QCBOREncode_CloseMap(pECtx);
 
    /* UUIDs */
@@ -754,14 +754,6 @@
       goto Done;
    }
 
-   QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
-   /* 0x7ff8000000000001ULL is a NaN with a payload. */
-   QCBOREncode_AddDoubleNoPreferred(&ECtx, UsefulBufUtil_CopyUint64ToDouble(0x7ff8000000000001ULL));
-   if(QCBOREncode_Finish(&ECtx, &Enc) != uExpectedErr) {
-      nReturn = -22;
-      goto Done;
-   }
-
 
    /* 0x7ffc000000000000ULL is a NaN with a payload. */
    QCBOREncode_AddDouble(&ECtx, UsefulBufUtil_CopyUint64ToDouble(0x7ff8000000000001ULL));
@@ -777,13 +769,6 @@
       goto Done;
    }
 
-   /* 0x7ff80001UL is a NaN with a payload. */
-   QCBOREncode_AddFloatNoPreferred(&ECtx, UsefulBufUtil_CopyUint32ToFloat(0x7ff80001UL));
-   if(QCBOREncode_Finish(&ECtx, &Enc) != uExpectedErr) {
-      nReturn = -24;
-      goto Done;
-   }
-
    /* 0x7ffc0000UL is a NaN with a payload. */
    QCBOREncode_AddFloat(&ECtx, UsefulBufUtil_CopyUint32ToFloat(0x7ffc0000UL));
    if(QCBOREncode_Finish(&ECtx, &Enc) != uExpectedErr) {
@@ -999,6 +984,7 @@
    return(nReturn);
 }
 
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
 /*
  9F                  # array(5)
    F5               # primitive(21)
@@ -1045,6 +1031,7 @@
 
    return(nReturn);
 }
+#endif
 
 /*
 A5                                      # map(5)
@@ -1711,7 +1698,7 @@
 
       // The result: 0 if scan happened and found nothing; 1 if it happened and
       // found something wrong; 2 if it didn't happen
-      QCBOREncode_Private_AddSimpleToMap(&ECtx, "integrity", uRResult);
+      QCBOREncode_AddSimpleToMap(&ECtx, "integrity", uRResult);
 
       // Add the diagnostic code
       QCBOREncode_AddSZStringToMap(&ECtx, "type", szType);
@@ -2698,7 +2685,7 @@
    /* ------ QCBOR_ERR_UNSUPPORTED -------- */
    QCBOREncode_Init(&EC, Large);
    QCBOREncode_OpenArray(&EC);
-   QCBOREncode_Private_AddSimple(&EC, 24); /* CBOR_SIMPLEV_RESERVED_START */
+   QCBOREncode_AddSimple(&EC, 24); /* CBOR_SIMPLEV_RESERVED_START */
    uErr = QCBOREncode_FinishGetSize(&EC, &xx);
 #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
    if(uErr != QCBOR_ERR_ENCODE_UNSUPPORTED) {
@@ -2713,7 +2700,7 @@
 
    QCBOREncode_Init(&EC, Large);
    QCBOREncode_OpenArray(&EC);
-   QCBOREncode_Private_AddSimple(&EC, 31); /* CBOR_SIMPLEV_RESERVED_END */
+   QCBOREncode_AddSimple(&EC, 31); /* CBOR_SIMPLEV_RESERVED_END */
    uErr = QCBOREncode_FinishGetSize(&EC, &xx);
 #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
    if(uErr != QCBOR_ERR_ENCODE_UNSUPPORTED) {
@@ -3626,7 +3613,6 @@
    uExpectedErr = QCBOR_SUCCESS;
 #endif
 
-
    /* Next, make sure methods that encode non-CDE error out */
    QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
    QCBOREncode_SerializationCDE(&EC);
@@ -3636,21 +3622,6 @@
       return 100;
    }
 
-
-   QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
-   QCBOREncode_SerializationCDE(&EC);
-   QCBOREncode_AddDoubleNoPreferred(&EC, 0);
-   if(QCBOREncode_GetErrorState(&EC) != uExpectedErr) {
-      return 101;
-   }
-
-   QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
-   QCBOREncode_SerializationCDE(&EC);
-   QCBOREncode_AddFloatNoPreferred(&EC, 0);
-   if(QCBOREncode_GetErrorState(&EC) != uExpectedErr) {
-      return 101;
-   }
-
    return 0;
 }
 
diff --git a/test/qcbor_encode_tests.h b/test/qcbor_encode_tests.h
index 7935862..5e2f978 100644
--- a/test/qcbor_encode_tests.h
+++ b/test/qcbor_encode_tests.h
@@ -80,9 +80,8 @@
 
 
 /*
- This tests the QCBOREncode_AddRaw() function by adding two chunks or
- RAWCBOR to an array and comparing with expected values. This is an
- encoding test.
+ This tests the QCBOREncode_AddRaw() function by adding two chunks of
+ raw CBOR to an array and comparing with expected values.
  */
 int32_t EncodeRawTest(void);