merge new tag encoding design
diff --git a/README.md b/README.md
index 34d8614..0b4e71b 100644
--- a/README.md
+++ b/README.md
@@ -61,6 +61,7 @@
 * Minimal length float encoding is added
 * indefinite length arrays/maps are supported
 * indefinite length strings are supported
+* Tag decoding is changed; unlimited number of tags supported, any tag value supported, tag utility function for easier tag checking
 * Addition functions in UsefulBuf
 * QCBOREncode_Init takes a UsefulBuf instead of a pointer and size
 * QCBOREncode_Finish takes a UsefulBufC and EncodedCBOR is remove
@@ -79,3 +80,4 @@
 
 
 
+
diff --git a/cmd_line_main.c b/cmd_line_main.c
index ee1180a..a01a0e0 100644
--- a/cmd_line_main.c
+++ b/cmd_line_main.c
@@ -51,6 +51,7 @@
     printf("sizeof(QCBORItem) %d\n", (uint32_t)sizeof(QCBORItem));
     printf("sizeof(QCBORStringAllocator) %d\n\n", (uint32_t)sizeof(QCBORStringAllocator));
 
+    // TODO: command line arg to select test
     int nNumTestsFailed = run_tests(&fputs_wrapper, stdout, NULL);
 
     return nNumTestsFailed;
diff --git a/inc/UsefulBuf.h b/inc/UsefulBuf.h
index c2b2e09..1d95477 100644
--- a/inc/UsefulBuf.h
+++ b/inc/UsefulBuf.h
@@ -311,7 +311,7 @@
  The terminating \0 (NULL) is NOT included in the length!
  
  */
-#define UsefulBuf_FromSZLiteral(szString) \
+#define UsefulBuf_FROM_SZ_LITERAL(szString) \
     ((UsefulBufC) {(szString), sizeof(szString)-1})
 
 
@@ -322,7 +322,7 @@
  It will not work on  non-literal arrays.
  
  */
-#define UsefulBuf_FromByteArrayLiteral(pBytes) \
+#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
     ((UsefulBufC) {(pBytes), sizeof(pBytes)})
 
 
@@ -330,12 +330,18 @@
  Make an automatic variable with name of type UsefulBuf and point it to a stack
  variable of the give size
  */
-#define  UsefulBuf_MakeStackUB(name, size) \
+#define  UsefulBuf_MAKE_STACK_UB(name, size) \
     uint8_t    __pBuf##name[(size)];\
     UsefulBuf  name = {__pBuf##name , sizeof( __pBuf##name )}
 
 
 /**
+ Make a byte array in to a UsefulBuf
+ */
+#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
+    ((UsefulBuf) {(pBytes), sizeof(pBytes)})
+
+/**
  @brief Convert a NULL terminated string to a UsefulBufC.
 
  @param[in] szString The string to convert
@@ -354,26 +360,6 @@
 
 
 /**
- @brief Copy one UsefulBuf into another
- 
- @param[in] Dest The destination buffer to copy into
- @param[out] Src  The source to copy from
- 
- @return filled in UsefulBufC on success, NULLUsefulBufC on failure
- 
- This fails if Src.len is greater than Dest.len.
- 
- Note that like memcpy, the pointers are not checked and
- this will crash, rather than return NULLUsefulBufC if
- they are NULL or invalid.
- 
- Results are undefined if Dest and Src overlap.
- 
- */
-UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
-
-
-/**
  @brief Copy one UsefulBuf into another at an offset
  
  @param[in] Dest Destiation buffer to copy into
@@ -395,6 +381,27 @@
 UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
 
 
+/**
+ @brief Copy one UsefulBuf into another
+ 
+ @param[in] Dest The destination buffer to copy into
+ @param[out] Src  The source to copy from
+ 
+ @return filled in UsefulBufC on success, NULLUsefulBufC on failure
+ 
+ This fails if Src.len is greater than Dest.len.
+ 
+ Note that like memcpy, the pointers are not checked and
+ this will crash, rather than return NULLUsefulBufC if
+ they are NULL or invalid.
+ 
+ Results are undefined if Dest and Src overlap.
+ 
+ */
+static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src) {
+   return UsefulBuf_CopyOffset(Dest, 0, Src);
+}
+
 
 /**
  @brief Set all bytes in a UsefulBuf to a value, for example 0
@@ -406,9 +413,10 @@
  this will crash if NULL or invalid.
  
  */
-static inline void UsefulBuf_Set(UsefulBuf *pDest, uint8_t value)
+static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value)
 {
-    memset(pDest->ptr, value, pDest->len);
+   memset(pDest.ptr, value, pDest.len);
+   return (UsefulBufC){pDest.ptr, pDest.len};
 }
 
 
@@ -509,17 +517,17 @@
 
 
 
-#if 1 // NOT_DEPRECATED
-/** Deprecated macro; use UsefulBuf_FromSZLiteral instead */
+#if 0 // NOT_DEPRECATED
+/** Deprecated macro; use UsefulBuf_FROM_SZ_LITERAL instead */
 #define SZLiteralToUsefulBufC(szString) \
     ((UsefulBufC) {(szString), sizeof(szString)-1})
 
-/** Deprecated macro; use UsefulBuf_MakeStackUB instead */
+/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
 #define  MakeUsefulBufOnStack(name, size) \
     uint8_t    __pBuf##name[(size)];\
     UsefulBuf  name = {__pBuf##name , sizeof( __pBuf##name )}
 
-/** Deprecated macro; use UsefulBuf_FromByteArrayLiteral instead */
+/** Deprecated macro; use UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
 #define ByteArrayLiteralToUsefulBufC(pBytes) \
     ((UsefulBufC) {(pBytes), sizeof(pBytes)})
 
diff --git a/inc/qcbor.h b/inc/qcbor.h
index 7d8b138..fd45f1a 100644
--- a/inc/qcbor.h
+++ b/inc/qcbor.h
@@ -191,6 +191,10 @@
    // private part of this file and QCBORStringAllocat is defined
    // later in the public part of this file.
    void *pStringAllocator;
+   
+   // This is NULL or points to QCBORTagList.
+   // It is type void for the same reason as above.
+   const void *pCallerConfiguredTagList;
 };
 
 // Used internally in the impementation here
@@ -198,6 +202,7 @@
 #define CBOR_MAJOR_NONE_TYPE_RAW  9
 #define CBOR_MAJOR_NONE_TAG_LABEL_REORDER 10
 
+
 /* ===========================================================================
    END OF PRIVATE PART OF THIS FILE
 
@@ -274,6 +279,11 @@
 #define CBOR_TAG_NEG_BIGNUM     3
 #define CBOR_TAG_FRACTION       4
 #define CBOR_TAG_BIGFLOAT       5
+
+#define CBOR_TAG_COSE_ENCRYPTO 16
+#define CBOR_TAG_COSE_MAC0     17
+#define CBOR_TAG_COSE_SIGN1    18
+
 /* The data in byte string should be converted in base 64 URL when encoding in JSON or similar text-based representations */
 #define CBOR_TAG_ENC_AS_B64URL 21
 /* The data in byte string should be encoded in base 64 when encoding in JSON */
@@ -293,6 +303,16 @@
 #define CBOR_TAG_MIME          36
 /** Binary UUID */
 #define CBOR_TAG_BIN_UUID      37
+
+#define CBOR_TAG_CWT           61
+
+#define CBOR_TAG_ENCRYPT       96
+#define CBOR_TAG_MAC           97
+#define CBOR_TAG_SIGN          98
+
+#define CBOR_TAG_GEO_COORD    103
+
+
 /** The data is CBOR data */
 #define CBOR_TAG_CBOR_MAGIC 55799
 #define CBOR_TAG_NONE  UINT64_MAX
@@ -406,8 +426,8 @@
  
  Implementors using this API will primarily work with labels. Generally
  tags are only needed for making up new data types. This implementation
- covers most of the data types defined in the RFC using tags. However,
- it does allow for the creation of news tags if necessary.
+ covers most of the data types defined in the RFC using tags. It also,
+ allows for the creation of news tags if necessary.
  
  This implementation explicitly supports labels that are text strings
  and integers. Text strings translate nicely into JSON objects and
@@ -473,7 +493,7 @@
  
  Note that when you nest arrays or maps in a map, the nested
  array or map has a label.
- 
+
  Usually it is not necessary to add tags explcitly as most
  tagged types have functions here, but they can be added by
  calling QCBOREncode_AddTag().  There is an IANA registry for new tags that are
@@ -524,6 +544,12 @@
 */
 #define QCBOR_MAX_ARRAY_NESTING  QCBOR_MAX_ARRAY_NESTING1
 
+/**
+ The maximum number of tags that can be in QCBORTagListIn and passed to
+ QCBORDecode_SetCallerConfiguredTagList()
+ */
+#define QCBOR_MAX_CUSTOM_TAGS    16
+
 
 
 
@@ -607,6 +633,9 @@
 /** The a break occurred outside an indefinite length item */
 #define QCBOR_ERR_BAD_BREAK               21
 
+/** Too many tags in the caller-configured tag list, or not enough space in QCBORTagListOut */
+#define QCBOR_ERR_TOO_MANY_TAGS           22
+
 
 /** See QCBORDecode_Init() */
 #define QCBOR_DECODE_MODE_NORMAL            0
@@ -695,6 +724,7 @@
       UsefulBufC  dateString; /** The value for uDataType QCBOR_TYPE_DATE_STRING */
       UsefulBufC  bigNum;     /** The value for uDataType QCBOR_TYPE_BIGNUM */
       uint8_t     uSimple;    /** The integer value for unknown simple types */
+      uint64_t    uTagV;
       
    } val;  /** The union holding the item's value. Select union member based on uDataType */
    
@@ -704,8 +734,7 @@
       uint64_t    uint64;  /** The label for uLabelType for QCBOR_TYPE_UINT64 */
    } label; /** Union holding the different label types selected based on uLabelType */
    
-   uint64_t uTag;     /** Any tag value that is greater than 63.  If there is more than one, then only the last one is recorded */
-   uint64_t uTagBits; /** Bits corresponding to tag values less than 63 as defined in RFC 7049, section 2.4 */
+   uint64_t uTagBits; /** Bit indicating which tags (major type 6) on this item.  */
    
 } QCBORItem;
 
@@ -739,25 +768,40 @@
 } QCBORStringAllocator;
 
 
-/** See the descriptions for CBOR_SIMPLEV_FALSE, CBOR_TAG_DATE_EPOCH... for
-    the meaning of the individual tags.  The values here are bit flags
-    associated with each tag.  These flags are set in uTagsBits in QCBORItem */
-#define QCBOR_TAGFLAG_DATE_STRING    (0x01LL << CBOR_TAG_DATE_STRING)
-#define QCBOR_TAGFLAG_DATE_EPOCH     (0x01LL << CBOR_TAG_DATE_EPOCH)
-#define QCBOR_TAGFLAG_POS_BIGNUM     (0x01LL << CBOR_TAG_POS_BIGNUM)
-#define QCBOR_TAGFLAG_NEG_BIGNUM     (0x01LL << CBOR_TAG_NEG_BIGNUM)
-#define QCBOR_TAGFLAG_FRACTION       (0x01LL << CBOR_TAG_FRACTION)
-#define QCBOR_TAGFLAG_BIGFLOAT       (0x01LL << CBOR_TAG_BIGFLOAT)
-#define QCBOR_TAGFLAG_ENC_AS_B64URL  (0x01LL << CBOR_TAG_ENC_AS_B64URL)
-#define QCBOR_TAGFLAG_ENC_AS_B64     (0x01LL << CBOR_TAG_ENC_AS_B64)
-#define QCBOR_TAGFLAG_ENC_AS_B16     (0x01LL << CBOR_TAG_ENC_AS_B16)
-#define QCBOR_TAGFLAG_CBOR           (0x01LL << CBOR_TAG_CBOR)
-#define QCBOR_TAGFLAG_URI            (0x01LL << CBOR_TAG_URI)
-#define QCBOR_TAGFLAG_B64URL         (0x01LL << CBOR_TAG_B64URL)
-#define QCBOR_TAGFLAG_B64            (0x01LL << CBOR_TAG_B64)
-#define QCBOR_TAGFLAG_REGEX          (0x01LL << CBOR_TAG_REGEX)
-#define QCBOR_TAGFLAG_MIME           (0x01LL << CBOR_TAG_MIME)
-#define QCBOR_TAGFLAG_CBOR_MAGIC     (0x01ULL << 63)
+
+/**
+ This is used to tell the decoder about tags that it should
+ record in uTagBits in QCBORItem beyond the built-in
+ tags. puTags points to an
+ array of uint64_t integers that are the tags. uNumTags
+ is the number of integers in the array. The maximum
+ size is QCBOR_MAX_CUSTOM_TAGS.  See QCBORDecode_IsTagged()
+ and QCBORDecode_SetCallerAddedTagMap().
+ */
+typedef struct {
+   uint8_t uNumTags;
+   const uint64_t *puTags;
+} QCBORTagListIn;
+
+
+/**
+ This is for QCBORDecode_GetNextWithTags() to be able to return the
+ full list of  tags on an item. It not needed for most CBOR protocol
+ implementations. Its primary use is for pretty-printing CBOR or
+ protocol conversion to another format.
+ 
+ On input, puTags points to a buffer to be filled in
+ and uNumAllocated is the number of uint64_t values
+ in the buffer.
+ 
+ On output the buffer contains the tags for the item.
+ uNumUsed tells how many there are.
+ */
+typedef struct {
+   uint8_t uNumUsed;
+   uint8_t uNumAllocated;
+   uint64_t *puTags;
+} QCBORTagListOut;
 
 
 /**
@@ -1737,7 +1781,7 @@
 
 /**
  QCBORDecodeContext is the data type that holds context decoding the
- data items for some received CBOR.  It is about 50 bytes so it can go
+ data items for some received CBOR.  It is about 100 bytes so it can go
  on the stack.  The contents are opaque and the caller should not
  access any internal items.  A context may be re used serially as long
  as it is re initialized.
@@ -1755,6 +1799,14 @@
  
  Initialize context for a pre-order traveral of the encoded CBOR tree.
  
+ Most CBOR decoding can be completed by calling this function to start
+ and QCBORDecode_GetNext() in a loop.  If indefinite length strings
+ are to be decoded, then QCBORDecode_SetMemPool() or QCBORDecode_SetUpAllocator()
+ must be called.  If tags other than built-in tags are to be
+ recognized, then QCBORDecode_SetCallerAddedTagMap() must be called.
+ The built-in tags are those for which a macro of the form
+ CBOR_TAG_XXX is defined.
+ 
  Three decoding modes are supported.  In normal mode, maps are decoded
  and strings and ints are accepted as map labels. If a label is other
  than these, the error QCBOR_ERR_MAP_LABEL_TYPE is returned by
@@ -1774,7 +1826,7 @@
 /**
  Set up the MemPool string allocator for indefinite length strings.
  
- @param[in] pCtx The decode context to initialize.
+ @param[in] pCtx The decode context.
  @param[in] MemPool The pointer and length of the memory pool.
  @param[in] bAllStrings true means to put even definite length strings in the pool.
  
@@ -1826,6 +1878,22 @@
 
 
 /**
+ @brief Configure list of caller selected tags to be recognized
+ 
+ @param[in] pCtx The decode context.
+ @param[out] pTagList Structure holding the list of tags to configure
+ 
+ This is used to tell the decoder about tags beyond those that are
+ built-in that should be recognized. The built-in tags are those
+ with macros of the form CBOR_TAG_XXX.
+ 
+ See description of QCBORTagListIn.
+ */
+
+void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pCtx, const QCBORTagListIn *pTagList);
+
+
+/**
  @brief This returns a string allocator that uses malloc
  
  @return pointer to string allocator or NULL
@@ -1846,13 +1914,12 @@
 
 
 /**
- Gets the next item (integer, byte string, array...) in pre order traversal of CBOR tree
+ @brief Gets the next item (integer, byte string, array...) in pre order traversal of CBOR tree
  
  @param[in]  pCtx          The decoder context.
  @param[out] pDecodedItem  Holds the CBOR item just decoded.
  
- @return
- 0 or error.
+ @return 0 or error.
  
  pDecodedItem is filled in with the value parsed. Generally, the
  folloinwg data is returned in the structure.
@@ -1881,10 +1948,6 @@
  if Items in the array or map.  Typically an implementation will call
  QCBORDecode_GetNext() in a for loop to fetch them all.
  
- Optional tags are integer tags that are prepended to the actual data
- item. That tell more about the data. For example it can indicate data
- is a date or a big number or a URL.
- 
  Note that when traversing maps, the count is the number of pairs of
  items, so the for loop would decrement once for every two calls to
  QCBORDecode_GetNext().
@@ -1938,25 +2001,105 @@
  the end of the current map or array has been encountered. This
  works the same for both definite and indefinite length arrays.
  
+ Most uses of this decoder will not need to do anything extra for
+ tag handling. The built-in tags, those with a macro of the form
+ CBOR_TAG_XXXX, will be enough.
+
+ If tags beyond built-in tags are to be recognized, they must be
+ configured by calling QCBORDecode_SetCallerConfiguredTags(). If
+ a tag is not recognized it is silently ignored.
+ 
+ Several tagged types are automatically recognized and decoded and
+ returned in their decoded form.
+ 
+ To find ound if a QCBORItem was tagged with a particular tag
+ call QCBORDecode_IsTagged(). This works only for built-in
+ tags and caller-configured tags.
+ 
+ To get the full list of tags on an Item without having to
+ pre-configure any predetermined list of tags use
+ QCBORDecode_GetNextWithTags().
+ 
  */
 
 int QCBORDecode_GetNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
 
 
 /**
- Check whether all the bytes have been decoded
+ @brief Gets the next item including full list of tags for item
+ 
+ @param[in]  pCtx          The decoder context.
+ @param[out] pDecodedItem  Holds the CBOR item just decoded.
+ @param[in,out] pTagList   On input array to put tags in; on output the tags on this item.
+ 
+ @return 0 or error.
+ 
+ This works the same as QCBORDecode_GetNext() except that it also returns
+ the full list of tags for the data item. This function should only
+ be needed when parsing CBOR to print it out or convert it to some other
+ format. It should not be needed in an actual CBOR protocol implementation.
+ 
+ Tags will be returned here whether or not they are in the built-in or
+ caller-configured tag lists.
+ 
+ CBOR has no upper bound of limit on the number of tags that can be
+ associated with a data item. In practice the number of tags on an item
+ will usually be small, perhaps less than five. This will return an error
+ if the array in pTagList is too small to hold all the tags for an item.
+ 
+ (This function is separate from  QCBORDecode_GetNext() so as to not have to
+ make QCBORItem large enough to be able to hold a full list of tags. Even a list of
+ five tags would nearly double its size because tags can be a uint64_t).
+ 
+ */
+
+int QCBORDecode_GetNextWithTags(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem, QCBORTagListOut *pTagList);
+
+
+/**
+ @brief Determine if a CBOR item was tagged with a particular tag
+ 
+ @param[in] pCtx    The decoder context.
+ @param[in] pItem   The CBOR item to check
+ @param[in] uTag    The tag to check
+
+ @return 1 if it was tagged, 0 if not
+ 
+ QCBORDecode_GetNext() processes tags by looking them up
+ in two lists and setting a bit corresponding to the tag
+ in uTagBits in the QCBORItem. To find out if a
+ QCBORItem was tagged with a particular tag, call
+ this function. It handles the mapping between
+ the two lists of tags and the bits set for it.
+ 
+ The first tag list is the built-in tags, those
+ with a macro of the form CBOR_TAG_XXX in this
+ header file. There are up to 48 of these,
+ corresponding to the lower 48 tag bits.
+ 
+ The other optional tag list is the ones
+ the caller configured using QCBORDecode_SetCallerConfiguredTagList()
+ There are QCBOR_MAX_CUSTOM_TAGS (16) of these corresponding to the
+ upper 16 tag bits.
+ 
+ See also QCBORDecode_GetTags() and QCBORDecode_GetNextWithTags()
+ 
+ */
+int QCBORDecode_IsTagged(QCBORDecodeContext *pCtx, const QCBORItem *pItem, uint64_t uTag);
+
+
+/**
+ Check whether all the bytes have been decoded and maps and arrays closed.
  
  @param[in]  pCtx          The context to check
  
- @return QCBOR_ERR_EXTRA_BYTES or QCBOR_SUCCESS
+ @return QCBOR_SUCCESS or error
  
- This tells you if all the bytes give to QCBORDecode_Init() have
- been consumed or not. In most cases all bytes should be consumed
- in a correct parse. 
- 
- It is OK to call this multiple times during decoding and to call
- QCBORDecode_GetNext() after calling this. This only
- performs a check. It does not change the state of the decoder.
+ This tells you if all the bytes given to QCBORDecode_Init() have
+ been consumed and whether all maps and arrays were closed.
+ The decode is considered to be incorrect or incomplete if not
+ and an error will be returned.
+
  */
 
 int QCBORDecode_Finish(QCBORDecodeContext *pCtx);
