merge recent changes in from master
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..9c5b625
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,20 @@
+os:
+  - linux
+
+language: c
+compiler:
+  - gcc
+
+env:
+sudo: false
+addons:
+  apt:
+    packages:
+      - make
+
+install:
+  - make
+
+script:
+  - ./qcbortest
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..8a5bcd0
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 3.10.2)
+project(qcbor
+	DESCRIPTION "QCBOR"
+	LANGUAGES C
+	VERSION 1.0.0)
+
+set(CMAKE_C_FLAGS "-pedantic -Wall -O3 -ffunction-sections")
+
+include_directories(inc)
+
+set(SOURCE
+	src/ieee754.c
+	src/qcbor_decode.c
+	src/qcbor_encode.c
+	src/qcbor_err_to_str.c
+	src/UsefulBuf.c
+) 
+
+add_library(qcbor ${SOURCE})
diff --git a/Makefile b/Makefile
index 805e702..f7e2e8c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,22 +1,27 @@
 # Makefile -- UNIX-style make for qcbor as a lib and command line test
 #
-# Copyright (c) 2018-2020, Laurence Lundblade. All rights reserved.
+# Copyright (c) 2018-2021, Laurence Lundblade. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
 # See BSD-3-Clause license in README.md
 #
 
-CC=cc
-#CC=/usr/local/bin/gcc-9
 
+# The math library is needed for floating-point support. To
+# avoid need for it #define QCBOR_DISABLE_FLOAT_HW_USE
 LIBS=-lm
-CFLAGS=$(CMD_LINE) -I inc -I test -Os -fPIC 
 
-# The following are used before a release of QCBOR help to make sure
-# the code compiles and runs in the most strict environments, but not
-# all compilers support them so they are not turned on.
-#CFLAGS=-I inc -I test -Os -fpic -Wall -pedantic-errors -Wextra -Wshadow -Wparentheses -Wconversion -xc -std=c99
+
+# The QCBOR makefile uses a minimum of compiler flags so that it will
+# work out-of-the-box with a wide variety of compilers.  For example,
+# some compiler error out on some of the warnings flags available with
+# gcc. The $(CMD_LINE) variable allows passing in extra flags. This is
+# used on the stringent build script that is in
+# https://github.com/laurencelundblade/qdv.  This script is used
+# before pushes to master (though not yet through and automated build
+# process)
+CFLAGS=$(CMD_LINE) -I inc -I test -Os -fPIC
 
 
 QCBOR_OBJ=src/UsefulBuf.o src/qcbor_encode.o src/qcbor_decode.o src/ieee754.o src/qcbor_err_to_str.o
@@ -37,6 +42,7 @@
 libqcbor.a: $(QCBOR_OBJ)
 	ar -r $@ $^
 
+
 # The shared library is not made by default because of platform
 # variability For example MacOS and Linux behave differently and some
 # IoT OS's don't support them at all.
diff --git a/QCBOR.xcodeproj/project.pbxproj b/QCBOR.xcodeproj/project.pbxproj
index 783af79..5b3ef68 100644
--- a/QCBOR.xcodeproj/project.pbxproj
+++ b/QCBOR.xcodeproj/project.pbxproj
@@ -164,7 +164,7 @@
 		E743D13124DE05CC0017899F /* QCBOR_Disable_Preferred_Float */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = QCBOR_Disable_Preferred_Float; sourceTree = BUILT_PRODUCTS_DIR; };
 		E743D132251014E60017899F /* Tagging.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = Tagging.md; path = doc/Tagging.md; sourceTree = "<group>"; };
 		E743D13325115A270017899F /* TRY SPIFFY DECODE.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "TRY SPIFFY DECODE.md"; sourceTree = "<group>"; };
-		E74BF411245D6713002CE8E8 /* UsefulBuf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UsefulBuf.h; path = inc/qcbor/UsefulBuf.h; sourceTree = "<group>"; };
+		E74BF411245D6713002CE8E8 /* UsefulBuf.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = UsefulBuf.h; path = inc/qcbor/UsefulBuf.h; sourceTree = "<group>"; tabWidth = 3; };
 		E772022723B52C02006E966E /* QCBOR_Disable_Exp_Mantissa */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = QCBOR_Disable_Exp_Mantissa; sourceTree = BUILT_PRODUCTS_DIR; };
 		E776E07C214ADF7F00E67947 /* QCBOR */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = QCBOR; sourceTree = BUILT_PRODUCTS_DIR; };
 		E776E08C214AE07400E67947 /* qcbor_encode.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = qcbor_encode.c; path = src/qcbor_encode.c; sourceTree = "<group>"; tabWidth = 3; };
diff --git a/README.md b/README.md
index 1f689c8..ecc93df 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # QCBOR
 
-QCBOR is an implementation of nearly everything in
+QCBOR is a powerful, commercial quality implementation of nearly everything in
 [RFC8949](https://tools.ietf.org/html/rfc8949). This RFC defines the
 Concise Binary Object Representation (CBOR). Since RFC 8949 is fully
 compatible with RFC 7049, this is also a near-complete implementation
@@ -227,6 +227,65 @@
 code. Its main use is on CPUs that have no floating-point hardware.
 
 See discussion in qcbor_encode.h for details.
+G
+## Comparison to TinyCBOR
+
+TinyCBOR is a popular widely used implementation. Like QCBOR,
+it is a solid, well-maintained commercial quality implementation. This
+section is for folks trying to understand the difference in
+the approach between QCBOR and TinyCBOR.
+
+TinyCBOR's API is a bit more minimalist and closer to the CBOR
+encoding mechanics than QCBOR's. QCBOR's API is at a somewhat higher
+level of abstraction.
+
+QCBOR really does implement just about everything described in
+RFC 8949. The main part missing is sorting of maps when encoding.
+TinyCBOR implements a smaller part of the standard.
+
+No detailed code size comparison has been made, but in a spot check
+that encodes and decodes a single integer shows QCBOR about 25%
+larger.  QCBOR encoding is actually smaller, but QCBOR decoding is
+larger. This includes the code to call the library, which is about the
+same for both libraries, and the code linked from the libraries. QCBOR
+is a bit more powerful, so you get value for the extra code brought
+in, especially when decoding more complex protocols.
+
+QCBOR tracks encoding and decoding errors internally so the caller
+doesn't have to check the return code of every call to an encode or
+decode function. In many cases the error check is only needed as the
+last step or an encode or decode. TinyCBOR requires an error check on
+each call.
+
+QCBOR provides a substantial feature that allows searching for data
+items in a map by label. It works for integer and text string labels
+(and at some point byte-string labels). This includes detection of
+items with duplicate labels. This makes the code for decoding CBOR
+simpler, similar to the encoding code and easier to read. TinyCBOR
+supports search by string, but no integer, nor duplicate detection.
+
+QCBOR provides explicit support many of the registered CBOR tags. For
+example, QCBOR supports big numbers and decimal fractions including
+their conversion to floats, uint64_t and such.
+
+Generally, QCBOR supports safe conversion of most CBOR number formats
+into number formats supported in C. For example, a data item can be
+fetched and converted to a C uint64_t whether the input CBOR is an
+unsigned 64-bit integer, signed 64-bit integer, floating-point number,
+big number, decimal fraction or a big float. The conversion is
+performed with full proper error detection of overflow and underflow.
+
+QCBOR has a special feature for decoding byte-string wrapped CBOR. It
+treats this similar to entering an array with one item. This is
+particularly use for CBOR protocols like COSE that make use of
+byte-string wrapping.  The implementation of these protocols is
+simpler and uses less memory.
+
+QCBOR's test suite is written in the same portable C that QCBOR is
+where TinyCBOR requires Qt for its test. QCBOR's test suite is
+designed to be able to run on small embedded devices the same as
+QCBOR.
+
 
 ## Code Size
 
@@ -235,7 +294,7 @@
     |               | smallest | largest |  
     |---------------|----------|---------|
     | encode only   |      850 |    2100 |
-    | decode only   |     2000 |   13400 |
+    | decode only   |     2000 |   13300 |
     | combined      |     2850 |   15500 |
     
  From the table above, one can see that the amount of code pulled in
@@ -275,7 +334,7 @@
  carefully written to be defensive.
 
  Disable features with defines like:
-   QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA (saves about 400 bytes) 
+   QCBOR_DISABLE_EXP_AND_MANTISSA (saves about 400 bytes) 
    QCBOR_DISABLE_ENCODE_USAGE_GUARDS (saves about 150), and
    QCBOR_DISABLE_PREFERRED_FLOAT (saves about 900 bytes), and
    QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS (saves about 400 bytes).  
@@ -351,6 +410,7 @@
 * Michael Eckel for Makefile improvements
 * Jan Jongboom for indefinite length encoding
 * Peter Uiterwijk for error strings and other
+* Michael Richarson for CI set up and additional compiler warnings
 
 
 ## Copyright and License
diff --git a/example.c b/example.c
index 5ec3f2f..4921e13 100644
--- a/example.c
+++ b/example.c
@@ -1,7 +1,7 @@
 /* =========================================================================
    example.c -- Example code for QCBOR
 
-   Copyright (c) 2020, Laurence Lundblade. All rights reserved.
+   Copyright (c) 2020-2021, Laurence Lundblade. All rights reserved.
 
    SPDX-License-Identifier: BSD-3-Clause
 
@@ -17,11 +17,20 @@
 #include "qcbor/qcbor_spiffy_decode.h"
 
 
+/**
+ * This is a simple example of encoding and decoding some CBOR from
+ * and to a C structure.
+ *
+ * This also includes a comparison between the original structure
+ * and the one decoded from the CBOR to confirm correctness.
+ */
+
+
 #define MAX_CYLINDERS 16
 
 /**
- The data structure representing a car engine that is encoded and
- decoded in this example.
+ * The data structure representing a car engine that is encoded and
+ * decoded in this example.
  */
 typedef struct
 {
@@ -32,15 +41,15 @@
    int64_t    uNumCylinders;
    bool       bTurboCharged;
    struct {
-      double uMeasuredCompression;
+      double dMeasuredCompression;
    } cylinders[MAX_CYLINDERS];
 } CarEngine;
 
 
 /**
- @brief Initialize the Engine data structure with values to encode/decode.
-
- @param[out] pE   The Engine structure to fill in
+ * @brief Initialize the Engine data structure with values to encode.
+ *
+ * @param[out] pE   The Engine structure to fill in
  */
 void EngineInit(CarEngine *pE)
 {
@@ -51,88 +60,91 @@
    pE->uNumCylinders       = 6;
    pE->bTurboCharged       = false;
 
-   pE->cylinders[0].uMeasuredCompression = 9.0;
-   pE->cylinders[1].uMeasuredCompression = 9.2;
-   pE->cylinders[2].uMeasuredCompression = 8.9;
-   pE->cylinders[3].uMeasuredCompression = 8.9;
-   pE->cylinders[4].uMeasuredCompression = 9.1;
-   pE->cylinders[5].uMeasuredCompression = 9.0;
+   pE->cylinders[0].dMeasuredCompression = 9.0;
+   pE->cylinders[1].dMeasuredCompression = 9.2;
+   pE->cylinders[2].dMeasuredCompression = 8.9;
+   pE->cylinders[3].dMeasuredCompression = 8.9;
+   pE->cylinders[4].dMeasuredCompression = 9.1;
+   pE->cylinders[5].dMeasuredCompression = 9.0;
 }
 
 
 /**
- @brief Compare two Engine structure for equality.
-
- @param[in] pE1  First Engine to compare.
- @param[in] pE2  Second Engine to compare.
-
- @retval Return @c true if the two Engine data structures are exactly the
- same.
+ * @brief Compare two Engine structure for equality.
+ *
+ * @param[in] pE1  First Engine to compare.
+ * @param[in] pE2  Second Engine to compare.
+ *
+ * @retval Return @c true if the two Engine data structures are exactly the
+ *         same.
  */
-bool EngineCompare(CarEngine *pE1, CarEngine *pE2)
+static bool EngineCompare(const CarEngine *pE1, const CarEngine *pE2)
 {
-    if(pE1->uNumCylinders != pE2->uNumCylinders) {
-        return false;
-    }
-    if(pE1->bTurboCharged != pE2->bTurboCharged) {
-        return false;
-    }
-    if(pE1->uDisplacement != pE2->uDisplacement) {
-        return false;
-    }
-    if(pE1->uHorsePower != pE2->uHorsePower) {
-        return false;
-    }
-    if(pE1->dDesignedCompresion != pE2->dDesignedCompresion) {
-        return false;
-    }
-    for(int64_t i = 0; i < pE2->uNumCylinders; i++) {
-        if(pE1->cylinders[i].uMeasuredCompression !=
-           pE2->cylinders[i].uMeasuredCompression) {
-            return false;
-        }
-    }
+   if(pE1->uNumCylinders != pE2->uNumCylinders) {
+      return false;
+   }
+   if(pE1->bTurboCharged != pE2->bTurboCharged) {
+      return false;
+   }
+   if(pE1->uDisplacement != pE2->uDisplacement) {
+      return false;
+   }
+   if(pE1->uHorsePower != pE2->uHorsePower) {
+      return false;
+   }
+   if(pE1->dDesignedCompresion != pE2->dDesignedCompresion) {
+      return false;
+   }
+   for(int64_t i = 0; i < pE2->uNumCylinders; i++) {
+      if(pE1->cylinders[i].dMeasuredCompression !=
+         pE2->cylinders[i].dMeasuredCompression) {
+         return false;
+      }
+   }
 
-    if(UsefulBuf_Compare(pE1->Manufacturer, pE2->Manufacturer)) {
-        return false;
-    }
+   if(UsefulBuf_Compare(pE1->Manufacturer, pE2->Manufacturer)) {
+      return false;
+   }
 
     return true;
 }
 
 
-#ifndef EXAMPLE_DISABLE_DEFINITE_LENGTH_ENCODE
 /**
- @brief Encode an initialized Engine data structure in CBOR.
-
- @param[in] pEngine  The data structure to encode.
- @param[in] Buffer   Pointer and length of buffer to output to.
-
- @return  The pointer and length of the encoded CBOR or
-          @ref NULLUsefulBufC on error.
-
- This is a simple CBOR encoding example. It outputs the Engine data
- structure as a map of label-value pairs as well as an array of
- floating point values.
-
- @c Buffer must be big enough to hold the output. If it is not @ref
- NULLUsefulBufC will be returned. @ref @ref NULLUsefulBufC will be
- returned for any other encoding errors.
-
- This encoding will use definite CBOR lengths. Definite lengths are
- preferred in CBOR. See EncodeEngineIndefinteLen() that encodes using
- indefinite lengths.
+ * @brief Encode an initialized CarEngine data structure in CBOR.
+ *
+ * @param[in] pEngine  The data structure to encode.
+ * @param[in] Buffer   Pointer and length of buffer to output to.
+ *
+ * @return  The pointer and length of the encoded CBOR or
+ *          @ref NULLUsefulBufC on error.
+ *
+ * This encodes the input structure \c pEngine as a CBOR map of
+ * label-value pairs. An array of float is one of the items in the
+ * map.
+ *
+ * This uses the UsefulBuf convention of passing in a non-const empty
+ * buffer to be filled in and returning a filled in const buffer. The
+ * buffer to write into is given as a pointer and length in a
+ * UsefulBuf. The buffer returned with the encoded CBOR is a
+ * UsefulBufC also a pointer and length. In this implementation the
+ * pointer to the returned data is exactly the same as that of the
+ * empty buffer. The returned length will be smaller than or equal to
+ * that of the empty buffer. This gives correct const-ness for the
+ * buffer passed in and the data returned.
+ *
+ * @c Buffer must be big enough to hold the output. If it is not @ref
+ * NULLUsefulBufC will be returned. @ref NULLUsefulBufC will be
+ * returned for any other encoding errors.
  */
 UsefulBufC EncodeEngineDefiniteLength(const CarEngine *pEngine, UsefulBuf Buffer)
 {
-    /* Initialize the encoder with the buffer big enough to hold the
-       expected output.  If it is too small, QCBOREncode_Finish() will
-       return an error. */
+   /* Set up the encoding context with the output buffer */
     QCBOREncodeContext EncodeCtx;
     QCBOREncode_Init(&EncodeCtx, Buffer);
 
     /* Proceed to output all the items, letting the internal error
-     tracking do its work. */
+     * tracking do its work */
     QCBOREncode_OpenMap(&EncodeCtx);
     QCBOREncode_AddTextToMap(&EncodeCtx, "Manufacturer", pEngine->Manufacturer);
     QCBOREncode_AddInt64ToMap(&EncodeCtx, "NumCylinders", pEngine->uNumCylinders);
@@ -141,14 +153,15 @@
     QCBOREncode_AddDoubleToMap(&EncodeCtx, "DesignedCompression", pEngine->dDesignedCompresion);
     QCBOREncode_OpenArrayInMap(&EncodeCtx, "Cylinders");
     for(int64_t i = 0 ; i < pEngine->uNumCylinders; i++) {
-        QCBOREncode_AddDouble(&EncodeCtx, pEngine->cylinders[i].uMeasuredCompression);
+        QCBOREncode_AddDouble(&EncodeCtx,
+                              pEngine->cylinders[i].dMeasuredCompression);
     }
     QCBOREncode_CloseArray(&EncodeCtx);
     QCBOREncode_AddBoolToMap(&EncodeCtx, "Turbo", pEngine->bTurboCharged);
     QCBOREncode_CloseMap(&EncodeCtx);
 
     /* Get the pointer and length of the encoded output. If there was
-       any error it will be returned here. */
+     * any encoding error, it will be returned here */
     UsefulBufC EncodedCBOR;
     QCBORError uErr;
     uErr = QCBOREncode_Finish(&EncodeCtx, &EncodedCBOR);
@@ -158,72 +171,10 @@
        return EncodedCBOR;
     }
 }
