Big simplification and cleanup of example (#94)

Removed the decoding example that are not spiffy decode so the whole example is much cleaner and easier to look at
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;