diff --git a/src/UsefulBuf.c b/src/UsefulBuf.c
index dcd7d34..4da1425 100644
--- a/src/UsefulBuf.c
+++ b/src/UsefulBuf.c
@@ -80,20 +80,6 @@
 
 #define USEFUL_OUT_BUF_MAGIC  (0x0B0F) // used to catch use of uninitialized or corrupted UOBs
 
-/*
-   Public function -- see UsefulBuf.h
- */
-UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
-{
-   if(Src.len > Dest.len) {
-      return NULLUsefulBufC;
-   }
-   
-   memcpy(Dest.ptr, Src.ptr, Src.len);
-    
-   return((UsefulBufC){Dest.ptr, Src.len});
-}
-
 
 /*
  Public function -- see UsefulBuf.h
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 831843c..db761d4 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -204,6 +204,126 @@
 
 
 
+/*
+ This list of built-in tags. Only add tags here that are
+ clearly established and useful. Once a tag is added here
+ it can't be taken out as that would break backwards compatibility.
+ There are only 48 slots available forever.
+ */
+static const uint16_t spBuiltInTagMap[] = {
+   CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_FOUR
+   CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_FOUR
+   CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_FOUR
+   CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_FOUR
+   CBOR_TAG_FRACTION,
+   CBOR_TAG_BIGFLOAT,
+   CBOR_TAG_COSE_ENCRYPTO,
+   CBOR_TAG_COSE_MAC0,
+   CBOR_TAG_COSE_SIGN1,
+   CBOR_TAG_ENC_AS_B64URL,
+   CBOR_TAG_ENC_AS_B64,
+   CBOR_TAG_ENC_AS_B16,
+   CBOR_TAG_CBOR,
+   CBOR_TAG_URI,
+   CBOR_TAG_B64URL,
+   CBOR_TAG_B64,
+   CBOR_TAG_REGEX,
+   CBOR_TAG_MIME,
+   CBOR_TAG_BIN_UUID,
+   CBOR_TAG_CWT,
+   CBOR_TAG_ENCRYPT,
+   CBOR_TAG_MAC,
+   CBOR_TAG_SIGN,
+   CBOR_TAG_GEO_COORD,
+   CBOR_TAG_CBOR_MAGIC
+};
+
+// This is used in a bit of cleverness in GetNext_TaggedItem() to
+// keep code size down and switch for the internal processing of
+// these types. This will break if the first four items in
+// spBuiltInTagMap don't have values 0,1,2,3. That is the
+// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3.
+#define QCBOR_TAGFLAG_DATE_STRING    (0x01LL << CBOR_TAG_DATE_STRING)
+#define QCBOR_TAGFLAG_DATE_EPOCH     (0x01LL << CBOR_TAG_DATE_EPOCH)
+#define QCBOR_TAGFLAG_POS_BIGNUM     (0x01LL << CBOR_TAG_POS_BIGNUM)
+#define QCBOR_TAGFLAG_NEG_BIGNUM     (0x01LL << CBOR_TAG_NEG_BIGNUM)
+
+#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
+                               QCBOR_TAGFLAG_DATE_EPOCH  |\
+                               QCBOR_TAGFLAG_POS_BIGNUM  |\
+                               QCBOR_TAGFLAG_NEG_BIGNUM)
+
+#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
+#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
+#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
+
+static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
+{
+   if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
+      // This is a cross-check to make sure the above array doesn't
+      // accidentally get made too big.
+      // In normal conditions the above test should optimize out
+      // as all the values are known at compile time.
+      return -1;
+   }
+   
+   if(uTag > UINT16_MAX) {
+      // This tag map works only on 16-bit tags
+      return -1;
+   }
+   
+   for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
+      if(spBuiltInTagMap[nTagBitIndex] == uTag) {
+         return nTagBitIndex;
+      }
+   }
+   return -1; // Indicates no match
+}
+
+static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
+{
+   for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
+      if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
+         return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
+      }
+   }
+   
+   return -1; // Indicates no match
+}
+
+/*
+  Find the tag bit index for a given tag value, or error out
+ 
+ This and the above functions could probably be optimized and made
+ clearer and neater. 
+ */
+static int TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag, uint8_t *puTagBitIndex)
+{
+   int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
+   if(nTagBitIndex >= 0) {
+      // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
+      *puTagBitIndex = (uint8_t)nTagBitIndex;
+      return QCBOR_SUCCESS;
+   }
+   
+   if(pCallerConfiguredTagMap) {
+      if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
+         return QCBOR_ERR_TOO_MANY_TAGS;
+      }
+      nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
+      if(nTagBitIndex >= 0) {
+         // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
+
+         *puTagBitIndex = (uint8_t)nTagBitIndex;
+         return QCBOR_SUCCESS;
+      }
+   }
+   
+   return QCBOR_ERR_BAD_OPT_TAG;
+}
+
+
+
 
 /*
  Public function, see header file
@@ -224,10 +344,15 @@
  */
 void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx, const QCBORStringAllocator *pAllocator, bool bAllocAll)
 {
-    pCtx->pStringAllocator = (void *)pAllocator;
+   pCtx->pStringAllocator = (void *)pAllocator;
    pCtx->bStringAllocateAll = bAllocAll;
 }
 