-#endif /* EXAMPLE_DISABLE_DEFINITE_LENGTH_ENCODE */
-
-
-
-
-#ifndef EXAMPLE_DISABLE_INDEFINITE_LENGTH_ENCODE_ENCODE
-/**
- @brief Encode an initialized Engine data structure using indefinite lengths.
-
- @param[in] pEngine  The data structure to encode.
- @param[in] Buffer   Pointer and length of buffer to output to.
-
- @return The pointer and length of the encoded CBOR or
-         @ref NULLUsefulBufC on error.
-
- This is virtually the same as EncodeEngineDefiniteLength(). The
- encoded CBOR is slightly different as the map and array use
- indefinite lengths, rather than definite lengths.
-
- A definite length array is encoded as an integer indicating the
- number of items in it. An indefinite length array is encoded as an
- opening byte, the items in it and a "break" byte to end
- it. Indefinite length arrays and maps are easier to encode, but
- harder to decode.
-
- The advantage of this implementation is that the encoding side will
- be a little less object code. (Eventually QCBOR will an ifdef to
- disable definite length encoding and the object code will be even
- smaller).  However, note that the encoding implementation for a
- protocol is just about always much smaller than the decoding
- implementation and that code savings for use of indefinite lengths is
- relatively small.
- */
-UsefulBufC EncodeEngineIndefinteLen(const CarEngine *pEngine, UsefulBuf Buffer)
-{
-    QCBOREncodeContext EncodeCtx;
-
-    QCBOREncode_Init(&EncodeCtx, Buffer);
-    QCBOREncode_OpenMapIndefiniteLength(&EncodeCtx);
-    QCBOREncode_AddTextToMap(&EncodeCtx, "Manufacturer", pEngine->Manufacturer);
-    QCBOREncode_AddInt64ToMap(&EncodeCtx, "Displacement", pEngine->uDisplacement);
-    QCBOREncode_AddInt64ToMap(&EncodeCtx, "Horsepower", pEngine->uHorsePower);
-    QCBOREncode_AddDoubleToMap(&EncodeCtx, "DesignedCompression", pEngine->dDesignedCompresion);
-    QCBOREncode_AddInt64ToMap(&EncodeCtx, "NumCylinders", pEngine->uNumCylinders);
-    QCBOREncode_OpenArrayIndefiniteLengthInMap(&EncodeCtx, "Cylinders");
-    for(int64_t i = 0 ; i < pEngine->uNumCylinders; i++) {
-        QCBOREncode_AddDouble(&EncodeCtx, pEngine->cylinders[i].uMeasuredCompression);
-    }
-    QCBOREncode_CloseArrayIndefiniteLength(&EncodeCtx);
-    QCBOREncode_AddBoolToMap(&EncodeCtx, "Turbo", pEngine->bTurboCharged);
-    QCBOREncode_CloseMapIndefiniteLength(&EncodeCtx);
-
-    UsefulBufC EncodedCBOR;
-    QCBORError uErr;
-    uErr = QCBOREncode_Finish(&EncodeCtx, &EncodedCBOR);
-    if(uErr != QCBOR_SUCCESS) {
-        return NULLUsefulBufC;
-    } else {
-       return EncodedCBOR;
-    }
-}
-#endif /* EXAMPLE_DISABLE_INDEFINITE_LENGTH_ENCODE */
 
 
 /**
- Error results when decoding an Engine data structure.
+ * Error results when decoding an Engine data structure.
  */
 typedef enum  {
     EngineSuccess,
@@ -235,9 +186,9 @@
 
 
 /**
- Convert @ref QCBORError to @ref EngineDecodeErrors.
+ * Convert @ref QCBORError to @ref EngineDecodeErrors.
  */
-EngineDecodeErrors ConvertError(QCBORError uErr)
+static EngineDecodeErrors ConvertError(QCBORError uErr)
 {
     EngineDecodeErrors uReturn;
 
@@ -260,39 +211,40 @@
 }
 
 
-#ifndef EXAMPLE_DISABLE_SPIFFY_DECODE
 /**
- @brief Simplest engine decode using spiffy decode features.
-
- @param[in] EncodedEngine  Pointer and length of CBOR-encoded engine.
- @param[out] pE            The structure filled in from the decoding.
-
- @return The decode error or success.
-
- This decodes the CBOR into the engine structure.
-
- As QCBOR automatically supports both definite and indefinite maps and
- arrays, this will decode either.
-
- This uses QCBOR's spiffy decode, so the implementation is simplest
- and closely parallels the encode implementation in
- EncodeEngineDefiniteLength().
-
- See two other ways to implement decoding in
- DecodeEngineSpiffyFaster() and DecodeEngineBasic().
-
- This version of the decoder has the simplest implementation, but
- pulls in more code from the QCBOR library.  This version uses the
- most CPU cycles because it scans the all the CBOR each time a data
- item is decoded. The CPU cycles used for a data structure as small as
- this is probably insignificant. CPU use for this style of decode is
- probably only a factor on slow CPUs with big CBOR inputs.
+ * @brief Simplest engine decode using spiffy decode features.
+ *
+ * @param[in] EncodedEngine  Pointer and length of CBOR-encoded engine.
+ * @param[out] pE            The structure filled in from the decoding.
+ *
+ * @return The decode error or success.
+ *
+ * This decodes the CBOR into the engine structure.
+ *
+ * As QCBOR automatically supports both definite and indefinite maps
+ * and arrays, this will decode either.
+ *
+ * This uses QCBOR's spiffy decode functions, so the implementation is
+ * simple and closely parallels the encode implementation in
+ * EncodeEngineDefiniteLength().
+ *
+ * Another way to decode without using spiffy decode functions is to
+ * use QCBORDecode_GetNext() to traverse the whole tree.  This
+ * requires a more complex implementation, but is faster and will pull
+ * in less code from the CBOR library. The speed advantage is likely
+ * of consequence when decoding much much larger CBOR on slow small
+ * CPUs.
+ *
+ * A middle way is to use the spiffy decode
+ * QCBORDecode_GetItemsInMap().  The implementation has middle
+ * complexity and uses less CPU.
  */
 EngineDecodeErrors DecodeEngineSpiffy(UsefulBufC EncodedEngine, CarEngine *pE)
 {
-    QCBORError uErr;
+    QCBORError         uErr;
     QCBORDecodeContext DecodeCtx;
 
+    /* Let QCBORDecode internal error tracking do its work. */
     QCBORDecode_Init(&DecodeCtx, EncodedEngine, QCBOR_DECODE_MODE_NORMAL);
     QCBORDecode_EnterMap(&DecodeCtx, NULL);
     QCBORDecode_GetTextStringInMapSZ(&DecodeCtx, "Manufacturer", &(pE->Manufacturer));
@@ -303,9 +255,9 @@
 
     QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "NumCylinders", &(pE->uNumCylinders));
 
-    /* Must check error before referencing pE->uNumCylinders to be
-       sure it is valid. If any of the above errored, it won't be
-       valid. */
+    /* Check the internal tracked error now before going on to
+     * reference any of the decoded data, particularly
+     * pE->uNumCylinders */
     uErr = QCBORDecode_GetError(&DecodeCtx);
     if(uErr != QCBOR_SUCCESS) {
         goto Done;
@@ -317,357 +269,33 @@
 
     QCBORDecode_EnterArrayFromMapSZ(&DecodeCtx, "Cylinders");
     for(int64_t i = 0; i < pE->uNumCylinders; i++) {
-        QCBORDecode_GetDouble(&DecodeCtx, &(pE->cylinders[i].uMeasuredCompression));
+        QCBORDecode_GetDouble(&DecodeCtx,
+                              &(pE->cylinders[i].dMeasuredCompression));
     }
     QCBORDecode_ExitArray(&DecodeCtx);
     QCBORDecode_ExitMap(&DecodeCtx);
 
-    /* Catch the remainder of errors here */
+    /* Catch further decoding error here */
     uErr = QCBORDecode_Finish(&DecodeCtx);
 
 Done:
     return ConvertError(uErr);
 }
 
-#endif /* EXAMPLE_DISABLE_SPIFFY_DECODE */
-
-
-
-#ifndef EXAMPLE_DISABLE_SPIFFY_DECODE_FAST
-/**
- @brief Decode an Engine structure with the faster spiffy decode features.
-
- @param[in] EncodedEngine  Pointer and length of CBOR-encoded engine.
- @param[out] pE            The structure filled in from the decoding.
-
- @return The decode error or success.
-
- This decodes the same as DecodeEngineSpiffy(), but uses different
- spiffy decode features.
-
- This version uses QCBORDecode_GetItemsInMap() which uses less CPU
- cycles because all the items except the array are pulled out of the
- map in one pass, rather than having to decode the whole map for each
- decoded item. This also pulls in less object code from the QCBOR
- library.
-
- See also DecodeEngineAdvanced() and DecodeEngineBasic().
-*/
-EngineDecodeErrors DecodeEngineSpiffyFaster(UsefulBufC EncodedEngine, CarEngine *pE)
-{
-    QCBORError uErr;
-    QCBORDecodeContext DecodeCtx;
-
-    QCBORDecode_Init(&DecodeCtx, EncodedEngine, QCBOR_DECODE_MODE_NORMAL);
-    QCBORDecode_EnterMap(&DecodeCtx, NULL);
-
-    QCBORItem EngineItems[7];
-    EngineItems[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
-    EngineItems[0].label.string = UsefulBuf_FROM_SZ_LITERAL("Manufacturer");
-    EngineItems[0].uDataType = QCBOR_TYPE_TEXT_STRING;
-
-    EngineItems[1].uLabelType = QCBOR_TYPE_TEXT_STRING;
-    EngineItems[1].label.string = UsefulBuf_FROM_SZ_LITERAL("Displacement");
-    EngineItems[1].uDataType = QCBOR_TYPE_INT64;
-
-    EngineItems[2].uLabelType = QCBOR_TYPE_TEXT_STRING;
-    EngineItems[2].label.string = UsefulBuf_FROM_SZ_LITERAL("Horsepower");
-    EngineItems[2].uDataType = QCBOR_TYPE_INT64;
-
-    EngineItems[3].uLabelType = QCBOR_TYPE_TEXT_STRING;
-    EngineItems[3].label.string = UsefulBuf_FROM_SZ_LITERAL("DesignedCompression");
-    EngineItems[3].uDataType = QCBOR_TYPE_DOUBLE;
-
-    EngineItems[4].uLabelType = QCBOR_TYPE_TEXT_STRING;
-    EngineItems[4].label.string = UsefulBuf_FROM_SZ_LITERAL("Turbo");
-    EngineItems[4].uDataType = QCBOR_TYPE_ANY;
-
-    EngineItems[5].uLabelType = QCBOR_TYPE_TEXT_STRING;
-    EngineItems[5].label.string = UsefulBuf_FROM_SZ_LITERAL("NumCylinders");
-    EngineItems[5].uDataType = QCBOR_TYPE_INT64;
-
-    EngineItems[6].uLabelType = QCBOR_TYPE_NONE;
-
-    QCBORDecode_GetItemsInMap(&DecodeCtx, EngineItems);
-    uErr = QCBORDecode_GetError(&DecodeCtx);
-    if(uErr != QCBOR_SUCCESS) {
-        goto Done;
-    }
-
-    pE->Manufacturer = EngineItems[0].val.string;
-    pE->uDisplacement = EngineItems[1].val.int64;
-    pE->uHorsePower = EngineItems[2].val.int64;
-    pE->dDesignedCompresion = EngineItems[3].val.dfnum;
-    pE->uNumCylinders = EngineItems[5].val.int64;
-
-    if(EngineItems[4].uDataType == QCBOR_TYPE_TRUE) {
-        pE->bTurboCharged = true;
-    } else if(EngineItems[4].uDataType == QCBOR_TYPE_FALSE) {
-        pE->bTurboCharged = false;
-    } else {
-        return EngineProtocolerror;
-    }
-
-
-    /* Must check error before referencing pE->uNumCylinders to be
-       sure it is valid. If any of the above errored, it won't be
-       valid. */
-    uErr = QCBORDecode_GetError(&DecodeCtx);
-    if(uErr != QCBOR_SUCCESS) {
-        goto Done;
-    }
-
-    if(pE->uNumCylinders > MAX_CYLINDERS) {
-        return TooManyCylinders;
-    }
-
-    QCBORDecode_EnterArrayFromMapSZ(&DecodeCtx, "Cylinders");
-    for(int64_t i = 0; i < pE->uNumCylinders; i++) {
-        QCBORDecode_GetDouble(&DecodeCtx, &(pE->cylinders[i].uMeasuredCompression));
-    }
-    QCBORDecode_ExitArray(&DecodeCtx);
-    QCBORDecode_ExitMap(&DecodeCtx);
-
-    /* Catch the remainder of errors here */
-    uErr = QCBORDecode_Finish(&DecodeCtx);
-
-Done:
-    return ConvertError(uErr);
-}
-
-#endif /* EXAMPLE_DISABLE_SPIFFY_DECODE_FAST */
-
-
-#ifndef EXAMPLE_DISABLE_BASIC_DECODE
-/**
- @brief Check the type and lable of an item.
-
- @param[in] szLabel     The expected string label.
- @param[in] uQCBORType  The expected type or @c QCBOR_TYPE_ANY.
- @param[in] pItem       The item to check.
-
- @retval QCBOR_ERR_LABEL_NOT_FOUND  The label doesn't match.
- @retval QCBOR_ERR_UNEXPECTED_TYPE  The label matches, but the type is
-                                    not as expected.
- @retval QCBOR_SUCCESS              Both label and type match.
- */
-QCBORError CheckLabelAndType(const char *szLabel, uint8_t uQCBORType, const QCBORItem *pItem)
-{
-    if(pItem->uLabelType != QCBOR_TYPE_TEXT_STRING) {
-        return QCBOR_ERR_LABEL_NOT_FOUND;
-    }
-
-    UsefulBufC Label = UsefulBuf_FromSZ(szLabel);
-
-    if(UsefulBuf_Compare(Label, pItem->label.string)) {
-        return QCBOR_ERR_LABEL_NOT_FOUND;
-    }
-
-    if(pItem->uDataType != uQCBORType && uQCBORType != QCBOR_TYPE_ANY) {
-        return QCBOR_ERR_UNEXPECTED_TYPE;
-    }
-
-    return QCBOR_SUCCESS;
-}
-
-
-/**
- @brief Decode the array of engine cylinders.
-
- @param[in] pDecodeCtx  The decode context from which to get items.
- @param[out] pE         The structure filled in from the decoding.
- @param[in] pItem       The data item that is the start of the array.
-
- @return Either @ref EngineSuccess or an error.
-
- This always consumes the whole array. If it has the wrong number of
- items in it, an error is returned.
- */
-EngineDecodeErrors DecodeCylinders(QCBORDecodeContext *pDecodeCtx,
-                                   CarEngine          *pE,
-                                   const QCBORItem    *pItem)
-{
-    int i = 0;
-    QCBORItem Item;
-
-    /* Loop getting all the items in the array. This uses nesting
-       level to detect the end so it works for both definite and
-       indefinite length arrays. */
-    do {
-        QCBORError uErr;
-
-        uErr = QCBORDecode_GetNext(pDecodeCtx, &Item);
-        if(uErr != QCBOR_SUCCESS) {
-            return CBORNotWellFormed;
-        }
-        if(Item.uDataType != QCBOR_TYPE_DOUBLE) {
-            return CBORNotWellFormed;
-        }
-
-        if(i < MAX_CYLINDERS) {
-            pE->cylinders[i].uMeasuredCompression = Item.val.dfnum;
-            i++;
-        }
-
-    } while (Item.uNextNestLevel == pItem->uNextNestLevel);
-
-    if(i != pE->uNumCylinders) {
-        return WrongNumberOfCylinders;
-    } else {
-        return EngineSuccess;
-    }
-}
-
-
-/**
- @brief Engine decode without spiffy decode.
-
- @param[in] EncodedEngine  Pointer and length of CBOR-encoded engine.
- @param[out] pE            The structure filled in from the decoding.
-
- @return The decode error or success.
-
- This is the third implementation of engine decoding, again
- implementing the same functionality as DecodeEngineSpiffy() and
- DecodeEngineSpiffyFaster().
-
- This version of the deocde is the most complex, but uses
- significantly less code (2-3KB less on 64-bit Intel) from the QCBOR
- library.  It is also the most CPU-efficient since it does only one
- pass through the CBOR.
-*/
-EngineDecodeErrors DecodeEngineBasic(UsefulBufC EncodedEngine, CarEngine *pE)
-{
-    QCBORDecodeContext DecodeCtx;
-
-    QCBORDecode_Init(&DecodeCtx, EncodedEngine, QCBOR_DECODE_MODE_NORMAL);
-
-    QCBORItem Item;
-    QCBORError uErr;
-    EngineDecodeErrors uReturn;
-
-
-    uErr = QCBORDecode_GetNext(&DecodeCtx, &Item);
-    if(uErr != QCBOR_SUCCESS) {
-        uReturn = CBORNotWellFormed;
-        goto Done;
-    }
-    if(Item.uDataType != QCBOR_TYPE_MAP) {
-        uReturn = CBORNotWellFormed;
-        goto Done;
-    }
-
-    while(1) {
-        uErr = QCBORDecode_GetNext(&DecodeCtx, &Item);
-        if(uErr != QCBOR_SUCCESS) {
-            if(uErr == QCBOR_ERR_NO_MORE_ITEMS) {
-                break; /* Non-error exit from the loop */
-            } else {
-                uReturn = CBORNotWellFormed;
-                goto Done;
-            }
-        }
-
-        uErr = CheckLabelAndType("Manufacturer", QCBOR_TYPE_TEXT_STRING, &Item);
-        if(uErr == QCBOR_SUCCESS) {
-            pE->Manufacturer = Item.val.string;
-            continue;
-        } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){
-            /* Maunfacturer field missing or badly formed */
-            return EngineProtocolerror;
-        } /* continue on and try for another match */
-
-        uErr = CheckLabelAndType("NumCylinders", QCBOR_TYPE_INT64, &Item);
-        if(uErr == QCBOR_SUCCESS) {
-            if(Item.val.int64 > MAX_CYLINDERS) {
-                return TooManyCylinders;
-            } else {
-                pE->uNumCylinders = (uint8_t)Item.val.int64;
-                continue;
-            }
-        } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){
-            /* NumCylinders field missing or badly formed */
-            return EngineProtocolerror;
-        } /* continue on and try for another match */
-
-        uErr = CheckLabelAndType("Cylinders", QCBOR_TYPE_ARRAY, &Item);
-        if(uErr == QCBOR_SUCCESS) {
-            DecodeCylinders(&DecodeCtx, pE, &Item);
-            continue;
-        } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){
-            return EngineProtocolerror;
-        }
-
-        uErr = CheckLabelAndType("Displacement", QCBOR_TYPE_INT64, &Item);
-        if(uErr == QCBOR_SUCCESS) {
-            pE->uDisplacement = Item.val.int64;
-            continue;
-        } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){
-            return EngineProtocolerror;
-        }
-
-        uErr = CheckLabelAndType("Horsepower", QCBOR_TYPE_INT64, &Item);
-        if(uErr == QCBOR_SUCCESS) {
-            pE->uHorsePower = Item.val.int64;
-            continue;
-        } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){
-            return EngineProtocolerror;
-        }
-
-        uErr = CheckLabelAndType("DesignedCompression", QCBOR_TYPE_DOUBLE, &Item);
-        if(uErr == QCBOR_SUCCESS) {
-            pE->dDesignedCompresion = Item.val.dfnum;
-            continue;
-        } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){
-            return EngineProtocolerror;
-        }
-
-        uErr = CheckLabelAndType("Turbo", QCBOR_TYPE_ANY, &Item);
-        if(uErr == QCBOR_SUCCESS) {
-            if(Item.uDataType == QCBOR_TYPE_TRUE) {
-                pE->bTurboCharged = true;
-            } else if(Item.uDataType == QCBOR_TYPE_FALSE) {
-                pE->bTurboCharged = false;
-            } else {
-                return EngineProtocolerror;
-            }
-            continue;
-        } else if(uErr != QCBOR_ERR_LABEL_NOT_FOUND){
-            return EngineProtocolerror;
-        }
-
-        /* Some label data item that is not known (could just ignore
-           extras data items) */
-        return EngineProtocolerror;
-    }
-    uReturn = EngineSuccess;
-
-    /* Catch the remainder of errors here */
-    uErr = QCBORDecode_Finish(&DecodeCtx);
-    if(uErr) {
-        uReturn = ConvertError(uErr);
-    }
-
-
-
-Done:
-    return uReturn;
-}
-
-#endif /* EXAMPLE_DISABLE_BASIC_DECODE */
-
 
 int32_t RunQCborExample()
 {
-   CarEngine                 E, DecodedEngine;
+   CarEngine                 InitialEngine;
+   CarEngine                 DecodedEngine;
 
    /* For every buffer used by QCBOR a pointer and a length are always
     * carried in a UsefulBuf. This is a secure coding and hygene
-    * practice to help make sure code never runs off the end of a buffer.
+    * practice to help make sure code never runs off the end of a
+    * buffer.
     *
     * UsefulBuf structures are passed as a stack parameter to make the
-    * code prettier. The object code generated isn't much different from
-    * passing a pointer parameter and a length parameter.
+    * code prettier. The object code generated isn't much different
+    * from passing a pointer parameter and a length parameter.
     *
     * This macro is equivalent to:
     *    uint8_t    __pBufEngineBuffer[300];
@@ -680,53 +308,33 @@
     * and is used to represent a buffer that has been written to.
     */
    UsefulBufC                EncodedEngine;
-
-   UsefulBuf_MAKE_STACK_UB(  InDefEngineBuffer, 300);
-   UsefulBufC                InDefEncodedEngine;
-
    EngineDecodeErrors        uErr;
 
-   EngineInit(&E);
+   /* Initialize the structure with some values. */
+   EngineInit(&InitialEngine);
 
-#ifndef EXAMPLE_DISABLE_DEFINITE_LENGTH_ENCODE
-   EncodedEngine = EncodeEngineDefiniteLength(&E, EngineBuffer);
-   printf("Definite Length Engine Encoded in %zu bytes\n", EncodedEngine.len);
-#endif /* EXAMPLE_DISABLE_DEFINITE_LENGTH_ENCODE */
+   /* Encode the engine structure. */
+   EncodedEngine = EncodeEngineDefiniteLength(&InitialEngine, EngineBuffer);
+   if(UsefulBuf_IsNULLC(EncodedEngine)) {
+      printf("Engine encode failed\n");
+      goto Done;
+   }
+   printf("Example: Definite Length Engine Encoded in %zu bytes\n",
+          EncodedEngine.len);
 
-
-#ifndef EXAMPLE_DISABLE_INDEFINITE_LENGTH_ENCODE_ENCODE
-   InDefEncodedEngine = EncodeEngineIndefinteLen(&E, InDefEngineBuffer);
-   printf("Indef Engine Encoded in %zu bytes\n", InDefEncodedEngine.len);
-#endif /* EXAMPLE_DISABLE_INDEFINITE_LENGTH_ENCODE_ENCODE */
-
-
-#ifndef EXAMPLE_DISABLE_SPIFFY_DECODE
+   /* Decode the CBOR */
    uErr = DecodeEngineSpiffy(EncodedEngine, &DecodedEngine);
-   printf("Spiffy Engine Decode Result: %d\n", uErr);
-
-   if(!EngineCompare(&E, &DecodedEngine)) {
-      printf("Spiffy Engine Decode comparison fail\n");
+   printf("Example: Spiffy Engine Decode Result: %d\n", uErr);
+   if(uErr) {
+      goto Done;
    }
-#endif /* EXAMPLE_DISABLE_SPIFFY_DECODE */
 
-#ifndef EXAMPLE_DISABLE_SPIFFY_DECODE_FAST
-   uErr = DecodeEngineSpiffyFaster(EncodedEngine, &DecodedEngine);
-   printf("Faster Spiffy Engine Decode Result: %d\n", uErr);
-
-   if(!EngineCompare(&E, &DecodedEngine)) {
-      printf("Faster Spiffy Engine Decode comparison fail\n");
+   /* Check the results */
+   if(!EngineCompare(&InitialEngine, &DecodedEngine)) {
+      printf("Example: Spiffy Engine Decode comparison fail\n");
    }
-#endif /* EXAMPLE_DISABLE_SPIFFY_DECODE_FAST */
 
-#ifndef EXAMPLE_DISABLE_BASIC_DECODE
-   uErr = DecodeEngineBasic(EncodedEngine, &DecodedEngine);
-   printf("Engine Basic Decode Result: %d\n", uErr);
-
-   if(!EngineCompare(&E, &DecodedEngine)) {
-      printf("Engine Basic Decode comparison fail\n");
-   }
-#endif /* EXAMPLE_DISABLE_BASIC_DECODE */
-
+Done:
    printf("\n");
 
    return 0;
diff --git a/inc/qcbor/UsefulBuf.h b/inc/qcbor/UsefulBuf.h
index 6792e49..31a2868 100644
--- a/inc/qcbor/UsefulBuf.h
+++ b/inc/qcbor/UsefulBuf.h
@@ -41,7 +41,9 @@
 
  when         who             what, where, why
  --------     ----            --------------------------------------------------
- 1/25/2021    llundblade      Improve comments and comment formatting.
+ 5/11/2021    llundblade      Improve comments and comment formatting.
+ 3/6/2021     mcr/llundblade  Fix warnings related to --Wcast-qual
+ 2/17/2021    llundblade      Add method to go from a pointer to an offset.
  1/25/2020    llundblade      Add some casts so static anlyzers don't complain.
  5/21/2019    llundblade      #define configs for efficient endianness handling.
  5/16/2019    llundblade      Add UsefulOutBuf_IsBufferNULL().
@@ -214,9 +216,15 @@
  * that has been filled in. The length is amount of valid data pointed
  * to.
  *
- * A common use is to pass a @ref UsefulBuf to a function, the
- * function fills it in, the function returns a @ref UsefulBufC. The
- * pointer is the same in both.
+ * A commn use mode is to pass a @ref UsefulBuf to a function, the
+ * function puts some data in it, then the function returns a @ref
+ * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
+ * "in" parameter and the @ref UsefulBufC is a const "out" parameter
+ * so the constness stays correct. There is no single "in,out"
+ * parameter (if there was, it would have to be non-const).  Note that
+ * the pointer returned in the @ref UsefulBufC usually ends up being
+ * the same pointer passed in as a @ref UsefulBuf, though this is not
+ * striclty required.
  *
  * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
  * @c NULL.
@@ -364,6 +372,15 @@
  * @param[in] UBC The @ref UsefulBuf to convert.
  *
  * @return A non-const @ref UsefulBuf struct.
+ *
+ * TODO: REWRITE THIS
+ * It is better to avoid use of this. The intended convention for
+ * UsefulBuf is to make an empty buffer, some memory, as a UsefulBuf,
+ * fill it in, and then make it a UsefulBufC. In that convension this
+ * function is not needed.
+ *
+ * This is an explicit way to quiet compiler warnings from
+ * -Wcast-qual.
  */
 static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
 
@@ -582,7 +599,18 @@
 size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
 
 
-#if 1 // NOT_DEPRECATED
+/**
+ @brief Convert a pointer to an offset with bounds checking.
+
+ @param[in] UB  Pointer to the UsefulInputBuf.
+ @param[in] p   Pointer to convert to offset.
+
+ @return SIZE_MAX if @c p is out of range, the byte offset if not.
+*/
+static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
+
+
+#ifndef USEFULBUF_DISABLE_DEPRECATED
 /** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
 #define SZLiteralToUsefulBufC(szString) \
     ((UsefulBufC) {(szString), sizeof(szString)-1})
@@ -599,9 +627,13 @@
 /** Deprecated function; use UsefulBuf_Unconst() instead */
 static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
 {
+   // See UsefulBuf_Unconst() implementation for comment on pragmas
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
     return (UsefulBuf){(void *)UBC.ptr, UBC.len};
+#pragma GCC diagnostic pop
 }
-#endif
+#endif /* USEFULBUF_DISABLE_DEPRECATED */
 
 
 
@@ -1325,6 +1357,18 @@
 static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
 
 
+
+/**
+ * @brief Convert a pointer to an offset with bounds checking.
+ *
+ * @param[in] pUInBuf  Pointer to the UsefulInputBuf.
+ * @param[in] p        Pointer to convert to offset.
+ *
+ * @return SIZE_MAX if @c p is out of range, the byte offset if not.
+ * TODO: details for this?
+*/
+static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
+
 /**
  * @brief Get pointer to bytes out of the input buffer.
  *
@@ -1575,10 +1619,15 @@
    return (UsefulBufC){UB.ptr, UB.len};
 }
 
-
 static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
 {
+   /* -Wcast-qual is a good warning flag to use in general. This is
+    * the one place in UsefulBuf where it needs to be quieted. Since
+    * clang supports GCC pragmas, this works for clang too. */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
    return (UsefulBuf){(void *)UBC.ptr, UBC.len};
+#pragma GCC diagnostic pop
 }
 
 
@@ -1625,13 +1674,35 @@
    } else if(UB.ptr == NULL) {
       ReturnValue = (UsefulBufC){NULL, UB.len - uAmount};
    } else {
-      ReturnValue = (UsefulBufC){(uint8_t *)UB.ptr + uAmount, UB.len - uAmount};
+      ReturnValue = (UsefulBufC){(const uint8_t *)UB.ptr + uAmount, UB.len - uAmount};
    }
 
    return ReturnValue;
 }
 
 
+static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
+{
+   if(UB.ptr == NULL) {
+      return SIZE_MAX;
+   }
+
+   if(p < UB.ptr) {
+      /* given pointer is before start of buffer */
+      return SIZE_MAX;
+   }
+
+   // Cast to size_t (from ptrdiff_t) is OK because of check above
+   const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
+
+    if(uOffset >= UB.len) {
+      /* given pointer is off the end of the buffer */
+      return SIZE_MAX;
+   }
+
+   return uOffset;
+}
+
 
 static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
 {
@@ -2005,6 +2076,12 @@
 }
 
 
+static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
+{
+   return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
+}
+
+
 static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
 {
    const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
@@ -2025,7 +2102,7 @@
     * needed to be completely explicit about types (for static
     * analyzers).
     */
-   return (uint8_t)(pResult ? *(uint8_t *)pResult : 0);
+   return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
 }
 
 static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
diff --git a/inc/qcbor/qcbor_common.h b/inc/qcbor/qcbor_common.h
index 853de87..6883e1b 100644
--- a/inc/qcbor/qcbor_common.h
+++ b/inc/qcbor/qcbor_common.h
@@ -49,6 +49,14 @@
 #define QCBOR_SPIFFY_DECODE
 
 
+/* It was originally defined as QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA,
+ * but this is incosistent with all the other QCBOR_DISABLE_
+ * #defines, so the name was changed and this was added for backwards
+ * compatibility
+ */
+#ifdef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#define QCBOR_DISABLE_EXP_AND_MANTISSA
+#endif
 
 
 /* Standard CBOR Major type for positive integers of various lengths */