+void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me, const QCBORTagListIn *pTagList)
+{
+   me->pCallerConfiguredTagList = pTagList;
+}
+
 
 /*
  This decodes the fundamental part of a CBOR data item, the type and number
@@ -246,6 +371,7 @@
  */
 inline static int DecodeTypeAndNumber(UsefulInputBuf *pUInBuf, int *pnMajorType, uint64_t *puNumber, uint8_t *puAdditionalInfo)
 {
+   // Stack usage: int/ptr 5 -- 40
    int nReturn;
    
    // Get the initial byte that every CBOR data item has
@@ -323,6 +449,7 @@
  */
 inline static int DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
 {
+   // Stack usage: int/ptr 1 -- 8
    int nReturn = QCBOR_SUCCESS;
    
    if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
@@ -385,6 +512,7 @@
 
 inline static int DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
 {
+   // Stack usage: 0
    int nReturn = QCBOR_SUCCESS;
    
    // uAdditionalInfo is 5 bits from the initial byte
@@ -443,6 +571,7 @@
  */
 inline static int DecodeBytes(const QCBORStringAllocator *pAlloc, int nMajorType, uint64_t uStrLen, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
 {
+   // Stack usage: UsefulBuf 2, int/ptr 1  40
    int nReturn = QCBOR_SUCCESS;
    
    UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uStrLen);
@@ -474,15 +603,16 @@
 /*
  Mostly just assign the right data type for the date string.
  */
-inline static int DecodeDateString(QCBORItem Item, QCBORItem *pDecodedItem)
+inline static int DecodeDateString(QCBORItem *pDecodedItem)
 {
-   if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) {
+   // Stack Use: UsefulBuf 1 16
+   if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
       return QCBOR_ERR_BAD_OPT_TAG;
    }
-   pDecodedItem->val.dateString = Item.val.string;
-   pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
-   pDecodedItem->uTagBits = Item.uTagBits;
-   pDecodedItem->uTag = Item.uTag;
+   
+   UsefulBufC Temp              = pDecodedItem->val.string;
+   pDecodedItem->val.dateString = Temp;
+   pDecodedItem->uDataType      = QCBOR_TYPE_DATE_STRING;
    return QCBOR_SUCCESS;
 }
 
@@ -490,15 +620,15 @@
 /*
  Mostly just assign the right data type for the bignum.
  */
-inline static int DecodeBigNum(QCBORItem Item, QCBORItem *pDecodedItem, uint64_t uTagFlags)
+inline static int DecodeBigNum(QCBORItem *pDecodedItem)
 {
-   if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
+   // Stack Use: UsefulBuf 1  -- 16
+   if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
       return QCBOR_ERR_BAD_OPT_TAG;
    }
-   pDecodedItem->val.bigNum     = Item.val.string;
-   pDecodedItem->uDataType      = uTagFlags & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
-   pDecodedItem->uTagBits       = Item.uTagBits;
-   pDecodedItem->uTag           = Item.uTag;
+   UsefulBufC Temp          = pDecodedItem->val.string;
+   pDecodedItem->val.bigNum = Temp;
+   pDecodedItem->uDataType  = pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM; // TODO: check this
    return QCBOR_SUCCESS;
 }
 
@@ -506,51 +636,46 @@
 /*
  The epoch formatted date. Turns lots of different forms of encoding date into uniform one
  */
-static int DecodeDateEpoch(QCBORItem Item, QCBORItem *pDecodedItem)
+static int DecodeDateEpoch(QCBORItem *pDecodedItem)
 {
+   // Stack usage: 1
    int nReturn = QCBOR_SUCCESS;
    
-   pDecodedItem->uTagBits                       = Item.uTagBits;
-   pDecodedItem->uTag                           = Item.uTag;
-   pDecodedItem->uDataType                      = QCBOR_TYPE_DATE_EPOCH;
    pDecodedItem->val.epochDate.fSecondsFraction = 0;
+   double d = pDecodedItem->val.dfnum; // Might not use this, but keeps code flow neater below
    
-   switch (Item.uDataType) {
+   switch (pDecodedItem->uDataType) {
          
       case QCBOR_TYPE_INT64:
-         pDecodedItem->val.epochDate.nSeconds = Item.val.int64;
+         pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
          break;
          
       case QCBOR_TYPE_UINT64:
-         if(Item.val.uint64 > INT64_MAX) {
-            nReturn = QCBOR_ERR_DATE_OVERFLOW; 
+         if(pDecodedItem->val.uint64 > INT64_MAX) {
+            nReturn = QCBOR_ERR_DATE_OVERFLOW;
             goto Done;
          }
-         pDecodedItem->val.epochDate.nSeconds = Item.val.uint64;
+         pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.uint64;
          break;
          
       case QCBOR_TYPE_FLOAT:
-         // TODO: can we save code by widening a float to a double here? Then drop into double-handling code
-         if(Item.val.fnum > INT64_MAX) {
-            nReturn = QCBOR_ERR_DATE_OVERFLOW;
-            goto Done;
-         }
-         pDecodedItem->val.epochDate.nSeconds = Item.val.fnum;
-         pDecodedItem->val.epochDate.fSecondsFraction = Item.val.fnum - pDecodedItem->val.epochDate.nSeconds;
-         break;
-
+         d = pDecodedItem->val.fnum;
+         // Fall through
+         
       case QCBOR_TYPE_DOUBLE:
-         if(Item.val.dfnum > INT64_MAX) {
+         if(d > INT64_MAX) {
             nReturn = QCBOR_ERR_DATE_OVERFLOW;
             goto Done;
          }
-         pDecodedItem->val.epochDate.nSeconds = Item.val.dfnum;
-         pDecodedItem->val.epochDate.fSecondsFraction = Item.val.dfnum - pDecodedItem->val.epochDate.nSeconds;
+         pDecodedItem->val.epochDate.nSeconds = d; // Float to integer conversion happening here.
+         pDecodedItem->val.epochDate.fSecondsFraction = d - pDecodedItem->val.epochDate.nSeconds;
          break;
          
       default:
          nReturn = QCBOR_ERR_BAD_OPT_TAG;
+         goto Done;
    }
+   pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
    
 Done:
    return nReturn;
@@ -577,6 +702,7 @@
  */
 static int GetNext_Item(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, const QCBORStringAllocator *pAlloc)
 {
+   // Stack usage: int/ptr 3 -- 24
    int nReturn;
    
    // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
@@ -628,7 +754,7 @@
          break;
          
       case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
-         pDecodedItem->uTag      = uNumber;
+         pDecodedItem->val.uTagV = uNumber;
          pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
          break;
          
@@ -649,13 +775,14 @@
 
 /*
  This layer deals with indefinite length strings. It pulls all the
- individual segment items together into one QCBORItem using the
+ individual chunk items together into one QCBORItem using the
  string allocator.
  
  Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
  */
-static int GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
+static inline int GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
 {
+   // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem  -- 96
    int nReturn;
    QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)me->pStringAllocator;
    UsefulBufC FullString = NULLUsefulBufC;
@@ -689,27 +816,27 @@
    // Track which type of string it is
    const uint8_t uStringType = pDecodedItem->uDataType;
    
-   // Loop getting segments of indefinite string
+   // Loop getting chunk of indefinite string
    for(;;) {
-      // Get item for next segment
-      QCBORItem StringSegmentItem;
-      // NULL passed to never string alloc segments of indefinite length strings
-      nReturn = GetNext_Item(&(me->InBuf), &StringSegmentItem, NULL);
+      // Get item for next chunk
+      QCBORItem StringChunkItem;
+      // NULL passed to never string alloc chunk of indefinite length strings
+      nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
       if(nReturn) {
-         break;  // Error getting the next segment
+         break;  // Error getting the next chunk
       }
       
       // See if it is a marker at end of indefinite length string
-      if(StringSegmentItem.uDataType == QCBOR_TYPE_BREAK) {
+      if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
          // String is complete
          pDecodedItem->val.string = FullString;
          pDecodedItem->uDataAlloc = 1;
          break;
       }
       
-      // Match data type of segment to type at beginning.
+      // Match data type of chunk to type at beginning.
       // Also catches error of other non-string types that don't belong.
-      if(StringSegmentItem.uDataType != uStringType) {
+      if(StringChunkItem.uDataType != uStringType) {
          nReturn = QCBOR_ERR_INDEFINITE_STRING_SEG;
          break;
       }
@@ -717,15 +844,15 @@
       // Alloc new buffer or expand previously allocated buffer so it can fit
       UsefulBuf NewMem = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext,
                                               UNCONST_POINTER(FullString.ptr),
-                                              FullString.len + StringSegmentItem.val.string.len);
+                                              FullString.len + StringChunkItem.val.string.len);
       if(UsefulBuf_IsNULL(NewMem)) {
          // Allocation of memory for the string failed
          nReturn = QCBOR_ERR_STRING_ALLOC;
          break;
       }
       
-      // Copy new string segment at the end of string so far.
-      FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringSegmentItem.val.string);
+      // Copy new string chunk at the end of string so far.
+      FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
    }
    
 Done:
@@ -742,86 +869,74 @@
  Returns an error if there was something wrong with the optional item or it couldn't
  be handled.
  */
-static int GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
+static int GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
 {
-   int nReturn;
-   
-   // TODO: optimize loop below so there is only one call to GetNext_FullItem?
-   nReturn = GetNext_FullItem(me, pDecodedItem);
-   if(nReturn) {
-      goto Done;
+   // Stack usage: int/ptr: 3 -- 24
+   int       nReturn;
+   uint64_t  uTagBits = 0;
+   if(pTags) {
+      pTags->uNumUsed = 0;
    }
-   
-   if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
-      goto Done;
-   }
-   
-   uint64_t uTagFlags = 0; // accumulate the tags in the form of flags
-   uint64_t uTagToProcess = pDecodedItem->uTag; // First process tag passed in
-   
-   QCBORItem Item;
-   
-   do {
-      if(uTagToProcess < 63) { // 63 is the number of bits in a uint64 - 1
-         uTagFlags |= 0x01LL << uTagToProcess;
-      } else if(uTagToProcess == CBOR_TAG_CBOR_MAGIC) {
-         uTagFlags |= QCBOR_TAGFLAG_CBOR_MAGIC;
-      }
-      /* This code ignores the all but the first tag of value
-       greater than 63. Ignoring tags that are not understoof
-       is allowed by the standard. Multiple tags are
-       presumably rare. */
-      
-      nReturn = GetNext_FullItem(me, &Item);
+
+   for(;;) {
+      nReturn = GetNext_FullItem(me, pDecodedItem);
       if(nReturn) {
-         // Bail out of the whole item fetch on any sort of error here
-         goto Done;
+         goto Done; // Error out of the loop
       }
       
-      if(Item.uDataType != QCBOR_TYPE_OPTTAG) {
+      if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
+         // Successful exit from loop; maybe got some tags, maybe not
+         pDecodedItem->uTagBits = uTagBits;
          break;
       }
+   
+      uint8_t uTagBitIndex;
+      // Tag was mapped, tag was not mapped, error with tag list
+      switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
+            
+         case QCBOR_SUCCESS:
+            // Successfully mapped the tag
+            uTagBits |= 0x01ULL << uTagBitIndex;
+            break;
+            
+         case QCBOR_ERR_BAD_OPT_TAG:
+            // Tag is not recognized. Do nothing
+            break;
+            
+         default:
+            // Error Condition
+            goto Done;
+      }
       
-      uTagToProcess = Item.uTag;
-   } while (1);
+      if(pTags) {
+         // Caller wants all tags recorded in the provided buffer
+         if(pTags->uNumUsed >= pTags->uNumAllocated) {
+            nReturn = QCBOR_ERR_TOO_MANY_TAGS;
+            goto Done;
+         }
+         pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
+         pTags->uNumUsed++;
+      }
+   }
    
-   
-   /*
-    CBOR allows multiple tags on a data item. It also defines
-    a number of standard tag values, most of which are
-    less than 64.  This code can deal with multiple tag
-    values that are less than 64 and the last tag of multiple
-    if the value is more than 64. Or said another way
-    if there is one tag with a value >64 this code works.
-    
-    The assumption is that multiple tag values > 64 are rare.
-    
-    At this point in this code. uTagFlags has all the flags
-    < 64 and uTagToProcess has the last tag.
-    
-    Does this deal with multiple tags on an item we process?
-    */
-   
-   Item.uTagBits = uTagFlags;
-   Item.uTag = uTagToProcess;
-   
-   switch(uTagFlags & (QCBOR_TAGFLAG_DATE_STRING | QCBOR_TAGFLAG_DATE_EPOCH | QCBOR_TAGFLAG_POS_BIGNUM |QCBOR_TAGFLAG_NEG_BIGNUM)) {
+   switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_FOUR) {
       case 0:
-         // No tags we know about. Pass them up
-         *pDecodedItem = Item;
+         // No tags at all or none we know about. Nothing to do.
+         // This is part of the pass-through path of this function
+         // that will mostly be taken when decoding any item.
          break;
          
       case QCBOR_TAGFLAG_DATE_STRING:
-         nReturn = DecodeDateString(Item, pDecodedItem);
+         nReturn = DecodeDateString(pDecodedItem);
          break;
          
       case QCBOR_TAGFLAG_DATE_EPOCH:
-         nReturn = DecodeDateEpoch(Item, pDecodedItem);
+         nReturn = DecodeDateEpoch(pDecodedItem);
          break;
          
       case QCBOR_TAGFLAG_POS_BIGNUM:
       case QCBOR_TAGFLAG_NEG_BIGNUM:
-         nReturn = DecodeBigNum(Item, pDecodedItem, uTagFlags);
+         nReturn = DecodeBigNum(pDecodedItem);
          break;
          
       default:
@@ -838,13 +953,15 @@
 /*
  This layer takes care of map entries. It combines the label and data items into one QCBORItem.
  */
-static inline int GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
+static inline int GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
 {
-   int nReturn = GetNext_TaggedItem(me, pDecodedItem);
+   // Stack use: int/ptr 1, QCBORItem  -- 56
+   int nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
    if(nReturn)
       goto Done;
    
    if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
+      // Break can't be a map entry
       goto Done;
    }
    
@@ -854,7 +971,7 @@
       
       // Get the next item which will be the real data; Item will be the label
       QCBORItem LabelItem = *pDecodedItem;
-      nReturn = GetNext_TaggedItem(me, pDecodedItem);
+      nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
       if(nReturn)
          goto Done;
       
@@ -881,6 +998,7 @@
       } else {
          // label is not an int or a string. It is an arrray
          // or a float or such and this implementation doesn't handle that.
+         // Also, tags on labels are ignored.
          nReturn = QCBOR_ERR_MAP_LABEL_TYPE ;
          goto Done;
       }
@@ -894,13 +1012,15 @@
 /*
  Public function, see header qcbor.h file
  */
-int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
+int QCBORDecode_GetNextWithTags(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
 {
+   // Stack ptr/int: 2, QCBORItem : 64
+
    // The public entry point for fetching and parsing the next QCBORItem.
    // All the CBOR parsing work is here and in subordinate calls.
    int nReturn;
    
-   nReturn = GetNext_MapEntry(me, pDecodedItem);
+   nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
    if(nReturn) {
       goto Done;
    }
@@ -974,6 +1094,12 @@
 }
 
 
+int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
+{
+   return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
+}
+
+
 /*
  Decoding items is done in 5 layered functions, one calling the
  next one down. If a layer has no work to do for a particular item
@@ -1003,12 +1129,34 @@
  item in CBOR, the thing with an initial byte containing
  the major type.
  
+ Roughly this takes 300 bytes of stack for vars. Need to
+ evaluate this more carefully and correctly.
+ 
  */
 
 
 /*
  Public function, see header qcbor.h file
  */
+int QCBORDecode_IsTagged(QCBORDecodeContext *me, const QCBORItem *pItem, uint64_t uTag)
+{
+   const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
+   
+   uint8_t uTagBitIndex;
+   // Do not care about errors in pCallerConfiguredTagMap here. They are
+   // caught during GetNext() before this is called.
+   if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
+      return 0;
+   }
+   
+   const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
+   return (uTagBit & pItem->uTagBits) != 0;
+}
+
+
+/*
+ Public function, see header qcbor.h file
+ */
 int QCBORDecode_Finish(QCBORDecodeContext *me)
 {
    int nReturn = QCBOR_SUCCESS;
diff --git a/test/UsefulBuf_Tests.c b/test/UsefulBuf_Tests.c
index f79c08c..4d7a277 100644
--- a/test/UsefulBuf_Tests.c
+++ b/test/UsefulBuf_Tests.c
@@ -68,7 +68,7 @@
 {
    const char *szReturn = NULL;
 
-   UsefulBuf_MakeStackUB(outbuf,50);
+   UsefulBuf_MAKE_STACK_UB(outbuf,50);
    
    UsefulOutBuf UOB;
    
@@ -114,7 +114,7 @@
       szReturn = "OutUBuf";
    }
    
-   UsefulBuf_MakeStackUB(buf, 50);
+   UsefulBuf_MAKE_STACK_UB(buf, 50);
    UsefulBufC Out =  UsefulOutBuf_CopyOut(&UOB, buf);
    
    if(UsefulBuf_IsNULLC(Out) || Out.len-1 != strlen(expected) || strcmp(expected, Out.ptr)) {
@@ -189,7 +189,7 @@
 
 const char *UOBTest_BoundaryConditionsTest()
 {
-   UsefulBuf_MakeStackUB(outbuf,2);
+   UsefulBuf_MAKE_STACK_UB(outbuf,2);
    
    UsefulOutBuf UOB;
    
@@ -228,7 +228,7 @@
       return "Bad insertion point not caught";
    
    
-   UsefulBuf_MakeStackUB(outBuf2,10);
+   UsefulBuf_MAKE_STACK_UB(outBuf2,10);
    
    UsefulOutBuf_Init(&UOB, outBuf2);
    
@@ -272,7 +272,7 @@
 
 const char *TestBasicSanity()
 {
-   UsefulBuf_MakeStackUB(outbuf,10);
+   UsefulBuf_MAKE_STACK_UB(outbuf,10);
    
    UsefulOutBuf UOB;
    
@@ -323,14 +323,14 @@
    if(Foo.len != 3 || strncmp(Foo.ptr, szFoo, 3))
       return "SZToUsefulBufC failed";
    
-   UsefulBufC Too = UsefulBuf_FromSZLiteral("Toooo");
+   UsefulBufC Too = UsefulBuf_FROM_SZ_LITERAL("Toooo");
    if(Too.len != 5 || strncmp(Too.ptr, "Toooo", 5))
-      return "UsefulBuf_FromSZLiteral failed";
+      return "UsefulBuf_FROM_SZ_LITERAL failed";
 
    uint8_t pB[] = {0x42, 0x6f, 0x6f};
-   UsefulBufC Boo = UsefulBuf_FromByteArrayLiteral(pB);
+   UsefulBufC Boo = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pB);
    if(Boo.len != 3 || strncmp(Boo.ptr, "Boo", 3))
-     return "UsefulBuf_FromByteArrayLiteral failed";
+     return "UsefulBuf_FROM_BYTE_ARRAY_LITERAL failed";
    
    char *sz = "not const"; // some data for the test
    UsefulBuf B = (UsefulBuf){sz, sizeof(sz)};
@@ -388,17 +388,17 @@
    }
    
    // test the Unconst.
-   if(UsefulBufC_Unconst(UBC).ptr != NULL) {
+   if(UsefulBuf_Unconst(UBC).ptr != NULL) {
       return "Unconst failed";
    }
    
    // Set 100 bytes of '+'; validated a few tests later
-   MakeUsefulBufOnStack(Temp, 100);
-   UsefulBuf_Set(&Temp, '+');
+   UsefulBuf_MAKE_STACK_UB(Temp, 100);
+   UsefulBufC TempC = UsefulBuf_Set(Temp, '+');
    
    // Try to copy into a buf that is too small and see failure
-   UsefulBuf_MakeStackUB(Temp2, 99);
-   if(!UsefulBuf_IsNULLC(UsefulBuf_Copy(Temp2, UsefulBuf_Const(Temp)))) {
+   UsefulBuf_MAKE_STACK_UB(Temp2, 99);
+   if(!UsefulBuf_IsNULLC(UsefulBuf_Copy(Temp2, TempC))) {
       return "Copy should have failed";
    }
    
@@ -406,16 +406,16 @@
       return "CopyPtr failed";
    }
    
-   UsefulBufC xxyy = UsefulBuf_CopyOffset(Temp2, 2, UsefulBuf_FromSZLiteral("yy"));
+   UsefulBufC xxyy = UsefulBuf_CopyOffset(Temp2, 2, UsefulBuf_FROM_SZ_LITERAL("yy"));
    if(UsefulBuf_IsNULLC(xxyy)) {
       return "CopyOffset Failed";
    }
    
-   if(UsefulBuf_Compare(UsefulBuf_Head(xxyy, 3), UsefulBuf_FromSZLiteral("xxy"))) {
+   if(UsefulBuf_Compare(UsefulBuf_Head(xxyy, 3), UsefulBuf_FROM_SZ_LITERAL("xxy"))) {
       return "head failed";
    }
 
-   if(UsefulBuf_Compare(UsefulBuf_Tail(xxyy, 1), UsefulBuf_FromSZLiteral("xyy"))) {
+   if(UsefulBuf_Compare(UsefulBuf_Tail(xxyy, 1), UsefulBuf_FROM_SZ_LITERAL("xyy"))) {
       return "tail failed";
    }
    
@@ -427,23 +427,23 @@
       return "tail should have failed";
    }
    
-   if(!UsefulBuf_IsNULLC(UsefulBuf_CopyOffset(Temp2, 100, UsefulBuf_FromSZLiteral("yy")))) {
+   if(!UsefulBuf_IsNULLC(UsefulBuf_CopyOffset(Temp2, 100, UsefulBuf_FROM_SZ_LITERAL("yy")))) {
       return "Copy Offset should have failed";
    }
    
    // Try to copy into a NULL/empty buf and see failure
    UsefulBuf UBNull = NULLUsefulBuf;
-   if(!UsefulBuf_IsNULLC(UsefulBuf_Copy(UBNull, UsefulBuf_Const(Temp)))) {
+   if(!UsefulBuf_IsNULLC(UsefulBuf_Copy(UBNull, TempC))) {
       return "Copy to NULL should have failed";
    }
    
    
    // Try to set a NULL/empty buf; nothing should happen
-   UsefulBuf_Set(&UBNull, '+'); // This will crash on failure
+   UsefulBuf_Set(UBNull, '+'); // This will crash on failure
    
    // Copy successfully to a buffer
-   MakeUsefulBufOnStack(Temp3, 101);
-   if(UsefulBuf_IsNULLC(UsefulBuf_Copy(Temp3, UsefulBuf_Const(Temp)))) {
+   UsefulBuf_MAKE_STACK_UB(Temp3, 101);
+   if(UsefulBuf_IsNULLC(UsefulBuf_Copy(Temp3, TempC))) {
       return "Copy should not have failed";
    }
    
@@ -459,9 +459,9 @@
       '+',  '+',  '+',  '+', '+',  '+',  '+', '+',  '+',  '+',
       '+',  '+',  '+',  '+', '+',  '+',  '+', '+',  '+',  '+',
    };
-   UsefulBufC Expected = ByteArrayLiteralToUsefulBufC(pExpected);
+   UsefulBufC Expected = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpected);
    // This validates comparison for equality and the UsefulBuf_Set
-   if(UsefulBuf_Compare(Expected, UsefulBuf_Const(Temp))) {
+   if(UsefulBuf_Compare(Expected, TempC)) {
       return "Set / Copy / Compare failed";
    }
    
@@ -488,7 +488,7 @@
       '+',  '+',  '+',  '+', '+',  '+',  '+', '+',  '+',  '+',
       '+',  '+',  '+',  '+', '+',  '+',  '+', '+',  '+',  ',',
    };
-   UsefulBufC ExpectedBigger = ByteArrayLiteralToUsefulBufC(pExpectedBigger);
+   UsefulBufC ExpectedBigger = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedBigger);
    
    // Expect -1 when the first arg is smaller
    if(UsefulBuf_Compare(Expected, ExpectedBigger) >= 0){
@@ -508,7 +508,7 @@
       '+',  '+',  '+',  '+', '+',  '+',  '+', '+',  '+',  '+',
       '+',  '+',  '+',  '+', '+',  '+',  '+', '+',  '+',  '*',
    };
-   UsefulBufC ExpectedSmaller = ByteArrayLiteralToUsefulBufC(pExpectedSmaller);
+   UsefulBufC ExpectedSmaller = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedSmaller);
    // Expect +1 when the first arg is larger
    if(UsefulBuf_Compare(Expected, ExpectedSmaller) <= 0){
       return "Compare with smaller";
@@ -527,7 +527,7 @@
       '+',  '+',  '+',  '+', '+',  '+',  '+', '+',  '+',  '+',
       '+',  '+',  '+',  '+', '+',  '+',  '+', '+',  '+',  '+', '+'
    };
-   UsefulBufC ExpectedLonger = ByteArrayLiteralToUsefulBufC(pExpectedLonger);
+   UsefulBufC ExpectedLonger = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedLonger);
    
    // Expect -1 when the first arg is smaller
    if(UsefulBuf_Compare(Expected, ExpectedLonger) >= 0){
@@ -547,7 +547,7 @@
       '+',  '+',  '+',  '+', '+',  '+',  '+', '+',  '+',  '+',
       '+',  '+',  '+',  '+', '+',  '+',  '+', '+',  '+',
    };
-   UsefulBufC ExpectedShorter = ByteArrayLiteralToUsefulBufC(pExpectedShorter);
+   UsefulBufC ExpectedShorter = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedShorter);
    // Expect +1 with the first arg is larger
    if(UsefulBuf_Compare(Expected, ExpectedShorter) <= 0){
       return "Compare with shorter";
@@ -565,7 +565,7 @@
    
    // look for ++* in ....++* and find it at the end
    static const uint8_t pToFind[] = {'+', '+', '*'};
-   UsefulBufC ToBeFound = ByteArrayLiteralToUsefulBufC(pToFind);
+   UsefulBufC ToBeFound = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pToFind);
    
    if(97 != UsefulBuf_FindBytes(ExpectedSmaller, ToBeFound)){
       return "Failed to find 2";
@@ -648,7 +648,7 @@
    if(UsefulBuf_IsNULLC(Four)) {
       return "Four is NULL";
    }
-   if(UsefulBuf_Compare(Four, UsefulBuf_FromByteArrayLiteral(pExpectedNetworkOrder))) {
+   if(UsefulBuf_Compare(Four, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedNetworkOrder))) {
       return "Four compare failed";
    }
    
diff --git a/test/float_tests.c b/test/float_tests.c
index 1d755d5..6486d02 100644
--- a/test/float_tests.c
+++ b/test/float_tests.c
@@ -34,9 +34,41 @@
 #include <math.h> // For INFINITY and NAN and isnan()
 
 
+/*
+ Output from http://cbor.me
+ [0.0,
+ 1.0,
+ 1.100000023841858,
+ 1.5,
+ 65504.0,
+ 100000.0,
+ 3.4028234663852886e+38,
+ Infinity,
+ 5.960464477539063e-8,
+ 0.00006103515625,
+ -4.0,
+ -4.099999904632568,
+ NaN,
+ Infinity,
+ -Infinity,
+ 0.0,
+ 1.0,
+ 1.1,
+ 1.5,
+ 65504.0,
+ 100000.0,
+ 3.4028234663852886e+38,
+ 1.0e+300,
+ 5.960464477539063e-8,
+ 0.00006103515625,
+ -4.0,
+ -4.1,
+ NaN,
+ Infinity,
+ -Infinity]
+ */
 
-
-static uint8_t pExpectedEncodedFloat[] = {
+static uint8_t spExpectedEncodedFloat[] = {
     0x98, 0x1e, 0xfa, 0x00, 0x00, 0x00, 0x00, 0xfa,
     0x3f, 0x80, 0x00, 0x00, 0xfa, 0x3f, 0x8c, 0xcc,
     0xcd, 0xfa, 0x3f, 0xc0, 0x00, 0x00, 0xfa, 0x47,
@@ -71,7 +103,7 @@
     QCBOREncodeContext ECtx;
     int nReturn = 0;
     
-    UsefulBuf_MakeStackUB(EncodedStorage, 1000);
+    UsefulBuf_MAKE_STACK_UB(EncodedStorage, 220);
     
     QCBOREncode_Init(&ECtx, EncodedStorage);
     QCBOREncode_OpenArray(&ECtx);
@@ -120,7 +152,7 @@
         nReturn = -1;
     }
     
-    if(UsefulBuf_Compare(Encoded, UsefulBuf_FromByteArrayLiteral(pExpectedEncodedFloat))) {
+    if(UsefulBuf_Compare(Encoded, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedEncodedFloat))) {
         nReturn = -2;
     }
     
@@ -132,7 +164,7 @@
 
 
 
-static const uint8_t ExpectedHalf[] = {
+static const uint8_t spExpectedHalf[] = {
     0xB1,
         0x64,
             0x7A, 0x65, 0x72, 0x6F,
@@ -184,9 +216,9 @@
 
 
 
-int half_precision_encode_basic()
+int HalfPrecisionEncodeBasicTests()
 {
-    UsefulBuf_MakeStackUB(EncodedHalfsMem, 250);
+    UsefulBuf_MAKE_STACK_UB(EncodedHalfsMem, 250);
 
     QCBOREncodeContext EC;
     QCBOREncode_Init(&EC, EncodedHalfsMem);
@@ -219,7 +251,7 @@
         return -1;
     }
     
-    if(UsefulBuf_Compare(EncodedHalfs, UsefulBuf_FromByteArrayLiteral(ExpectedHalf))) {
+    if(UsefulBuf_Compare(EncodedHalfs, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedHalf))) {
         return -3;
     }
     
@@ -227,9 +259,9 @@
 }
 
 
-int half_precision_decode_basic()
+int HalfPrecisionDecodeBasicTests()
 {
-    UsefulBufC HalfPrecision = UsefulBuf_FromByteArrayLiteral(ExpectedHalf);
+    UsefulBufC HalfPrecision = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedHalf);
     
     QCBORDecodeContext DC;
     QCBORDecode_Init(&DC, HalfPrecision, 0);
@@ -331,11 +363,11 @@
 }
 
 
-int half_precision_to_float_transitive_test()
+int HalfPrecisionTransitiveTest()
 {
     for(uint32_t uHalfP = 0; uHalfP < 0xffff; uHalfP += 1) {
         // Contruct the CBOR for the half-precision float by hand
-        UsefulBuf_MakeStackUB(EncodedCBORMem, 3);
+        UsefulBuf_MAKE_STACK_UB(EncodedCBORMem, 3);
         UsefulOutBuf UOB;
         UsefulOutBuf_Init(&UOB, EncodedCBORMem);
         
@@ -358,7 +390,7 @@
 
         
         // Now generate CBOR with the half-precision value. This will invoke the conversion from float to half
-        UsefulBuf_MakeStackUB(OtherEncodedCBORMem, 5);
+        UsefulBuf_MAKE_STACK_UB(OtherEncodedCBORMem, 5);
         QCBOREncodeContext EC;
         QCBOREncode_Init(&EC, OtherEncodedCBORMem);
         QCBOREncode_AddFloatAsHalf(&EC, Item.val.fnum);
@@ -381,7 +413,7 @@
 }
 
 
-int half_precision_to_float_vs_rfc_test()
+int HalfPrecisionAgainstRFCCodeTest()
 {
     for(uint32_t uHalfP = 0; uHalfP < 0xffff; uHalfP += 60) {
         unsigned char x[2];
@@ -390,7 +422,7 @@
         double d = decode_half(x);
         
         // Contruct the CBOR for the half-precision float by hand
-        UsefulBuf_MakeStackUB(__xx, 3);
+        UsefulBuf_MAKE_STACK_UB(__xx, 3);
         UsefulOutBuf UOB;
         UsefulOutBuf_Init(&UOB, __xx);
         
@@ -429,18 +461,76 @@
 
 
 /*
- {"zero": 0.0, "negative zero": -0.0, "infinitity": Infinity, "negative infinitity": -Infinity, "NaN": NaN, "one": 1.0, "one third": 0.333251953125, "largest half-precision": 65504.0, "largest half-precision point one": 65504.1, "too-large half-precision": 65536.0, "smallest subnormal": 5.96046448e-8, "smallest normal": 0.00006103515261202119, "biggest subnormal": 0.00006103515625, "subnormal single": 4.00000646641519e-40, 3: -2.0, "large single exp": 2.5521177519070385e+38, "too-large single exp": 5.104235503814077e+38, "biggest single with prec": 16777216.0, "first single with prec loss": 16777217.0, 1: "fin"}
- 
+ {"zero": 0.0,
+  "negative zero": -0.0,
+  "infinitity": Infinity,
+  "negative infinitity": -Infinity,
+  "NaN": NaN,
+  "one": 1.0,
+  "one third": 0.333251953125,
+  "largest half-precision": 65504.0,
+  "largest half-precision point one": 65504.1,
+  "too-large half-precision": 65536.0,
+  "smallest subnormal": 5.96046448e-8,
+  "smallest normal": 0.00006103515261202119,
+  "biggest subnormal": 0.00006103515625,
+  "subnormal single": 4.00000646641519e-40,
+  3: -2.0,
+  "large single exp": 2.5521177519070385e+38,
+  "too-large single exp": 5.104235503814077e+38,
+  "biggest single with prec": 16777216.0,
+  "first single with prec loss": 16777217.0,
+  1: "fin"}
  */
-static const uint8_t sExpectedSmallest[] = {
-    0xB4, 0x64, 0x7A, 0x65, 0x72, 0x6F, 0xF9, 0x00, 0x00, 0x6D, 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x7A, 0x65, 0x72, 0x6F, 0xF9, 0x80, 0x00, 0x6A, 0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79, 0xF9, 0x7C, 0x00, 0x73, 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79, 0xF9, 0xFC, 0x00, 0x63, 0x4E, 0x61, 0x4E, 0xF9, 0x7E, 0x00, 0x63, 0x6F, 0x6E, 0x65, 0xF9, 0x3C, 0x00, 0x69, 0x6F, 0x6E, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, 0xF9, 0x35, 0x55, 0x76, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0xF9, 0x7B, 0xFF, 0x78, 0x20, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x20, 0x6F, 0x6E, 0x65, 0xFB, 0x40, 0xEF, 0xFC, 0x03, 0x33, 0x33, 0x33, 0x33, 0x78, 0x18, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x20, 0x68, 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0xFA, 0x47, 0x80, 0x00, 0x00, 0x72, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0xFB, 0x3E, 0x70, 0x00, 0x00, 0x00, 0x1C, 0x5F, 0x68, 0x6F, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0xFA, 0x38, 0x7F, 0xFF, 0xFF, 0x71, 0x62, 0x69, 0x67, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0xF9, 0x04, 0x00, 0x70, 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0xFB, 0x37, 0xC1, 0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF9, 0xC0, 0x00, 0x70, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x65, 0x78, 0x70, 0xFA, 0x7F, 0x40, 0x00, 0x00, 0x74, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x65, 0x78, 0x70, 0xFB, 0x47, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x18, 0x62, 0x69, 0x67, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x70, 0x72, 0x65, 0x63, 0xFA, 0x4B, 0x80, 0x00, 0x00, 0x78, 0x1B, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x70, 0x72, 0x65, 0x63, 0x20, 0x6C, 0x6F, 0x73, 0x73, 0xFB, 0x41, 0x70, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x63, 0x66, 0x69, 0x6E
+static const uint8_t spExpectedSmallest[] = {
+    0xB4, 0x64, 0x7A, 0x65, 0x72, 0x6F, 0xF9, 0x00, 0x00, 0x6D,
+    0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x7A,
+    0x65, 0x72, 0x6F, 0xF9, 0x80, 0x00, 0x6A, 0x69, 0x6E, 0x66,
+    0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79, 0xF9, 0x7C, 0x00,
+    0x73, 0x6E, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20,
+    0x69, 0x6E, 0x66, 0x69, 0x6E, 0x69, 0x74, 0x69, 0x74, 0x79,
+    0xF9, 0xFC, 0x00, 0x63, 0x4E, 0x61, 0x4E, 0xF9, 0x7E, 0x00,
+    0x63, 0x6F, 0x6E, 0x65, 0xF9, 0x3C, 0x00, 0x69, 0x6F, 0x6E,
+    0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, 0xF9, 0x35, 0x55,
+    0x76, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68,
+    0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73,
+    0x69, 0x6F, 0x6E, 0xF9, 0x7B, 0xFF, 0x78, 0x20, 0x6C, 0x61,
+    0x72, 0x67, 0x65, 0x73, 0x74, 0x20, 0x68, 0x61, 0x6C, 0x66,
+    0x2D, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6F, 0x6E,
+    0x20, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x20, 0x6F, 0x6E, 0x65,
+    0xFB, 0x40, 0xEF, 0xFC, 0x03, 0x33, 0x33, 0x33, 0x33, 0x78,
+    0x18, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72, 0x67, 0x65,
+    0x20, 0x68, 0x61, 0x6C, 0x66, 0x2D, 0x70, 0x72, 0x65, 0x63,
+    0x69, 0x73, 0x69, 0x6F, 0x6E, 0xFA, 0x47, 0x80, 0x00, 0x00,
+    0x72, 0x73, 0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20,
+    0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0xFB,
+    0x3E, 0x70, 0x00, 0x00, 0x00, 0x1C, 0x5F, 0x68, 0x6F, 0x73,
+    0x6D, 0x61, 0x6C, 0x6C, 0x65, 0x73, 0x74, 0x20, 0x6E, 0x6F,
+    0x72, 0x6D, 0x61, 0x6C, 0xFA, 0x38, 0x7F, 0xFF, 0xFF, 0x71,
+    0x62, 0x69, 0x67, 0x67, 0x65, 0x73, 0x74, 0x20, 0x73, 0x75,
+    0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C, 0xF9, 0x04, 0x00,
+    0x70, 0x73, 0x75, 0x62, 0x6E, 0x6F, 0x72, 0x6D, 0x61, 0x6C,
+    0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0xFB, 0x37, 0xC1,
+    0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF9, 0xC0, 0x00,
+    0x70, 0x6C, 0x61, 0x72, 0x67, 0x65, 0x20, 0x73, 0x69, 0x6E,
+    0x67, 0x6C, 0x65, 0x20, 0x65, 0x78, 0x70, 0xFA, 0x7F, 0x40,
+    0x00, 0x00, 0x74, 0x74, 0x6F, 0x6F, 0x2D, 0x6C, 0x61, 0x72,
+    0x67, 0x65, 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20,
+    0x65, 0x78, 0x70, 0xFB, 0x47, 0xF8, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x78, 0x18, 0x62, 0x69, 0x67, 0x67, 0x65, 0x73,
+    0x74, 0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x77,
+    0x69, 0x74, 0x68, 0x20, 0x70, 0x72, 0x65, 0x63, 0xFA, 0x4B,
+    0x80, 0x00, 0x00, 0x78, 0x1B, 0x66, 0x69, 0x72, 0x73, 0x74,
+    0x20, 0x73, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x77, 0x69,
+    0x74, 0x68, 0x20, 0x70, 0x72, 0x65, 0x63, 0x20, 0x6C, 0x6F,
+    0x73, 0x73, 0xFB, 0x41, 0x70, 0x00, 0x00, 0x10, 0x00, 0x00,
+    0x00, 0x01, 0x63, 0x66, 0x69, 0x6E
 };
 
 
-
-int double_as_smallest_encode_basic()
+int DoubleAsSmallestTest()
 {
-    UsefulBuf_MakeStackUB(EncodedHalfsMem, 420);
+    UsefulBuf_MAKE_STACK_UB(EncodedHalfsMem, 420);
     
     QCBOREncodeContext EC;
     QCBOREncode_Init(&EC, EncodedHalfsMem);
@@ -562,7 +652,7 @@
         return -1;
     }
     
-    if(UsefulBuf_Compare(EncodedHalfs, UsefulBuf_FromByteArrayLiteral(sExpectedSmallest))) {
+    if(UsefulBuf_Compare(EncodedHalfs, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedSmallest))) {
         return -3;
     }
     
diff --git a/test/float_tests.h b/test/float_tests.h
index 5bb638b..fba80d7 100644
--- a/test/float_tests.h
+++ b/test/float_tests.h
@@ -33,15 +33,15 @@
 
 int FloatValuesTest1(void);
 
-int half_precision_encode_basic(void);
+int HalfPrecisionEncodeBasicTests(void);
 
-int half_precision_decode_basic(void);
+int HalfPrecisionDecodeBasicTests(void);
 
-int half_precision_to_float_transitive_test(void);
+int HalfPrecisionTransitiveTest(void);
 
-int double_as_smallest_encode_basic(void);
+int DoubleAsSmallestTest(void);
 
-int half_precision_to_float_vs_rfc_test(void);
+int HalfPrecisionAgainstRFCCodeTest(void);
 
 
 #endif /* float_tests_h */
diff --git a/test/qcbor_decode_malloc_tests.c b/test/qcbor_decode_malloc_tests.c
index 91fff98..71497cf 100644
--- a/test/qcbor_decode_malloc_tests.c
+++ b/test/qcbor_decode_malloc_tests.c
@@ -42,8 +42,8 @@
     QCBORDecodeContext DC;
     
     // Next parse, save pointers to a few strings, destroy original and see all is OK.
-    MakeUsefulBufOnStack(CopyOfStorage, 160);
-    UsefulBufC CopyOf = UsefulBuf_Copy(CopyOfStorage, UsefulBuf_FromByteArrayLiteral(pValidMapEncoded));
+    UsefulBuf_MAKE_STACK_UB(CopyOfStorage, 160);
+    UsefulBufC CopyOf = UsefulBuf_Copy(CopyOfStorage, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded));
     
     QCBORDecode_Init(&DC, CopyOf, QCBOR_DECODE_MODE_NORMAL);
     QCBORStringAllocator *pAlloc = QCBORDecode_MakeMallocStringAllocator();
@@ -66,7 +66,7 @@
     if((nCBORError = QCBORDecode_GetNext(&DC, &Item4)))
         return nCBORError;
     
-    UsefulBuf_Set(&CopyOfStorage, '_');
+    UsefulBuf_Set(CopyOfStorage, '_');
     
     if(Item1.uLabelType != QCBOR_TYPE_TEXT_STRING ||
        Item1.label.string.len != 13 ||
diff --git a/test/qcbor_decode_tests.c b/test/qcbor_decode_tests.c
index 0bc2525..749a5d2 100644
--- a/test/qcbor_decode_tests.c
+++ b/test/qcbor_decode_tests.c
@@ -83,7 +83,7 @@
 // TODO: -- add a test for counting the top level items and adding it back in with AddRaw()
 
 
-static const uint8_t pExpectedEncodedInts[] = {
+static const uint8_t spExpectedEncodedInts[] = {
    0x98, 0x2f, 0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0x3b, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x00, 0x3a, 0xff, 0xff, 0xff,
@@ -110,13 +110,6 @@
    0xff, 0xff};
 
 
-
-
-
-
-
-
-
 // return CBOR error or -1 if type of value doesn't match
 
 static int IntegerValuesParseTestInternal(QCBORDecodeContext *pDCtx)
@@ -456,7 +449,7 @@
    int n;
    QCBORDecodeContext DCtx;
    
-   QCBORDecode_Init(&DCtx, (UsefulBufC){pExpectedEncodedInts, sizeof(pExpectedEncodedInts)}, QCBOR_DECODE_MODE_NORMAL);
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedEncodedInts), QCBOR_DECODE_MODE_NORMAL);
    
    n = IntegerValuesParseTestInternal(&DCtx);
    
@@ -524,21 +517,22 @@
  */
 
 static uint8_t pValidMapEncoded[] = {
-   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 } ;
-
-
-
-
-
-
+   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 } ;
 
 static int ParseOrderedArray(const uint8_t *pEncoded, size_t nLen, int64_t *pInt1, int64_t *pInt2,  const uint8_t **pBuf3, size_t *pBuf3Len,  const uint8_t **pBuf4, size_t *pBuf4Len)
 {
@@ -614,7 +608,7 @@
 
 
 
-static uint8_t s_pDeepArrays[] = {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80};
+static uint8_t spDeepArrays[] = {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80};
 
 int ParseDeepArrayTest()
 {
@@ -622,7 +616,7 @@
    int nReturn = 0;
    int i;
    
-   QCBORDecode_Init(&DCtx, (UsefulBufC){s_pDeepArrays, sizeof(s_pDeepArrays)}, QCBOR_DECODE_MODE_NORMAL);
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spDeepArrays), QCBOR_DECODE_MODE_NORMAL);
    
    for(i = 0; i < 10; i++) {
       QCBORItem Item;
@@ -639,7 +633,7 @@
 }
 
 
-static uint8_t s_pTooDeepArrays[] = {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80};
+static uint8_t spTooDeepArrays[] = {0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80};
 
 int ParseTooDeepArrayTest()
 {
@@ -649,7 +643,7 @@
    QCBORItem Item;
    
    
-   QCBORDecode_Init(&DCtx, (UsefulBufC){s_pTooDeepArrays, sizeof(s_pTooDeepArrays)}, QCBOR_DECODE_MODE_NORMAL);
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spTooDeepArrays), QCBOR_DECODE_MODE_NORMAL);
    
    for(i = 0; i < 10; i++) {
       
@@ -670,18 +664,16 @@
 
 
 
-
-
 int ShortBufferParseTest()
 {
    int nResult  = 0;
    QCBORDecodeContext DCtx;
    int num;
    
-   for(num = sizeof(pExpectedEncodedInts)-1; num; num--) {
+   for(num = sizeof(spExpectedEncodedInts)-1; num; num--) {
       int n;
       
-      QCBORDecode_Init(&DCtx, (UsefulBufC){pExpectedEncodedInts, num}, QCBOR_DECODE_MODE_NORMAL);
+      QCBORDecode_Init(&DCtx, (UsefulBufC){spExpectedEncodedInts, num}, QCBOR_DECODE_MODE_NORMAL);
       
       n = IntegerValuesParseTestInternal(&DCtx);
       
@@ -1065,7 +1057,7 @@
 }
 
 
-static uint8_t s_pSimpleValues[] = {0x8a, 0xf4, 0xf5, 0xf6, 0xf7, 0xff, 0xe0, 0xf3, 0xf8, 0x00, 0xf8, 0x13, 0xf8, 0x1f, 0xf8, 0x20, 0xf8, 0xff};
+static uint8_t spSimpleValues[] = {0x8a, 0xf4, 0xf5, 0xf6, 0xf7, 0xff, 0xe0, 0xf3, 0xf8, 0x00, 0xf8, 0x13, 0xf8, 0x1f, 0xf8, 0x20, 0xf8, 0xff};
 
 int ParseSimpleTest()
 {
@@ -1074,7 +1066,7 @@
    int nCBORError;
    
    
-   QCBORDecode_Init(&DCtx, UsefulBuf_FromByteArrayLiteral(s_pSimpleValues), QCBOR_DECODE_MODE_NORMAL);
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSimpleValues), QCBOR_DECODE_MODE_NORMAL);
    
    
    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
@@ -1215,7 +1207,7 @@
       QCBORItem Item;
       int nCBORError;
       
-      QCBORDecode_Init(&DCtx, UsefulBuf_FromByteArrayLiteral(s_pSimpleValues), QCBOR_DECODE_MODE_NORMAL);
+      QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSimpleValues), QCBOR_DECODE_MODE_NORMAL);
 
       if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
          return nCBORError;
@@ -1292,14 +1284,15 @@
    return 0;
 }
 
-static uint8_t s_DateTestInput[] = {
+static uint8_t spDateTestInput[] = {
    0xc0, // tag for string date
    0x6a, '1','9','8','5','-','0','4','-','1','2', // Date string
    
    0xc1, // tag for epoch date
    0x1a, 0x53, 0x72, 0x4E, 0x00, // Epoch date 1400000000; Tue, 13 May 2014 16:53:20 GMT
 
-   0xc1, 0xcf, 0xd8, 0xee, // Epoch date with extra tags
+   // CBOR_TAG_B64
+   0xc1, 0xcf, 0xd8, 0x22, // 0xee, // Epoch date with extra tags TODO: fix this test
    0x1a, 0x53, 0x72, 0x4E, 0x01,
 
    0xc1, // tag for epoch date
@@ -1331,7 +1324,12 @@
    QCBORItem Item;
    int nCBORError;
    
-   QCBORDecode_Init(&DCtx, UsefulBuf_FromByteArrayLiteral(s_DateTestInput), QCBOR_DECODE_MODE_NORMAL);
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spDateTestInput), QCBOR_DECODE_MODE_NORMAL);
+   
+   const uint64_t uTags[] = {15};
+   QCBORTagListIn TagList = {1, uTags};
+      
+   QCBORDecode_SetCallerConfiguredTagList(&DCtx, &TagList);
    
    // String date
    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
@@ -1350,14 +1348,14 @@
       return -1;
    }
    
-   // Epoch date with extra tags
+   // Epoch date with extra CBOR_TAG_B64 tag that doesn't really mean anything
+   // but want to be sure extra tag doesn't cause a problem
    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
       return -1;
    if(Item.uDataType != QCBOR_TYPE_DATE_EPOCH ||
       Item.val.epochDate.nSeconds != 1400000001 ||
       Item.val.epochDate.fSecondsFraction != 0 ||
-      Item.uTagBits != (0x02 | (0x01 << 0x0f)) ||
-      Item.uTag != 0xee) {
+      !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_B64)) {
       return -1;
    }
    
@@ -1385,35 +1383,335 @@
    return 0;
 }
 
-static uint8_t s_OptTestInput[] = {
+// Really simple basic input for tagging test
+static uint8_t spOptTestInput[] = {
    0xd9, 0xd9, 0xf7, // CBOR magic number
-   0x81,
-   0xd8, 62, // 62 is decimal intentionally
-   0x00};
+   0x81, // Array of one
+   0xd8, 0x04, // non-preferred serialization of tag 4
+   0x82, 0x01, 0x03}; // fraction 1/3
+
+static uint8_t spEncodedLargeTag[] = {0xdb, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x80};
+
+// 0x9192939495969798, 0x88, 0x01, 0x04
+static uint8_t spLotsOfTags[] = {0xdb, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0xd8, 0x88, 0xc5, 0xc4, 0x80};
+
+/*
+ The cbor.me parse of this.
+ 55799(55799(55799({6(7(-23)): 5859837686836516696(7({7(-20): 11({17(-18): 17(17(17("Organization"))),
+ 9(-17): 773("SSG"), -15: 4(5(6(7(8(9(10(11(12(13(14(15("Confusion")))))))))))), 17(-16): 17("San Diego"),
+ 17(-14): 17("US")}), 23(-19): 19({-11: 9({-9: -7}),
+ 90599561(90599561(90599561(-10))): 12(h'0102030405060708090A')})})),
+ 16(-22): 23({11(8(7(-5))): 8(-3)})})))
+ */
+static uint8_t spCSRWithTags[] = {
+   0xd9, 0xd9, 0xf7, 0xd9, 0xd9, 0xf7, 0xd9, 0xd9, 0xf7, 0xa2,
+      0xc6, 0xc7, 0x36,
+      0xdb, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0xc7, 0xa2,
+         0xda, 0x00, 0x00, 0x00, 0x07, 0x33,
+         0xcb, 0xa5,
+            0xd1, 0x31,
+            0xd1, 0xd1, 0xd1, 0x6c,
+               0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+            0xc9, 0x30,
+            0xd9, 0x03, 0x05, 0x63,
+               0x53, 0x53, 0x47,
+            0x2e,
+            0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0x69,
+               0x43, 0x6f, 0x6e, 0x66, 0x75, 0x73, 0x69, 0x6f, 0x6e,
+            0xd1, 0x2f,
+            0xd1, 0x69,
+               0x53, 0x61, 0x6e, 0x20, 0x44, 0x69, 0x65, 0x67, 0x6f,
+            0xd1, 0x2d,
+            0xd1, 0x62,
+               0x55, 0x53,
+         0xd7, 0x32,
+         0xd3, 0xa2,
+            0x2a,
+            0xc9, 0xa1,
+               0x28,
+               0x26,
+            0xda, 0x05, 0x66, 0x70, 0x89, 0xda, 0x05, 0x66, 0x70, 0x89, 0xda, 0x05, 0x66, 0x70, 0x89, 0x29,
+            0xcc, 0x4a,
+               0x01, 0x02, 0x03, 0x04, 0x05, 0x06,0x07, 0x08, 0x09, 0x0a,
+   0xd0, 0x35,
+   0xd7, 0xa1,
+      0xcb, 0xc8, 0xc7, 0x24,
+      0xc8, 0x22};
+
+static int CheckCSRMaps(QCBORDecodeContext *pDC);
+
 
 int OptTagParseTest()
 {
    QCBORDecodeContext DCtx;
    QCBORItem Item;
-   int nCBORError;
    
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spOptTestInput), QCBOR_DECODE_MODE_NORMAL);
    
-   QCBORDecode_Init(&DCtx, UsefulBuf_FromByteArrayLiteral(s_OptTestInput), QCBOR_DECODE_MODE_NORMAL);
-   
-   //
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
-      return -1;
+   //-------------------------
+   // This text matches the magic number tag and the fraction tag
+   if(QCBORDecode_GetNext(&DCtx, &Item)) {
+      return -2;
+   }
    if(Item.uDataType != QCBOR_TYPE_ARRAY ||
-      Item.uTagBits != QCBOR_TAGFLAG_CBOR_MAGIC) {
-      return -1;
+      !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_CBOR_MAGIC)) {
+      return -3;
    }
    
-   if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
-      return -1;
+   if(QCBORDecode_GetNext(&DCtx, &Item)) {
+      return -4;
+   }
+   if(Item.uDataType != QCBOR_TYPE_ARRAY ||
+      !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_FRACTION) ||
+      Item.val.uCount != 2) {
+      return -5;
+   }
+   
+   // --------------------------------
+   // This test decodes the very large tag, but it is not in
+   // any list so it is ignored.
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEncodedLargeTag), QCBOR_DECODE_MODE_NORMAL);
+   if(QCBORDecode_GetNext(&DCtx, &Item)) {
+      return -6;
+   }
+   if(Item.uTagBits) {
+      return -7;
+   }
+   
+   // ----------------------------------
+   // This test sets up a caller-config list that includes the very large tage and then matches it.
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEncodedLargeTag), QCBOR_DECODE_MODE_NORMAL);
+   const uint64_t puList[] = {0x9192939495969798, 257};
+   const QCBORTagListIn TL = {2, puList};
+   QCBORDecode_SetCallerConfiguredTagList(&DCtx, &TL);
+   
+   if(QCBORDecode_GetNext(&DCtx, &Item)) {
+      return -8;
+   }
+   if(Item.uDataType != QCBOR_TYPE_ARRAY ||
+      !QCBORDecode_IsTagged(&DCtx, &Item, 0x9192939495969798) ||
+      QCBORDecode_IsTagged(&DCtx, &Item, 257) ||
+      QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_BIGFLOAT) ||
+      Item.val.uCount != 0) {
+      return -9;
+   }
+   
+   //------------------------
+   // This test sets up a caller-configured list, and looks up something not in it
+   const uint64_t puLongList[17] = {1,2,1};
+   const QCBORTagListIn TLLong = {17, puLongList};
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spEncodedLargeTag), QCBOR_DECODE_MODE_NORMAL);
+   QCBORDecode_SetCallerConfiguredTagList(&DCtx, &TLLong);
+   if(QCBORDecode_GetNext(&DCtx, &Item)) {
+      return -11;
+   }
+   
+   // -----------------------
+   // This tests retrievel of the full tag list
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spLotsOfTags), QCBOR_DECODE_MODE_NORMAL);
+   uint64_t puTags[16];
+   QCBORTagListOut Out = {0, 4, puTags};
+   if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) {
+      return -12;
+   }
+   if(puTags[0] != 0x9192939495969798 ||
+      puTags[1] != 0x88 ||
+      puTags[2] != 0x05 ||
+      puTags[3] != 0x04) {
+      return -13;
+   }
+   
+   // ----------------------
+   // This text if too small of an out list
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spLotsOfTags), QCBOR_DECODE_MODE_NORMAL);
+   QCBORTagListOut OutSmall = {0, 3, puTags};
+   if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &OutSmall) != QCBOR_ERR_TOO_MANY_TAGS) {
+      return -14;
+   }
+   
+   // ---------------
+   // Parse a version of the "CSR" that has had a ton of tags randomly inserted
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRWithTags), QCBOR_DECODE_MODE_NORMAL);
+   int n = CheckCSRMaps(&DCtx);
+   if(n) {
+      return n-2000;
+   }
+   
+   Out = (QCBORTagListOut){0,16, puTags};
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRWithTags), QCBOR_DECODE_MODE_NORMAL);
+   
+   const uint64_t puTagList[] = {773, 1, 90599561};
+   const QCBORTagListIn TagList = {3, puTagList};
+   QCBORDecode_SetCallerConfiguredTagList(&DCtx, &TagList);
+   
+   
+   if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) {
+      return -100;
+   }
+   if(Item.uDataType != QCBOR_TYPE_MAP ||
+      !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_CBOR_MAGIC) ||
+      QCBORDecode_IsTagged(&DCtx, &Item, 90599561) ||
+      QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_DATE_EPOCH) ||
+      Item.val.uCount != 2 ||
+      puTags[0] != CBOR_TAG_CBOR_MAGIC ||
+      puTags[1] != CBOR_TAG_CBOR_MAGIC ||
+      puTags[2] != CBOR_TAG_CBOR_MAGIC ||
+      Out.uNumUsed != 3) {
+      return -101;
+   }
+   
+   if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) {
+      return -102;
+   }
+   if(Item.uDataType != QCBOR_TYPE_MAP ||
+      QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_CBOR_MAGIC) ||
+      QCBORDecode_IsTagged(&DCtx, &Item, 6) ||
+      QCBORDecode_IsTagged(&DCtx, &Item, 7) || // item is tagged 7, but 7 is not configured to be recognized
+      Item.val.uCount != 2 ||
+      puTags[0] != 5859837686836516696 ||
+      puTags[1] != 7 ||
+      Out.uNumUsed != 2) {
+      return -103;
+   }
+   
+   if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) {
+      return -104;
+   }
+   if(Item.uDataType != QCBOR_TYPE_MAP ||
+      Item.uTagBits ||
+      Item.val.uCount != 5 ||
+      puTags[0] != 0x0b ||
+      Out.uNumUsed != 1) {
+      return -105;
+   }
+   
+   if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) {
+      return -106;
+   }
+   if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_COSE_MAC0) ||
+      Item.val.string.len != 12 ||
+      puTags[0] != CBOR_TAG_COSE_MAC0 ||
+      puTags[1] != CBOR_TAG_COSE_MAC0 ||
+      puTags[2] != CBOR_TAG_COSE_MAC0 ||
+      Out.uNumUsed != 3) {
+      return -105;
+   }
+   
+   if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) {
+      return -107;
+   }
+   if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      !QCBORDecode_IsTagged(&DCtx, &Item, 773) ||
+      Item.val.string.len != 3 ||
+      puTags[0] != 773 ||
+      Out.uNumUsed != 1) {
+      return -108;
+   }
+   
+   if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) {
+      return -109;
+   }
+   if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      !QCBORDecode_IsTagged(&DCtx, &Item, 4) ||
+      Item.val.string.len != 9 ||
+      puTags[0] != 4 ||
+      puTags[11] != 0x0f ||
+      Out.uNumUsed != 12) {
+      return -110;
+   }
+   
+   if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) {
+      return -111;
+   }
+   if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      !QCBORDecode_IsTagged(&DCtx, &Item, 17) ||
+      Item.val.string.len != 9 ||
+      puTags[0] != 17 ||
+      Out.uNumUsed != 1) {
+      return -112;
+   }
+   
+   if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) {
+      return -111;
+   }
+   if(Item.uDataType != QCBOR_TYPE_TEXT_STRING ||
+      !QCBORDecode_IsTagged(&DCtx, &Item, 17) ||
+      Item.val.string.len != 2 ||
+      puTags[0] != 17 ||
+      Out.uNumUsed != 1) {
+      return -112;
+   }
+
+   if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) {
+      return -113;
+   }
+   if(Item.uDataType != QCBOR_TYPE_MAP ||
+      QCBORDecode_IsTagged(&DCtx, &Item, 19) ||
+      Item.val.uCount != 2 ||
+      puTags[0] != 19 ||
+      Out.uNumUsed != 1) {
+      return -114;
+   }
+   
+   if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) {
+      return -115;
+   }
+   if(Item.uDataType != QCBOR_TYPE_MAP ||
+      QCBORDecode_IsTagged(&DCtx, &Item, 9) ||
+      Item.uTagBits ||
+      Item.val.uCount != 1 ||
+      puTags[0] != 9 ||
+      Out.uNumUsed != 1) {
+      return -116;
+   }
+
+   if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) {
+      return -116;
+   }
    if(Item.uDataType != QCBOR_TYPE_INT64 ||
-      Item.uTagBits != (0x01LL << 62) ||
-      Item.val.int64 != 0)
-      return -1;
+      Item.val.int64 != -7 ||
+      Item.uTagBits ||
+      Out.uNumUsed != 0) {
+      return -117;
+   }
+
+   if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) {
+      return -118;
+   }
+   if(Item.uDataType != QCBOR_TYPE_BYTE_STRING ||
+      Item.val.string.len != 10 ||
+      Item.uTagBits ||
+      puTags[0] != 12 ||
+      Out.uNumUsed != 1) {
+      return -119;
+   }
+   
+   if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) {
+      return -120;
+   }
+   if(Item.uDataType != QCBOR_TYPE_MAP ||
+      !QCBORDecode_IsTagged(&DCtx, &Item, CBOR_TAG_ENC_AS_B16) ||
+      Item.val.uCount != 1 ||
+      puTags[0] != 0x17 ||
+      Out.uNumUsed != 1) {
+      return -121;
+   }
+   
+   if(QCBORDecode_GetNextWithTags(&DCtx, &Item, &Out)) {
+      return -122;
+   }
+   if(Item.uDataType != QCBOR_TYPE_INT64 ||
+      QCBORDecode_IsTagged(&DCtx, &Item, 8) ||
+      Item.val.int64 != -3 ||
+      puTags[0] != 8 ||
+      Out.uNumUsed != 1) {
+      return -123;
+   }
+   
+   if(QCBORDecode_Finish(&DCtx)) {
+      return -124;
+   }
    
    return 0;
 }
@@ -1421,7 +1719,7 @@
 
 
    
-static uint8_t s_BigNumInput[] = {
+static uint8_t spBigNumInput[] = {
  0x83,
    0xC2, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1436,7 +1734,7 @@
        0xC3, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
 
-static uint8_t sBigNum[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static uint8_t spBigNum[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
 
 int BignumParseTest()
@@ -1445,7 +1743,7 @@
    QCBORItem Item;
    int nCBORError;
    
-   QCBORDecode_Init(&DCtx, UsefulBuf_FromByteArrayLiteral(s_BigNumInput), QCBOR_DECODE_MODE_NORMAL);
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNumInput), QCBOR_DECODE_MODE_NORMAL);
    
    
    //
@@ -1459,7 +1757,7 @@
    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
       return -1;
    if(Item.uDataType != QCBOR_TYPE_POSBIGNUM ||
-      UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FromByteArrayLiteral(sBigNum))){
+      UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){
       return -1;
    }
 
@@ -1467,7 +1765,7 @@
    if((nCBORError = QCBORDecode_GetNext(&DCtx, &Item)))
       return -1;
    if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM ||
-      UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FromByteArrayLiteral(sBigNum))){
+      UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){
       return -1;
    }
    
@@ -1482,7 +1780,7 @@
       return -1;
    if(Item.uDataType != QCBOR_TYPE_POSBIGNUM ||
       Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
-      UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FromByteArrayLiteral(sBigNum))){
+      UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){
       return -1;
    }
 