@@ -435,7 +443,7 @@
 
    /** All well-formed data items have been consumed and there are no
        more. If parsing a CBOR stream this indicates the non-error end
-       of the stream. If parsing a CBOR stream / sequence, this
+       of the stream. If not parsing a CBOR stream / sequence, this
        probably indicates that some data items expected are not
        present.  See also @ref QCBOR_ERR_HIT_END. */
    QCBOR_ERR_NO_MORE_ITEMS = 33,
diff --git a/inc/qcbor/qcbor_decode.h b/inc/qcbor/qcbor_decode.h
index 960e810..94126bd 100644
--- a/inc/qcbor/qcbor_decode.h
+++ b/inc/qcbor/qcbor_decode.h
@@ -1,6 +1,6 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2020, Laurence Lundblade.
+ Copyright (c) 2018-2021, Laurence Lundblade.
  All rights reserved.
 
  Redistribution and use in source and binary forms, with or without
@@ -318,7 +318,7 @@
       UsefulBufC  bigNum;
       /** The integer value for unknown simple types. */
       uint8_t     uSimple;
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
       /** @anchor expAndMantissa
 
           The value for bigfloats and decimal fractions.  The use of the
@@ -348,7 +348,7 @@
             UsefulBufC bigNum;
          } Mantissa;
       } expAndMantissa;
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
       uint64_t    uTagV;  // Used internally during decoding
 
    } val;
@@ -866,6 +866,21 @@
 
 
 /**
+ @brief QCBORDecode_GetNext() and consume entire map or array.
+
+ @param[in]  pCtx          The decoder context.
+ @param[out] pDecodedItem  Holds the CBOR item just decoded.
+
+ This is the same as QCBORDecode_VGetNext() but the contents of the
+ entire map or array will be consumed if the next item is a map or array.
+
+ In order to go back to decode the contents of a map or array consumed
+ by this, the decoder must be rewound using QCBORDecode_Rewind().
+*/
+void QCBORDecode_VGetNextConsume(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
+
+
+/**
  @brief Get the next data item without consuming it.
 
  @param[in]  pCtx          The decoder context.
@@ -881,12 +896,13 @@
 
  This is useful for looking ahead to determine the type
  of a data item to know which type-specific spiffy decode
- function to call. 
+ function to call.
  */
 QCBORError
 QCBORDecode_PeekNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
 
 
+
 /**
  @brief Gets the next item including full list of tags for item.
 
@@ -1031,10 +1047,39 @@
  input was well-formed and there are extra bytes at the end @ref
  QCBOR_ERR_EXTRA_BYTES will be returned.  This can be considered a
  successful decode.
+
+ See also QCBORDecode_PartialFinish().
  */
 QCBORError QCBORDecode_Finish(QCBORDecodeContext *pCtx);
 
 
+/**
+ @brief Return number of bytes consumed so far.
+
+ @param[in]  pCtx        The context to check.
+ @param[out] puConsumed  The number of bytes consumed so far. May be @c NULL.
+
+ @returns The same as QCBORDecode_Finish();
+
+ This is primarily for partially decoding CBOR sequences. It is the
+ same as QCBORDecode_Finish() except it returns the number of bytes
+ consumed and doesn't call the destructor for the string allocator
+ (See @ref and QCBORDecode_SetMemPool()).
+
+ When this is called before all input bytes are consumed, @ref
+ QCBOR_ERR_EXTRA_BYTES will be returned as QCBORDecode_Finish()
+ does. For typical use of this, that particular error is disregarded.
+
+ Decoding with the same @ref QCBORDecodeContext can continue after
+ calling this and this may be called many times.
+
+ Another way to resume decoding is to call QCBORDecode_Init() on the
+ bytes not decoded, but this only works on CBOR sequences when the
+ decoding stopped with no open arrays, maps or byte strings.
+ */
+QCBORError
+QCBORDecode_PartialFinish(QCBORDecodeContext *pCtx, size_t *puConsumed);
+
 
 /**
  @brief Get the decoding error.
@@ -1236,12 +1281,12 @@
 
 static inline QCBORError QCBORDecode_GetError(QCBORDecodeContext *pMe)
 {
-    return pMe->uLastError;
+    return (QCBORError)pMe->uLastError;
 }
 
 static inline QCBORError QCBORDecode_GetAndResetError(QCBORDecodeContext *pMe)
 {
-    const QCBORError uReturn = pMe->uLastError;
+    const QCBORError uReturn = (QCBORError)pMe->uLastError;
     pMe->uLastError = QCBOR_SUCCESS;
     return uReturn;
 }
diff --git a/inc/qcbor/qcbor_encode.h b/inc/qcbor/qcbor_encode.h
index 2460897..ba654ee 100644
--- a/inc/qcbor/qcbor_encode.h
+++ b/inc/qcbor/qcbor_encode.h
@@ -1,6 +1,6 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2020, Laurence Lundblade.
+ Copyright (c) 2018-2021, Laurence Lundblade.
  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -920,7 +920,7 @@
                                                 UsefulBufC          Bytes);
 
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
 /**
  @brief Add a decimal fraction to the encoded output.
 
@@ -1162,7 +1162,7 @@
                                                 UsefulBufC          Mantissa,
                                                 bool                bIsNegative,
                                                 int64_t             nBase2Exponent);
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
 
 
 /**
@@ -1722,6 +1722,8 @@
  @param[out] pEncodedCBOR  Structure in which the pointer and length of the encoded
                            CBOR is returned.
 
+ @retval QCBOR_SUCCESS                     Encoded CBOR is returned.
+
  @retval QCBOR_ERR_TOO_MANY_CLOSES         Nesting error
 
  @retval QCBOR_ERR_CLOSE_MISMATCH          Nesting error
@@ -2390,7 +2392,7 @@
 
 
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
 
 static inline void
 QCBOREncode_AddTDecimalFraction(QCBOREncodeContext *pMe,
@@ -2683,7 +2685,7 @@
 {
    QCBOREncode_AddTBigFloatBigNumToMapN(pMe, nLabel, QCBOR_ENCODE_AS_TAG, Mantissa, bIsNegative, nBase2Exponent);
 }
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
 
 
 static inline void
diff --git a/inc/qcbor/qcbor_private.h b/inc/qcbor/qcbor_private.h
index 5ddc16f..abd6ba2 100644
--- a/inc/qcbor/qcbor_private.h
+++ b/inc/qcbor/qcbor_private.h
@@ -152,11 +152,11 @@
        QCBOR_TYPE_MAP or QCBOR_TYPE_ARRAY or QCBOR_TYPE_MAP_AS_ARRAY
        for 2).
 
-       Item tracking is either be for definite or indefinite length
+       Item tracking is either for definite or indefinite-length
        maps/arrays. For definite lengths, the total count and items
-       unconsumed are tracked. For indefinite length, uTotalCount is
+       unconsumed are tracked. For indefinite-length, uTotalCount is
        QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH (UINT16_MAX) and there
-       is no per-item count of members. For indefinite length maps and
+       is no per-item count of members. For indefinite-length maps and
        arrays, uCountCursor is UINT16_MAX if not consumed and zero if
        it is consumed in the pre-order traversal. Additionally, if
        entered in bounded mode, uCountCursor is
@@ -185,9 +185,12 @@
             uint32_t uStartOffset;
          } ma; /* for maps and arrays */
          struct {
-            uint32_t uEndOfBstr;
-            uint32_t uPreviousEndOffset;
-         } bs; /* for top-level sequence and bstr wrapped CBOR */
+            /* The end of the input before the bstr was entered so that
+             * it can be restored when the bstr is exited. */
+            uint32_t uSavedEndOffset;
+            /* The beginning of the bstr so that it can be rewound. */
+            uint32_t uBstrStartOffset;
+         } bs; /* for top-level sequence and bstr-wrapped CBOR */
       } u;
    } pLevels[QCBOR_MAX_ARRAY_NESTING1+1],
     *pCurrent,
diff --git a/inc/qcbor/qcbor_spiffy_decode.h b/inc/qcbor/qcbor_spiffy_decode.h
index 0ea6a71..3e69221 100644
--- a/inc/qcbor/qcbor_spiffy_decode.h
+++ b/inc/qcbor/qcbor_spiffy_decode.h
@@ -1,7 +1,7 @@
 /*============================================================================
   qcbor_spiffy_decode.h -- higher-level easier-to-use CBOR decoding.
 
-  Copyright (c) 2020, Laurence Lundblade. All rights reserved.
+  Copyright (c) 2020-2021, Laurence Lundblade. All rights reserved.
 
   SPDX-License-Identifier: BSD-3-Clause
 
@@ -32,7 +32,7 @@
 
  This section just discusses spiff decoding assuming familiarity with
  the general description of this encoder / decoder in section
- @ref Overview and @ref BasicDecoding.
+ @ref Overview and @ref BasicDecode.
 
  Spiffy decode is extra decode features over and above the @ref
  BasicDecode features that generally are easier to use, mirror the
@@ -102,23 +102,34 @@
 
  An easy and clean way to use this decoder is to always use EnterMap
  and EnterArray for each array or map. They will error if the input
- CBOR is not the expected array or map.  Then use GetInt, GetString to
- get the individual items of of the maps and arrays making use of the
- internal error tracking provided by this decoder. The only error
- check needed is the call to Finish.
+ CBOR is not the expected array or map.  Then use GetInt, GetString
+ and such to get the individual items of the maps and arrays making
+ use of the internal error tracking provided by this decoder. The only
+ error check needed is the call to QCBORDecode_Finish().
 
  QCBORDecode_GetNext() is the exception to this. It returns an
  error. It doesn't set the internal error state. It will attempt to
- decode evening when in the error state.
+ decode even when in the error state.
 
- When getting an item by label from a map the whole map is traversed
- including traversal of nested arrays and maps. If there is any
- unrecoverable error anywhere in the that traversal the retrieval by
- label will fail and the unrecoverable error will be returned even if
- it is not due to the labeled item being sought. Recoverable errors
- will be ignored unless they are on the item being sought, in which
- case the unrecoverable error will be returned. Unrecoverable errors
- are those indicated by QCBORDecode_IsUnrecoverableError().
+ The effect of a decoding error on the traversal cursor position
+ varies by the type of decoding method called. The methods for getting
+ an item in a map by label don't affect the traversal cursor when
+ there is an error (nor when they succeed).
+ QCBORDecode_GetInt64InMapN() is an example of this. The other methods
+ like QCBORDecode_GetInt64() and QCBORDecode_GetNext() that normally
+ advance the traversal cursor will also advance it also when there is
+ an error unless the error is unrecoverable due to CBOR that is not
+ well formed or such. QCBORDecode_Rewind() can be used to reset the
+ cursor position after any error.
+
+ When getting an item by label from a map the whole map is internally
+ traversed including traversal of nested arrays and maps. If there is
+ any unrecoverable error anywhere in the that traversal the retrieval
+ by label will fail and the unrecoverable error will be returned even
+ if it is not because item being sought is in error. Recoverable
+ errors will be ignored unless they are on the item being sought, in
+ which case the unrecoverable error will be returned. Unrecoverable
+ errors are those indicated by QCBORDecode_IsUnrecoverableError().
 
  @anchor Tag-Usage
  ## Tag Usage
@@ -151,7 +162,7 @@
  example, to decode an epoch date tag the content must be an integer
  or floating-point value.
 
- If the parameter indicates it should not be a tag 
+ If the parameter indicates it should not be a tag
  (@ref  QCBOR_TAG_REQUIREMENT_NOT_A_TAG), then
   @ref QCBOR_ERR_UNEXPECTED_TYPE set if it is a tag or the type of the
  encoded CBOR is not what is expected.  In the example of an epoch
@@ -659,6 +670,10 @@
 
  This sets the pre-order traversal cursor to the item after the array
  that was exited.
+
+ This will result in an error if any item in the array is not well
+ formed (since all items in the array must be decoded to find its
+ end), or there are not enough items in the array.
 */
 static void QCBORDecode_ExitArray(QCBORDecodeContext *pCtx);
 
@@ -729,13 +744,36 @@
  The items in the map that was entered do not have to have been
  consumed for this to succeed.
 
- This sets the pre-order traversal cursor to the item after
- the map that was exited.
+ This sets the pre-order traversal cursor to the item after the map
+ that was exited.
+
+ This will result in an error if any item in the map is not well
+ formed (since all items in the map must be decoded to find its end),
+ or there are not enough items in the map.
 */
 static void QCBORDecode_ExitMap(QCBORDecodeContext *pCtx);
 
 
 /**
+ @brief Reset traversal cursor to start of map, array, byte-string
+ wrapped CBOR or start of input.
+
+ @param[in] pCtx  The decode context.
+
+ If an array, map or wrapping byte string has been entered this sets
+ the traversal cursor to its beginning. If several arrays, maps or
+ byte strings have been entered, this sets the traversal cursor to the
+ beginning of the one most recently entered.
+
+ If no map or array has been entered, this resets the traversal cursor
+ to the beginning of the input CBOR.
+
+ This also resets the error state.
+ */
+void QCBORDecode_Rewind(QCBORDecodeContext *pCtx);
+
+
+/**
  @brief Get an item in map by label and type.
 
  @param[in] pCtx   The decode context.
@@ -743,8 +781,8 @@
  @param[in] uQcborType  The QCBOR type. One of @c QCBOR_TYPE_XXX.
  @param[out] pItem  The returned item.
 
- A map must have been entered to use this. If not @ref QCBOR_ERR_MAP_NOT_ENTERED is
- set.
+ A map must have been entered to use this. If not @ref
+ QCBOR_ERR_MAP_NOT_ENTERED is set.
 
  The map is searched for an item of the requested label and type.
  @ref QCBOR_TYPE_ANY can be given to search for the label without
@@ -894,7 +932,7 @@
  The CBOR item to decode must be either the CBOR simple value (CBOR
  type 7) @c true or @c false.
 
- See @ref Decode-Errors for discussion on how error handling works.  It
+ See @ref Decode-Errors for discussion on how error handling works.  If
  the CBOR item to decode is not true or false the @ref
  QCBOR_ERR_UNEXPECTED_TYPE error is set.
 */
@@ -909,8 +947,43 @@
                                 bool               *pbBool);
 
 
+/**
+ @brief Decode the next item as a null.
+
+ @param[in] pCtx   The decode context.
+
+ The CBOR item to decode must be the CBOR simple value (CBOR type 7)
+ @c null. The reason to call this is to see if an error is returned or
+ not indicating whether the item is a CBOR null. If it is not then the
+ @ref QCBOR_ERR_UNEXPECTED_TYPE error is set.
+*/
+static void QCBORDecode_GetNull(QCBORDecodeContext *pCtx);
+
+static void QCBORDecode_GetNullInMapN(QCBORDecodeContext *pCtx,
+                                      int64_t             nLabel);
+
+static void QCBORDecode_GetNullInMapSZ(QCBORDecodeContext *pCtx,
+                                       const char         *szLabel);
 
 
+/**
+ @brief Decode the next item as a CBOR "undefined" item.
+
+ @param[in] pCtx   The decode context.
+
+ The CBOR item to decode must be the CBOR simple value (CBOR type 7)
+ @c undefined. The reason to call this is to see if an error is
+ returned or not indicating whether the item is a CBOR undefed
+ item. If it is not then the @ref QCBOR_ERR_UNEXPECTED_TYPE error is
+ set.
+*/
+static void QCBORDecode_GetUndefined(QCBORDecodeContext *pCtx);
+
+static void QCBORDecode_GetUndefinedInMapN(QCBORDecodeContext *pCtx,
+                                           int64_t             nLabel);
+
+static void QCBORDecode_GetUndefinedInMapSZ(QCBORDecodeContext *pCtx,
+                                            const char         *szLabel);
 
 
 /**
@@ -1055,7 +1128,7 @@
 
 
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
 /**
  @brief Decode the next item as a decimal fraction.
 
@@ -1253,7 +1326,7 @@
                                        UsefulBufC         *pMantissa,
                                        bool               *pbMantissaIsNegative,
                                        int64_t            *pnExponent);
-#endif /* #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA */
 
 
 
@@ -1512,6 +1585,9 @@
  CBOR. QCBORDecode_ExitBstrWrapped() must be called to resume processing
  CBOR outside the wrapped CBOR.
 
+ This does not (currently) work on indefinite-length strings. The
+ (confusing) error @ref QCBOR_ERR_INPUT_TOO_LARGE will be set.
+
  If @c pBstr is not @c NULL the pointer and length of the wrapped
  CBOR will be returned. This is usually not needed, but sometimes
  useful, particularly in the case of verifying signed data like the
@@ -1906,7 +1982,7 @@
 static inline void
 QCBORDecode_GetByteString(QCBORDecodeContext *pMe,  UsefulBufC *pValue)
 {
-   // Complier should make this just 64-bit integer parameter
+   // Complier should make this just a 64-bit integer parameter
    const TagSpecification TagSpec =
       {
          QCBOR_TAG_REQUIREMENT_NOT_A_TAG,
@@ -1993,6 +2069,60 @@
    QCBORDecode_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pText);
 }
 
+static inline void
+QCBORDecode_GetNull(QCBORDecodeContext *pMe)
+{
+   QCBORItem item;
+
+   QCBORDecode_VGetNext(pMe, &item);
+   if(pMe->uLastError == QCBOR_SUCCESS && item.uDataType != QCBOR_TYPE_NULL) {
+      pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+}
+
+static inline void
+QCBORDecode_GetNullInMapN(QCBORDecodeContext *pMe,
+                          int64_t             nLabel)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_NULL, &Item);
+}
+
+static inline void
+QCBORDecode_GetNullInMapSZ(QCBORDecodeContext *pMe,
+                                      const char * szLabel)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_NULL, &Item);
+}
+
+static inline void
+QCBORDecode_GetUndefined(QCBORDecodeContext *pMe)
+{
+   QCBORItem item;
+
+   QCBORDecode_VGetNext(pMe, &item);
+   if(pMe->uLastError == QCBOR_SUCCESS && item.uDataType != QCBOR_TYPE_UNDEF) {
+      pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+}
+
+static inline void
+QCBORDecode_GetUndefinedInMapN(QCBORDecodeContext *pMe,
+                          int64_t             nLabel)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_UNDEF, &Item);
+}
+
+static inline void
+QCBORDecode_GetUndefinedInMapSZ(QCBORDecodeContext *pMe,
+                                      const char * szLabel)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_UNDEF, &Item);
+}
+
 
 static inline void
 QCBORDecode_GetDateString(QCBORDecodeContext *pMe,
diff --git a/src/UsefulBuf.c b/src/UsefulBuf.c
index a96f74e..e5be98a 100644
--- a/src/UsefulBuf.c
+++ b/src/UsefulBuf.c
@@ -1,6 +1,6 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2020, Laurence Lundblade.
+ Copyright (c) 2018-2021, Laurence Lundblade.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -41,6 +41,7 @@
 
  when        who          what, where, why
  --------    ----         ---------------------------------------------------
+ 3/6/2021     mcr/llundblade  Fix warnings related to --Wcast-qual
  01/28/2020  llundblade   Refine integer signedness to quiet static analysis.
  01/08/2020  llundblade   Documentation corrections & improved code formatting.
  11/08/2019  llundblade   Re check pointer math and update comments
@@ -106,12 +107,12 @@
       return 0;
    }
 
-   const uint8_t * const pEnd = (uint8_t *)UB.ptr + UB.len;
+   const uint8_t * const pEnd = (const uint8_t *)UB.ptr + UB.len;
    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.*/
-         return (size_t)(p - (uint8_t *)UB.ptr);
+         return (size_t)(p - (const uint8_t *)UB.ptr);
       }
    }
 
@@ -130,7 +131,7 @@
    }
 
    for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
-      if(!UsefulBuf_Compare((UsefulBufC){((uint8_t *)BytesToSearch.ptr) + uPos, BytesToFind.len}, BytesToFind)) {
+      if(!UsefulBuf_Compare((UsefulBufC){((const uint8_t *)BytesToSearch.ptr) + uPos, BytesToFind.len}, BytesToFind)) {
          return uPos;
       }
    }
@@ -358,7 +359,7 @@
    }
 
    // This is going to succeed
-   const void * const result = ((uint8_t *)pMe->UB.ptr) + pMe->cursor;
+   const void * const result = ((const uint8_t *)pMe->UB.ptr) + pMe->cursor;
    // Will not 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 ebcbc97..4d31b69 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -46,12 +46,6 @@
 
 
 
-/*
- * This casts away the const-ness of a pointer, usually so it can be
- * freed or realloced.
- */
-#define UNCONST_POINTER(ptr)    ((void *)(ptr))
-
 #define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
 
 
@@ -422,10 +416,10 @@
 
 static inline QCBORError
 DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
-                                     uint32_t uEndOffset,
-                                     uint32_t uEndOfBstr)
+                                     uint32_t            uEndOffset,
+                                     uint32_t            uStartOffset)
 {
-   QCBORError uError = QCBOR_SUCCESS;
+   QCBORError uError;
 
    uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
    if(uError != QCBOR_SUCCESS) {
@@ -433,8 +427,8 @@
    }
 
    /* Fill in the new byte string level */
-   pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
-   pNesting->pCurrent->u.bs.uEndOfBstr         = uEndOfBstr;
+   pNesting->pCurrent->u.bs.uSavedEndOffset  = uEndOffset;
+   pNesting->pCurrent->u.bs.uBstrStartOffset = uStartOffset;
 
    /* Bstr wrapped levels are always bounded */
    pNesting->pCurrentBounded = pNesting->pCurrent;
@@ -454,7 +448,9 @@
 static inline void
 DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
 {
-   pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
+   if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
+      pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
+   }
 }
 
 
@@ -472,8 +468,6 @@
                                   QCBORDecodeNesting *pSave)
 {
    *pSave = *pNesting;
-   pNesting->pCurrent = pNesting->pCurrentBounded;
-   DecodeNesting_ResetMapOrArrayCount(pNesting);
 }
 
 
@@ -486,16 +480,9 @@
 
 
 static inline uint32_t
-DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
-{
-   return pMe->pCurrentBounded->u.bs.uEndOfBstr;
-}
-
-
-static inline uint32_t
 DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
 {
-   return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
+   return pMe->pCurrentBounded->u.bs.uSavedEndOffset;
 }
 
 
@@ -511,19 +498,30 @@
   ===========================================================================*/
 
 static inline void
-StringAllocator_Free(const QCBORInternalAllocator *pMe, void *pMem)
+StringAllocator_Free(const QCBORInternalAllocator *pMe, const void *pMem)
 {
-   (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
+   /* These pragmas allow the "-Wcast-qual" warnings flag to be set for
+    * gcc and clang. This is the one place where the const needs to be
+    * cast away so const can be use in the rest of the code.
+    */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
+   (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)pMem, 0);
+#pragma GCC diagnostic pop
 }
 
 // StringAllocator_Reallocate called with pMem NULL is
 // equal to StringAllocator_Allocate()
 static inline UsefulBuf
 StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
-                           void *pMem,
+                           const void *pMem,
                            size_t uSize)
 {
-   return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
+   /* See comment in StringAllocator_Free() */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
+   return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)pMem, uSize);
+#pragma GCC diagnostic pop
 }
 
 static inline UsefulBuf
@@ -535,9 +533,13 @@
 static inline void
 StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
 {
+   /* See comment in StringAllocator_Free() */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
    if(pMe->pfAllocator) {
       (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
    }
+#pragma GCC diagnostic pop
 }
 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
 
@@ -1297,7 +1299,7 @@
        * not NULL and a reallocation happens.
        */
       UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
-                                                    UNCONST_POINTER(FullString.ptr),
+                                                    FullString.ptr,
                                                     FullString.len + StringChunkItem.val.string.len);
 
       if(UsefulBuf_IsNULL(NewMem)) {
@@ -1311,7 +1313,7 @@
 
    if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
       /* Getting the item failed, clean up the allocated memory */
-      StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
+      StringAllocator_Free(pAllocator, FullString.ptr);
    }
 #else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
    uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
@@ -1466,7 +1468,7 @@
       memmove(&auItemsTags[1], auItemsTags, sizeof(auItemsTags) - sizeof(auItemsTags[0]));
 
       /* Map the tag */
-      uint16_t uMappedTagNumer;
+      uint16_t uMappedTagNumer = 0;
       uReturn = MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumer);
       /* Continue even on error so as to consume all tags wrapping
        * this data item so decoding can go on. If MapTagNumber()
@@ -1985,7 +1987,7 @@
 }
 
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
 /**
  * @brief Decode decimal fractions and big floats.
  *
@@ -2096,7 +2098,7 @@
 Done:
   return uReturn;
 }
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
 
 
 #ifndef QCBOR_DISABLE_UNCOMMON_TAGS
@@ -2253,11 +2255,11 @@
       } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
          uReturn = DecodeDateEpoch(pDecodedItem);
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
       } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
                 uTagToProcess == CBOR_TAG_BIGFLOAT) {
          uReturn = QCBORDecode_MantissaAndExponent(pMe, pDecodedItem);
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
 #ifndef QCBOR_DISABLE_UNCOMMON_TAGS
       } else if(uTagToProcess == CBOR_TAG_MIME ||
                 uTagToProcess == CBOR_TAG_BINARY_MIME) {
@@ -2398,8 +2400,12 @@
 /*
  * Public function, see header qcbor/qcbor_decode.h file
  */
-QCBORError QCBORDecode_Finish(QCBORDecodeContext *pMe)
+QCBORError QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
 {
+   if(puConsumed != NULL) {
+      *puConsumed = pMe->InBuf.cursor;
+   }
+
    QCBORError uReturn = pMe->uLastError;
 
    if(uReturn != QCBOR_SUCCESS) {
@@ -2418,6 +2424,15 @@
    }
 
 Done:
+   return uReturn;
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+QCBORError QCBORDecode_Finish(QCBORDecodeContext *pMe)
+{
 #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
    /* Call the destructor for the string allocator if there is one.
     * Always called, even if there are errors; always have to clean up.
@@ -2425,7 +2440,7 @@
    StringAllocator_Destruct(&(pMe->StringAllocator));
 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
 
-   return uReturn;
+   return QCBORDecode_PartialFinish(pMe, NULL);
 }
 
 
@@ -2703,6 +2718,71 @@
 }
 
 
+void QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
+{
+   uint8_t    uNextNestLevel;
+
+   QCBORDecode_VGetNext(pMe, pDecodedItem);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      pMe->uLastError = (uint8_t)ConsumeItem(pMe, pDecodedItem, &uNextNestLevel);
+      pDecodedItem->uNextNestLevel = uNextNestLevel;
+   }
+}
+
+
+
+/* Call only on maps and arrays. Rewinds the cursor
+ * to the start as if it was just entered.
+ */
+static void RewindMapOrArray(QCBORDecodeContext *pMe)
+{
+   /* Reset nesting tracking to the deepest bounded level */
+   DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
+
+   DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
+
+   /* Reposition traversal cursor to the start of the map/array */
+   UsefulInputBuf_Seek(&(pMe->InBuf),
+                       DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
+}
+
+
+/*
+ Public function, see header qcbor/qcbor_decode.h file
+ */
+void QCBORDecode_Rewind(QCBORDecodeContext *pMe)
+{
+   if(pMe->nesting.pCurrentBounded != NULL) {
+      /* In a bounded map, array or bstr-wrapped CBOR */
+
+      if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
+         /* In bstr-wrapped CBOR. */
+
+         /* Reposition traversal cursor to start of wrapping byte string */
+         UsefulInputBuf_Seek(&(pMe->InBuf),
+                             pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
+         DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
+
+      } else {
+         /* In a map or array */
+         RewindMapOrArray(pMe);
+      }
+
+   } else {
+      /* Not in anything bounded */
+
+      /* Reposition traversal cursor to the start of input CBOR */
+      UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
+
+      /* Reset nesting tracking to beginning of input. */
+      DecodeNesting_Init(&(pMe->nesting));
+   }
+
+   pMe->uLastError = QCBOR_SUCCESS;
+}
+
+
 /* Return true if the labels in Item1 and Item2 are the same.
    Works only for integer and string labels. Returns false
    for any other type. */
@@ -2823,8 +2903,7 @@
    DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
 
    /* Reposition to search from the start of the map / array */
-   UsefulInputBuf_Seek(&(pMe->InBuf),
-                       DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
+   RewindMapOrArray(pMe);
 
    /*
     Loop over all the items in the map or array. Each item
@@ -2872,14 +2951,14 @@
                uReturn = QCBOR_ERR_DUPLICATE_LABEL;
                goto Done;
             }
-            /* Also try to match its type */
-            if(!MatchType(Item, pItemArray[nIndex])) {
-               uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
+            if(uResult != QCBOR_SUCCESS) {
+               /* The label matches, but the data item is in error */
+               uReturn = uResult;
                goto Done;
             }
-
-            if(uResult != QCBOR_SUCCESS) {
-               uReturn = uResult;
+            if(!MatchType(Item, pItemArray[nIndex])) {
+               /* The data item is not of the type(s) requested */
+               uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
                goto Done;
             }
 
@@ -3194,7 +3273,9 @@
       return;
    }
 
-   /*
+
+   /* The map or array was found. Now enter it.
+    *
     * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
     * next item for the pre-order traversal cursor to be the map/array
     * found by MapSearch(). The next few lines of code force the
@@ -3435,16 +3516,11 @@
    }
 
    if(pMe->uLastError != QCBOR_SUCCESS) {
-      // Already in error state; do nothing.
+      /* Already in error state; do nothing. */
       return pMe->uLastError;
    }
 
-   QCBORError uError = QCBOR_SUCCESS;
-
-   if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
-      uError = QCBOR_ERR_UNEXPECTED_TYPE;
-      goto Done;;
-   }
+   QCBORError uError;
 
    const TagSpecification TagSpec =
       {
@@ -3459,9 +3535,10 @@
    }
 
    if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
-      // Reverse the decrement done by GetNext() for the bstr so the
-      // increment in QCBORDecode_NestLevelAscender() called by ExitBoundedLevel()
-      // will work right.
+      /* Reverse the decrement done by GetNext() for the bstr so the
+       * increment in QCBORDecode_NestLevelAscender() called by
+       * ExitBoundedLevel() will work right.
+       */
       DecodeNesting_ReverseDecrement(&(pMe->nesting));
    }
 
@@ -3469,34 +3546,40 @@
       *pBstr = pItem->val.string;
    }
 
-   // This saves the current length of the UsefulInputBuf and then
-   // narrows the UsefulInputBuf to start and length of the wrapped
-   // CBOR that is being entered.
-   //
-   // This makes sure the length is less than
-   // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
-   // UINT32_MAX. The value UINT32_MAX is used as a special indicator
-   // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
-   // the casts safe.  uEndOfBstr will always be less than
-   // uPreviousLength because of the way UsefulInputBuf works so there
-   // is no need to check it.  There is also a range check in the
-   // seek.
-   //
-   // Most of these calls are simple inline accessors so this doesn't
-   // amount to much code.
-   // Cast of uPreviousLength to uint32_t for cases where SIZE_MAX < UINT32_MAX.
+   /* This saves the current length of the UsefulInputBuf and then
+    * narrows the UsefulInputBuf to start and length of the wrapped
+    * CBOR that is being entered.
+    *
+    * Most of these calls are simple inline accessors so this doesn't
+    * amount to much code.
+    */
+
    const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
-   if((uint32_t)uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
+   /* This check makes the cast of uPreviousLength to uint32_t below safe. */
+   if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
       uError = QCBOR_ERR_INPUT_TOO_LARGE;
       goto Done;
    }
-   const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
-   UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
+
+   const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
+                                                              pItem->val.string.ptr);
+   /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
+   if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
+      /* This should never happen because pItem->val.string.ptr should
+       * always be valid since it was just returned.
+       */
+      uError = QCBOR_ERR_INPUT_TOO_LARGE;
+      goto Done;
+   }
+
+   const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
+
+   UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
    UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
 
    uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
                                                  (uint32_t)uPreviousLength,