@@ -1491,7 +1789,7 @@
    if(Item.uDataType != QCBOR_TYPE_POSBIGNUM ||
       Item.uLabelType != QCBOR_TYPE_INT64 ||
       Item.label.int64 != 64 ||
-      UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FromByteArrayLiteral(sBigNum))){
+      UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){
       return -1;
    }
    
@@ -1499,7 +1797,7 @@
       return -1;
    if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM ||
       Item.uLabelType != QCBOR_TYPE_TEXT_STRING ||
-      UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FromByteArrayLiteral(sBigNum))){
+      UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){
       return -1;
    }
    
@@ -1508,7 +1806,7 @@
    if(Item.uDataType != QCBOR_TYPE_NEGBIGNUM ||
       Item.uLabelType != QCBOR_TYPE_INT64 ||
       Item.label.int64 != -64 ||
-      UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FromByteArrayLiteral(sBigNum))){
+      UsefulBuf_Compare(Item.val.bigNum, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spBigNum))){
       return -1;
    }
    
@@ -1597,7 +1895,7 @@
  */
 
 
-static uint8_t s_CSRInput[] = {
+static uint8_t spCSRInput[] = {
    0xa2, 0x36, 0xa2, 0x33, 0xa5, 0x31, 0x6c, 0x4f,
    0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74,
    0x69, 0x6f, 0x6e, 0x30, 0x63, 0x53, 0x53, 0x47,
@@ -1612,28 +1910,29 @@
 {
    QCBORDecodeContext DCtx;
    
-   QCBORDecode_Init(&DCtx, UsefulBuf_FromByteArrayLiteral(s_CSRInput), QCBOR_DECODE_MODE_NORMAL);
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRInput), QCBOR_DECODE_MODE_NORMAL);
    
    return CheckCSRMaps(&DCtx);
 }
 
 // Same map as above, but using indefinite lengths
-static uint8_t s_CSRInputIndefLen[] = {
+static uint8_t spCSRInputIndefLen[] = {
    0xbf, 0x36, 0xbf, 0x33, 0xbf, 0x31, 0x6c, 0x4f,
    0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74,
    0x69, 0x6f, 0x6e, 0x30, 0x63, 0x53, 0x53, 0x47,
    0x2e, 0x69, 0x43, 0x6f, 0x6e, 0x66, 0x75, 0x73,
    0x69, 0x6f, 0x6e, 0x2f, 0x69, 0x53, 0x61, 0x6e,
    0x20, 0x44, 0x69, 0x65, 0x67, 0x6f, 0x2d, 0x62,
-   0x55, 0x53,  0xff, 0x32, 0xbf, 0x2a, 0xbf, 0x28,  0x26, 0xff,
-   0x29, 0x4a, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
-   0x07, 0x08, 0x09, 0x0a, 0xff, 0xff, 0x35, 0xbf, 0x24, 0x22, 0xff, 0xff};
+   0x55, 0x53, 0xff, 0x32, 0xbf, 0x2a, 0xbf, 0x28,
+   0x26, 0xff, 0x29, 0x4a, 0x01, 0x02, 0x03, 0x04,
+   0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0xff, 0xff,
+   0x35, 0xbf, 0x24, 0x22, 0xff, 0xff};
 
 int NestedMapTestIndefLen()
 {
    QCBORDecodeContext DCtx;
    
-   QCBORDecode_Init(&DCtx, UsefulBuf_FromByteArrayLiteral(s_CSRInputIndefLen), QCBOR_DECODE_MODE_NORMAL);
+   QCBORDecode_Init(&DCtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRInputIndefLen), QCBOR_DECODE_MODE_NORMAL);
    
    return CheckCSRMaps(&DCtx);
 }
@@ -1693,7 +1992,7 @@
 
 int IndefiniteLengthNestTest()
 {
-   UsefulBuf_MakeStackUB(Storage, 50);
+   UsefulBuf_MAKE_STACK_UB(Storage, 50);
    int i;
    for(i=1; i < QCBOR_MAX_ARRAY_NESTING+4; i++) { 
       UsefulBufC Nested = make_nested_indefinite_arrays(i, Storage);
@@ -1707,21 +2006,21 @@
 
 
 
-static const uint8_t pIndefiniteArray[] = {0x9f, 0x01, 0x82, 0x02, 0x03, 0xff}; // [1, [2, 3]]
-static const uint8_t pIndefiniteArrayBad1[] = {0x9f}; // No closing break
-static const uint8_t pIndefiniteArrayBad2[] = {0x9f, 0x9f, 0x02, 0xff}; // Not enough closing breaks
-static const uint8_t pIndefiniteArrayBad3[] = {0x9f, 0x02, 0xff, 0xff}; // Too many closing breaks
-static const uint8_t pIndefiniteArrayBad4[] = {0x81, 0x9f}; // Unclosed indeflen inside def len
-static const uint8_t pIndefiniteArrayBad5[] = {0x9f, 0xc7, 0xff}; // confused tag
+static const uint8_t spIndefiniteArray[]     = {0x9f, 0x01, 0x82, 0x02, 0x03, 0xff}; // [1, [2, 3]]
+static const uint8_t spIndefiniteArrayBad1[] = {0x9f}; // No closing break
+static const uint8_t spIndefiniteArrayBad2[] = {0x9f, 0x9f, 0x02, 0xff}; // Not enough closing breaks
+static const uint8_t spIndefiniteArrayBad3[] = {0x9f, 0x02, 0xff, 0xff}; // Too many closing breaks
+static const uint8_t spIndefiniteArrayBad4[] = {0x81, 0x9f}; // Unclosed indeflen inside def len
+static const uint8_t spIndefiniteArrayBad5[] = {0x9f, 0xd1, 0xff}; // confused tag
 
 int IndefiniteLengthArrayMapTest()
 {
    int nResult;
    // --- first test -----
-    UsefulBufC IndefLen = UsefulBuf_FromByteArrayLiteral(pIndefiniteArray);
+    UsefulBufC IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArray);
    
     // Decode it and see if it is OK
-    UsefulBuf_MakeStackUB(MemPool, 150);
+    UsefulBuf_MAKE_STACK_UB(MemPool, 150);
     QCBORDecodeContext DC;
     QCBORItem Item;
     QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL);
@@ -1769,7 +2068,7 @@
     }
    
    // --- next test -----
-   IndefLen = UsefulBuf_FromByteArrayLiteral(pIndefiniteArrayBad1);
+   IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad1);
    
    QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL);
    
@@ -1787,7 +2086,7 @@
 
    
    // --- next test -----
-   IndefLen = UsefulBuf_FromByteArrayLiteral(pIndefiniteArrayBad2);
+   IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad2);
    
    QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL);
    
@@ -1815,7 +2114,7 @@
    
    
    // --- next test -----
-   IndefLen = UsefulBuf_FromByteArrayLiteral(pIndefiniteArrayBad3);
+   IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad3);
    
    QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL);
    
@@ -1833,7 +2132,7 @@
 
    
    // --- next test -----
-   IndefLen = UsefulBuf_FromByteArrayLiteral(pIndefiniteArrayBad4);
+   IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad4);
    
    QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL);
    
@@ -1855,7 +2154,7 @@
    }
    
    // --- next test -----
-   IndefLen = UsefulBuf_FromByteArrayLiteral(pIndefiniteArrayBad5);
+   IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteArrayBad5);
    
    QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL);
    
@@ -1875,7 +2174,7 @@
 }
 
 
-static const uint8_t pIndefiniteLenString[] = {
+static const uint8_t spIndefiniteLenString[] = {
    0x81, // Array of length one
    0x7f, // text string marked with indefinite length
    0x65, 0x73, 0x74, 0x72, 0x65, 0x61, // first segment
@@ -1883,7 +2182,7 @@
    0xff // ending break
 };
 
-static const uint8_t pIndefiniteLenStringBad2[] = {
+static const uint8_t spIndefiniteLenStringBad2[] = {
    0x81, // Array of length one
    0x7f, // text string marked with indefinite length
    0x65, 0x73, 0x74, 0x72, 0x65, 0x61, // first segment
@@ -1891,14 +2190,14 @@
    0xff // ending break
 };
 
-static const uint8_t pIndefiniteLenStringBad3[] = {
+static const uint8_t spIndefiniteLenStringBad3[] = {
    0x81, // Array of length one
    0x7f, // text string marked with indefinite length
    0x01, 0x02, // Not a string
    0xff // ending break
 };
 
-static const uint8_t pIndefiniteLenStringBad4[] = {
+static const uint8_t spIndefiniteLenStringBad4[] = {
    0x81, // Array of length one
    0x7f, // text string marked with indefinite length
    0x65, 0x73, 0x74, 0x72, 0x65, 0x61, // first segment
@@ -1906,7 +2205,7 @@
    // missing end of string
 };
 
-static const uint8_t pIndefiniteLenStringLabel[] = {
+static const uint8_t spIndefiniteLenStringLabel[] = {
    0xa1, // Array of length one
    0x7f, // text string marked with indefinite length
    0x65, 0x73, 0x74, 0x72, 0x75, 0x75, // first segment
@@ -1957,10 +2256,10 @@
    QCBORDecodeContext DC;
    QCBORItem Item;
    // big enough for MakeIndefiniteBigBstr() + MemPool overhead
-   UsefulBuf_MakeStackUB(MemPool, 320);
+   UsefulBuf_MAKE_STACK_UB(MemPool, 320);
    
    // --- Simple normal indefinite length string ------
-   UsefulBufC IndefLen = UsefulBuf_FromByteArrayLiteral(pIndefiniteLenString);
+   UsefulBufC IndefLen = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenString);
    QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL);
     
    if(QCBORDecode_SetMemPool(&DC, MemPool, false)) {
@@ -1985,7 +2284,7 @@
    }
 
    // ----- types mismatch ---
-   QCBORDecode_Init(&DC, UsefulBuf_FromByteArrayLiteral(pIndefiniteLenStringBad2), QCBOR_DECODE_MODE_NORMAL);
+   QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringBad2), QCBOR_DECODE_MODE_NORMAL);
    
    if(QCBORDecode_SetMemPool(&DC,  MemPool, false)) {
       return -7;
@@ -2003,7 +2302,7 @@
    }
 
    // ----- not a string ---
-   QCBORDecode_Init(&DC, UsefulBuf_FromByteArrayLiteral(pIndefiniteLenStringBad3), QCBOR_DECODE_MODE_NORMAL);
+   QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringBad3), QCBOR_DECODE_MODE_NORMAL);
    
    if(QCBORDecode_SetMemPool(&DC,  MemPool, false)) {
       return -11;
@@ -2021,7 +2320,7 @@
    }
 
    // ----- no end -----