-                                                 (uint32_t)uEndOfBstr);
+                                                 (uint32_t)uStartOfBstr);
 Done:
    return uError;
 }
@@ -3514,7 +3597,7 @@
       return;
    }
 
-   /* Get the data item that is the map that is being searched */
+   /* Get the data item that is the byte string being entered */
    QCBORItem Item;
    pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
    if(pMe->uLastError != QCBOR_SUCCESS) {
@@ -3579,6 +3662,8 @@
       return;
    }
 
+   const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
+
    /*
     Reset the length of the UsefulInputBuf to what it was before
     the bstr wrapped CBOR was entered.
@@ -3587,83 +3672,77 @@
                                DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
 
 
-   QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
+   QCBORError uErr = ExitBoundedLevel(pMe, uEndOfBstr);
    pMe->uLastError = (uint8_t)uErr;
 }
 
 
 
 
-
-
-
-
-static QCBORError
-InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
+static inline void
+ProcessBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
 {
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      /* Already in error state, do nothing */
+      return;
+   }
+
    switch(pItem->uDataType) {
       case QCBOR_TYPE_TRUE:
          *pBool = true;
-         return QCBOR_SUCCESS;
          break;
 
       case QCBOR_TYPE_FALSE:
          *pBool = false;
-         return QCBOR_SUCCESS;
          break;
 
       default:
-         return QCBOR_ERR_UNEXPECTED_TYPE;
+         pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
          break;
    }
    CopyTags(pMe, pItem);
 }
 
 
-
 /*
- Public function, see header qcbor/qcbor_decode.h file
-*/
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
 void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
 {
    if(pMe->uLastError != QCBOR_SUCCESS) {
-      // Already in error state, do nothing
+      /* Already in error state, do nothing */
       return;
    }
 
-   QCBORError nError;
    QCBORItem  Item;
 
-   nError = QCBORDecode_GetNext(pMe, &Item);
-   if(nError != QCBOR_SUCCESS) {
-      pMe->uLastError = (uint8_t)nError;
-      return;
-   }
-   pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
+   pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
+
+   ProcessBool(pMe, &Item, pValue);
 }
 
 
 /*
- Public function, see header qcbor/qcbor_decode.h file
-*/
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
 void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
 {
    QCBORItem Item;
    QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
 
-   pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
+   ProcessBool(pMe, &Item, pValue);
 }
 
 
 /*
- Public function, see header qcbor/qcbor_decode.h file
-*/
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
 void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
 {
    QCBORItem Item;
    QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
 
-   pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
+   ProcessBool(pMe, &Item, pValue);
 }
 
 
@@ -3923,7 +4002,7 @@
 
 
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
 
 typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
 
@@ -4070,7 +4149,7 @@
    return (*pfExp)(uMantissa, nExponent, puResult);
 }
 
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
 
 
 
@@ -4308,7 +4387,7 @@
          }
          break;
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
       case QCBOR_TYPE_DECIMAL_FRACTION:
          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
             return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
@@ -4398,7 +4477,7 @@
             return QCBOR_ERR_UNEXPECTED_TYPE;
          }
          break;
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
 
 
       default:
@@ -4653,7 +4732,7 @@
          }
          break;
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
 
       case QCBOR_TYPE_DECIMAL_FRACTION:
          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
@@ -4726,7 +4805,7 @@
             return QCBOR_ERR_UNEXPECTED_TYPE;
          }
          break;
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
       default:
          return QCBOR_ERR_UNEXPECTED_TYPE;
    }
@@ -4972,7 +5051,7 @@
    */
    switch(pItem->uDataType) {
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
       case QCBOR_TYPE_DECIMAL_FRACTION:
          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
             // Underflow gives 0, overflow gives infinity
@@ -4992,7 +5071,7 @@
             return QCBOR_ERR_UNEXPECTED_TYPE;
          }
          break;
-#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
 
       case QCBOR_TYPE_POSBIGNUM:
          if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
@@ -5010,7 +5089,7 @@
          }
          break;
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
       case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
          if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
             double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
@@ -5046,7 +5125,7 @@
             return QCBOR_ERR_UNEXPECTED_TYPE;
          }
          break;
-#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
 
       default:
          return QCBOR_ERR_UNEXPECTED_TYPE;
@@ -5143,7 +5222,7 @@
 
 
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
 static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
 {
    while((uInt & 0xff00000000000000UL) == 0) {
@@ -5694,4 +5773,4 @@
                                  pnExponent);
 }
 
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
diff --git a/src/qcbor_encode.c b/src/qcbor_encode.c
index 654bda9..59c420b 100644
--- a/src/qcbor_encode.c
+++ b/src/qcbor_encode.c
@@ -734,7 +734,7 @@
 }
 
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
 /*
  * Semi-public function. It is exposed to the user of the interface,
  * but one of the inline wrappers will usually be called rather than
@@ -775,7 +775,7 @@
    }
    QCBOREncode_CloseArray(pMe);
 }
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
 
 
 /*
diff --git a/test/UsefulBuf_Tests.c b/test/UsefulBuf_Tests.c
index 1c2634e..264fbca 100644
--- a/test/UsefulBuf_Tests.c
+++ b/test/UsefulBuf_Tests.c
@@ -1,6 +1,6 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2020, Laurence Lundblade.
+ Copyright (c) 2018-2021, Laurence Lundblade.
  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,7 @@
 
    There is nothing adversarial in this test
  */
-const char * UOBTest_NonAdversarial()
+const char * UOBTest_NonAdversarial(void)
 {
    const char *szReturn = NULL;
 
@@ -160,7 +160,7 @@
 
  */
 
-const char *UOBTest_BoundaryConditionsTest()
+const char *UOBTest_BoundaryConditionsTest(void)
 {
    UsefulBuf_MAKE_STACK_UB(outbuf,2);
 
@@ -248,7 +248,7 @@
 
 // Test function to get size and magic number check
 
-const char *TestBasicSanity()
+const char *TestBasicSanity(void)
 {
    UsefulBuf_MAKE_STACK_UB(outbuf,10);
 
@@ -293,7 +293,7 @@
 
 
 
-const char *UBMacroConversionsTest()
+const char *UBMacroConversionsTest(void)
 {
    char *szFoo = "foo";
 
@@ -310,16 +310,17 @@
    if(Boo.len != 3 || strncmp(Boo.ptr, "Boo", 3))
      return "UsefulBuf_FROM_BYTE_ARRAY_LITERAL failed";
 
-   UsefulBuf B = (UsefulBuf){(void *)Too.ptr, Too.len};
+   char *String = "string"; // Intentionally not const
+   UsefulBuf B = (UsefulBuf){(void *)String, strlen(String)};
    UsefulBufC BC = UsefulBuf_Const(B);
-   if(BC.len != Too.len || BC.ptr != Too.ptr)
+   if(BC.len != strlen(String) || BC.ptr != String)
       return "UsefulBufConst failed";
 
    return NULL;
 }
 
 
-const char *UBUtilTests()
+const char *UBUtilTests(void)
 {
    UsefulBuf UB = NULLUsefulBuf;
 
@@ -591,13 +592,46 @@
       return "Failed to find 3";
    }
 
+
+   const uint8_t pB[] = {0x01, 0x02, 0x03};
+   UsefulBufC Boo = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pB);
+   // Try to map a pointer before
+   if(UsefulBuf_PointerToOffset(Boo, pB-1) != SIZE_MAX) {
+      return "Didn't error on pointer before";
+   }
+
+   // Try to map a pointer after
+   if(UsefulBuf_PointerToOffset(Boo, pB+sizeof(pB)) != SIZE_MAX) {
+      return "Didn't error on pointer after";
+   }
+
+   // Try to map a pointer inside
+   if(UsefulBuf_PointerToOffset(Boo, pB+1) != 1) {
+      return "Incorrect pointer offset";
+   }
+
+   // Try to map a pointer at the start
+   if(UsefulBuf_PointerToOffset(Boo, pB) != 0) {
+      return "Incorrect pointer offset for start";
+   }
+
+   // Try to map a pointer at the end
+   if(UsefulBuf_PointerToOffset(Boo, pB + sizeof(pB)-1) != 2) {
+      return "Incorrect pointer offset for end";
+   }
+
+   // Try to map a pointer on a NULL UB
+   if(UsefulBuf_PointerToOffset(NULLUsefulBufC, pB ) != SIZE_MAX) {
+      return "Incorrect pointer offset for start";
+   }
+
    return NULL;
 }
 
 
-const char *  UIBTest_IntegerFormat()
+const char *  UIBTest_IntegerFormat(void)
 {
-   UsefulOutBuf_MakeOnStack(UOB,100);
+   UsefulOutBuf_MakeOnStack(UOB, 100);
 
    const uint32_t u32 = 0x0A0B0C0D; // from https://en.wikipedia.org/wiki/Endianness
    const uint64_t u64 = 1984738472938472;
@@ -695,11 +729,15 @@
       return "expected error after seek";
    }
 
+   if(UsefulInputBuf_PointerToOffset(&UIB, O.ptr) != 0) {
+      return "PointerToOffset not working";
+   }
+
    return NULL;
 }
 
 
-const char *UBUTest_CopyUtil()
+const char *UBUTest_CopyUtil(void)
 {
    if(UsefulBufUtil_CopyFloatToUint32(65536.0F) != 0x47800000) {
       return "CopyFloatToUint32 failed";
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index acde3ca..236f59c 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -1,6 +1,6 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2020, Laurence Lundblade.
+ Copyright (c) 2018-2021, Laurence Lundblade.
  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -918,6 +918,48 @@
    return 0;
 }
 
+
+static const uint8_t sEmptyMap[] = {
+                              0xA1,     //# map(1)
+                              0x02,     //# unsigned(2)
+                              0xA0,     //# map(0)
+};
+
+int32_t ParseEmptyMapInMapTest(void)
+{
+   QCBORDecodeContext DCtx;
+   QCBORItem Item;
+   int nReturn = 0;
+   QCBORError uErr;
+
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(sEmptyMap),
+                    QCBOR_DECODE_MODE_NORMAL);
+
+   /* now open the first Map */
+   uErr = QCBORDecode_GetNext(&DCtx, &Item);
+    if(uErr != QCBOR_SUCCESS ||
+       Item.uDataType != QCBOR_TYPE_MAP) {
+      nReturn = -3;
+      goto done;
+    }
+
+   if(QCBORDecode_GetNext(&DCtx, &Item) != 0) {
+     nReturn = -1;
+     goto done;
+   }
+   if(Item.uDataType != QCBOR_TYPE_MAP ||
+      Item.uNestingLevel != 1 ||
+      Item.label.int64 != 2) {
+     nReturn = -2;
+     goto done;
+   }
+
+ done:
+   return(nReturn);
+}
+
+
 /* [[[[[[[[[[]]]]]]]]]] */
 static const uint8_t spDeepArrays[] = {
    0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
@@ -1771,7 +1813,7 @@
       }
 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
 
-      
+
       // Iterate until there is an error of some sort error
       QCBORItem Item;
       do {
@@ -2985,7 +3027,7 @@
     4([1,3])
     */
    uError = QCBORDecode_GetNext(&DCtx, &Item);
-#ifdef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifdef QCBOR_DISABLE_EXP_AND_MANTISSA
    if(uError != QCBOR_SUCCESS ||
       Item.uDataType != QCBOR_TYPE_ARRAY ||
       !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_DECIMAL_FRACTION) ||
@@ -3001,7 +3043,7 @@
    uError = QCBORDecode_GetNext(&DCtx, &Item);
    uError = QCBORDecode_GetNext(&DCtx, &Item);
 
-#else /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#else /* QCBOR_DISABLE_EXP_AND_MANTISSA */
    if(uError != QCBOR_SUCCESS ||
       Item.uDataType != QCBOR_TYPE_DECIMAL_FRACTION ||
       QCBORDecode_GetNthTag(&DCtx, &Item, 0) != CBOR_TAG_INVALID64 ||
@@ -3011,7 +3053,7 @@
       QCBORDecode_GetNthTag(&DCtx, &Item, 4) != CBOR_TAG_INVALID64 ) {
       return -5;
    }
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
 
    /*
     More than 4 tags on an item 225(226(227(228(229([])))))
@@ -4449,7 +4491,7 @@
 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
 
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
 
 /*  exponent, mantissa
   [
@@ -4754,7 +4796,7 @@
                                         struct FailInput));
 }
 
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
 
 
 
@@ -5001,7 +5043,7 @@
 
 /* Repeatedly enter and exit maps and arrays, go off the end of maps
  and arrays and such. */
-static int32_t DecodeNestedIterate()
+static int32_t DecodeNestedIterate(void)
 {
    QCBORDecodeContext DCtx;
    int32_t            nReturn;
@@ -5151,6 +5193,9 @@
 };
 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
 
+const unsigned char not_well_formed_submod_section[] = {
+   0xa1, 0x14, 0x1f,
+};
 
 int32_t EnterMapTest()
 {
@@ -5440,9 +5485,65 @@
    }
 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
 
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), 0);
+   QCBORDecode_VGetNextConsume(&DCtx, &Item1);
+   if(Item1.uDataType != QCBOR_TYPE_MAP) {
+      return 2401;
+   }
+   if(QCBORDecode_GetError(&DCtx)) {
+      return 2402;
+   }
+
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), 0);
+   QCBORDecode_VGetNext(&DCtx, &Item1);
+   if(Item1.uDataType != QCBOR_TYPE_MAP ||
+      Item1.val.uCount != 3 ||
+      Item1.uNextNestLevel != 1) {
+      return 2403;
+   }
+   if(QCBORDecode_GetError(&DCtx)) {
+      return 2404;
+   }
+   QCBORDecode_VGetNextConsume(&DCtx, &Item1);
+   if(Item1.uDataType != QCBOR_TYPE_INT64 ||
+      Item1.uNextNestLevel != 1 ||
+      Item1.val.int64 != 42) {
+      return 2405;
+   }
+   if(QCBORDecode_GetError(&DCtx)) {
+      return 2406;
+   }
+   QCBORDecode_VGetNextConsume(&DCtx, &Item1);
+   if(Item1.uDataType != QCBOR_TYPE_ARRAY ||
+      Item1.uNestingLevel != 1 ||
+      Item1.uNextNestLevel != 1 ||
+      Item1.val.uCount != 2) {
+      return 2407;
+   }
+   if(QCBORDecode_GetError(&DCtx)) {
+      return 2408;
+   }
+   QCBORDecode_VGetNextConsume(&DCtx, &Item1);
+   if(Item1.uDataType != QCBOR_TYPE_MAP ||
+      Item1.uNestingLevel != 1 ||
+      Item1.uNextNestLevel != 0 ||
+      Item1.val.uCount != 4) {
+      return 2409;
+   }
+   if(QCBORDecode_GetError(&DCtx)) {
+      return 2410;
+   }
 
    nReturn = DecodeNestedIterate();
 
+
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(not_well_formed_submod_section), 0);
+   QCBORDecode_EnterMap(&DCtx, NULL);
+   QCBORDecode_EnterMapFromMapN(&DCtx, 20);
+   if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_BAD_INT) {
+      return 2500;
+   }
+
    return nReturn;
 }
 
@@ -5493,61 +5594,61 @@
       "Decimal Fraction with positive bignum 257 * 10e3",
       {(uint8_t[]){0xC4, 0x82, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
                                0xC2, 0x42, 0x01, 0x01}, 15},
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
       257000,
       QCBOR_SUCCESS,
       257000,
       QCBOR_SUCCESS,
       257000.0,
       QCBOR_SUCCESS
-#else /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#else /* QCBOR_DISABLE_EXP_AND_MANTISSA */
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0.0,
       QCBOR_ERR_UNEXPECTED_TYPE
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA*/
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA*/
    },
    {
       "bigfloat with negative bignum -258 * 2e3",
       {(uint8_t[]){0xC5, 0x82, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
                                0xC3, 0x42, 0x01, 0x01}, 15},
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
       -2064,
       QCBOR_SUCCESS,
       0,
       QCBOR_ERR_NUMBER_SIGN_CONVERSION,
       -2064.0,
       QCBOR_SUCCESS
-#else /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#else /* QCBOR_DISABLE_EXP_AND_MANTISSA */
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0.0,
       QCBOR_ERR_UNEXPECTED_TYPE
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA*/
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA*/
    },
    {
       "bigfloat with positive bignum 257 * 2e3",
       {(uint8_t[]){0xC5, 0x82, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
                                0xC2, 0x42, 0x01, 0x01}, 15},
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
       2056,
       QCBOR_SUCCESS,
       2056,
       QCBOR_SUCCESS,
       2056.0,
       QCBOR_SUCCESS
-#else /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#else /* QCBOR_DISABLE_EXP_AND_MANTISSA */
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0.0,
       QCBOR_ERR_UNEXPECTED_TYPE
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA*/
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA*/
    },
    {
       "negative bignum 0xc349010000000000000000 -18446744073709551617",
@@ -5575,60 +5676,60 @@
       "Decimal Fraction with neg bignum [9223372036854775807, -4759477275222530853137]",
       {(uint8_t[]){0xC4, 0x82, 0x1B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
                                0xC3, 0x4A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,}, 23},
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
       0,
       QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW,
       0,
       QCBOR_ERR_NUMBER_SIGN_CONVERSION,
       -INFINITY,
       QCBOR_SUCCESS
-#else /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#else /* QCBOR_DISABLE_EXP_AND_MANTISSA */
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0.0,
       QCBOR_ERR_UNEXPECTED_TYPE
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
    },
    {
       "big float [9223372036854775806,  9223372036854775806]",
       {(uint8_t[]){0xC5, 0x82, 0x1B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
                                0x1B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE}, 20},
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
       0,
       QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW,
       0,
       QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW,
       INFINITY,
       QCBOR_SUCCESS
-#else /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#else /* QCBOR_DISABLE_EXP_AND_MANTISSA */
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0.0,
       QCBOR_ERR_UNEXPECTED_TYPE
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
    },
    {
       "Big float 3 * 2^^2",
       {(uint8_t[]){0xC5, 0x82, 0x02, 0x03}, 4},
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
       12,
       QCBOR_SUCCESS,
       12,
       QCBOR_SUCCESS,
       12.0,
       QCBOR_SUCCESS
-#else /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#else /* QCBOR_DISABLE_EXP_AND_MANTISSA */
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0.0,
       QCBOR_ERR_UNEXPECTED_TYPE
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
    },
    {
       "Positive integer 18446744073709551615",
@@ -5738,21 +5839,21 @@
    {
       "Decimal fraction 3/10",
       {(uint8_t[]){0xC4, 0x82, 0x20, 0x03}, 4},
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
       0,
       QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW,
       0,
       QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW,
       0.30000000000000004,
       QCBOR_SUCCESS
-#else /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#else /* QCBOR_DISABLE_EXP_AND_MANTISSA */
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0.0,
       QCBOR_ERR_UNEXPECTED_TYPE
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
    },
    {
       "+inifinity",
@@ -5914,21 +6015,21 @@
          0xC5, 0x82,
             0x3B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
             0x1B, 0x7f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE}, 20},
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
       0,
       QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW,
       0,
       QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW,
       0,
       QCBOR_SUCCESS
-#else /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#else /* QCBOR_DISABLE_EXP_AND_MANTISSA */
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0.0,
       QCBOR_ERR_UNEXPECTED_TYPE
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
    },
 
    {
@@ -5937,21 +6038,21 @@
          0xC5, 0x82,
             0x1B, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
             0xC3, 0x42, 0x01, 0x01}, 15},
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
       0,
       QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW,
       0,
       QCBOR_ERR_NUMBER_SIGN_CONVERSION,
       -INFINITY,
       QCBOR_SUCCESS
-#else /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#else /* QCBOR_DISABLE_EXP_AND_MANTISSA */
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0,
       QCBOR_ERR_UNEXPECTED_TYPE,
       0.0,
       QCBOR_ERR_UNEXPECTED_TYPE
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA*/
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA*/
    },
 };
 
@@ -6048,8 +6149,9 @@
 int32_t CBORSequenceDecodeTests(void)
 {
    QCBORDecodeContext DCtx;
-   QCBORItem Item;
-   QCBORError uCBORError;
+   QCBORItem          Item;
+   QCBORError         uCBORError;
+   size_t             uConsumed;
 
    // --- Test a sequence with extra bytes ---
 
@@ -6069,12 +6171,24 @@
       return 2;
    }
 
+   uCBORError = QCBORDecode_PartialFinish(&DCtx, &uConsumed);
+   if(uCBORError != QCBOR_ERR_EXTRA_BYTES ||
+      uConsumed != 12) {
+      return 102;
+   }
+
    // Get a second item
    uCBORError = QCBORDecode_GetNext(&DCtx, &Item);
    if(uCBORError != QCBOR_ERR_BAD_OPT_TAG) {
       return 66;
    }
 
+   uCBORError = QCBORDecode_PartialFinish(&DCtx, &uConsumed);
+   if(uCBORError != QCBOR_ERR_EXTRA_BYTES ||
+      uConsumed != 14) {
+      return 102;
+   }
+
    // Get a third item
    uCBORError = QCBORDecode_GetNext(&DCtx, &Item);
    if(uCBORError != QCBOR_SUCCESS) {
@@ -6984,8 +7098,90 @@
 #endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
 
 
+/*
+ * An array of an integer and an array. The second array contains
+ * a bstr-wrapped map.
+ *
+ * [7, [h'A36D6669... (see next lines) 73']]
+ *
+ * {"first integer": 42,
+ *   "an array of two strings": ["string1", "string2"],
+ *    "map in a map":
+ *      { "bytes 1": h'78787878',
+ *        "bytes 2": h'79797979',
+ *        "another int": 98,
+ *        "text 2": "lies, damn lies and statistics"
+ *      }
+ *   }
+ */
 
-int32_t PeekTest()
+static const uint8_t pValidWrappedMapEncoded[] = {
+   0x82, 0x07, 0x81, 0x58, 0x97,
+   0xa3, 0x6d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69, 0x6e,
+   0x74, 0x65, 0x67, 0x65, 0x72, 0x18, 0x2a, 0x77, 0x61, 0x6e,
+   0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20,
+   0x74, 0x77, 0x6f, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+   0x73, 0x82, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31,
+   0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x32, 0x6c, 0x6d,
+   0x61, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x6d, 0x61,
+   0x70, 0xa4, 0x67, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x31,
+   0x44, 0x78, 0x78, 0x78, 0x78, 0x67, 0x62, 0x79, 0x74, 0x65,
+   0x73, 0x20, 0x32, 0x44, 0x79, 0x79, 0x79, 0x79, 0x6b, 0x61,
+   0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x74,
+   0x18, 0x62, 0x66, 0x74, 0x65, 0x78, 0x74, 0x20, 0x32, 0x78,
+   0x1e, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x64, 0x61, 0x6d,
+   0x6e, 0x20, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64,
+   0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63,
+   0x73
+};
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+
+/* As above, but the arrays are indefinite length */
+static const uint8_t pValidIndefWrappedMapEncoded[] = {
+   0x9f, 0x07, 0x9f, 0x58, 0x97,
+   0xa3, 0x6d, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69, 0x6e,
+   0x74, 0x65, 0x67, 0x65, 0x72, 0x18, 0x2a, 0x77, 0x61, 0x6e,
+   0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20,
+   0x74, 0x77, 0x6f, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+   0x73, 0x82, 0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x31,
+   0x67, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x32, 0x6c, 0x6d,
+   0x61, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x6d, 0x61,
+   0x70, 0xa4, 0x67, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x31,
+   0x44, 0x78, 0x78, 0x78, 0x78, 0x67, 0x62, 0x79, 0x74, 0x65,
+   0x73, 0x20, 0x32, 0x44, 0x79, 0x79, 0x79, 0x79, 0x6b, 0x61,
+   0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x74,
+   0x18, 0x62, 0x66, 0x74, 0x65, 0x78, 0x74, 0x20, 0x32, 0x78,
+   0x1e, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x64, 0x61, 0x6d,
+   0x6e, 0x20, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64,
+   0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63,
+   0x73,
+   0xff, 0xff
+};
+#endif
+
+
+static const uint8_t pWithEmptyMap[] = {0x82, 0x18, 0x64, 0xa0};
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+static const uint8_t pWithEmptyMapInDef[] = {0x9f, 0x18, 0x64, 0xbf, 0xff, 0xff};
+#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
+static const uint8_t pWrappedByIndefiniteLength[] = {
+   0x81,
+   0xd8, 0x18,
+   0x5f,
+   0x41, 0x83,
+   0x41, 0x18,
+   0x43, 0x2A, 0x18, 0x2B,
+   0x42, 0x18, 0x2C,
+   0xff
+};
+#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
+
+
+int32_t PeekAndRewindTest()
 {
    QCBORItem          Item;
    QCBORError         nCBORError;
@@ -7055,8 +7251,9 @@
       Item.uLabelAlloc ||
       UsefulBufCompareToSZ(Item.label.string, "an array of two strings") ||
       Item.uDataType != QCBOR_TYPE_ARRAY ||
-      Item.val.uCount != 2)
+      Item.val.uCount != 2) {
       return 1400;
+   }
 
    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
       return 1500 + (int32_t)nCBORError;
@@ -7155,8 +7352,9 @@
       Item.uLabelAlloc ||
       UsefulBufCompareToSZ(Item.label.string, "another int") ||
       Item.uDataType != QCBOR_TYPE_INT64 ||
-      Item.val.int64 != 98)
+      Item.val.int64 != 98) {
       return 2900;
+   }
 
    if((nCBORError = QCBORDecode_PeekNext(&DCtx, &Item))) {
       return 3000 + (int32_t)nCBORError;
@@ -7182,5 +7380,571 @@
       return 3300;
    }
 