-   QCBORDecode_Init(&DC, UsefulBuf_FromByteArrayLiteral(pIndefiniteLenStringBad4), QCBOR_DECODE_MODE_NORMAL);
+   QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringBad4), QCBOR_DECODE_MODE_NORMAL);
    
    if(QCBORDecode_SetMemPool(&DC,  MemPool, false)) {
       return -15;
@@ -2051,7 +2350,7 @@
    }
    
    // ----- Mempool is way too small -----
-   UsefulBuf_MakeStackUB(MemPoolTooSmall, 20); // 20 is too small no matter what
+   UsefulBuf_MAKE_STACK_UB(MemPoolTooSmall, 20); // 20 is too small no matter what
 
    QCBORDecode_Init(&DC, IndefLen, QCBOR_DECODE_MODE_NORMAL);
    if(!QCBORDecode_SetMemPool(&DC,  MemPoolTooSmall, false)) {
@@ -2059,10 +2358,10 @@
    }
    
    // ----- Mempool is way too small -----
-   UsefulBuf_MakeStackUB(BigIndefBStrStorage, 290);
+   UsefulBuf_MAKE_STACK_UB(BigIndefBStrStorage, 290);
    UsefulBufC BigIndefBStr = MakeIndefiniteBigBstr(BigIndefBStrStorage);
    
-   UsefulBuf_MakeStackUB(MemPoolSmall, 80); // 80 is big enough for MemPool overhead, but not BigIndefBStr
+   UsefulBuf_MAKE_STACK_UB(MemPoolSmall, 80); // 80 is big enough for MemPool overhead, but not BigIndefBStr
    
    QCBORDecode_Init(&DC, BigIndefBStr, QCBOR_DECODE_MODE_NORMAL);
    if(QCBORDecode_SetMemPool(&DC,  MemPoolSmall, false)) {
@@ -2105,7 +2404,7 @@
    }
    
    // --- label is an indefinite length string ------
-   QCBORDecode_Init(&DC, UsefulBuf_FromByteArrayLiteral(pIndefiniteLenStringLabel), QCBOR_DECODE_MODE_NORMAL);
+   QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spIndefiniteLenStringLabel), QCBOR_DECODE_MODE_NORMAL);
    
    if(QCBORDecode_SetMemPool(&DC,  MemPool, false)) {
       return -30;
@@ -2138,9 +2437,9 @@
    QCBORDecodeContext DC;
    
    // First test, use the "CSRMap" as easy input and checking
-   QCBORDecode_Init(&DC, UsefulBuf_FromByteArrayLiteral(s_CSRInput), QCBOR_DECODE_MODE_NORMAL);
+   QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spCSRInput), QCBOR_DECODE_MODE_NORMAL);
    
-   UsefulBuf_MakeStackUB(Pool, 300);
+   UsefulBuf_MAKE_STACK_UB(Pool, 300);
    
    QCBORDecode_SetMemPool(&DC, Pool, 1); // Turn on copying.
    
@@ -2149,8 +2448,8 @@
    }
    
    // Next parse, save pointers to a few strings, destroy original and see all is OK.
-   MakeUsefulBufOnStack(CopyOfStorage, 160);
-   UsefulBufC CopyOf = UsefulBuf_Copy(CopyOfStorage, UsefulBuf_FromByteArrayLiteral(pValidMapEncoded));
+   UsefulBuf_MAKE_STACK_UB(CopyOfStorage, 160);
+   UsefulBufC CopyOf = UsefulBuf_Copy(CopyOfStorage, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded));
 
    QCBORDecode_Init(&DC, CopyOf, QCBOR_DECODE_MODE_NORMAL);
    QCBORDecode_SetMemPool(&DC, Pool, 1); // Turn on copying.
@@ -2171,7 +2470,7 @@
    if((nCBORError = QCBORDecode_GetNext(&DC, &Item4)))
       return nCBORError;
    
-   UsefulBuf_Set(&CopyOfStorage, '_');
+   UsefulBuf_Set(CopyOfStorage, '_');
    
    if(Item1.uLabelType != QCBOR_TYPE_TEXT_STRING ||
       Item1.label.string.len != 13 ||
@@ -2199,8 +2498,8 @@
       return -1;
    
    // Next parse with a pool that is too small
-   UsefulBuf_MakeStackUB(SmallPool, 80);
-   QCBORDecode_Init(&DC, UsefulBuf_FromByteArrayLiteral(pValidMapEncoded), QCBOR_DECODE_MODE_NORMAL);
+   UsefulBuf_MAKE_STACK_UB(SmallPool, 80);
+   QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pValidMapEncoded), QCBOR_DECODE_MODE_NORMAL);
    QCBORDecode_SetMemPool(&DC, SmallPool, 1); // Turn on copying.
    if((nCBORError = QCBORDecode_GetNext(&DC, &Item1)))
       return nCBORError;
@@ -2228,9 +2527,9 @@
     
     const uint8_t pMinimalCBOR[] = {0xa0}; // One empty map
     
-    QCBORDecode_Init(&DC, UsefulBuf_FromByteArrayLiteral(pMinimalCBOR),0);
+    QCBORDecode_Init(&DC, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pMinimalCBOR),0);
     
-    UsefulBuf_MakeStackUB(Pool, 100);
+    UsefulBuf_MAKE_STACK_UB(Pool, 100);
     
     QCBORDecode_SetMemPool(&DC, Pool, 0);
     
diff --git a/test/qcbor_encode_tests.c b/test/qcbor_encode_tests.c
index 598e775..8da104f 100644
--- a/test/qcbor_encode_tests.c
+++ b/test/qcbor_encode_tests.c
@@ -55,14 +55,22 @@
 
 #include "qcbor.h"
 #include "qcbor_encode_tests.h"
-#include <strings.h>
-#include <stdlib.h>
 
 
+/*
+ This is the test set for CBOR encoding.
+ 
+ This is largely complete for the implemented.
+ 
+ A few more things to do include:
+   - Add a test for counting the top level items and adding it back in with AddRaw()
+   - Run on some different CPUs like 32-bit and maybe even 16-bit
+   - Test the large array count limit
+   - Add the CBOR diagnostic output for every expected
+ 
+ */
 
-// TODO: -- test on a 32-bit machine)
-
-// TODO: test QCBOR_MAX_ITEMS_IN_ARRAY (this is very large...)
+//#define PRINT_FUNCTIONS_FOR_DEBUGGINGXX
 
 #if PRINT_FUNCTIONS_FOR_DEBUGGINGXX
 #include <stdio.h>
@@ -81,9 +89,8 @@
 }
 
 
-#include <stdio.h>
-
-int Compare(UsefulBufC U1, UsefulBufC U2) {
+// Do the comparison and print out where it fails
+static int UsefulBuf_Compare_Print(UsefulBufC U1, UsefulBufC U2) {
    size_t i;
    for(i = 0; i < U1.len; i++) {
       if(((uint8_t *)U1.ptr)[i] != ((uint8_t *)U2.ptr)[i]) {
@@ -96,7 +103,7 @@
 }
 
 #define CheckResults(Enc, Expected) \
-   Compare(Enc, (UsefulBufC){Expected, sizeof(Expected)})
+   UsefulBuf_Compare_Print(Enc, (UsefulBufC){Expected, sizeof(Expected)})
 
 #else
 
@@ -107,28 +114,30 @@
 
 
 
-
+// One big buffer that is used by all the tests to encode into
+// Putting it in uninitialized data is better than using a lot
+// of stack. The tests should run on small devices too.
+static uint8_t spBigBuf[2200];
 
 
 
 /*
  Some very minimal tests.
  */
-int basic_encode_test()
+int BasicEncodeTest()
 {
    // Very simple CBOR, a map with one boolean that is true in it
-   UsefulBuf_MakeStackUB(MemoryForEncoded, 100);
    QCBOREncodeContext EC;
    
-   QCBOREncode_Init(&EC, MemoryForEncoded);
-   
+   QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
+
    QCBOREncode_OpenMap(&EC);
    QCBOREncode_AddBoolToMapN(&EC, 66, true);
    QCBOREncode_CloseMap(&EC);
    
    UsefulBufC Encoded;
    if(QCBOREncode_Finish2(&EC, &Encoded)) {
-      return -3;
+      return -1;
    }
    
    
@@ -139,21 +148,21 @@
    
    QCBORDecode_GetNext(&DC, &Item);
    if(Item.uDataType != QCBOR_TYPE_MAP) {
-      return -1;
+      return -2;
    }
    
    QCBORDecode_GetNext(&DC, &Item);
    if(Item.uDataType != QCBOR_TYPE_TRUE) {
-      return -1;
+      return -3;
    }
    
    if(QCBORDecode_Finish(&DC)) {
-      return -2;
+      return -4;
    }
    
    
    // Make another encoded message with the CBOR from the previous put into this one
-   UsefulBuf_MakeStackUB(MemoryForEncoded2, 100);
+   UsefulBuf_MAKE_STACK_UB(MemoryForEncoded2, 20);
    QCBOREncode_Init(&EC, MemoryForEncoded2);
    QCBOREncode_OpenArray(&EC);
    QCBOREncode_AddUInt64(&EC, 451);
@@ -165,7 +174,7 @@
    
    UsefulBufC Encoded2;
    if(QCBOREncode_Finish2(&EC, &Encoded2)) {
-      return -3;
+      return -5;
    }
     /*
      [                // 0    1:3
@@ -200,47 +209,47 @@
    // 0    1:3
    QCBORDecode_GetNext(&DC, &Item);
    if(Item.uDataType != QCBOR_TYPE_ARRAY || Item.val.uCount != 3) {
-      return -1;
+      return -6;
    }
    
    // 1    1:2
    QCBORDecode_GetNext(&DC, &Item);
    if(Item.uDataType != QCBOR_TYPE_INT64 || Item.val.uint64 != 451) {
-      return -1;
+      return -7;
    }
    
    // 1    1:2   2:1
    QCBORDecode_GetNext(&DC, &Item);
    if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 1) {
-      return -1;
+      return -8;
    }
    
    // 2    1:1
    QCBORDecode_GetNext(&DC, &Item);
    if(Item.uDataType != QCBOR_TYPE_TRUE) {
-      return -1;
+      return -9;
    }
    
    // 1    1:1   2:1
    QCBORDecode_GetNext(&DC, &Item);
    if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 1) {
-      return -1;
+      return -10;
    }
    
    // 2    1:1   2:1   3:1
    QCBORDecode_GetNext(&DC, &Item);
    if(Item.uDataType != QCBOR_TYPE_MAP || Item.val.uCount != 1 || Item.uLabelType != QCBOR_TYPE_INT64 || Item.label.int64 != -70000) {
-      return -1;
+      return -11;
    }
    
    // 3    XXXXXX
    QCBORDecode_GetNext(&DC, &Item);
    if(Item.uDataType != QCBOR_TYPE_TRUE || Item.uLabelType != QCBOR_TYPE_INT64 || Item.label.int64 != 66) {
-      return -1;
+      return -12;
    }
    
    if(QCBORDecode_Finish(&DC)) {
-      return -2;
+      return -13;
    }
    
    return 0;
@@ -248,8 +257,7 @@
 
 
 
-static const uint8_t pExpectedEncodedAll[] = {
-   
+static const uint8_t spExpectedEncodedAll[] = {
  0x98, 0x29, 0x66, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x32, 0xd8,
  0x64, 0x1a, 0x05, 0x5d, 0x23, 0x15, 0x65, 0x49, 0x4e, 0x54,
  0x36, 0x34, 0xd8, 0x4c, 0x1b, 0x00, 0x00, 0x00, 0x12, 0x16,
@@ -495,10 +503,7 @@
    QCBOREncodeContext ECtx;
    int nReturn = 0;
    
-   uint8_t pEncoded[3000];
-   size_t nEncodedLen = sizeof(pEncoded);
-   
-   QCBOREncode_Init(&ECtx, (UsefulBuf){pEncoded, nEncodedLen});
+   QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
    
    QCBOREncode_OpenArray(&ECtx);
 
@@ -556,28 +561,28 @@
    QCBOREncode_CloseMap(&ECtx);
    
    // text blobs
-   QCBOREncode_AddText(&ECtx, SZLiteralToUsefulBufC("bar bar foo bar"));
+   QCBOREncode_AddText(&ECtx, UsefulBuf_FROM_SZ_LITERAL("bar bar foo bar"));
    QCBOREncode_AddSZString(&ECtx, "oof\n");
-   QCBOREncode_AddURI(&ECtx, SZLiteralToUsefulBufC("http://stackoverflow.com/questions/28059697/how-do-i-toggle-between-debug-and-release-builds-in-xcode-6-7-8"));
-   QCBOREncode_AddB64Text(&ECtx, SZLiteralToUsefulBufC("YW55IGNhcm5hbCBwbGVhc3VyZQ=="));
-   QCBOREncode_AddRegex(&ECtx, SZLiteralToUsefulBufC("[^abc]+"));
+   QCBOREncode_AddURI(&ECtx, UsefulBuf_FROM_SZ_LITERAL("http://stackoverflow.com/questions/28059697/how-do-i-toggle-between-debug-and-release-builds-in-xcode-6-7-8"));
+   QCBOREncode_AddB64Text(&ECtx, UsefulBuf_FROM_SZ_LITERAL("YW55IGNhcm5hbCBwbGVhc3VyZQ=="));
+   QCBOREncode_AddRegex(&ECtx, UsefulBuf_FROM_SZ_LITERAL("[^abc]+"));
    QCBOREncode_AddMIMEData(&ECtx, UsefulBuf_FromSZ(szMIME));
    
    // text blobs in maps
    QCBOREncode_OpenMap(&ECtx);
-   QCBOREncode_AddTextToMap(&ECtx, "#####", SZLiteralToUsefulBufC("foo bar foo foo"));
-   QCBOREncode_AddTextToMap(&ECtx, "____", SZLiteralToUsefulBufC("foo bar")); // TODO _2? 
+   QCBOREncode_AddTextToMap(&ECtx, "#####", UsefulBuf_FROM_SZ_LITERAL("foo bar foo foo"));
+   QCBOREncode_AddTextToMap(&ECtx, "____", UsefulBuf_FROM_SZ_LITERAL("foo bar")); // TODO _2?
    QCBOREncode_AddTag(&ECtx, 1000);
    QCBOREncode_AddSZString_2(&ECtx, "()()()", QCBOR_NO_INT_LABEL, "rab rab oof");
-   QCBOREncode_AddTextToMapN(&ECtx,22, SZLiteralToUsefulBufC("foo foo foo foo"));
+   QCBOREncode_AddTextToMapN(&ECtx,22, UsefulBuf_FROM_SZ_LITERAL("foo foo foo foo"));
    QCBOREncode_AddSZStringToMap(&ECtx, "^^", "oooooooof");
    QCBOREncode_AddSZStringToMapN(&ECtx, 99, "ffffoooooooof");
-   QCBOREncode_AddURIToMap(&ECtx, "RFC", SZLiteralToUsefulBufC("https://tools.ietf.org/html/rfc7049#section-2.4.5"));
-   QCBOREncode_AddURIToMapN(&ECtx, 0x89, SZLiteralToUsefulBufC("http://cbor.me/"));
-   QCBOREncode_AddB64TextToMap(&ECtx, "whenim64", SZLiteralToUsefulBufC("cGxlYXN1cmUu"));
-   QCBOREncode_AddB64TextToMapN(&ECtx, 64, SZLiteralToUsefulBufC("c3VyZS4="));
-   QCBOREncode_AddRegexToMap(&ECtx, "popo", SZLiteralToUsefulBufC("100\\s*mk")); //   x code string literal bug
-   QCBOREncode_AddRegexToMapN(&ECtx, -51, SZLiteralToUsefulBufC("perl\\B"));  //   x code string literal bug
+   QCBOREncode_AddURIToMap(&ECtx, "RFC", UsefulBuf_FROM_SZ_LITERAL("https://tools.ietf.org/html/rfc7049#section-2.4.5"));
+   QCBOREncode_AddURIToMapN(&ECtx, 0x89, UsefulBuf_FROM_SZ_LITERAL("http://cbor.me/"));
+   QCBOREncode_AddB64TextToMap(&ECtx, "whenim64", UsefulBuf_FROM_SZ_LITERAL("cGxlYXN1cmUu"));
+   QCBOREncode_AddB64TextToMapN(&ECtx, 64, UsefulBuf_FROM_SZ_LITERAL("c3VyZS4="));
+   QCBOREncode_AddRegexToMap(&ECtx, "popo", UsefulBuf_FROM_SZ_LITERAL("100\\s*mk")); //   x code string literal bug
+   QCBOREncode_AddRegexToMapN(&ECtx, -51, UsefulBuf_FROM_SZ_LITERAL("perl\\B"));  //   x code string literal bug
    QCBOREncode_AddMIMEDataToMap(&ECtx, "Ned", UsefulBuf_FromSZ(szMIME));
    QCBOREncode_AddMIMEDataToMapN(&ECtx, 10, UsefulBuf_FromSZ(szMIME));
    QCBOREncode_CloseMap(&ECtx);
@@ -639,8 +644,8 @@
    
    
    // UUIDs
-   static uint8_t ppppUUID[] = {0x53, 0x4D, 0x41, 0x52, 0x54, 0x43, 0x53, 0x4C, 0x54, 0x54, 0x43, 0x46, 0x49, 0x43, 0x41, 0x32};
-   UsefulBufC XXUUID = ByteArrayLiteralToUsefulBufC(ppppUUID);
+   static const uint8_t ppppUUID[] = {0x53, 0x4D, 0x41, 0x52, 0x54, 0x43, 0x53, 0x4C, 0x54, 0x54, 0x43, 0x46, 0x49, 0x43, 0x41, 0x32};
+   UsefulBufC XXUUID = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(ppppUUID);
    QCBOREncode_AddBinaryUUID(&ECtx, XXUUID);
    QCBOREncode_OpenMap(&ECtx);
    QCBOREncode_AddBinaryUUIDToMap(&ECtx, "UUUU", XXUUID);
@@ -657,8 +662,8 @@
    QCBOREncode_CloseMap(&ECtx);
 
 
-   static uint8_t pBignum[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-   UsefulBufC BIGNUM = ByteArrayLiteralToUsefulBufC(pBignum);
+   static const uint8_t pBignum[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+   UsefulBufC BIGNUM = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBignum);
    QCBOREncode_AddPositiveBignum(&ECtx, BIGNUM);
    QCBOREncode_AddNegativeBignum(&ECtx, BIGNUM);
    QCBOREncode_OpenMap(&ECtx);
@@ -677,19 +682,64 @@
       goto Done;
    }
    
-   //printencodedE(Enc);
-   
-   if(CheckResults(Enc, pExpectedEncodedAll))
-      nReturn = -1;
+   if(CheckResults(Enc, spExpectedEncodedAll))
+      nReturn = -2;
    
 Done:
    return nReturn;
 }
 
-// todo -- add a test for counting the top level items and adding it back in with AddRaw()
-
-
-static const uint8_t pExpectedEncodedInts[] = {
+/*
+ 98 2F                  # array(47)
+   3B 7FFFFFFFFFFFFFFF # negative(9223372036854775807)
+   3B 0000000100000000 # negative(4294967296)
+   3A FFFFFFFF         # negative(4294967295)
+   3A FFFFFFFE         # negative(4294967294)
+   3A FFFFFFFD         # negative(4294967293)
+   3A 7FFFFFFF         # negative(2147483647)
+   3A 7FFFFFFE         # negative(2147483646)
+   3A 00010001         # negative(65537)
+   3A 00010000         # negative(65536)
+   39 FFFF             # negative(65535)
+   39 FFFE             # negative(65534)
+   39 FFFD             # negative(65533)
+   39 0100             # negative(256)
+   38 FF               # negative(255)
+   38 FE               # negative(254)
+   38 FD               # negative(253)
+   38 18               # negative(24)
+   37                  # negative(23)
+   36                  # negative(22)
+   20                  # negative(0)
+   00                  # unsigned(0)
+   00                  # unsigned(0)
+   01                  # unsigned(1)
+   16                  # unsigned(22)
+   17                  # unsigned(23)
+   18 18               # unsigned(24)
+   18 19               # unsigned(25)
+   18 1A               # unsigned(26)
+   18 FE               # unsigned(254)
+   18 FF               # unsigned(255)
+   19 0100             # unsigned(256)
+   19 0101             # unsigned(257)
+   19 FFFE             # unsigned(65534)
+   19 FFFF             # unsigned(65535)
+   1A 00010000         # unsigned(65536)
+   1A 00010001         # unsigned(65537)
+   1A 00010002         # unsigned(65538)
+   1A 7FFFFFFF         # unsigned(2147483647)
+   1A 7FFFFFFF         # unsigned(2147483647)
+   1A 80000000         # unsigned(2147483648)
+   1A 80000001         # unsigned(2147483649)
+   1A FFFFFFFE         # unsigned(4294967294)
+   1A FFFFFFFF         # unsigned(4294967295)
+   1B 0000000100000000 # unsigned(4294967296)
+   1B 0000000100000001 # unsigned(4294967297)
+   1B 7FFFFFFFFFFFFFFF # unsigned(9223372036854775807)
+   1B FFFFFFFFFFFFFFFF # unsigned(18446744073709551615)
+ */
+static const uint8_t spExpectedEncodedInts[] = {
    0x98, 0x2f, 0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff,
    0xff, 0xff, 0xff, 0x3b, 0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x00, 0x3a, 0xff, 0xff, 0xff,
@@ -729,10 +779,7 @@
    QCBOREncodeContext ECtx;
    int nReturn = 0;
    
-   uint8_t pEncoded[1000];
-   size_t nEncodedLen = sizeof(pEncoded);
-   
-   QCBOREncode_Init(&ECtx, (UsefulBuf){pEncoded, nEncodedLen});
+   QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
    QCBOREncode_OpenArray(&ECtx);
 
    QCBOREncode_AddInt64(&ECtx, -9223372036854775807LL - 1);
@@ -790,32 +837,33 @@
       nReturn = -1;
    }
    
-   if(CheckResults(Enc, pExpectedEncodedInts))
-     return -1;
-   
-   if(Enc.len != sizeof(pExpectedEncodedInts) || memcmp(pEncoded, pExpectedEncodedInts, Enc.len))
-      nReturn = -1;
-   
-   //printencoded(pEncoded, nEncodedLen);
+   if(CheckResults(Enc, spExpectedEncodedInts))
+     return -2;
    
    return(nReturn);
 }
 
 
-
-static uint8_t pExpectedEncodedSimple[] = {
+/*
+ 85                  # array(5)
+   F5               # primitive(21)
+   F4               # primitive(20)
+   F6               # primitive(22)
+   F7               # primitive(23)
+   A1               # map(1)
+      65            # text(5)
+         554E446566 # "UNDef"
+      F7            # primitive(23)
+ */
+static const uint8_t spExpectedEncodedSimple[] = {
    0x85, 0xf5, 0xf4, 0xf6, 0xf7, 0xa1, 0x65, 0x55, 0x4e, 0x44, 0x65, 0x66, 0xf7};
 
-
 int SimpleValuesTest1()
 {
    QCBOREncodeContext ECtx;
    int nReturn = 0;
    
-   uint8_t pEncoded[100];
-   size_t nEncodedLen = sizeof(pEncoded);
-   
-   QCBOREncode_Init(&ECtx, (UsefulBuf) {pEncoded, nEncodedLen});
+   QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
    QCBOREncode_OpenArray(&ECtx);
    
    QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_TRUE);
@@ -835,28 +883,41 @@
       nReturn = -1;
    }
    
-   if(ECBOR.len != sizeof(pExpectedEncodedSimple) || memcmp(pEncoded, pExpectedEncodedSimple, ECBOR.len))
-      nReturn = -1;
-   
-   // printencoded(pEncoded, nEncodedLen);
+   if(CheckResults(ECBOR, spExpectedEncodedSimple))
+      return -2;
    
    return(nReturn);
 }
 
 
-
-static uint8_t pExpectedEncodedDates[] = {
-   0x83, 0xc0, 0x74, 0x32, 0x30, 0x31, 0x33, 0x2d, 0x30, 0x33, 0x2d, 0x32, 0x31, 0x54,
-   0x32, 0x30, 0x3a, 0x30, 0x34, 0x3a, 0x30, 0x30,
-   0x5a, 0xc1, 0x1a, 0x51, 0x4b, 0x67, 0xb0, 0xa2,
-   0x78, 0x19, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65,
-   0x20, 0x44, 0x61, 0x74, 0x65, 0x20, 0x66, 0x72,
-   0x6f, 0x6d, 0x20, 0x52, 0x46, 0x43, 0x20, 0x33,
-   0x33, 0x33, 0x39, 0xc0, 0x77, 0x31, 0x39, 0x38,
-   0x35, 0x2d, 0x30, 0x34, 0x2d, 0x31, 0x32, 0x54,
-   0x32, 0x33, 0x3a, 0x32, 0x30, 0x3a, 0x35, 0x30,
-   0x2e, 0x35, 0x32, 0x5a, 0x62, 0x53, 0x44, 0xc1,
-   0x19, 0x03, 0xe7
+/*
+ 83                                      # array(3)
+   C0                                   # tag(0)
+      74                                # text(20)
+         323031332D30332D32315432303A30343A30305A # "2013-03-21T20:04:00Z"
+   C1                                   # tag(1)
+      1A 514B67B0                       # unsigned(1363896240)
+   A2                                   # map(2)
+      78 19                             # text(25)
+         53616D706C6520446174652066726F6D205246432033333339 # "Sample Date from RFC 3339"
+      C0                                # tag(0)
+         77                             # text(23)
+            313938352D30342D31325432333A32303A35302E35325A # "1985-04-12T23:20:50.52Z"
+      62                                # text(2)
+         5344                           # "SD"
+      C1                                # tag(1)
+         19 03E7                        # unsigned(999)
+ */
+static const uint8_t spExpectedEncodedDates[] = {
+   0x83, 0xc0, 0x74, 0x32, 0x30, 0x31, 0x33, 0x2d, 0x30, 0x33,
+   0x2d, 0x32, 0x31, 0x54, 0x32, 0x30, 0x3a, 0x30, 0x34, 0x3a,
+   0x30, 0x30, 0x5a, 0xc1, 0x1a, 0x51, 0x4b, 0x67, 0xb0, 0xa2,
+   0x78, 0x19, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x44,
+   0x61, 0x74, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x52,
+   0x46, 0x43, 0x20, 0x33, 0x33, 0x33, 0x39, 0xc0, 0x77, 0x31,
+   0x39, 0x38, 0x35, 0x2d, 0x30, 0x34, 0x2d, 0x31, 0x32, 0x54,
+   0x32, 0x33, 0x3a, 0x32, 0x30, 0x3a, 0x35, 0x30, 0x2e, 0x35,
+   0x32, 0x5a, 0x62, 0x53, 0x44, 0xc1, 0x19, 0x03, 0xe7
 };
 
 int EncodeDateTest()
@@ -864,10 +925,7 @@
    QCBOREncodeContext ECtx;
    int nReturn = 0;
    
-   uint8_t pEncoded[1000];
-   size_t nEncodedLen = sizeof(pEncoded);
-   
-   QCBOREncode_Init(&ECtx, (UsefulBuf){pEncoded, nEncodedLen});
+   QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
    
    QCBOREncode_OpenArray(&ECtx);
 
@@ -880,36 +938,32 @@
 
    QCBOREncode_AddDateStringToMap(&ECtx, "Sample Date from RFC 3339", "1985-04-12T23:20:50.52Z");
    
-   
    QCBOREncode_AddDateEpochToMap(&ECtx, "SD", 999);
    
    QCBOREncode_CloseMap(&ECtx);
    
    QCBOREncode_CloseArray(&ECtx);
 
-   
-   if(QCBOREncode_Finish(&ECtx, &nEncodedLen)) {
+   UsefulBufC ECBOR;
+
+   if(QCBOREncode_Finish2(&ECtx, &ECBOR)) {
       nReturn = -1;
    }
    
-   if(nEncodedLen != sizeof(pExpectedEncodedDates) || memcmp(pEncoded, pExpectedEncodedDates, nEncodedLen))
-      nReturn = -1;
-   
-   //printencoded(pEncoded, nEncodedLen);
+   if(CheckResults(ECBOR, spExpectedEncodedDates))
+      return -2;
    
    return(nReturn);
-   
 }
 
+
 int ArrayNestingTest1()
 {
    QCBOREncodeContext ECtx;
    int i;
    int nReturn = 0;
    
-   UsefulBuf_MakeStackUB(Encode, 100);
-
-   QCBOREncode_Init(&ECtx, Encode);
+   QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
    for(i = QCBOR_MAX_ARRAY_NESTING; i; i--) {
       QCBOREncode_OpenArray(&ECtx);
    }
@@ -920,7 +974,6 @@
    if(QCBOREncode_Finish(&ECtx, &nEncodedLen)) {
       nReturn = -1;
    }
-   //printencoded(pEncoded, nEncodedLen);
 
    return(nReturn);
 }
@@ -933,9 +986,7 @@
    int i;
    int nReturn = 0;
    
-   UsefulBuf_MakeStackUB(Encode, 100);
-   
-   QCBOREncode_Init(&ECtx, Encode);
+   QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
    for(i = QCBOR_MAX_ARRAY_NESTING+1; i; i--) {
       QCBOREncode_OpenArray(&ECtx);
    }
@@ -959,9 +1010,7 @@
    int i;
    int nReturn = 0;
    
-   UsefulBuf_MakeStackUB(Encode, 100);
-
-   QCBOREncode_Init(&ECtx, Encode);
+   QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
    for(i = QCBOR_MAX_ARRAY_NESTING; i; i--) {
       QCBOREncode_OpenArray(&ECtx);
    }
@@ -977,10 +1026,73 @@
 }
 
 
-static uint8_t s_pFiveArrarys[] = {0x81, 0x81, 0x81, 0x81, 0x80};
+/*
+ 81             # array(1)
+ 81          # array(1)
+ 81       # array(1)
+ 81    # array(1)
+ 80 # array(0)
+*/
+static const uint8_t spFiveArrarys[] = {0x81, 0x81, 0x81, 0x81, 0x80};
 
 // Validated at http://cbor.me and by manually examining its output
-static uint8_t s_pEncodeRawExpected[] = {
+/*
+ 82                        # array(2)
+ 81                     # array(1)
+ 81                  # array(1)
+ 81               # array(1)
+ 81            # array(1)
+ 80         # array(0)
+ 98 2F                  # array(47)
+ 3B 7FFFFFFFFFFFFFFF # negative(9223372036854775807)
+ 3B 0000000100000000 # negative(4294967296)
+ 3A FFFFFFFF         # negative(4294967295)
+ 3A FFFFFFFE         # negative(4294967294)
+ 3A FFFFFFFD         # negative(4294967293)
+ 3A 7FFFFFFF         # negative(2147483647)
+ 3A 7FFFFFFE         # negative(2147483646)
+ 3A 00010001         # negative(65537)
+ 3A 00010000         # negative(65536)
+ 39 FFFF             # negative(65535)
+ 39 FFFE             # negative(65534)
+ 39 FFFD             # negative(65533)
+ 39 0100             # negative(256)
+ 38 FF               # negative(255)
+ 38 FE               # negative(254)
+ 38 FD               # negative(253)
+ 38 18               # negative(24)
+ 37                  # negative(23)
+ 36                  # negative(22)
+ 20                  # negative(0)
+ 00                  # unsigned(0)
+ 00                  # unsigned(0)
+ 01                  # unsigned(1)
+ 16                  # unsigned(22)
+ 17                  # unsigned(23)
+ 18 18               # unsigned(24)
+ 18 19               # unsigned(25)
+ 18 1A               # unsigned(26)
+ 18 FE               # unsigned(254)
+ 18 FF               # unsigned(255)
+ 19 0100             # unsigned(256)
+ 19 0101             # unsigned(257)
+ 19 FFFE             # unsigned(65534)
+ 19 FFFF             # unsigned(65535)
+ 1A 00010000         # unsigned(65536)
+ 1A 00010001         # unsigned(65537)
+ 1A 00010002         # unsigned(65538)
+ 1A 7FFFFFFF         # unsigned(2147483647)
+ 1A 7FFFFFFF         # unsigned(2147483647)
+ 1A 80000000         # unsigned(2147483648)
+ 1A 80000001         # unsigned(2147483649)
+ 1A FFFFFFFE         # unsigned(4294967294)
+ 1A FFFFFFFF         # unsigned(4294967295)
+ 1B 0000000100000000 # unsigned(4294967296)
+ 1B 0000000100000001 # unsigned(4294967297)
+ 1B 7FFFFFFFFFFFFFFF # unsigned(9223372036854775807)
+ 1B FFFFFFFFFFFFFFFF # unsigned(18446744073709551615)
+ */
+static const uint8_t spEncodeRawExpected[] = {
    0x82, 0x81, 0x81, 0x81, 0x81, 0x80, 0x98, 0x2f,
    0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    0xff, 0x3b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
@@ -1009,14 +1121,12 @@
 
 int EncodeRawTest()
 {
-   UsefulBuf_MakeStackUB(RawTestStorage, 220);
-   
    QCBOREncodeContext ECtx;
 
-   QCBOREncode_Init(&ECtx, RawTestStorage);
+   QCBOREncode_Init(&ECtx, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
    QCBOREncode_OpenArray(&ECtx);
-   QCBOREncode_AddEncoded(&ECtx, UsefulBuf_FromByteArrayLiteral(s_pFiveArrarys));
-   QCBOREncode_AddEncoded(&ECtx, UsefulBuf_FromByteArrayLiteral(pExpectedEncodedInts));
+   QCBOREncode_AddEncoded(&ECtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spFiveArrarys));
+   QCBOREncode_AddEncoded(&ECtx, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedEncodedInts));
    QCBOREncode_CloseArray(&ECtx);
    
    UsefulBufC EncodedRawTest;
@@ -1025,16 +1135,16 @@
       return -4;
    }
    
-   if(UsefulBuf_Compare(EncodedRawTest, UsefulBuf_FromByteArrayLiteral(s_pEncodeRawExpected))) {
+   if(CheckResults(EncodedRawTest, spEncodeRawExpected)) {
       return -5;
    }
    
    return 0;
 }
 
-
-
-
+/*
+ This returns a pointer to spBigBuf
+ */
 static int CreateMap(uint8_t **pEncoded, size_t *pEncodedLen)
 {
    QCBOREncodeContext ECtx;
@@ -1042,6 +1152,7 @@
    
    *pEncoded = NULL;
    *pEncodedLen = INT32_MAX;
+   size_t uFirstSizeEstimate = 0;
    
    // loop runs CBOR encoding twice. First with no buffer to
    // calucate the length so buffer can be allocated correctly,
@@ -1066,28 +1177,70 @@
       if(QCBOREncode_Finish(&ECtx, pEncodedLen))
          goto Done;
       if(*pEncoded != NULL) {
-         nReturn = 0;
+         if(uFirstSizeEstimate != *pEncodedLen) {
+            nReturn = 1;
+         } else {
+            nReturn = 0;
+         }
          goto Done;
       }
-      *pEncoded = malloc(*pEncodedLen);
+      *pEncoded = spBigBuf;
+      uFirstSizeEstimate = *pEncodedLen;
+      
    } while(1);
    
  Done:
    return(nReturn);
 }
 
-
-static uint8_t pValidMapEncoded[] = {
-   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 } ;
-
+/*
+ A3                                      # map(3)
+   6D                                   # text(13)
+      666972737420696E7465676572        # "first integer"
+   18 2A                                # unsigned(42)
+   77                                   # text(23)
+      616E206172726179206F662074776F20737472696E6773 # "an array of two strings"
+   82                                   # array(2)
+      67                                # text(7)
+         737472696E6731                 # "string1"
+      67                                # text(7)
+         737472696E6732                 # "string2"
+   6C                                   # text(12)
+      6D617020696E2061206D6170          # "map in a map"
+   A4                                   # map(4)
+      67                                # text(7)
+         62797465732031                 # "bytes 1"
+      44                                # bytes(4)
+         78787878                       # "xxxx"
+      67                                # text(7)
+         62797465732032                 # "bytes 2"
+      44                                # bytes(4)
+         79797979                       # "yyyy"
+      6B                                # text(11)
+         616E6F7468657220696E74         # "another int"
+      18 62                             # unsigned(98)
+      66                                # text(6)
+         746578742032                   # "text 2"
+      78 1E                             # text(30)
+         6C6965732C2064616D6E206C69657320616E642073746174697374696373 # "lies, damn lies and statistics"
+ */
+static const uint8_t spValidMapEncoded[] = {
+   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 } ;
 
 
 int MapEncodeTest()
@@ -1096,14 +1249,12 @@
    size_t nEncodedMapLen;
    
    if(CreateMap(&pEncodedMaps, &nEncodedMapLen)) {
-      return(-1);
+      return -1;
    }
    
-   //printencoded(pEncodedMaps, nEncodedMapLen);
-   
    int nReturn = 0;
-   if(memcmp(pValidMapEncoded, pEncodedMaps, sizeof(pValidMapEncoded)))
-      nReturn = 1;
+   if(memcmp(spValidMapEncoded, pEncodedMaps, sizeof(spValidMapEncoded)))
+      nReturn = 2;
    
    return(nReturn);
 }
@@ -1130,7 +1281,7 @@
  
  */
 
-int FormatRTICResults(int nRResult, uint64_t time, const char *szType, const char *szAlexString, uint8_t *pOut, size_t *pnLen)
+static UsefulBufC FormatRTICResults(int nRResult, uint64_t time, const char *szType, const char *szAlexString, UsefulBuf Storage)
 {
    // Buffer that the result will be written in to
    // It is fixed size and small that a stack variable will be fine
@@ -1138,7 +1289,7 @@
    
    // Context for the encoder
    QCBOREncodeContext ECtx;
-   QCBOREncode_Init(&ECtx, (UsefulBuf){pOut, *pnLen});
+   QCBOREncode_Init(&ECtx, Storage);
    
    // All the RTIC results are grouped in a CBOR Map which will get turned into a JSON Object
    // Contents are label / value pairs
@@ -1172,7 +1323,7 @@
          QCBOREncode_AddInt64ToMap(&ECtx, "IQ", 0xffffffff);
 
          // Add a few fake integers and buffers for now.
-         const uint8_t pPV[] = {0x66, 0x67, 0x00, 0x56, 0xaa, 0xbb, 0x01, 0x01};
+         static const uint8_t pPV[] = {0x66, 0x67, 0x00, 0x56, 0xaa, 0xbb, 0x01, 0x01};
          UsefulBufC WSPV = {pPV, sizeof(pPV)};
             
          QCBOREncode_AddBytesToMap(&ECtx, "WhaleSharkPatternVector", WSPV);
@@ -1185,41 +1336,93 @@
    // Close the map
    QCBOREncode_CloseMap(&ECtx);
    
-   return QCBOREncode_Finish(&ECtx, pnLen);
+   UsefulBufC Result;
+   
+   QCBOREncode_Finish2(&ECtx, &Result);
+   
+   return Result;
 }
 
 
-static const uint8_t pExpectedRTIC[] = {0xa5, 0x69, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79, 0xf4, 0x64, 0x74, 0x79, 0x70, 0x65, 0x66, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x64, 0x74, 0x69, 0x6d, 0x65, 0xc1, 0x1a, 0x58, 0x0d, 0x41, 0x72, 0x64, 0x64, 0x69, 0x61, 0x67, 0x6a, 0x30, 0x78, 0x41, 0x31, 0x65, 0x43, 0x35, 0x30, 0x30, 0x31, 0x69, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0xa3, 0x69, 0x53, 0x68, 0x6f, 0x65, 0x20, 0x53, 0x69, 0x7a, 0x65, 0x0c, 0x62, 0x49, 0x51, 0x1a, 0xff, 0xff, 0xff, 0xff, 0x77, 0x57, 0x68, 0x61, 0x6c, 0x65, 0x53, 0x68, 0x61, 0x72, 0x6b, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x56, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x48, 0x66, 0x67, 0x00, 0x56, 0xaa, 0xbb, 0x01, 0x01};
+/*
+ A5                                      # map(5)
+   69                                   # text(9)
+      696E74656772697479                # "integrity"
+   F4                                   # primitive(20)
+   64                                   # text(4)
+      74797065                          # "type"
+   66                                   # text(6)
+      726563656E74                      # "recent"
+   64                                   # text(4)
+      74696D65                          # "time"
+   C1                                   # tag(1)
+      1A 580D4172                       # unsigned(1477263730)
+   64                                   # text(4)
+      64696167                          # "diag"
+   6A                                   # text(10)
+      30784131654335303031              # "0xA1eC5001"
+   69                                   # text(9)
+      74656C656D65747279                # "telemetry"
+   A3                                   # map(3)
+      69                                # text(9)
+         53686F652053697A65             # "Shoe Size"
+      0C                                # unsigned(12)
+      62                                # text(2)
+         4951                           # "IQ"
+      1A FFFFFFFF                       # unsigned(4294967295)
+      77                                # text(23)
+         5768616C65536861726B5061747465726E566563746F72 # "WhaleSharkPatternVector"
+      48                                # bytes(8)
+         66670056AABB0101               # "fg\x00V\xAA\xBB\x01\x01"
+ */
+static const uint8_t spExpectedRTIC[] = {
+   0xa5, 0x69, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74,
+   0x79, 0xf4, 0x64, 0x74, 0x79, 0x70, 0x65, 0x66, 0x72, 0x65,
+   0x63, 0x65, 0x6e, 0x74, 0x64, 0x74, 0x69, 0x6d, 0x65, 0xc1,
+   0x1a, 0x58, 0x0d, 0x41, 0x72, 0x64, 0x64, 0x69, 0x61, 0x67,
+   0x6a, 0x30, 0x78, 0x41, 0x31, 0x65, 0x43, 0x35, 0x30, 0x30,
+   0x31, 0x69, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72,
+   0x79, 0xa3, 0x69, 0x53, 0x68, 0x6f, 0x65, 0x20, 0x53, 0x69,
+   0x7a, 0x65, 0x0c, 0x62, 0x49, 0x51, 0x1a, 0xff, 0xff, 0xff,
+   0xff, 0x77, 0x57, 0x68, 0x61, 0x6c, 0x65, 0x53, 0x68, 0x61,
+   0x72, 0x6b, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x56,
+   0x65, 0x63, 0x74, 0x6f, 0x72, 0x48, 0x66, 0x67, 0x00, 0x56,
+   0xaa, 0xbb, 0x01, 0x01};
 
 
 int RTICResultsTest()
 {
-   uint8_t out[200];
-   size_t len = sizeof(out);
-   
-   int nResult = FormatRTICResults(CBOR_SIMPLEV_FALSE, 1477263730, "recent", "0xA1eC5001",  out, &len);
-   if(nResult)
+   UsefulBufC Encoded = FormatRTICResults(CBOR_SIMPLEV_FALSE, 1477263730,
+                                          "recent", "0xA1eC5001",
+                                          UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
+   if(UsefulBuf_IsNULLC(Encoded)) {
       return -1;
+   }
    
-   if(memcmp(pExpectedRTIC, out, sizeof(pExpectedRTIC)))
-      return 1;
-   
-   //printencoded(out,  len);
+   if(CheckResults(Encoded, spExpectedRTIC)) {
+      return -2;
+   }
    
    return 0;  
 }
 
 
+/*
+ 82           # array(2)
+   19 01C3   # unsigned(451)
+   43        # bytes(3)
+      1901D2 # "\x19\x01\xD2"
+*/
+static const uint8_t spExpectedBstrWrap[] = {0x82, 0x19, 0x01, 0xC3, 0x43, 0x19, 0x01, 0xD2};
 
 /*
  Very basic bstr wrapping test
  */
-int bstrwraptest()
+int BstrWrapTest()
 {
-   UsefulBuf_MakeStackUB(MemoryForEncoded, 100);
    QCBOREncodeContext EC;
    
-   QCBOREncode_Init(&EC, MemoryForEncoded);
+   QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
    
    QCBOREncode_OpenArray(&EC);
    QCBOREncode_AddUInt64(&EC, 451);
@@ -1237,8 +1440,7 @@
       return -1;
    }
    
-   const uint8_t pExpected[] = {0x82, 0x19, 0x01, 0xC3, 0x43, 0x19, 0x01, 0xD2};
-   if(UsefulBuf_Compare(UsefulBuf_FromByteArrayLiteral(pExpected), Encoded)) {
+   if(CheckResults(Encoded, spExpectedBstrWrap)) {
       return -2;
    }
    
@@ -1247,13 +1449,12 @@
 
 
 
-int bstr_wrap_error_test()
+int BstrWrapErrorTest()
 {
    // -------------- Test closing a bstrwrap when it is an array that is open -----------
-   UsefulBuf_MakeStackUB(MemoryForEncoded, 100);
    QCBOREncodeContext EC;
    
-   QCBOREncode_Init(&EC, MemoryForEncoded);
+   QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
    
    QCBOREncode_OpenArray(&EC);
    QCBOREncode_AddUInt64(&EC, 451);
@@ -1273,14 +1474,14 @@
    }
    
    // ----------- test closing a bstrwrap when nothing is open ---------------------
-   QCBOREncode_Init(&EC, MemoryForEncoded);
+   QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
    QCBOREncode_CloseBstrWrap(&EC, &Wrapped);
    if(QCBOREncode_Finish2(&EC, &Encoded2) != QCBOR_ERR_TOO_MANY_CLOSES) {
       return -2;
    }
    
    // --------------- test nesting too deep ----------------------------------
-   QCBOREncode_Init(&EC, MemoryForEncoded);
+   QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
    for(int i = 1; i < 18; i++) {
       QCBOREncode_BstrWrap(&EC);
    }
@@ -1342,7 +1543,22 @@
  
  
  */
-static const uint8_t sExpectedDeepBstr[] =
+
+
+/*
+ 83                                      # array(3)
+   56                                   # bytes(22)
+      00530150024D034A0447054406410700010203040506 # "\x00S\x01P\x02M\x03J\x04G\x05D\x06A\a\x00\x01\x02\x03\x04\x05\x06"
+   07                                   # unsigned(7)
+   A2                                   # map(2)
+      18 20                             # unsigned(32)
+      54                                # bytes(20)
+         8210A21821448111183018406568656C6C6F1831 # "\x82\x10\xA2\x18!D\x81\x11\x180\x18@ehello\x181"
+      18 41                             # unsigned(65)
+      65                                # text(5)
+         68656C6C6F                     # "hello"
+ */
+static const uint8_t spExpectedDeepBstr[] =
 {
    0x83, 0x56, 0x00, 0x53, 0x01, 0x50, 0x02, 0x4D,
    0x03, 0x4A, 0x04, 0x47, 0x05, 0x44, 0x06, 0x41,
@@ -1355,7 +1571,7 @@
 };
 
 // Part of bstr_wrap_nest_test
-static int decode_next_nested(UsefulBufC Wrapped)
+static int DecodeNextNested(UsefulBufC Wrapped)
 {
    int nReturn;
    QCBORDecodeContext DC;
@@ -1377,7 +1593,7 @@
    if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
       return -13;
    }
-   nReturn =  decode_next_nested(Item.val.string);
+   nReturn =  DecodeNextNested(Item.val.string);
    if(nReturn) {
       return nReturn;
    }
@@ -1398,7 +1614,7 @@
 }
 
 // Part of bstr_wrap_nest_test
-static int decode_next_nested2(UsefulBufC Wrapped)
+static int DecodeNextNested2(UsefulBufC Wrapped)
 {
    int nReturn;
    QCBORDecodeContext DC;
@@ -1436,7 +1652,7 @@
    if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
       return -13;
    }
-   nReturn =  decode_next_nested2(Item.val.string);
+   nReturn =  DecodeNextNested2(Item.val.string);
    if(nReturn) {
       return nReturn;
    }
@@ -1464,11 +1680,10 @@
 }
 
 
-int bstr_wrap_nest_test()
+int BstrWrapNestTest()
 {
-   UsefulBuf_MakeStackUB(MemoryForEncoded, 300);
    QCBOREncodeContext EC;
-   QCBOREncode_Init(&EC, MemoryForEncoded);
+   QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
    
    // ---- Make a complicated nested CBOR structure ---
    QCBOREncode_OpenArray(&EC);
@@ -1505,7 +1720,7 @@
    }
    
    // ---Compare it to expected. Expected was hand checked with use of CBOR playground ----
-   if(UsefulBuf_Compare(UsefulBuf_FromByteArrayLiteral(sExpectedDeepBstr), Encoded)) {
+   if(UsefulBuf_Compare(UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spExpectedDeepBstr), Encoded)) {
       return -25;
    }
    
@@ -1525,7 +1740,7 @@
       return -3;
    }
    