+
+
+   // Rewind to top level after entering several maps
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), 0);
+
+   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+       return (int32_t)nCBORError;
+    }
+    if(Item.uDataType != QCBOR_TYPE_MAP ||
+       Item.val.uCount != 3) {
+       return 400;
+    }
+
+    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+       return 4000+(int32_t)nCBORError;
+    }
+
+    if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
+       Item.uDataType != QCBOR_TYPE_INT64 ||
+       Item.val.int64 != 42 ||
+       Item.uDataAlloc ||
+       Item.uLabelAlloc ||
+       UsefulBufCompareToSZ(Item.label.string, "first integer")) {
+       return 4100;
+    }
+
+    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+       return 4100+(int32_t)nCBORError;
+    }
+    if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
+       Item.uDataAlloc ||
+       Item.uLabelAlloc ||
+       UsefulBufCompareToSZ(Item.label.string, "an array of two strings") ||
+       Item.uDataType != QCBOR_TYPE_ARRAY ||
+       Item.val.uCount != 2) {
+       return 4200;
+    }
+
+    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+       return 4200+(int32_t)nCBORError;
+    }
+    if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+       Item.uDataAlloc ||
+       Item.uLabelAlloc ||
+       UsefulBufCompareToSZ(Item.val.string, "string1")) {
+       return 4300;
+    }
+
+    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+       return 4300+(int32_t)nCBORError;
+    }
+    if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+       Item.uDataAlloc ||
+       Item.uLabelAlloc ||
+       UsefulBufCompareToSZ(Item.val.string, "string2")) {
+       return 4400;
+    }
+
+   QCBORDecode_Rewind(&DCtx);
+
+   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+       return 4400+(int32_t)nCBORError;
+    }
+    if(Item.uDataType != QCBOR_TYPE_MAP ||
+       Item.val.uCount != 3) {
+       return 4500;
+    }
+
+    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+       return (int32_t)nCBORError;
+    }
+
+    if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
+       Item.uDataType != QCBOR_TYPE_INT64 ||
+       Item.val.int64 != 42 ||
+       Item.uDataAlloc ||
+       Item.uLabelAlloc ||
+       UsefulBufCompareToSZ(Item.label.string, "first integer")) {
+       return 4600;
+    }
+
+    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+       return (int32_t)nCBORError;
+    }
+    if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
+       Item.uDataAlloc ||
+       Item.uLabelAlloc ||
+       UsefulBufCompareToSZ(Item.label.string, "an array of two strings") ||
+       Item.uDataType != QCBOR_TYPE_ARRAY ||
+       Item.val.uCount != 2) {
+       return 4700;
+    }
+
+    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+       return (int32_t)nCBORError;
+    }
+    if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+       Item.uDataAlloc ||
+       Item.uLabelAlloc ||
+       UsefulBufCompareToSZ(Item.val.string, "string1")) {
+       return 4800;
+    }
+
+    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+       return 4900+(int32_t)nCBORError;
+    }
+    if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+       Item.uDataAlloc ||
+       Item.uLabelAlloc ||
+       UsefulBufCompareToSZ(Item.val.string, "string2")) {
+       return 5000;
+    }
+
+
+   // Rewind an entered map
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), 0);
+
+   QCBORDecode_EnterMap(&DCtx, NULL);
+
+   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+       return 5100+(int32_t)nCBORError;
+   }
+
+   if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
+       Item.uDataType != QCBOR_TYPE_INT64 ||
+       Item.val.int64 != 42 ||
+       Item.uDataAlloc ||
+       Item.uLabelAlloc ||
+       UsefulBufCompareToSZ(Item.label.string, "first integer")) {
+       return 5200;
+    }
+
+    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+       return 5200+(int32_t)nCBORError;
+    }
+    if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
+       Item.uDataAlloc ||
+       Item.uLabelAlloc ||
+       UsefulBufCompareToSZ(Item.label.string, "an array of two strings") ||
+       Item.uDataType != QCBOR_TYPE_ARRAY ||
+       Item.val.uCount != 2) {
+       return -5300;
+    }
+
+   QCBORDecode_Rewind(&DCtx);
+
+   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+       return 5300+(int32_t)nCBORError;
+   }
+
+   if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
+      Item.uDataType != QCBOR_TYPE_INT64 ||
+      Item.val.int64 != 42 ||
+      Item.uDataAlloc ||
+      Item.uLabelAlloc ||
+      UsefulBufCompareToSZ(Item.label.string, "first integer")) {
+      return 5400;
+   }
+
+   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return 5400+(int32_t)nCBORError;
+   }
+   if(Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
+      Item.uDataAlloc ||
+      Item.uLabelAlloc ||
+      UsefulBufCompareToSZ(Item.label.string, "an array of two strings") ||
+      Item.uDataType != QCBOR_TYPE_ARRAY ||
+      Item.val.uCount != 2) {
+      return 5500;
+   }
+
+
+   // Rewind and entered array inside an entered map
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), 0);
+
+   QCBORDecode_EnterMap(&DCtx, NULL);
+
+   QCBORDecode_EnterArrayFromMapSZ(&DCtx, "an array of two strings");
+
+   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return 5600+(int32_t)nCBORError;
+   }
+   if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      Item.uDataAlloc ||
+      Item.uLabelAlloc ||
+      UsefulBufCompareToSZ(Item.val.string, "string1")) {
+      return 5700;
+   }
+
+   QCBORDecode_Rewind(&DCtx);
+
+   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return 5700+(int32_t)nCBORError;
+   }
+   if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      Item.uDataAlloc ||
+      Item.uLabelAlloc ||
+      UsefulBufCompareToSZ(Item.val.string, "string1")) {
+      return 5800;
+   }
+
+   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return (int32_t)nCBORError;
+   }
+   if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      Item.uDataAlloc ||
+      Item.uLabelAlloc ||
+      UsefulBufCompareToSZ(Item.val.string, "string2")) {
+      return 5900;
+   }
+
+   QCBORDecode_Rewind(&DCtx);
+
+   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return 5900+(int32_t)nCBORError;
+   }
+   if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      Item.uDataAlloc ||
+      Item.uLabelAlloc ||
+      UsefulBufCompareToSZ(Item.val.string, "string1")) {
+      return 6000;
+   }
+
+
+   // Rewind a byte string inside an array inside an array
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidWrappedMapEncoded), 0);
+
+   QCBORDecode_EnterArray(&DCtx, NULL);
+
+   uint64_t i;
+   QCBORDecode_GetUInt64(&DCtx, &i);
+
+   QCBORDecode_EnterArray(&DCtx, NULL);
+
+   QCBORDecode_EnterBstrWrapped(&DCtx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL);
+   if(QCBORDecode_GetError(&DCtx)) {
+      return 6100;
+   }
+
+   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return (int32_t)nCBORError;
+   }
+   if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 3) {
+      return 6200;
+   }
+
+   QCBORDecode_Rewind(&DCtx);
+
+   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return 6300+(int32_t)nCBORError;
+   }
+   if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 3) {
+      return 6400;
+   }
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+   // Rewind a byte string inside an indefinite-length array inside
+   // indefinite-length array
+
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidIndefWrappedMapEncoded), 0);
+
+   QCBORDecode_EnterArray(&DCtx, NULL);
+
+   QCBORDecode_GetUInt64(&DCtx, &i);
+
+   QCBORDecode_EnterArray(&DCtx, NULL);
+
+   QCBORDecode_EnterBstrWrapped(&DCtx, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, NULL);
+   if(QCBORDecode_GetError(&DCtx)) {
+      return 6500;
+   }
+
+   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return 6600+(int32_t)nCBORError;
+   }
+   if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 3) {
+      return 6700;
+   }
+
+   QCBORDecode_Rewind(&DCtx);
+
+   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item))) {
+      return 6800+(int32_t)nCBORError;
+   }
+   if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 3) {
+      return 6900;
+   }
+#endif
+
+   // Rewind an empty map
+   // [100, {}]
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pWithEmptyMap), 0);
+   QCBORDecode_EnterArray(&DCtx, NULL);
+   QCBORDecode_GetUInt64(&DCtx, &i);
+   if(i != 100) {
+      return 7010;
+   }
+   QCBORDecode_EnterMap(&DCtx, NULL);
+
+   /* Do it 5 times to be sure multiple rewinds work */
+   for(int n = 0; n < 5; n++) {
+      nCBORError = QCBORDecode_GetNext(&DCtx, &Item);
+      if(nCBORError != QCBOR_ERR_NO_MORE_ITEMS) {
+         return 7000 + n;
+      }
+      QCBORDecode_Rewind(&DCtx);
+   }
+   QCBORDecode_ExitMap(&DCtx);
+   QCBORDecode_Rewind(&DCtx);
+   QCBORDecode_GetUInt64(&DCtx, &i);
+   if(i != 100) {
+      return 7010;
+   }
+   QCBORDecode_ExitArray(&DCtx);
+   QCBORDecode_Rewind(&DCtx);
+   QCBORDecode_EnterArray(&DCtx, NULL);
+   i = 9;
+   QCBORDecode_GetUInt64(&DCtx, &i);
+   if(i != 100) {
+      return 7020;
+   }
+   if(QCBORDecode_GetError(&DCtx)){
+      return 7030;
+   }
+
+   // Rewind an empty indefinite length map
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pWithEmptyMapInDef), 0);
+   QCBORDecode_EnterArray(&DCtx, NULL);
+   QCBORDecode_GetUInt64(&DCtx, &i);
+   if(i != 100) {
+      return 7810;
+   }
+   QCBORDecode_EnterMap(&DCtx, NULL);
+
+   /* Do it 5 times to be sure multiple rewinds work */
+   for(int n = 0; n < 5; n++) {
+      nCBORError = QCBORDecode_GetNext(&DCtx, &Item);
+      if(nCBORError != QCBOR_ERR_NO_MORE_ITEMS) {
+         return 7800 + n;
+      }
+      QCBORDecode_Rewind(&DCtx);
+   }
+   QCBORDecode_ExitMap(&DCtx);
+   QCBORDecode_Rewind(&DCtx);
+   QCBORDecode_GetUInt64(&DCtx, &i);
+   if(i != 100) {
+      return 7810;
+   }
+   QCBORDecode_ExitArray(&DCtx);
+   QCBORDecode_Rewind(&DCtx);
+   QCBORDecode_EnterArray(&DCtx, NULL);
+   i = 9;
+   QCBORDecode_GetUInt64(&DCtx, &i);
+   if(i != 100) {
+      return 7820;
+   }
+   if(QCBORDecode_GetError(&DCtx)){
+      return 7830;
+   }
+#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+
+   // Rewind an indefnite length byte-string wrapped sequence
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pWrappedByIndefiniteLength),
+                    0);
+   UsefulBuf_MAKE_STACK_UB(Pool, 100);
+   QCBORDecode_SetMemPool(&DCtx, Pool, 0);
+
+   QCBORDecode_EnterArray(&DCtx, NULL);
+   QCBORDecode_EnterBstrWrapped(&DCtx, 2, NULL);
+   if(QCBORDecode_GetError(&DCtx) != QCBOR_ERR_INPUT_TOO_LARGE) {
+      /* this is what happens when trying to enter
+       indefinite-length byte string
+       wrapped CBOR.  Tolerate for now. Eventually it needs
+       to be fixed so this works, but that is not simple. */
+      return 7300;
+   }
+
+   /*
+   QCBORDecode_GetUInt64(&DCtx, &i);
+   if(i != 42) {
+      return 7110;
+   }
+   QCBORDecode_Rewind(&DCtx);
+   QCBORDecode_GetUInt64(&DCtx, &i);
+   if(i != 42) {
+      return 7220;
+   }*/
+#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
+
+
+   // Rewind an indefnite length byte-string wrapped sequence
+
+   return 0;
+}
+
+
+
+
+static const uint8_t spBooleansInMap[] =
+{
+   0xa1, 0x08, 0xf5
+};
+
+static const uint8_t spBooleansInMapWrongType[] =
+{
+   0xa1, 0x08, 0xf6
+};
+
+static const uint8_t spBooleansInMapNWF[] =
+{
+   0xa1, 0x08, 0x1a
+};
+
+static const uint8_t spNullInMap[] =
+{
+   0xa1, 0x08, 0xf6
+};
+
+static const uint8_t spUndefinedInMap[] =
+{
+   0xa1, 0x08, 0xf7
+};
+
+
+int32_t BoolTest(void)
+{
+   QCBORDecodeContext DCtx;
+   bool               b;
+
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBooleansInMap),
+                    0);
+   QCBORDecode_EnterMap(&DCtx, NULL);
+   QCBORDecode_GetBool(&DCtx, &b);
+   if(QCBORDecode_GetAndResetError(&DCtx) || !b) {
+      return 1;
+   }
+
+   QCBORDecode_GetBoolInMapN(&DCtx, 7, &b);
+   if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_LABEL_NOT_FOUND) {
+       return 2;
+   }
+
+   QCBORDecode_GetBoolInMapN(&DCtx, 8, &b);
+   if(QCBORDecode_GetAndResetError(&DCtx) || !b) {
+      return 3;
+   }
+
+
+   QCBORDecode_GetBoolInMapSZ(&DCtx, "xx", &b);
+   if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_LABEL_NOT_FOUND) {
+       return 4;
+    }
+
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBooleansInMapWrongType),
+                    0);
+   QCBORDecode_EnterMap(&DCtx, NULL);
+   QCBORDecode_GetBool(&DCtx, &b);
+   if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) {
+      return 5;
+   }
+
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBooleansInMapNWF),
+                    0);
+   QCBORDecode_EnterMap(&DCtx, NULL);
+   QCBORDecode_GetBool(&DCtx, &b);
+   if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_HIT_END) {
+      return 6;
+   }
+
+
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spNullInMap),
+                    0);
+   QCBORDecode_EnterMap(&DCtx, NULL);
+   QCBORDecode_GetNull(&DCtx);
+   if(QCBORDecode_GetAndResetError(&DCtx)) {
+      return 7;
+   }
+
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBooleansInMap),
+                    0);
+   QCBORDecode_EnterMap(&DCtx, NULL);
+   QCBORDecode_GetNull(&DCtx);
+   if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) {
+      return 8;
+   }
+
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spNullInMap),
+                    0);
+   QCBORDecode_EnterMap(&DCtx, NULL);
+   QCBORDecode_GetNullInMapN(&DCtx, 8);
+   if(QCBORDecode_GetAndResetError(&DCtx)) {
+      return 9;
+   }
+
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBooleansInMap),
+                    0);
+   QCBORDecode_EnterMap(&DCtx, NULL);
+   QCBORDecode_GetNullInMapN(&DCtx, 8);
+   if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) {
+      return 10;
+   }
+
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBooleansInMapNWF),
+                    0);
+   QCBORDecode_EnterMap(&DCtx, NULL);
+   QCBORDecode_GetUndefined(&DCtx);
+   if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_HIT_END) {
+      return 11;
+   }
+
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spUndefinedInMap),
+                    0);
+   QCBORDecode_EnterMap(&DCtx, NULL);
+   QCBORDecode_GetUndefined(&DCtx);
+   if(QCBORDecode_GetAndResetError(&DCtx)) {
+      return 12;
+   }
+
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBooleansInMap),
+                    0);
+   QCBORDecode_EnterMap(&DCtx, NULL);
+   QCBORDecode_GetUndefined(&DCtx);
+   if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) {
+      return 13;
+   }
+
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spUndefinedInMap),
+                    0);
+   QCBORDecode_EnterMap(&DCtx, NULL);
+   QCBORDecode_GetUndefinedInMapN(&DCtx, 8);
+   if(QCBORDecode_GetAndResetError(&DCtx)) {
+      return 14;
+   }
+
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBooleansInMap),
+                    0);
+   QCBORDecode_EnterMap(&DCtx, NULL);
+   QCBORDecode_GetUndefinedInMapN(&DCtx, 8);
+   if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_UNEXPECTED_TYPE) {
+      return 15;
+   }
+
+   QCBORDecode_Init(&DCtx,
+                    UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBooleansInMapNWF),
+                    0);
+   QCBORDecode_EnterMap(&DCtx, NULL);
+   QCBORDecode_GetUndefined(&DCtx);
+   if(QCBORDecode_GetAndResetError(&DCtx) != QCBOR_ERR_HIT_END) {
+      return 15;
+   }
+
    return 0;
 }
diff --git a/test/qcbor_decode_tests.h b/test/qcbor_decode_tests.h
index 7e11e35..54e125a 100644
--- a/test/qcbor_decode_tests.h
+++ b/test/qcbor_decode_tests.h
@@ -1,6 +1,6 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2020, Laurence Lundblade.
+ Copyright (c) 2018-2021, Laurence Lundblade.
  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -112,6 +112,10 @@
  */
 int32_t ParseMapTest(void);
 
+/*
+  Parses a map that contains a zero-length map as value.
+*/
+int32_t ParseEmptyMapInMapTest(void);
 
 /*
 Test the decoder mode where maps are treated as arrays.
@@ -243,7 +247,7 @@
 int32_t SetUpAllocatorTest(void);
 
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
 /*
  Test decoding of decimal fractions and big floats, both of which are
  made up of an exponent and mantissa.
@@ -255,7 +259,7 @@
  Hostile input tests for decimal fractions and big floats.
  */
 int32_t ExponentAndMantissaDecodeFailTests(void);
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
 
 
 int32_t EnterMapTest(void);
@@ -301,8 +305,13 @@
 /*
  Test PeekNext().
  */
-int32_t PeekTest(void);
+int32_t PeekAndRewindTest(void);
 
 
+/*
+Test decoding of booleans
+*/
+int32_t BoolTest(void);
+
 
 #endif /* defined(__QCBOR__qcbort_decode_tests__) */
diff --git a/test/qcbor_encode_tests.c b/test/qcbor_encode_tests.c
index f9d8507..6655aed 100644
--- a/test/qcbor_encode_tests.c
+++ b/test/qcbor_encode_tests.c
@@ -1,6 +1,6 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2020, Laurence Lundblade.
+ Copyright (c) 2018-2021, Laurence Lundblade.
  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -96,7 +96,7 @@
 #endif
 
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
 /*
  Returns 0 if UsefulBufs are equal
  Returns 1000000 + offeset if they are not equal.
@@ -116,10 +116,10 @@
                                 struct UBCompareDiagnostic *pDiag) {
    size_t i;
    for(i = 0; i < Actual.len; i++) {
-      if(((uint8_t *)Actual.ptr)[i] != ((uint8_t *)Expected.ptr)[i]) {
+      if(((const uint8_t *)Actual.ptr)[i] != ((const uint8_t *)Expected.ptr)[i]) {
          if(pDiag) {
-            pDiag->uActual   = ((uint8_t *)Actual.ptr)[i];
-            pDiag->uExpected = ((uint8_t *)Expected.ptr)[i];
+            pDiag->uActual   = ((const uint8_t *)Actual.ptr)[i];
+            pDiag->uExpected = ((const uint8_t *)Expected.ptr)[i];
             pDiag->uOffset   = i;
          }
          // Cast to int is OK as this is only a diagnostic and the sizes
@@ -130,7 +130,7 @@
    return 0;
 
 }
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
 
 
 // One big buffer that is used by all the tests to encode into
@@ -2513,7 +2513,7 @@
 }
 
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
 /*
    [
       4([-1, 3]),
@@ -2711,7 +2711,7 @@
    return 0;
 }
 
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
 
 
 int32_t QCBORHeadTest()
diff --git a/test/qcbor_encode_tests.h b/test/qcbor_encode_tests.h
index e54168a..ae64f7d 100644
--- a/test/qcbor_encode_tests.h
+++ b/test/qcbor_encode_tests.h
@@ -1,6 +1,6 @@
 /*==============================================================================
  Copyright (c) 2016-2018, The Linux Foundation.
- Copyright (c) 2018-2020, Laurence Lundblade.
+ Copyright (c) 2018-2021, Laurence Lundblade.
  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -165,13 +165,13 @@
 int32_t CoseSign1TBSTest(void);
 
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
 /*
  Test encoding of decimal fractions and big floats, both of which are
  made up of an exponent and mantissa
  */
 int32_t ExponentAndMantissaEncodeTests(void);
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
 
 
 /*
diff --git a/test/run_tests.c b/test/run_tests.c
index 0146d93..53d83f6 100644
--- a/test/run_tests.c
+++ b/test/run_tests.c
@@ -1,7 +1,7 @@
 /*==============================================================================
  run_tests.c -- test aggregator and results reporting
 
- Copyright (c) 2018-2020, Laurence Lundblade. All rights reserved.
+ Copyright (c) 2018-2021, Laurence Lundblade. All rights reserved.
 
  SPDX-License-Identifier: BSD-3-Clause
 
@@ -20,6 +20,12 @@
 #include "UsefulBuf_Tests.h"
 
 
+
+// For size printing and some conditionals
+#include "qcbor/qcbor_encode.h"
+#include "qcbor/qcbor_decode.h"
+#include "qcbor/qcbor_spiffy_decode.h"
+
 /*
  Test configuration
  */
@@ -123,13 +129,15 @@
     TEST_ENTRY(CBORSequenceDecodeTests),
     TEST_ENTRY(IntToTests),
     TEST_ENTRY(DecodeTaggedTypeTests),
-    TEST_ENTRY(PeekTest),
-#ifndef     QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+    TEST_ENTRY(PeekAndRewindTest),
+#ifndef     QCBOR_DISABLE_EXP_AND_MANTISSA
     TEST_ENTRY(EncodeLengthThirtyoneTest),
     TEST_ENTRY(ExponentAndMantissaDecodeTests),
     TEST_ENTRY(ExponentAndMantissaDecodeFailTests),
     TEST_ENTRY(ExponentAndMantissaEncodeTests),
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
+    TEST_ENTRY(ParseEmptyMapInMapTest),
+    TEST_ENTRY(BoolTest)
 };
 
 
@@ -295,10 +303,6 @@
 }
 
 
-// For size printing
-#include "qcbor/qcbor_encode.h"
-#include "qcbor/qcbor_decode.h"
-#include "qcbor/qcbor_spiffy_decode.h"
 
 
 /*