-   int nReturn = decode_next_nested(Item.val.string);
+   int nReturn = DecodeNextNested(Item.val.string);
    if(nReturn) {
       return nReturn;
    }
@@ -1547,7 +1762,7 @@
    if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
       return -3;
    }
-   nReturn = decode_next_nested2(Item.val.string);
+   nReturn = DecodeNextNested2(Item.val.string);
    if(nReturn) {
       return nReturn;
    }
@@ -1568,6 +1783,41 @@
 }
 
 
+static const uint8_t spSignature[] = {
+   0x8e, 0xb3, 0x3e, 0x4c, 0xa3, 0x1d, 0x1c, 0x46, 0x5a, 0xb0,
+   0x5a, 0xac, 0x34, 0xcc, 0x6b, 0x23, 0xd5, 0x8f, 0xef, 0x5c,
+   0x08, 0x31, 0x06, 0xc4, 0xd2, 0x5a, 0x91, 0xae, 0xf0, 0xb0,
+   0x11, 0x7e, 0x2a, 0xf9, 0xa2, 0x91, 0xaa, 0x32, 0xe1, 0x4a,
+   0xb8, 0x34, 0xdc, 0x56, 0xed, 0x2a, 0x22, 0x34, 0x44, 0x54,
+   0x7e, 0x01, 0xf1, 0x1d, 0x3b, 0x09, 0x16, 0xe5, 0xa4, 0xc3,
+   0x45, 0xca, 0xcb, 0x36};
+
+/*
+ D2                                      # tag(18)
+   84                                   # array(4)
+      43                                # bytes(3)
+         A10126                         # "\xA1\x01&"
+      A1                                # map(1)
+         04                             # unsigned(4)
+         42                             # bytes(2)
+            3131                        # "11"
+      54                                # bytes(20)
+         546869732069732074686520636F6E74656E742E # "This is the content."
+      58 40                             # bytes(64)
+         8EB33E4CA31D1C465AB05AAC34CC6B23D58FEF5C083106C4D25A91AEF0B0117E2AF9A291AA32E14AB834DC56ED2A223444547E01F11D3B0916E5A4C345CACB36 # "\x8E\xB3>L\xA3\x1D\x1CFZ\xB0Z\xAC4\xCCk#\xD5\x8F\xEF\\\b1\x06\xC4\xD2Z\x91\xAE\xF0\xB0\x11~*\xF9\xA2\x91\xAA2\xE1J\xB84\xDCV\xED*\"4DT~\x01\xF1\x1D;\t\x16\xE5\xA4\xC3E\xCA\xCB6"
+ */
+static const uint8_t spExpected[] = {
+   0xD2, 0x84, 0x43, 0xA1, 0x01, 0x26, 0xA1, 0x04, 0x42, 0x31,
+   0x31, 0x54, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
+   0x74, 0x68, 0x65, 0x20, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E,
+   0x74, 0x2E, 0x58, 0x40, 0x8E, 0xB3, 0x3E, 0x4C, 0xA3, 0x1D,
+   0x1C, 0x46, 0x5A, 0xB0, 0x5A, 0xAC, 0x34, 0xCC, 0x6B, 0x23,
+   0xD5, 0x8F, 0xEF, 0x5C, 0x08, 0x31, 0x06, 0xC4, 0xD2, 0x5A,
+   0x91, 0xAE, 0xF0, 0xB0, 0x11, 0x7E, 0x2A, 0xF9, 0xA2, 0x91,
+   0xAA, 0x32, 0xE1, 0x4A, 0xB8, 0x34, 0xDC, 0x56, 0xED, 0x2A,
+   0x22, 0x34, 0x44, 0x54, 0x7E, 0x01, 0xF1, 0x1D, 0x3B, 0x09,
+   0x16, 0xE5, 0xA4, 0xC3, 0x45, 0xCA, 0xCB, 0x36};
+
 /*
  this corresponds exactly to the example in RFC 8152
  section C.2.1. This doesn't actually verify the signature
@@ -1575,43 +1825,23 @@
  really good. That would require bring in ECDSA crypto
  to this test.
  */
-int cose_sign1_tbs_test()
+int CoseSign1TBSTest()
 {
    // All of this is from RFC 8152 C.2.1
    const char *szKid = "11";
    UsefulBufC Kid = UsefulBuf_FromSZ(szKid);
    const char *szPayload = "This is the content.";
    UsefulBufC Payload = UsefulBuf_FromSZ(szPayload);
-   const uint8_t pProtectedHeaders[] = {0xa1, 0x01, 0x26};
-   UsefulBufC ProtectedHeaders = UsefulBuf_FromByteArrayLiteral(pProtectedHeaders);
-   const uint8_t sSignature[] = {
-      0x8e, 0xb3, 0x3e, 0x4c, 0xa3, 0x1d, 0x1c, 0x46, 0x5a, 0xb0,
-      0x5a, 0xac, 0x34, 0xcc, 0x6b, 0x23, 0xd5, 0x8f, 0xef, 0x5c,
-      0x08, 0x31, 0x06, 0xc4, 0xd2, 0x5a, 0x91, 0xae, 0xf0, 0xb0,
-      0x11, 0x7e, 0x2a, 0xf9, 0xa2, 0x91, 0xaa, 0x32, 0xe1, 0x4a,
-      0xb8, 0x34, 0xdc, 0x56, 0xed, 0x2a, 0x22, 0x34, 0x44, 0x54,
-      0x7e, 0x01, 0xf1, 0x1d, 0x3b, 0x09, 0x16, 0xe5, 0xa4, 0xc3,
-      0x45, 0xca, 0xcb, 0x36};
+   static const uint8_t pProtectedHeaders[] = {0xa1, 0x01, 0x26};
+   UsefulBufC ProtectedHeaders = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pProtectedHeaders);
+
    // It would be good to compare this to the output from
    // a COSE implementation like COSE-C. It has been checked
    // against the CBOR playground.
-   UsefulBufC Signature = UsefulBuf_FromByteArrayLiteral(sSignature);
-   const uint8_t sExpected[] = {
-      0xD2, 0x84, 0x43, 0xA1, 0x01, 0x26, 0xA1, 0x04, 0x42, 0x31,
-      0x31, 0x54, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
-      0x74, 0x68, 0x65, 0x20, 0x63, 0x6F, 0x6E, 0x74, 0x65, 0x6E,
-      0x74, 0x2E, 0x58, 0x40, 0x8E, 0xB3, 0x3E, 0x4C, 0xA3, 0x1D,
-      0x1C, 0x46, 0x5A, 0xB0, 0x5A, 0xAC, 0x34, 0xCC, 0x6B, 0x23,
-      0xD5, 0x8F, 0xEF, 0x5C, 0x08, 0x31, 0x06, 0xC4, 0xD2, 0x5A,
-      0x91, 0xAE, 0xF0, 0xB0, 0x11, 0x7E, 0x2A, 0xF9, 0xA2, 0x91,
-      0xAA, 0x32, 0xE1, 0x4A, 0xB8, 0x34, 0xDC, 0x56, 0xED, 0x2A,
-      0x22, 0x34, 0x44, 0x54, 0x7E, 0x01, 0xF1, 0x1D, 0x3B, 0x09,
-      0x16, 0xE5, 0xA4, 0xC3, 0x45, 0xCA, 0xCB, 0x36};
-   UsefulBufC Expected = UsefulBuf_FromByteArrayLiteral(sExpected);
+   UsefulBufC Signature = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(spSignature);
    
-   UsefulBuf_MakeStackUB(MemoryForEncoded, 98);
    QCBOREncodeContext EC;
-   QCBOREncode_Init(&EC, MemoryForEncoded);
+   QCBOREncode_Init(&EC, UsefulBuf_FROM_BYTE_ARRAY(spBigBuf));
    
    // top level array for cose sign1, 18 is the tag for COSE sign
    QCBOREncode_AddTag(&EC, 18); // TODO: replace with constant
@@ -1651,7 +1881,7 @@
       return -3;
    }
    
-   if(UsefulBuf_Compare(COSE_Sign1, Expected)) {
+   if(CheckResults(COSE_Sign1, spExpected)) {
       return -4;
    }
    
diff --git a/test/qcbor_encode_tests.h b/test/qcbor_encode_tests.h
index 8625fe2..948c903 100644
--- a/test/qcbor_encode_tests.h
+++ b/test/qcbor_encode_tests.h
@@ -49,7 +49,7 @@
 /*
  Most basic test.
  */
-int basic_encode_test(void);
+int BasicEncodeTest(void);
 
 
 /*
@@ -127,13 +127,13 @@
 /*
  The binary string wrapping of maps and arrays used by COSE
  */
-int  bstrwraptest(void);
+int  BstrWrapTest(void);
 
-int bstr_wrap_error_test(void);
+int BstrWrapErrorTest(void);
 
-int bstr_wrap_nest_test(void);
+int BstrWrapNestTest(void);
 
-int cose_sign1_tbs_test(void);
+int CoseSign1TBSTest(void);
 
 
 
diff --git a/test/run_tests.c b/test/run_tests.c
index 41c70e0..0424b16 100644
--- a/test/run_tests.c
+++ b/test/run_tests.c
@@ -133,7 +133,7 @@
     TEST_ENTRY(ComprehensiveInputTest),
     TEST_ENTRY(ParseMapTest),
     TEST_ENTRY(IndefiniteLengthArrayMapTest),
-    TEST_ENTRY(basic_encode_test),
+    TEST_ENTRY(BasicEncodeTest),
     TEST_ENTRY(NestedMapTest),
     TEST_ENTRY(BignumParseTest),
     TEST_ENTRY(OptTagParseTest),
@@ -145,15 +145,15 @@
     TEST_ENTRY(IntegerValuesParseTest),
     TEST_ENTRY(MemPoolTest),
     TEST_ENTRY(IndefiniteLengthStringTest),
-    TEST_ENTRY(half_precision_encode_basic),
-    TEST_ENTRY(half_precision_decode_basic),
-    TEST_ENTRY(half_precision_to_float_transitive_test),
-    TEST_ENTRY(double_as_smallest_encode_basic),
-    TEST_ENTRY(half_precision_to_float_vs_rfc_test),
-    TEST_ENTRY(bstrwraptest),
-    TEST_ENTRY(bstr_wrap_error_test),
-    TEST_ENTRY(bstr_wrap_nest_test),
-    TEST_ENTRY(cose_sign1_tbs_test),
+    TEST_ENTRY(HalfPrecisionEncodeBasicTests),
+    TEST_ENTRY(HalfPrecisionDecodeBasicTests),
+    TEST_ENTRY(HalfPrecisionTransitiveTest),
+    TEST_ENTRY(DoubleAsSmallestTest),
+    TEST_ENTRY(HalfPrecisionAgainstRFCCodeTest),
+    TEST_ENTRY(BstrWrapTest),
+    TEST_ENTRY(BstrWrapErrorTest),
+    TEST_ENTRY(BstrWrapNestTest),
+    TEST_ENTRY(CoseSign1TBSTest),
     //TEST_ENTRY(fail_test),
 };
 
@@ -162,7 +162,7 @@
 {
     int nTestsFailed = 0;
     int nTestsRun = 0;
-    UsefulBuf_MakeStackUB(StringStorage, 5);
+    UsefulBuf_MAKE_STACK_UB(StringStorage, 5);
 
     test_entry2 *t2;
     const test_entry2 *s_tests2_end = s_tests2 + sizeof(s_tests2)/sizeof(test_entry2);