big change for simpler encoding design for tags and labels
diff --git a/inc/qcbor.h b/inc/qcbor.h
index dad939a..e31f233 100644
--- a/inc/qcbor.h
+++ b/inc/qcbor.h
@@ -704,7 +704,7 @@
       uint64_t    uint64;     /** The value for uDataType QCBOR_TYPE_UINT64 */
 
       UsefulBufC  string;     /** The value for uDataType QCBOR_TYPE_BYTE_STRING and QCBOR_TYPE_TEXT_STRING */
-      uint16_t    uCount;     /** The "value" for uDataType QCBOR_TYPE_ARRAY or QCBOR_TYPE_MAP -- the number of items in the array or map */ // TODO: indefinite len arrays
+      uint16_t    uCount;     /** The "value" for uDataType QCBOR_TYPE_ARRAY or QCBOR_TYPE_MAP -- the number of items in the array or map */
       double      dfnum;      /** The value for uDataType QCBOR_TYPE_DOUBLE */
       struct {
          int64_t  nSeconds;
@@ -794,13 +794,6 @@
 
 
 /**
- Constant passed for paramenter nLabel to indicate that no integer
- label should be added for this item. This also means that you can
- never use INT64_MAX as an integer label.
- */
-#define QCBOR_NO_INT_LABEL           INT64_MAX
-
-/**
  QCBOREncodeContext is the data type that holds context for all the
  encoding functions. It is a little over 100 bytes so it can go on 
  the stack. The contents are opaque and the caller should not access
@@ -843,36 +836,12 @@
 
 
 /**
- @brief[in] Add an optional tag
- 
- @param[in] pCtx  The encoding context to add the integer to.
- @param[in] uTag  The tag to add
-
- The tag is applied to the next data item added to the encoded
- output. That data item can be of any major CBOR type.
- 
- Any number of tags can be added to a data item.
- 
- When one of the Add functions is called with either a string or
- integer label after a call to this function, the output will be
- re ordered so that the tag comes after the label and tags the
- value, not the label.
- */
-void QCBOREncode_AddTag(QCBOREncodeContext *pCtx,uint64_t uTag);
-
-
-/**
- @brief  Add a 64-bit integer to the encoded output
+ @brief  Add a signed 64-bit integer to the encoded output.
  
  @param[in] pCtx      The encoding context to add the integer to.
- @param[in] szLabel   The string map label for this integer value.
- @param[in] nLabel    The integer map label for this integer value.
  @param[in] nNum      The integer to add.
  
- The functions and macros with a "U" add unsigned integers and those
- without add signed. The main reason to use the unsigned versions is
- when the integers are in the range of MAX_INT to MAX_UINT, values
- that can be expressed by a uint64_t, but not an int64_t.
+ The integer will be encoded and added to the CBOR output.
  
  This function figures out the size and the sign and encodes in the
  correct minimal CBOR. Specifically it will select CBOR major type 0 or 1
@@ -895,35 +864,92 @@
  There are no functions to add int16_t or int32_t because they are
  not necessary because this always encodes to the smallest number
  of bytes based on the value (If this code is running on a 32-bit
- machine having way to add 32-bit integers would reduce code size some).
+ machine having a way to add 32-bit integers would reduce code size some).
  
  If the encoding context is in an error state, this will do
- nothing. If this causes an error such as going off the end of the
- buffer an internal error flag will be set and the error will be
- returned when QCBOREncode_Finish() is called.
+ nothing. If an error occurs when adding this integer the internal
+ error flag will be set and the error will be returned when
+ QCBOREncode_Finish() is called.
+ 
+ See also QCBOREncode_AddUInt64().
  
  */
+void QCBOREncode_AddInt64(QCBOREncodeContext *pCtx, int64_t nNum);
 
-void QCBOREncode_AddInt64_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, int64_t nNum);
-void QCBOREncode_AddUInt64_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, uint64_t uNum);
+static void QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t uNum);
 
-#define QCBOREncode_AddUInt64(pCtx, uNum) \
-      QCBOREncode_AddUInt64_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (uNum))
+static void QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t uNum);
 
-#define QCBOREncode_AddUInt64ToMap(pCtx, szLabel, uNum) \
-      QCBOREncode_AddUInt64_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (uNum))
 
-#define QCBOREncode_AddUInt64ToMapN(pCtx, nLabel, uNum) \
-      QCBOREncode_AddUInt64_2((pCtx), NULL, (nLabel), (uNum))
+/**
+ @brief  Add an unsigned 64-bit integer to the encoded output.
+ 
+ @param[in] pCtx      The encoding context to add the integer to.
+ @param[in] uNum      The integer to add.
+ 
+ The integer will be encoded and added to the CBOR output.
+ 
+ The only reason so use this function is for integers larger than
+ INT64_MAX and smaller than UINT64_MAX. Otherwise QCBOREncode_AddInt64()
+ will work fine.
+ 
+ Error handling is the same as for QCBOREncode_AddInt64().
+ 
+ */
+void QCBOREncode_AddUInt64(QCBOREncodeContext *pCtx, uint64_t uNum);
 
-#define QCBOREncode_AddInt64(pCtx, nNum) \
-      QCBOREncode_AddInt64_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (nNum))
+static void QCBOREncode_AddUInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t uNum);
 
-#define QCBOREncode_AddInt64ToMap(pCtx, szLabel, nNum) \
-      QCBOREncode_AddInt64_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (nNum))
+static void QCBOREncode_AddUInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, uint64_t uNum);
 
-#define QCBOREncode_AddInt64ToMapN(pCtx, nLabel, nNum) \
-      QCBOREncode_AddInt64_2((pCtx), NULL, (nLabel), (nNum))
+
+
+/**
+ 
+ @brief  Add a UTF-8 text string to the encoded output
+ 
+ @param[in] pCtx     The context to initialize.
+ @param[in] Text    Pointer and length of text to add.
+ 
+ The text passed in must be unencoded UTF-8 according to RFC
+ 3629. There is no NULL termination. The text is added as CBOR
+ major type 3.
+ 
+ If called with nBytesLen equal to 0, an empty string will be
+ added. When nBytesLen is 0, pBytes may be NULL.
+ 
+ Note that the restriction of the buffer length to an uint32_t is
+ entirely intentional as this encoder is not capable of encoding
+ lengths greater. This limit to 4GB for a text string should not be a
+ problem.
+ 
+ Error handling is the same as QCBOREncode_AddInt64().
+ 
+ */
+static void QCBOREncode_AddText(QCBOREncodeContext *pCtx, UsefulBufC Text);
+
+static void QCBOREncode_AddTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Text);
+
+static void QCBOREncode_AddTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Text);
+
+
+
+/**
+ 
+ @brief  Add a UTF-8 text string to the encoded output
+ 
+ @param[in] pCtx      The context to initialize.
+ @param[in] szString  Null-terminated text to add.
+ 
+This works the same as QCBOREncode_AddText().
+ 
+ */
+static void QCBOREncode_AddSZString(QCBOREncodeContext *pCtx, const char *szString);
+
+static void QCBOREncode_AddSZStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szString);
+
+static void QCBOREncode_AddSZStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szString);
+
 
 
 
@@ -931,9 +957,9 @@
  @brief  Add a floating point number to the encoded output
  
  @param[in] pCtx      The encoding context to add the float to.
- @param[in] szLabel   The string map label for this integer value.
- @param[in] nLabel    The integer map label for this integer value.
- @param[in] dNum      The float to add.
+ @param[in] dNum      The double precision number to add.
+ 
+ This outputs a floating point number with CBOR major type 7.
  
  This will selectively encode the double-precision floating point number as either
  double-precision, single-precision or half-precision. It will always encode infinity, NaN and 0
@@ -945,39 +971,50 @@
  Half-precision floating point numbers take up 2 bytes, half that of single-precision,
  one quarter of double-preceision
  
- This reduces the size of encoded messages a lot, maybe even by four if a most of values are
+ This automatically reduces the size of encoded messages a lot, maybe even by four if most of values are
  0, infinity or NaN.
  
- On decode, these will always be represented has float or double. Half-precision values
- will decode as float as standard C doesn't have a widely used
- standard representation for half-precision floats yet. The designer of the protocol
- using this approach can / should assume that floats received actually have the precision
- of double. They should probably cast the float received to double.
+ On decode, these will always be returned as a double.
  
- This works the same as QCBOREncode_AddInt64_2() except it is for floating point types.
- 
+ Error handling is the same as QCBOREncode_AddInt64().
+
  */
 
-void QCBOREncode_AddDouble_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, double dNum);
+void QCBOREncode_AddDouble(QCBOREncodeContext *pCtx, double dNum);
 
-#define QCBOREncode_AddDoubleAsSmallest(pCtx, dNum) \
-      QCBOREncode_AddDouble_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (dNum))
+static void QCBOREncode_AddDoubleToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum);
 
-#define QCBOREncode_AddDoubleAsSmallestToMap(pCtx, szLabel, dNum) \
-      QCBOREncode_AddDouble_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (dNum))
+static void QCBOREncode_AddDoubleToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum);
 
-#define QCBOREncode_AddDoubleAsSmallestToMapN(pCtx, nLabel, dNum) \
-      QCBOREncode_AddDouble_2((pCtx), NULL, (nLabel), (dNum))
 
 
 
 /**
+ @brief[in] Add an optional tag
+ 
+ @param[in] pCtx  The encoding context to add the integer to.
+ @param[in] uTag  The tag to add
+ 
+ This outputs a CBOR major type 6 optional tag.
+ 
+ The tag is applied to the next data item added to the encoded
+ output. That data item that is to be tagged can be of any major
+ CBOR type. Any number of tags can be added to a data item by calling
+ this multiple times before the data item is added.
+ 
+ For many of the common standard tags a function to encode
+ data using it already exists and this is not needed. For example,
+ QCBOREncode_AddDateEpoch() already exists to output
+ integers representing dates with the right tag.
+*/
+void QCBOREncode_AddTag(QCBOREncodeContext *pCtx,uint64_t uTag);
+
+
+/**
  
  @brief  Add an epoch-based date
  
  @param[in] pCtx     The encoding context to add the simple value to.
- @param[in] szLabel  The string map label for this integer value.
- @param[in] nLabel   The integer map label for this integer value.
  @param[in] date     Number of seconds since 1970-01-01T00:00Z in UTC time.
  
  As per RFC 7049 this is similar to UNIX/Linux/POSIX dates. This is
@@ -996,37 +1033,16 @@
  
  This implementation cannot encode fractional seconds using float or double
  even though that is allowed by CBOR, but you can encode them if you
- want to by calling QCBOREncode_AddFloat_2() or QCBOREncode_AddDouble_2()
+ want to by calling QCBOREncode_AddDouble()
  with the right parameters.
  
- Error handling is the same as QCBOREncode_AddInt64_2().
+ Error handling is the same as QCBOREncode_AddInt64().
  */
+static void QCBOREncode_AddDateEpoch(QCBOREncodeContext *pCtx, int64_t date);
 
-static inline void QCBOREncode_AddDateEpoch_2(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t nLabel, int64_t date)
-{
-   QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_EPOCH);
-   QCBOREncode_AddInt64_2(pCtx, szLabel, nLabel, date);
-}
+static void QCBOREncode_AddDateEpochToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t date);
 
-#define QCBOREncode_AddDateEpoch(pCtx, date) \
-      QCBOREncode_AddDateEpoch_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (date))
-
-#define QCBOREncode_AddDateEpochToMap(pCtx, szLabel, date) \
-      QCBOREncode_AddDateEpoch_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (date))
-
-#define QCBOREncode_AddDateEpochToMapN(pCtx, nLabel, date) \
-      QCBOREncode_AddDateEpoch_2((pCtx), NULL, (nLabel), (date))
-
-
-/*
- Use QCBOREncode_AddBytes_2() or QCBOREncode_AddBText_2() or
- QCBOREncode_AddEncoded_2() instead of this. Their inline
- implementations call this to do their work.
- 
- The code is structured like this with the inline functions
- to reduce object code.
- */
-void QCBOREncode_AddBuffer_2(QCBOREncodeContext *me, uint8_t uMajorType, const char *szLabel, int64_t nLabel, UsefulBufC Bytes);
+static  void QCBOREncode_AddDateEpochToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t date);
 
 
 /**
@@ -1034,220 +1050,142 @@
  @brief Add a byte string to the encoded output.
  
  @param[in] pCtx      The context to initialize.
- @param[in] szLabel   The string map label for this integer value.
- @param[in] nLabel    The integer map label for this integer value.
  @param[in] Bytes     Pointer and length of the input data.
  
- Simply adds the bytes to the encoded output and CBOR major type 2.
+ Simply adds the bytes to the encoded output as CBOR major type 2.
  
  If called with Bytes.len equal to 0, an empty string will be
  added. When Bytes.len is 0, Bytes.ptr may be NULL.
  
+ Error handling is the same as QCBOREncode_AddInt64().
  */
 
-static inline void QCBOREncode_AddBytes_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
-{
-   QCBOREncode_AddBuffer_2(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING, szLabel, nLabel, Bytes);
-}
+static void QCBOREncode_AddBytes(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
 
-#define QCBOREncode_AddBytes(pCtx, Bytes) \
-      QCBOREncode_AddBytes_2((pCtx), NULL, QCBOR_NO_INT_LABEL, Bytes)
+static void QCBOREncode_AddBytesToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
 
-#define QCBOREncode_AddBytesToMap(pCtx, szLabel, Bytes) \
-      QCBOREncode_AddBytes_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (Bytes))
-
-#define QCBOREncode_AddBytesToMapN(pCtx, nLabel, Bytes) \
-      QCBOREncode_AddBytes_2((pCtx), NULL, (nLabel), (Bytes))
-
-
-
-static inline void QCBOREncode_AddBinaryUUID_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
-{
-   QCBOREncode_AddTag(pCtx, CBOR_TAG_BIN_UUID);
-   QCBOREncode_AddBytes_2(pCtx, szLabel, nLabel, Bytes);
-}
-
-
-#define QCBOREncode_AddBinaryUUID(pCtx, Bytes) \
-      QCBOREncode_AddBinaryUUID_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (Bytes))
-
-#define QCBOREncode_AddBinaryUUIDToMap(pCtx, szLabel, Bytes) \
-      QCBOREncode_AddBinaryUUID_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (Bytes))
-
-#define QCBOREncode_AddBinaryUUIDToMapN(pCtx, nLabel, Bytes) \
-      QCBOREncode_AddBinaryUUID_2((pCtx), NULL, (nLabel), (Bytes))
-
-
-static inline void QCBOREncode_AddPositiveBignum_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
-{
-   QCBOREncode_AddTag(pCtx, CBOR_TAG_POS_BIGNUM);
-   QCBOREncode_AddBytes_2(pCtx, szLabel, nLabel, Bytes);
-}
-
-#define QCBOREncode_AddPositiveBignum(pCtx, Bytes) \
-      QCBOREncode_AddPositiveBignum_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (Bytes))
-
-#define QCBOREncode_AddPositiveBignumToMap(pCtx, szLabel, Bytes) \
-      QCBOREncode_AddPositiveBignum_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (Bytes))
-
-#define QCBOREncode_AddPositiveBignumToMapN(pCtx, nLabel, Bytes) \
-      QCBOREncode_AddPositiveBignum_2((pCtx), NULL, (nLabel), (Bytes))
-
-
-static inline void QCBOREncode_AddNegativeBignum_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
-{
-   QCBOREncode_AddTag(pCtx, CBOR_TAG_NEG_BIGNUM);
-   QCBOREncode_AddBytes_2(pCtx, szLabel, nLabel, Bytes);
-}
-
-#define QCBOREncode_AddNegativeBignum(pCtx, Bytes) \
-      QCBOREncode_AddNegativeBignum_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (Bytes))
-
-#define QCBOREncode_AddNegativeBignumToMap(pCtx, szLabel, Bytes) \
-      QCBOREncode_AddNegativeBignum_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (Bytes))
-
-#define QCBOREncode_AddNegativeBignumToMapN(pCtx, nLabel, Bytes) \
-      QCBOREncode_AddNegativeBignum_2((pCtx), NULL, (nLabel), (Bytes))
+static void QCBOREncode_AddBytesToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
 
 
 
 /**
+ @brief Add a binary UUID to the encoded output.
  
- @brief  Add a UTF-8 text string to the encoded output
+ @param[in] pCtx      The context to initialize.
+ @param[in] Bytes     Pointer and length of the binary UUID.
  
- @param[in] pCtx     The context to initialize.
- @param[in] szLabel  The string map label for this integer value.
- @param[in] nLabel   The integer map label for this integer value.
- @param[in] Bytes    Pointer and length of text to add.
+ A binary UUID as defined in RFC 4122 is added to the ouput.
  
- The text passed in must be unencoded UTF-8 according to RFC
- 3629. There is no NULL termination.
- 
- If called with nBytesLen equal to 0, an empty string will be
- added. When nBytesLen is 0, pBytes may be NULL.
- 
- 
- Note that the restriction of the buffer length to an uint32_t is
- entirely intentional as this encoder is not capable of encoding
- lengths greater. This limit to 4GB for a text string should not be a
- problem.
- 
- Error handling is the same as QCBOREncode_AddInt64_2().
- 
+ It is output as CBOR major type 2, a binary string, with
+ optional tag 36 indicating the binary string is a UUID.
  */
-static inline void QCBOREncode_AddText_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
-{
-   QCBOREncode_AddBuffer_2(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, szLabel, nLabel, Bytes);
-}
 
-#define QCBOREncode_AddText(pCtx, Bytes) \
-      QCBOREncode_AddText_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (Bytes))
+static void QCBOREncode_AddBinaryUUID(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
 
-#define QCBOREncode_AddTextToMap(pCtx, szLabel, Bytes) \
-      QCBOREncode_AddText_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (Bytes))
+static void QCBOREncode_AddBinaryUUIDToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
 
-#define QCBOREncode_AddTextToMapN(pCtx, nLabel, Bytes) \
-      QCBOREncode_AddText_2((pCtx), NULL, (nLabel),  (Bytes))
+static void QCBOREncode_AddBinaryUUIDToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
 
 
-inline static void QCBOREncode_AddSZString_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, const char *szString)
-{
-   QCBOREncode_AddText_2(pCtx, szLabel, nLabel,UsefulBuf_FromSZ(szString));
-}
 
-#define QCBOREncode_AddSZString(pCtx, szString) \
-      QCBOREncode_AddSZString_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (szString))
+/**
+ @brief Add a positive big number to the encoded output.
+ 
+ @param[in] pCtx      The context to initialize.
+ @param[in] Bytes     Pointer and length of the big number.
+ 
+ Big numbers are integers larger than 64-bits. Their format
+ is described in RFC 7049.
+ 
+ It is output as CBOR major type 2, a binary string, with
+ optional tag 2 indicating the binary string is a positive big
+ number.
+ 
+ Often big numbers are used to represent cryptographic keys,
+ however COSE which defines representations for keys chose not
+ to use this particular type.
+ */
+static void QCBOREncode_AddPositiveBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
 
-#define QCBOREncode_AddSZStringToMap(pCtx, szLabel, szString) \
-      QCBOREncode_AddSZString_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (szString))
+static void QCBOREncode_AddPositiveBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
 
-#define QCBOREncode_AddSZStringToMapN(pCtx, nLabel, szString) \
-      QCBOREncode_AddSZString_2((pCtx), NULL, (nLabel), (szString))
+static void QCBOREncode_AddPositiveBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
+
+
+
+/**
+ @brief Add a negative big number to the encoded output.
+ 
+ @param[in] pCtx      The context to initialize.
+ @param[in] Bytes     Pointer and length of the big number.
+ 
+ Big numbers are integers larger than 64-bits. Their format
+ is described in RFC 7049.
+ 
+ It is output as CBOR major type 2, a binary string, with
+ optional tag 2 indicating the binary string is a negative big
+ number.
+ 
+ Often big numbers are used to represent cryptographic keys,
+ however COSE which defines representations for keys chose not
+ to use this particular type.
+ */
+static void QCBOREncode_AddNegativeBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
+
+static void QCBOREncode_AddNegativeBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
+
+static void QCBOREncode_AddNegativeBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
 
 
 
 
-static inline void QCBOREncode_AddURI_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
-{
-   QCBOREncode_AddTag(pCtx, CBOR_TAG_URI);
-   QCBOREncode_AddText_2(pCtx, szLabel, nLabel, Bytes);
-}
-
-#define QCBOREncode_AddURI(pCtx, Bytes) \
-      QCBOREncode_AddURI_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (Bytes))
-
-#define QCBOREncode_AddURIToMap(pCtx, szLabel, Bytes) \
-      QCBOREncode_AddURI_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (Bytes))
-
-#define QCBOREncode_AddURIToMapN(pCtx, nLabel, Bytes) \
-      QCBOREncode_AddURI_2((pCtx), NULL, (nLabel), (Bytes))
 
 
-static inline void QCBOREncode_AddB64Text_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
-{
-   QCBOREncode_AddTag(pCtx, CBOR_TAG_B64);
-   QCBOREncode_AddText_2(pCtx, szLabel, nLabel, Bytes);
-}
+static void QCBOREncode_AddURI(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
 
-#define QCBOREncode_AddB64Text(pCtx, Bytes) \
-      QCBOREncode_AddB64Text_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (Bytes))
+static void QCBOREncode_AddURIToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
 
-#define QCBOREncode_AddB64TextToMap(pCtx, szLabel, Bytes) \
-      QCBOREncode_AddB64Text_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (Bytes))
-
-#define QCBOREncode_AddB64TextToMapN(pCtx, nLabel, Bytes) \
-      QCBOREncode_AddB64Text_2((pCtx), NULL, (nLabel), (Bytes))
+static void QCBOREncode_AddURIToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
 
 
 
-static inline void QCBOREncode_AddB64URLText_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
-{
-   QCBOREncode_AddTag(pCtx, CBOR_TAG_B64URL);
-   QCBOREncode_AddText_2(pCtx, szLabel, nLabel, Bytes);
-}
-
-#define QCBOREncode_AddB64URLText(pCtx, Bytes) \
-      QCBOREncode_AddB64URLText_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (Bytes))
-
-#define QCBOREncode_AddB64URLTextToMap(pCtx, szLabel, Bytes) \
-      QCBOREncode_AddB64URLText_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (Bytes))
-
-#define QCBOREncode_AddB64URLTextToMapN(pCtx, nLabel, Bytes) \
-      QCBOREncode_AddB64URLText_2((pCtx), NULL, (nLabel), (Bytes))
 
 
 
-static inline void QCBOREncode_AddRegex_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
-{
-   QCBOREncode_AddTag(pCtx, CBOR_TAG_REGEX);
-   QCBOREncode_AddText_2(pCtx, szLabel, nLabel, Bytes);
-}
+static void QCBOREncode_AddB64Text(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
 
-#define QCBOREncode_AddRegex(pCtx, Bytes) \
-      QCBOREncode_AddRegex_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (Bytes))
+static void QCBOREncode_AddB64TextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
 
-#define QCBOREncode_AddRegexToMap(pCtx, szLabel, Bytes) \
-      QCBOREncode_AddRegex_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (Bytes))
-
-#define QCBOREncode_AddRegexToMapN(pCtx, nLabel, Bytes) \
-      QCBOREncode_AddRegex_2((pCtx), NULL, (nLabel), (Bytes))
+static void QCBOREncode_AddB64TextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
 
 
 
-static inline void QCBOREncode_AddMIMEData_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
-{
-   QCBOREncode_AddTag(pCtx, CBOR_TAG_MIME);
-   QCBOREncode_AddText_2(pCtx, szLabel, nLabel, Bytes);
-}
 
-#define QCBOREncode_AddMIMEData(pCtx, Bytes) \
-      QCBOREncode_AddMIMEData_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (Bytes))
+static void QCBOREncode_AddB64URLText(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
 
-#define QCBOREncode_AddMIMEDataToMap(pCtx, szLabel, Bytes) \
-      QCBOREncode_AddMIMEData_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (Bytes))
+static void QCBOREncode_AddB64URLTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
 
-#define QCBOREncode_AddMIMEDataToMapN(pCtx, nLabel, Bytes) \
-      QCBOREncode_AddMIMEData_2((pCtx), NULL, (nLabel), (Bytes))
+static void QCBOREncode_AddB64URLTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
+
+
+
+
+static void QCBOREncode_AddRegex(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
+
+static void QCBOREncode_AddRegexToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
+
+static void QCBOREncode_AddRegexToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
+
+
+
+
+
+static void QCBOREncode_AddMIMEData(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
+
+static void QCBOREncode_AddMIMEDataToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
+
+static void QCBOREncode_AddMIMEDataToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
+
 
 
 
@@ -1257,122 +1195,85 @@
  
  @param[in] pCtx      The encoding context to add the simple value to.
  @param[in] szDate    Null-terminated string with date to add
- @param[in] szLabel   A string label for the bytes to add. NULL if no label.
- @param[in] nLabel    The integer map label for this integer value.
- 
- None.
- 
- The string szDate should be in the form of RFC 3339 as refined by section
+
+ The string szDate should be in the form of RFC 3339 as defined by section
  3.3 in RFC 4287. This is as described in section 2.4.1 in RFC 7049.
  
  Note that this function doesn't validate the format of the date string
  at all. If you add an incorrect format date string, the generated
  CBOR will be incorrect and the receiver may not be able to handle it.
  
- Error handling is the same as QCBOREncode_AddInt64_2().
- 
+ Error handling is the same as QCBOREncode_AddInt64().
+
  */
-static inline void QCBOREncode_AddDateString_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, const char *szDate)
-{
-   QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_STRING);
-   QCBOREncode_AddSZString_2(pCtx, szLabel, nLabel, szDate);
-}
+static void QCBOREncode_AddDateString(QCBOREncodeContext *pCtx, const char *szDate);
 
-#define QCBOREncode_AddDateString(pCtx, szDate) \
-      QCBOREncode_AddDateString_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (szDate))
+static void QCBOREncode_AddDateStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szDate);
 
-#define QCBOREncode_AddDateStringToMap(pCtx, szLabel, szDate)  \
-      QCBOREncode_AddDateString_2(pCtx, szLabel, QCBOR_NO_INT_LABEL, (szDate))
-
-#define QCBOREncode_AddDateStringToMapN(pCtx, nLabel, szDate)  \
-      QCBOREncode_AddDateString_2(pCtx, NULL, (nLabel), (szDate))
-
-
-/*
-Use QCBOREncode_AddSimple_2() or QCBOREncode_AddBool_2()
-instead of this. Their inline
-implementations call this to do their work.
-
-The code is structured like this with the inline functions
-to reduce object code.
- */
-void QCBOREncode_AddType7_2(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, size_t uSize, uint64_t uNum);
+static void QCBOREncode_AddDateStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szDate);
 
 
 /**
  
- @brief  Add true, false, null and undef
+ @brief  Add a standard boolean.
  
- @param[in] pCtx      The encoding context to add the simple value to.
- @param[in] szLabel   A string label for the bytes to add. NULL if no label.
- @param[in] nLabel    The integer map label for this integer value.
- @param[in] uSimple   One of CBOR_SIMPLEV_FALSE through _UNDEF
-
- CBOR defines encoding for special values "true", "false", "null" and "undef". This
- function can add these values.
- 
- Error handling is the same as QCBOREncode_AddInt64_2().
- */
-static inline void QCBOREncode_AddSimple_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, uint8_t uSimple)
-{
-   if(uSimple < CBOR_SIMPLEV_FALSE || uSimple > CBOR_SIMPLEV_UNDEF) {
-      pCtx->uError = QCBOR_ERR_BAD_SIMPLE;
-   } else {
-      QCBOREncode_AddType7_2(pCtx, szLabel, nLabel, 0, uSimple);
-   }
-}
-
-#define QCBOREncode_AddSimple(pCtx, uSimple) \
-      QCBOREncode_AddSimple_2((pCtx), NULL,  QCBOR_NO_INT_LABEL, (uSimple))
-
-#define QCBOREncode_AddSimpleToMap(pCtx, szLabel, uSimple) \
-      QCBOREncode_AddSimple_2((pCtx), (szLabel),  QCBOR_NO_INT_LABEL, (uSimple))
-
-#define QCBOREncode_AddSimpleToMapN(pCtx, nLabel, uSimple) \
-      QCBOREncode_AddSimple_2((pCtx), NULL, (nLabel), (uSimple))
-
-
-
-/**
- 
- @brief  Add a standard boolean
- 
- @param[in] pCtx      The encoding context to add the simple value to.
- @param[in] szLabel   A string label for the bytes to add. NULL if no label.
- @param[in] nLabel    The integer map label for this integer value.
+ @param[in] pCtx   The encoding context to add the simple value to.
  @param[in] b      true or false from stdbool. Anything will result in an error.
  
- Error handling is the same as QCBOREncode_AddInt64_2().
- */
-
-inline static void QCBOREncode_AddBool_2(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nLabel, bool b)
-{
-   uint8_t uSimple = CBOR_SIMPLE_BREAK; // CBOR_SIMPLE_BREAK is invalid here. The point is to cause an error later
-   if(b == true || b == false)
-      uSimple = CBOR_SIMPLEV_FALSE + b;;
-   QCBOREncode_AddSimple_2(pCtx, szLabel, nLabel, uSimple);
-}
-
-#define QCBOREncode_AddBool(pCtx, bool) \
-   QCBOREncode_AddBool_2((pCtx), NULL,  QCBOR_NO_INT_LABEL, (bool))
-
-#define QCBOREncode_AddBoolToMap(pCtx, szLabel, bool) \
-   QCBOREncode_AddBool_2((pCtx), (szLabel),  QCBOR_NO_INT_LABEL, (bool))
-
-#define QCBOREncode_AddBoolToMapN(pCtx, nLabel, bool) \
-   QCBOREncode_AddBool_2((pCtx), NULL, (nLabel), (bool))
-
-
-
-/*
-  Call QCBOREncode_OpenArray_2(), QCBOREncode_OpenMap_2() or
- QCBOREncode_OpenBstrWrap_2() instead of this. Their inline
- implementations call this to do their work.
+ Adds a boolean value as CBOR major type 7.
  
- The code is structured like this with the inline functions
- to reduce object code.
+ Error handling is the same as QCBOREncode_AddInt64().
  */
-void QCBOREncode_OpenMapOrArray_2(QCBOREncodeContext *me, uint8_t uMajorType, const char *szLabel, uint64_t nLabel);
+
+static void QCBOREncode_AddBool(QCBOREncodeContext *pCtx, bool b);
+
+static void QCBOREncode_AddBoolToMap(QCBOREncodeContext *pCtx, const char *szLabel, bool b);
+
+static void QCBOREncode_AddBoolToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, bool b);
+
+
+
+/**
+ 
+ @brief  Add a NULL to the encoded output.
+ 
+ @param[in] pCtx   The encoding context to add the simple value to.
+ 
+ Adds the NULL value as CBOR major type 7.
+ 
+ This NULL doesn't have any special meaning in CBOR such as a terminating
+ value for a string or an empty value.
+ 
+ Error handling is the same as QCBOREncode_AddInt64().
+ */
+static void QCBOREncode_AddNULL(QCBOREncodeContext *pCtx);
+
+static void QCBOREncode_AddNULLToMap(QCBOREncodeContext *pCtx, const char *szLabel);
+
+static void QCBOREncode_AddNULLToMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
+
+
+/**
+ 
+ @brief  Add an "undef" to the encoded output.
+ 
+ @param[in] pCtx   The encoding context to add the simple value to.
+ 
+ Adds the undef value as CBOR major type 7.
+ 
+ Note that this value will not translate to JSON.
+ 
+ This Undef doesn't have any special meaning in CBOR such as a terminating
+ value for a string or an empty value.
+ 
+ Error handling is the same as QCBOREncode_AddInt64().
+ */
+static void QCBOREncode_AddUndef(QCBOREncodeContext *pCtx);
+
+static void QCBOREncode_AddUndefToMap(QCBOREncodeContext *pCtx, const char *szLabel);
+
+static void QCBOREncode_AddUndefToMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
+
 
 
 /**
@@ -1380,13 +1281,13 @@
  @brief  Indicates that the next items added are in an array.
  
  @param[in] pCtx The encoding context to open the array in.
- @param[in] szLabel A NULL-terminated string label for the map. May be a NULL pointer.
- @param[in] nLabel An integer label for the whole map. QCBOR_NO_INT_LABEL for no integer label.
  
  Arrays are the basic CBOR aggregate or structure type. Call this
- function to start or open an array. The call the various AddXXX
+ function to start or open an array. Then call the various AddXXX
  functions to add the items that go into the array. Then call
- QCBOREncode_CloseArray() when all items have been added.
+ QCBOREncode_CloseArray() when all items have been added. The
+ data items in the array can be of any type and can be of
+ mixed types.
  
  Nesting of arrays and maps is allowed and supported just by calling
  OpenArray again before calling CloseArray.  While CBOR has no limit
@@ -1400,39 +1301,46 @@
  If you try to add more than 32,767 items to an array or map, incorrect CBOR will
  be produced by this encoder.
  
- An array itself may have a label if it is being added to a map. Either the
- string array or integer label should be filled in, but not both. Note that
+ An array itself must have a label if it is being added to a map.  Note that
  array elements do not have labels (but map elements do).
  
  An array itself may be tagged.
  
- When constructing signed CBOR objects, maps or arrays, they are encoded
- normally and then wrapped as a byte string. The COSE standard for example
- does this. The wrapping is simply treating the encoded CBOR map
- as a byte string.
- 
- The stated purpose of this wrapping is to prevent code relaying the signed data
- but not verifying it from tampering with the signed data thus making
- the signature unverifiable. It is also quite beneficial for the
- signature verification code. Standard CBOR parsers usually do not give
- access to partially parsed CBOR as would be need to check the signature
- of some CBOR. With this wrapping, standard CBOR parsers can be used
- to get to all the data needed for a signature verification.
  */
 
-static inline void QCBOREncode_OpenArray_2(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t nLabel)
-{
-   QCBOREncode_OpenMapOrArray_2(pCtx, CBOR_MAJOR_TYPE_ARRAY, szLabel, nLabel);
-}
+static void QCBOREncode_OpenArray(QCBOREncodeContext *pCtx);
 
-#define QCBOREncode_OpenArray(pCtx) \
-      QCBOREncode_OpenArray_2((pCtx), NULL, QCBOR_NO_INT_LABEL)
+static void QCBOREncode_OpenArrayInMap(QCBOREncodeContext *pCtx, const char *szLabel);
 
-#define QCBOREncode_OpenArrayInMap(pCtx, szLabel) \
-      QCBOREncode_OpenArray_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL)
+static void QCBOREncode_OpenArrayInMapN(QCBOREncodeContext *pCtx,  int64_t nLabel);
 
-#define QCBOREncode_OpenArrayInMapN(pCtx, nLabel) \
-      QCBOREncode_OpenArray_2((pCtx), NULL, (nLabel))
+
+/**
+ 
+ @brief Close an open array.
+ 
+ @param[in] pCtx The context to add to.
+ 
+ The closes an array opened by QCBOREncode_OpenArray(). It reduces
+ nesting level by one. All arrays (and maps) must be closed
+ before calling QCBOREncode_Finish().
+ 
+ When an error occurs as a result of this call, the encoder records
+ the error and enters the error state. The error will be returned when
+ QCBOREncode_Finish() is called.
+ 
+ If this has been called more times then QCBOREncode_OpenArray(),
+ then QCBOR_ERR_TOO_MANY_CLOSES will be returned when
+ QCBOREncode_Finish() is called.
+ 
+ If this is called and it is not an array that is currently
+ open, QCBOR_ERR_CLOSE_MISMATCH will be returned when QCBOREncode_Finish()
+ is called.
+ 
+ */
+
+static void QCBOREncode_CloseArray(QCBOREncodeContext *pCtx);
+
 
 
 /**
@@ -1440,91 +1348,72 @@
  @brief  Indicates that the next items added are in a map.
  
  @param[in] pCtx The context to add to.
- @param[in] szLabel A NULL-terminated string label for the map. May be a NULL pointer.
- @param[in] nLabel An integer label for the whole map. QCBOR_NO_INT_LABEL for no integer label.
  
  See QCBOREncode_OpenArray() for more information.
  
- When adding items to maps, they must be added in pairs, the label and
- the value. This can be done making two calls to QCBOREncode_AddXXX
- one for the map label and one for the value.
+ CBOR maps are an aggregate type where each item in the map consists
+ of a label and a value. They are similar to JSON objects.
  
- It can also be accomplished by calling one of the add functions that
- takes an additional NULL-terminated text string parameter that is the
- label.  This is useful for encoding CBOR you which to translate easily
+ The value can be any CBOR type including another map.
+ 
+ The label can also be any CBOR type, but in practice they are
+ typically integers as this gives the most compact output. They
+ might also be text strings which gives readability and translation
  to JSON.
  
- Note that labels do not have to be strings. They can be integers or
- other. Small integers < 24 are a good choice for map labels when the
- size of the encoded data should be as small and simple as possible.
-
+ Every QCBOREncode_AddXXX() call has once version that is "InMap" for
+ adding items to maps with string labels and on that is "InMapN" that
+ is for adding with integer labels.
+ 
+ RFC 7049 uses the term "key" instead of "label".
+ 
+ If you wish to use map labels that are neither integer labels or
+ text strings, then just call the QCBOREncode_AddXXX() function
+ explicitly to add the label. Then call it again to add the value.
+ 
  See the RFC7049 for a lot more information on creating maps.
  
  */
 
-static inline void QCBOREncode_OpenMap_2(QCBOREncodeContext *pCtx, const char *szLabel,  uint64_t nLabel)
-{
-   QCBOREncode_OpenMapOrArray_2(pCtx, CBOR_MAJOR_TYPE_MAP, szLabel, nLabel);
-}
+static void QCBOREncode_OpenMap(QCBOREncodeContext *pCtx);
 
-#define QCBOREncode_OpenMap(pCtx) \
-      QCBOREncode_OpenMap_2((pCtx), NULL, QCBOR_NO_INT_LABEL)
+static void QCBOREncode_OpenMapInMap(QCBOREncodeContext *pCtx, const char *szLabel);
 
-#define QCBOREncode_OpenMapInMap(pCtx, szLabel) \
-      QCBOREncode_OpenMap_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL)
+static void QCBOREncode_OpenMapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
 
-#define QCBOREncode_OpenMapInMapN(pCtx, nLabel) \
-      QCBOREncode_OpenMap_2((pCtx), NULL, (nLabel))
 
 
 /**
  
- @brief Closes array, map or bstr wrapping
+ @brief Close an open map.
  
  @param[in] pCtx The context to add to.
- @param[in] uMajorType The major CBOR type to close
- @param[out] pWrappedCBOR UsefulBufC containing wrapped bytes
  
- This reduces the nesting level by one. Usually one of the macros
- below is called rather than calling this directly.
+ The closes a map opened by QCBOREncode_OpenMap(). It reduces
+ nesting level by one.
  
- If more Close's have been called than Open's the error state is
- entered, no value is returned and the error can be discovered when
- QCBOREncode_Finish() is called. The error will be
- QCBOR_ERR_TOO_MANY_CLOSES.
+ When an error occurs as a result of this call, the encoder records
+ the error and enters the error state. The error will be returned when
+ QCBOREncode_Finish() is called.
  
- If uMajorType doesn't match the type of what is open then
- QCBOR_ERR_CLOSE_MISMATCH will be returned when QCBOREncode_Finish()
+ If this has been called more times then QCBOREncode_OpenMap(),
+ then QCBOR_ERR_TOO_MANY_CLOSES will be returned when
+ QCBOREncode_Finish() is called.
+ 
+ If this is called and it is not a map that is currently
+ open, QCBOR_ERR_CLOSE_MISMATCH will be returned when QCBOREncode_Finish()
  is called.
  
- A pointer and length of the enclosed encoded CBOR is returned in
- *pWrappedCBOR if it is not NULL. The main purpose of this is so this
- data can be hashed (e.g., with SHA-256) as part of a COSE (RFC 8152)
- implementation. **WARNING**, this pointer and length should be used
- right away before any other calls to QCBOREncode_xxxx() as they will
- move data around and the pointer and length will no longer be to the
- correct encoded CBOR.
- 
  */
-void QCBOREncode_Close(QCBOREncodeContext *pCtx, uint8_t uMajorType, UsefulBufC *pWrappedCBOR);
 
-#define QCBOREncode_CloseBstrWrap(pCtx, pWrappedCBOR) \
-    QCBOREncode_Close(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING, pWrappedCBOR)
-
-#define QCBOREncode_CloseArray(pCtx) \
-    QCBOREncode_Close(pCtx, CBOR_MAJOR_TYPE_ARRAY, NULL)
-
-#define QCBOREncode_CloseMap(pCtx) \
-    QCBOREncode_Close(pCtx, CBOR_MAJOR_TYPE_MAP, NULL)
+static void QCBOREncode_CloseMap(QCBOREncodeContext *pCtx);
 
 
 /**
- @brief Indicate start of encoded CBOR to be wrapped in a bstr
+ @brief Indicate start of encoded CBOR to be wrapped in a bstr.
  
  @param[in] pCtx The context to add to.
- @param[in] szLabel A NULL-terminated string label for the map. May be a NULL pointer.
- @param[in] nLabel An integer label for the whole map. QCBOR_NO_INT_LABEL for no integer label.
-
+ 
  All added encoded items between this call and a call to
  QCBOREncode_CloseBstrWrap() will be wrapped in a bstr. They will
  appear in the final output as a byte string.  That byte string will
@@ -1536,35 +1425,73 @@
  buffer (e.g., the COSE payload) and then add that buffer as a bstr to
  another encoding (e.g. the COSE to-be-signed bytes, the
  Sig_structure) potentially saving a lot of memory.
+ 
+ When constructing cryptographically signed CBOR objects, maps or arrays, they
+ typically are encoded
+ normally and then wrapped as a byte string. The COSE standard for example
+ does this. The wrapping is simply treating the encoded CBOR map
+ as a byte string.
+ 
+ The stated purpose of this wrapping is to prevent code relaying the signed data
+ but not verifying it from tampering with the signed data thus making
+ the signature unverifiable. It is also quite beneficial for the
+ signature verification code. Standard CBOR parsers usually do not give
+ access to partially parsed CBOR as would be need to check the signature
+ of some CBOR. With this wrapping, standard CBOR parsers can be used
+ to get to all the data needed for a signature verification.
+ 
+ */
+static void QCBOREncode_BstrWrap(QCBOREncodeContext *pCtx);
+
+static void QCBOREncode_BstrWrapInMap(QCBOREncodeContext *pCtx, const char *szLabel);
+
+static void QCBOREncode_BstrWrapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
+
+
+/**
+ 
+ @brief Close a wrapping bstr.
+ 
+ @param[in] pCtx The context to add to.
+ @param[out] pWrappedCBOR UsefulBufC containing wrapped bytes
+ 
+ The closes a wrapping bstr opened by QCBOREncode_BstrWrap(). It reduces
+ nesting level by one.
+ 
+ A pointer and length of the enclosed encoded CBOR is returned in
+ *pWrappedCBOR if it is not NULL. The main purpose of this is so this
+ data can be hashed (e.g., with SHA-256) as part of a COSE (RFC 8152)
+ implementation. **WARNING**, this pointer and length should be used
+ right away before any other calls to QCBOREncode_xxxx() as they will
+ move data around and the pointer and length will no longer be to the
+ correct encoded CBOR.
+ 
+ When an error occurs as a result of this call, the encoder records
+ the error and enters the error state. The error will be returned when
+ QCBOREncode_Finish() is called.
+ 
+ If this has been called more times then QCBOREncode_BstrWrap(),
+ then QCBOR_ERR_TOO_MANY_CLOSES will be returned when
+ QCBOREncode_Finish() is called.
+ 
+ If this is called and it is not a wrapping bstr that is currently
+ open, QCBOR_ERR_CLOSE_MISMATCH will be returned when QCBOREncode_Finish()
+ is called.
 
  */
-static inline void QCBOREncode_OpenBstrWrap_2(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t nLabel)
-{
-   QCBOREncode_OpenMapOrArray_2(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING, szLabel, nLabel);
-}
-
-#define QCBOREncode_BstrWrap(pCtx) \
-      QCBOREncode_OpenBstrWrap_2((pCtx), NULL, QCBOR_NO_INT_LABEL)
-
-#define QCBOREncode_BstrWrapInMap(pCtx, szLabel) \
-      QCBOREncode_OpenBstrWrap_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL)
-
-#define QCBOREncode_BstrWrapMapN(pCtx, nLabel) \
-      QCBOREncode_OpenBstrWrap_2((pCtx), NULL, (nLabel))
+static void QCBOREncode_CloseBstrWrap(QCBOREncodeContext *pCtx, UsefulBufC *pWrappedCBOR);
 
 
 
 /**
- Add some already-encoded CBOR bytes
+ Add some already-encoded CBOR bytes.
  
  @param[in] pCtx The context to add to.
- @param[in] szLabel A NULL-terminated string label for the map. May be a NULL pointer.
- @param[in] nLabel An integer label for the whole map. QCBOR_NO_INT_LABEL for no integer label.
  @param[in] Encoded The already-encoded CBOR to add to the context.
  
  The encoded CBOR being added must be fully conforming CBOR. It must
  be complete with no arrays or maps that are incomplete. While this
- encoder doesn't every produce indefinite lengths, it is OK for the
+ encoder doesn't ever produce indefinite lengths, it is OK for the
  raw CBOR added here to have indefinite lengths.
  
  The raw CBOR added here is not checked in anyway. If it is not
@@ -1573,23 +1500,17 @@
  
  If the encoded CBOR being added here contains multiple items, they
  must be enclosed in a map or array. At the top level the raw
- CBOR must have a single item. 
+ CBOR must be a single data item.
  
  */
 
-static inline void QCBOREncode_AddEncodedToMap_2(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t nLabel, UsefulBufC Encoded)
-{
-   QCBOREncode_AddBuffer_2(pCtx, CBOR_MAJOR_NONE_TYPE_RAW, szLabel, nLabel, Encoded);
-}
+static void QCBOREncode_AddEncoded(QCBOREncodeContext *pCtx, UsefulBufC Encoded);
 
-#define QCBOREncode_AddEncodedToMapN(pCtx, nLabel, Encoded) \
-      QCBOREncode_AddEncodedToMap_2((pCtx), NULL, (nLabel), Encoded)
+static void QCBOREncode_AddEncodedToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Encoded);
 
-#define QCBOREncode_AddEncoded(pCtx, Encoded) \
-      QCBOREncode_AddEncodedToMap_2((pCtx), NULL, QCBOR_NO_INT_LABEL, (Encoded))
+static void QCBOREncode_AddEncodedToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Encoded);
 
-#define QCBOREncode_AddEncodedToMap(pCtx, szLabel, Encoded) \
-      QCBOREncode_AddEncodedToMap_2((pCtx), (szLabel), QCBOR_NO_INT_LABEL, (Encoded))
+
 
 
 /**
@@ -1606,11 +1527,11 @@
  
  If no buffer was passed to QCBOR_Init(), then only the length and
  number of items was computed. The length is in
- pEncodedCBOR->Bytes.len. The number of items is in
- pEncodedCBOR->nItems. pEncodedCBOR->Bytes.ptr is NULL. TODO: fix documentation
+ pEncodedCBOR->Bytes.len. pEncodedCBOR->Bytes.ptr is NULL.
  
  If a buffer was passed, then pEncodedCBOR->Bytes.ptr is the same as
- the buffer passed to QCBOR_Init() and contains the encoded CBOR.
+ the buffer passed to QCBOR_Init() and contains the encoded CBOR
+ and the length is filled in.
  
  If an error is returned, the buffer may have partially encoded
  incorrect CBOR in it and it should not be used. Likewise the length
@@ -1618,13 +1539,14 @@
  
  Note that the error could have occurred in one of the many
  QCBOR_AddXXX calls long before QCBOREncode_Finish() was called. This
- error handling reduces the CBOR implementation size, but makes
- debugging harder.
+ error handling approach reduces the CBOR implementation size, but makes
+ debugging a problem a little more difficult.
  
  */
 
 QCBORError QCBOREncode_Finish(QCBOREncodeContext *pCtx, UsefulBufC *pEncodedCBOR);
 
+
 /**
  Get the encoded CBOR and error status.
  
@@ -2115,5 +2037,570 @@
 
 
 
+
+
+/* ===========================================================================
+ BEGINNING OF PRIVATE INLINE IMPLEMENTATION
+ 
+ =========================================================================== */
+
+/**
+ @brief Semi-private method to add a buffer full of bytes to encoded output
+ 
+ @param[in] pCtx       The encoding context to add the integer to.
+ @param[in] uMajorType The CBOR major type of the bytes.
+ @param[in] Bytes      The bytes to add.
+ 
+ Use QCBOREncode_AddText() or QCBOREncode_AddBytes() or
+ QCBOREncode_AddEncoded() instead. They are inline functions
+ that call this and supply the correct major type. This function
+ is public to make the inline functions work to keep the overall
+ code size down and because the C language has no way to make
+ it private.
+ 
+ If this is called the major type should be CBOR_MAJOR_TYPE_TEXT_STRING,
+ CBOR_MAJOR_TYPE_BYTE_STRING or CBOR_MAJOR_NONE_TYPE_RAW. The last
+ one is special for adding already-encoded CBOR.
+ 
+ */
+
+void QCBOREncode_AddBuffer(QCBOREncodeContext *pCtx, uint8_t uMajorType, UsefulBufC Bytes);
+
+
+/**
+ 
+ @brief Semi-private method to open a map, array or bstr wrapped CBOR
+ 
+ @param[in] pCtx The context to add to.
+ @param[in] uMajorType The major CBOR type to close
+ 
+ Call QCBOREncode_OpenArray(), QCBOREncode_OpenMap() or
+ QCBOREncode_BstrWrap() instead of this.
+ */
+
+void QCBOREncode_OpenMapOrArray(QCBOREncodeContext *pCtx, uint8_t uMajorType);
+
+
+/**
+ 
+ @brief Semi-private method to close a map, array or bstr wrapped CBOR
+ 
+ @param[in] pCtx The context to add to.
+ @param[in] uMajorType The major CBOR type to close
+ @param[out] pWrappedCBOR UsefulBufC containing wrapped bytes
+ 
+ Call QCBOREncode_CloseArray(), QCBOREncode_CloseMap() or
+ QCBOREncode_CloseBstrWrap() instead of this.
+ */
+
+void QCBOREncode_CloseMapOrArray(QCBOREncodeContext *pCtx, uint8_t uMajorType, UsefulBufC *pWrappedCBOR);
+
+
+/**
+ @brief  Semi-private method to add simple types.
+ 
+ @param[in] pCtx      The encoding context to add the simple value to.
+ @param[in] uSimple   One of CBOR_SIMPLEV_FALSE through _UNDEF
+ 
+ CBOR defines encoding for special values "true", "false", "null" and "undef". This
+ function can add these values.
+ 
+ This function can add simple values that are not defined by CBOR yet. These expansion
+ point in CBOR should not be used unless they are standardized.
+ 
+ Error handling is the same as QCBOREncode_AddInt64().
+ */
+
+void QCBOREncode_AddSimple(QCBOREncodeContext *pCtx, uint8_t uSimple);
+
+static void QCBOREncode_AddSimpleToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint8_t uSimple);
+
+static void QCBOREncode_AddSimpleToMapN(QCBOREncodeContext *pCtx, int nLabel, uint8_t uSimple);
+
+
+
+static void inline QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t uNum)
+{
+   QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, UsefulBuf_FromSZ(szLabel)); // AddSZString not defined yet
+   QCBOREncode_AddInt64(pCtx, uNum);
+}
+
+static void inline QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t uNum)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddInt64(pCtx, uNum);
+}
+
+
+
+static void inline QCBOREncode_AddUInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t uNum)
+{
+   QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, UsefulBuf_FromSZ(szLabel)); // AddSZString not defined yet
+   QCBOREncode_AddUInt64(pCtx, uNum);
+}
+
+static void inline QCBOREncode_AddUInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, uint64_t uNum)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddUInt64(pCtx, uNum);
+}
+
+
+
+static inline void QCBOREncode_AddText(QCBOREncodeContext *pCtx, UsefulBufC Text)
+{
+   QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_TEXT_STRING, Text);
+}
+
+static inline void QCBOREncode_AddTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Text)
+{
+   QCBOREncode_AddText(pCtx, UsefulBuf_FromSZ(szLabel)); // AddSZString not defined yet
+   QCBOREncode_AddText(pCtx, Text);
+}
+
+static inline void QCBOREncode_AddTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Text)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddText(pCtx, Text);
+}
+
+
+
+inline static void QCBOREncode_AddSZString(QCBOREncodeContext *pCtx, const char *szString)
+{
+   QCBOREncode_AddText(pCtx, UsefulBuf_FromSZ(szString));
+}
+
+static inline void QCBOREncode_AddSZStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szString)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddSZString(pCtx, szString);
+}
+
+static inline void QCBOREncode_AddSZStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szString)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddSZString(pCtx, szString);
+}
+
+
+static void inline QCBOREncode_AddDoubleToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddDouble(pCtx, dNum);
+}
+
+static void inline QCBOREncode_AddDoubleToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddDouble(pCtx, dNum);
+}
+
+
+
+static inline void QCBOREncode_AddDateEpoch(QCBOREncodeContext *pCtx, int64_t date)
+{
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_EPOCH);
+   QCBOREncode_AddInt64(pCtx, date);
+}
+
+static inline void QCBOREncode_AddDateEpochToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t date)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_EPOCH);
+   QCBOREncode_AddInt64(pCtx, date);
+}
+
+
+static inline void QCBOREncode_AddDateEpochToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t date)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_EPOCH);
+   QCBOREncode_AddInt64(pCtx, date);
+}
+
+
+
+static inline void QCBOREncode_AddBytes(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
+{
+   QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING, Bytes);
+}
+
+static inline void QCBOREncode_AddBytesToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddBytes(pCtx, Bytes);
+}
+
+static inline void QCBOREncode_AddBytesToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddBytes(pCtx, Bytes);
+}
+
+
+
+static inline void QCBOREncode_AddBinaryUUID(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
+{
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_BIN_UUID);
+   QCBOREncode_AddBytes(pCtx, Bytes);
+}
+
+
+static inline void QCBOREncode_AddBinaryUUIDToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_BIN_UUID);
+   QCBOREncode_AddBytes(pCtx, Bytes);
+}
+
+static inline void QCBOREncode_AddBinaryUUIDToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_BIN_UUID);
+   QCBOREncode_AddBytes(pCtx, Bytes);
+}
+
+
+static inline void QCBOREncode_AddPositiveBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
+{
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_POS_BIGNUM);
+   QCBOREncode_AddBytes(pCtx, Bytes);
+}
+
+static inline void QCBOREncode_AddPositiveBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_POS_BIGNUM);
+   QCBOREncode_AddBytes(pCtx, Bytes);
+}
+
+static inline void QCBOREncode_AddPositiveBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_POS_BIGNUM);
+   QCBOREncode_AddBytes(pCtx, Bytes);
+}
+
+
+
+static inline void QCBOREncode_AddNegativeBignum(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
+{
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_NEG_BIGNUM);
+   QCBOREncode_AddBytes(pCtx, Bytes);
+}
+
+
+static inline void QCBOREncode_AddNegativeBignumToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_NEG_BIGNUM);
+   QCBOREncode_AddBytes(pCtx, Bytes);
+}
+
+
+static inline void QCBOREncode_AddNegativeBignumToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_NEG_BIGNUM);
+   QCBOREncode_AddBytes(pCtx, Bytes);
+}
+
+
+
+static inline void QCBOREncode_AddURI(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
+{
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_URI);
+   QCBOREncode_AddText(pCtx, Bytes);
+}
+
+static inline void QCBOREncode_AddURIToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_URI);
+   QCBOREncode_AddText(pCtx, Bytes);
+}
+
+static inline void QCBOREncode_AddURIToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_URI);
+   QCBOREncode_AddText(pCtx, Bytes);
+}
+
+
+
+static inline void QCBOREncode_AddB64Text(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
+{
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_B64);
+   QCBOREncode_AddText(pCtx, Bytes);
+}
+
+
+static inline void QCBOREncode_AddB64TextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_B64);
+   QCBOREncode_AddText(pCtx, Bytes);
+}
+
+static inline void QCBOREncode_AddB64TextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_B64);
+   QCBOREncode_AddText(pCtx, Bytes);
+}
+
+
+static inline void QCBOREncode_AddB64URLText(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
+{
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_B64URL);
+   QCBOREncode_AddText(pCtx, Bytes);
+}
+
+static inline void QCBOREncode_AddB64URLTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_B64URL);
+   QCBOREncode_AddText(pCtx, Bytes);
+}
+
+static inline void QCBOREncode_AddB64URLTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_B64URL);
+   QCBOREncode_AddText(pCtx, Bytes);
+}
+
+
+
+static inline void QCBOREncode_AddRegex(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
+{
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_REGEX);
+   QCBOREncode_AddText(pCtx, Bytes);
+}
+
+static inline void QCBOREncode_AddRegexToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_REGEX);
+   QCBOREncode_AddText(pCtx, Bytes);
+}
+
+static inline void QCBOREncode_AddRegexToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_REGEX);
+   QCBOREncode_AddText(pCtx, Bytes);
+}
+
+
+
+static inline void QCBOREncode_AddMIMEData(QCBOREncodeContext *pCtx, UsefulBufC Bytes)
+{
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_MIME);
+   QCBOREncode_AddText(pCtx, Bytes);
+}
+
+static inline void QCBOREncode_AddMIMEDataToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_MIME);
+   QCBOREncode_AddText(pCtx, Bytes);
+}
+
+
+static inline void QCBOREncode_AddMIMEDataToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_MIME);
+   QCBOREncode_AddText(pCtx, Bytes);
+}
+
+static inline void QCBOREncode_AddDateString(QCBOREncodeContext *pCtx, const char *szDate)
+{
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_STRING);
+   QCBOREncode_AddSZString(pCtx, szDate);
+}
+
+static inline void QCBOREncode_AddDateStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szDate)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_STRING);
+   QCBOREncode_AddSZString(pCtx, szDate);
+}
+
+static inline void QCBOREncode_AddDateStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szDate)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddTag(pCtx, CBOR_TAG_DATE_STRING);
+   QCBOREncode_AddSZString(pCtx, szDate);
+}
+
+
+
+static inline void QCBOREncode_AddSimpleToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint8_t uSimple)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddSimple(pCtx, uSimple);
+}
+
+static inline void QCBOREncode_AddSimpleToMapN(QCBOREncodeContext *pCtx, int nLabel, uint8_t uSimple)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddSimple(pCtx, uSimple);
+}
+
+
+static inline void QCBOREncode_AddBool(QCBOREncodeContext *pCtx, bool b)
+{
+   uint8_t uSimple = CBOR_SIMPLE_BREAK; // CBOR_SIMPLE_BREAK is invalid here. The point is to cause an error later
+   if(b == true || b == false) { // TODO: test this with hostile values of b
+      uSimple = CBOR_SIMPLEV_FALSE + b;
+   }
+   QCBOREncode_AddSimple(pCtx, uSimple);
+}
+
+static inline void QCBOREncode_AddBoolToMap(QCBOREncodeContext *pCtx, const char *szLabel, bool b)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddBool(pCtx, b);
+}
+
+
+static inline void QCBOREncode_AddBoolToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, bool b)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddBool(pCtx, b);
+}
+
+
+static inline void QCBOREncode_AddNULL(QCBOREncodeContext *pCtx)
+{
+   QCBOREncode_AddSimple(pCtx, CBOR_SIMPLEV_NULL);
+}
+
+static inline void QCBOREncode_AddNULLToMap(QCBOREncodeContext *pCtx, const char *szLabel)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddNULL(pCtx);
+}
+
+static inline void QCBOREncode_AddNULLToMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddNULL(pCtx);
+}
+
+
+static inline void QCBOREncode_AddUndef(QCBOREncodeContext *pCtx)
+{
+   QCBOREncode_AddSimple(pCtx, CBOR_SIMPLEV_UNDEF);
+}
+
+static inline void QCBOREncode_AddUndefToMap(QCBOREncodeContext *pCtx, const char *szLabel)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddUndef(pCtx);
+}
+
+static inline void QCBOREncode_AddUndefToMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddUndef(pCtx);
+}
+
+
+
+static inline void QCBOREncode_OpenArray(QCBOREncodeContext *pCtx)
+{
+   QCBOREncode_OpenMapOrArray(pCtx, CBOR_MAJOR_TYPE_ARRAY);
+}
+
+static inline void QCBOREncode_OpenArrayInMap(QCBOREncodeContext *pCtx, const char *szLabel)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_OpenArray(pCtx);
+}
+
+static inline void QCBOREncode_OpenArrayInMapN(QCBOREncodeContext *pCtx,  int64_t nLabel)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_OpenArray(pCtx);
+}
+
+static inline void QCBOREncode_CloseArray(QCBOREncodeContext *pCtx)
+{
+   QCBOREncode_CloseMapOrArray(pCtx, CBOR_MAJOR_TYPE_ARRAY, NULL);
+}
+
+
+
+static inline void QCBOREncode_OpenMap(QCBOREncodeContext *pCtx)
+{
+   QCBOREncode_OpenMapOrArray(pCtx, CBOR_MAJOR_TYPE_MAP);
+}
+
+static inline void QCBOREncode_OpenMapInMap(QCBOREncodeContext *pCtx, const char *szLabel)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_OpenMap(pCtx);
+}
+
+static inline void QCBOREncode_OpenMapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_OpenMap(pCtx);
+}
+
+
+
+static inline void QCBOREncode_CloseMap(QCBOREncodeContext *pCtx)
+{
+   QCBOREncode_CloseMapOrArray(pCtx, CBOR_MAJOR_TYPE_MAP, NULL);
+}
+
+
+
+static inline void QCBOREncode_BstrWrap(QCBOREncodeContext *pCtx)
+{
+   QCBOREncode_OpenMapOrArray(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING);
+}
+
+static inline void QCBOREncode_BstrWrapInMap(QCBOREncodeContext *pCtx, const char *szLabel)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_BstrWrap(pCtx);
+}
+
+static inline void QCBOREncode_BstrWrapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_BstrWrap(pCtx);
+}
+
+static inline void QCBOREncode_CloseBstrWrap(QCBOREncodeContext *pCtx, UsefulBufC *pWrappedCBOR)
+{
+   QCBOREncode_CloseMapOrArray(pCtx, CBOR_MAJOR_TYPE_BYTE_STRING, pWrappedCBOR);
+}
+
+
+static inline void QCBOREncode_AddEncoded(QCBOREncodeContext *pCtx, UsefulBufC Encoded)
+{
+   QCBOREncode_AddBuffer(pCtx, CBOR_MAJOR_NONE_TYPE_RAW, Encoded);
+}
+
+static inline void QCBOREncode_AddEncodedToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Encoded)
+{
+   QCBOREncode_AddSZString(pCtx, szLabel);
+   QCBOREncode_AddEncoded(pCtx, Encoded);
+}
+
+static inline void QCBOREncode_AddEncodedToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Encoded)
+{
+   QCBOREncode_AddInt64(pCtx, nLabel);
+   QCBOREncode_AddEncoded(pCtx, Encoded);
+}
+
 #endif /* defined(__QCBOR__qcbor__) */
 
diff --git a/src/qcbor_encode.c b/src/qcbor_encode.c
index 1ad89ba..595f7eb 100644
--- a/src/qcbor_encode.c
+++ b/src/qcbor_encode.c
@@ -42,6 +42,11 @@
  
  when               who             what, where, why
  --------           ----            ---------------------------------------------------
+ 11/29/18           llundblade      Rework to simpler handling of tags and labels.
+ 11/9/18            llundblade      Error codes are now enums.
+ 11/1/18            llundblade      Floating support.
+ 10/31/18           llundblade      Switch to one license that is almost BSD-3.
+ 09/28/18           llundblade      Added bstr wrapping feature for COSE implementation.
  02/05/18           llundbla        Works on CPUs which require integer alignment. 
                                     Requires new version of UsefulBuf.
  07/05/17           llundbla        Add bstr wrapping of maps/arrays for COSE
@@ -148,7 +153,7 @@
 /*
  Error tracking plan -- Errors are tracked internally and not returned
  until Finish is called. The CBOR errors are in me->uError.
- UsefulOutBuf also tracks whether the the buffer is full or not in its
+ UsefulOutBuf also tracks whether the buffer is full or not in its
  context.  Once either of these errors is set they are never
  cleared. Only Init() resets them. Or said another way, they must
  never be cleared or we'll tell the caller all is good when it is not.
@@ -176,6 +181,24 @@
  correct. This could also automatically size some of the data
  structures like array/map nesting resulting in some good memory
  savings.
+ 
+ Errors returned here fall into three categories:
+ 
+ Sizes
+   QCBOR_ERR_BUFFER_TOO_LARGE -- A buffer passed in > UINT32_MAX
+   QCBOR_ERR_BUFFER_TOO_SMALL -- output buffer too small
+ 
+   QCBOR_ERR_ARRAY_NESTING_TOO_DEEP -- Too many opens without closes
+   QCBOR_ERR_ARRAY_TOO_LONG -- Too many things added to an array/map
+ 
+ Nesting constructed incorrectly
+   QCBOR_ERR_TOO_MANY_CLOSES -- more close calls than opens
+   QCBOR_ERR_CLOSE_MISMATCH -- Type of close does not match open
+   QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN -- Finish called without enough closes
+ 
+ Bad data
+   QCBOR_ERR_BAD_SIMPLE -- Simple value integer not valid
+ 
  */
 
 
@@ -231,7 +254,7 @@
  for cannonical CBOR.
  
  This function inserts them into the output buffer at the specified
- position.  AppendEncodedTypeAndNumber() appends to the end.
+ position. AppendEncodedTypeAndNumber() appends to the end.
  
  This function takes care of converting to network byte order. 
  
@@ -239,8 +262,8 @@
  function is called the float or double must be copied into a
  uint64_t. That is how they are passed in. They are then converted to
  network byte order correctly. The uMinLen param makes sure that even
- if all the digits of a float or double are 0 it is still correctly
- encoded in 4 or 8 bytes.
+ if all the digits of a halft, float or double are 0 it is still correctly
+ encoded in 2, 4 or 8 bytes.
  
  */
 static void InsertEncodedTypeAndNumber(QCBOREncodeContext *me, uint8_t uMajorType, size_t uMinLen, uint64_t uNumber, size_t uPos)
@@ -288,36 +311,77 @@
 }
 
 
+/*
+ Internal function for adding floating point and simple
+ types to the encoded output.
+ */
+static void AppendType7(QCBOREncodeContext *me, size_t uSize, uint64_t uNum)
+{
+   if(me->uError == QCBOR_SUCCESS) {
+      // This function call takes care of endian swapping for the float / double
+      InsertEncodedTypeAndNumber(me,
+                                 CBOR_MAJOR_TYPE_SIMPLE,  // The major type for
+                                 // floats and doubles
+                                 uSize,                   // min size / tells
+                                 // encoder to do it right
+                                 uNum,                    // Bytes of the floating
+                                 // point number as a uint
+                                 UsefulOutBuf_GetEndPosition(&(me->OutBuf))); // end position for append
+      
+      me->uError = Nesting_Increment(&(me->nesting), 1);
+   }
+}
+
+
 
 
 /*
- Internal function for adding positive and negative integers of all different sizes
+ Public functions for closing arrays and maps. See header qcbor.h
  */
-void InsertInt64(QCBOREncodeContext *me, int64_t nNum, size_t uPos)
+void QCBOREncode_AddUInt64(QCBOREncodeContext *me, uint64_t uValue)
 {
-   uint8_t      uMajorType;
-   uint64_t     uValue;
-   
-   if(nNum < 0) {
-      uValue = (uint64_t)(-nNum - 1); // This is the way negative ints work in CBOR. -1 encodes as 0x00 with major type negative int.
-      uMajorType = CBOR_MAJOR_TYPE_NEGATIVE_INT;
-   } else {
-      uValue = (uint64_t)nNum;
-      uMajorType = CBOR_MAJOR_TYPE_POSITIVE_INT;
+   if(me->uError == QCBOR_SUCCESS) {
+      AppendEncodedTypeAndNumber(me, CBOR_MAJOR_TYPE_POSITIVE_INT, uValue);
+      me->uError = Nesting_Increment(&(me->nesting), 1);
    }
-   
-   InsertEncodedTypeAndNumber(me, uMajorType, 0, uValue, uPos);
-   me->uError = Nesting_Increment(&(me->nesting), 1);
 }
 
 
 /*
+ Public functions for closing arrays and maps. See header qcbor.h
+ */
+void QCBOREncode_AddInt64(QCBOREncodeContext *me, int64_t nNum)
+{
+   if(me->uError == QCBOR_SUCCESS) {
+      uint8_t      uMajorType;
+      uint64_t     uValue;
+      
+      if(nNum < 0) {
+         uValue = (uint64_t)(-nNum - 1); // This is the way negative ints work in CBOR. -1 encodes as 0x00 with major type negative int.
+         uMajorType = CBOR_MAJOR_TYPE_NEGATIVE_INT;
+      } else {
+         uValue = (uint64_t)nNum;
+         uMajorType = CBOR_MAJOR_TYPE_POSITIVE_INT;
+      }
+      
+      AppendEncodedTypeAndNumber(me, uMajorType, uValue);
+      me->uError = Nesting_Increment(&(me->nesting), 1);
+   }
+}
+
+
+/*
+ Semi-private function. It is exposed to user of the interface,
+ but they will usually call one of the inline wrappers rather than this.
+ 
+ See header qcbor.h
+ 
  Does the work of adding some bytes to the CBOR output. Works for a
  byte and text strings, which are the same in in CBOR though they have
  different major types.  This is also used to insert raw
  pre-encoded CBOR.
  */
-static void AddBufferInternal(QCBOREncodeContext *me, UsefulBufC Bytes, uint8_t uMajorType, size_t uPos)
+void QCBOREncode_AddBuffer(QCBOREncodeContext *me, uint8_t uMajorType, UsefulBufC Bytes)
 {
    if(Bytes.len >= UINT32_MAX) {
       // This implementation doesn't allow buffers larger than UINT32_MAX.
@@ -331,16 +395,14 @@
       if(!me->uError) {
          // If it is not Raw CBOR, add the type and the length
          if(uMajorType != CBOR_MAJOR_NONE_TYPE_RAW) {
-            const size_t uPosBeforeInsert = UsefulOutBuf_GetEndPosition(&(me->OutBuf));
-            InsertEncodedTypeAndNumber(me, uMajorType, 0, Bytes.len, uPos);
+            AppendEncodedTypeAndNumber(me, uMajorType, Bytes.len);
             // The increment in uPos is to account for bytes added for
             // type and number so the buffer being added goes to the
             // right place
-            uPos += UsefulOutBuf_GetEndPosition(&(me->OutBuf)) - uPosBeforeInsert;
          }
          
          // Actually add the bytes
-         UsefulOutBuf_InsertUsefulBuf(&(me->OutBuf), Bytes, uPos);
+         UsefulOutBuf_AppendUsefulBuf(&(me->OutBuf), Bytes);
          
          // Update the array counting if there is any nesting at all
          me->uError = Nesting_Increment(&(me->nesting), 1);
@@ -350,70 +412,42 @@
 
 
 /*
- Add an optional label. It will go in front of a real data item.
- */
-static void AddLabel(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel)
-{
-   size_t uPos = UsefulOutBuf_GetEndPosition(&(me->OutBuf));
-   if(Nesting_GetMajorType(&(me->nesting)) == CBOR_MAJOR_NONE_TAG_LABEL_REORDER) {
-      // Have to insert the label rather than just appen if a tag
-      // has been added. This is so the tag ends up on the value, not
-      // on the label.
-      uPos = Nesting_GetStartPos(&(me->nesting));
-      Nesting_Decrease(&(me->nesting));
-   }
-
-   if(szLabel) {
-      const UsefulBufC SZText = UsefulBuf_FromSZ(szLabel);
-      AddBufferInternal(me, SZText, CBOR_MAJOR_TYPE_TEXT_STRING, uPos);
-   } else if (QCBOR_NO_INT_LABEL != nLabel) {
-      InsertInt64(me, nLabel, uPos);
-   }
-}
-
-
-/*
- Public Function
+ Public functions for closing arrays and maps. See header qcbor.h
  */
 void QCBOREncode_AddTag(QCBOREncodeContext *me, uint64_t uTag)
 {
-   uint8_t uNestingType = Nesting_GetMajorType(&(me->nesting));
-   if(uNestingType == CBOR_MAJOR_TYPE_MAP || uNestingType == CBOR_MAJOR_TYPE_ARRAY) {
-      // Remember where the first tag is for this item
-      // So we can go back and insert the label in front of it.
-      // Cast to uint32_t here OK as all inputs are limited to 4GB
-      const uint32_t uPos = (uint32_t)UsefulOutBuf_GetEndPosition(&(me->OutBuf));
-      me->uError = Nesting_Increase(&(me->nesting), CBOR_MAJOR_NONE_TAG_LABEL_REORDER, uPos);
-   }
-
    AppendEncodedTypeAndNumber(me, CBOR_MAJOR_TYPE_OPTIONAL, uTag);
 }
 
 
 /*
- Semi-public interface. Called by inline functions to add text and byte strings
- and already-encoded CBOR. They are the real public interface, even though this
- is the main entry point. The code is structured like this to reduce code size.
+ Public functions for closing arrays and maps. See header qcbor.h
  */
-void QCBOREncode_AddBuffer_2(QCBOREncodeContext *me, uint8_t uMajorType, const char *szLabel, int64_t nLabel, UsefulBufC Bytes)
+void QCBOREncode_AddSimple(QCBOREncodeContext *pCtx, uint8_t uSimple)
 {
-   AddLabel(me, szLabel, nLabel);
-   if(!me->uError) {
-      AddBufferInternal(me, Bytes, uMajorType, UsefulOutBuf_GetEndPosition(&(me->OutBuf)));
-   }
+   AppendType7(pCtx, 0, uSimple);
 }
 
 
 /*
- Semi-public interfaced. Called by inline functions to open arrays, maps and
- bstr wrapped CBOR. They are the real public interface, even though this is the
- main entry point. This code is structured like this to reduce code size.
+ Public functions for closing arrays and maps. See header qcbor.h
  */
-void QCBOREncode_OpenMapOrArray_2(QCBOREncodeContext *me, uint8_t uMajorType, const char *szLabel, uint64_t nLabel)
+void QCBOREncode_AddDouble(QCBOREncodeContext *me, double dNum)
 {
-   AddLabel(me, szLabel, nLabel);
+   const IEEE754_union uNum = IEEE754_DoubleToSmallest(dNum);
    
-   if(!me->uError) {
+   AppendType7(me, uNum.uSize, uNum.uValue);
+}
+
+
+/*
+ Semi-public function. It is exposed to user of the interface,
+ but they will usually call one of the inline wrappers rather than this.
+ 
+ See header qcbor.h
+*/
+void QCBOREncode_OpenMapOrArray(QCBOREncodeContext *me, uint8_t uMajorType)
+{
       // Add one item to the nesting level we are in for the new map or array
       me->uError = Nesting_Increment(&(me->nesting), 1);
       if(!me->uError) {
@@ -422,20 +456,19 @@
          // size is limited to UINT32_MAX in QCBOR_Init().
          me->uError = Nesting_Increase(&(me->nesting), uMajorType, (uint32_t)UsefulOutBuf_GetEndPosition(&(me->OutBuf)));
       }
-   }
 }
 
 
 /*
  Public functions for closing arrays and maps. See header qcbor.h
  */
-void QCBOREncode_Close(QCBOREncodeContext *me, uint8_t uMajorType, UsefulBufC *pWrappedCBOR)
+void QCBOREncode_CloseMapOrArray(QCBOREncodeContext *me, uint8_t uMajorType, UsefulBufC *pWrappedCBOR)
 {
    if(!me->uError) {
       if(!Nesting_IsInNest(&(me->nesting))) {
          me->uError = QCBOR_ERR_TOO_MANY_CLOSES;
       } else if( Nesting_GetMajorType(&(me->nesting)) != uMajorType) {
-         me->uError = QCBOR_ERR_CLOSE_MISMATCH; 
+         me->uError = QCBOR_ERR_CLOSE_MISMATCH;
       } else {
          // When the array, map or bstr wrap was started, nothing was done
          // except note the position of the start of it. This code goes back
@@ -478,89 +511,20 @@
 }
 
 
-/*
- Public functions for adding integers. See header qcbor.h
- */
-void QCBOREncode_AddUInt64_2(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, uint64_t uNum)
-{
-   AddLabel(me, szLabel, nLabel);
-   if(!me->uError) {
-      AppendEncodedTypeAndNumber(me, CBOR_MAJOR_TYPE_POSITIVE_INT, uNum);
-      me->uError = Nesting_Increment(&(me->nesting), 1);
-   }
-}
-
-
-/*
- Public functions for adding integers. See header qcbor.h
- */
-void QCBOREncode_AddInt64_2(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, int64_t nNum)
-{
-   AddLabel(me, szLabel, nLabel);
-   if(!me->uError) {
-      // Cast is OK here because the output buffer is limited to 4GB in Init().
-      InsertInt64(me, nNum, (uint32_t)UsefulOutBuf_GetEndPosition(&(me->OutBuf)));
-   }
-}
-
-
-/*
- Semi-public interfaced. Called by inline functions to add simple and float
- types. They are the real public interface, even though this is the
- main entry point. This code is structured like this to reduce code size.
- 
- Common code for adding floats and doubles and simple types like true and false
- 
- One way to look at simple values is that they are:
-  - type 7
-  - an additional integer from 0 to 255
-     - additional integer 0-19 are unassigned and could be used in an update to CBOR
-     - additional integers 20, 21, 22 and 23 are false, true, null and undef
-     - additional integer 24 is not available
-     - when the additional value is 25, 26, or 27 there is additionally a half, float or double in following bytes
-     - additional integers 28, 29 and 30 are unassigned / reserved
-     - additional integer 31 is a "break"
-     - additional integers 32-255 are unassigned and could be used in an update to CBOR
- */
-void QCBOREncode_AddType7_2(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, size_t uSize, uint64_t uNum)
-{
-   AddLabel(me, szLabel, nLabel);
-   if(!me->uError) {
-      // This function call takes care of endian swapping for the float / double
-      InsertEncodedTypeAndNumber(me,
-                                 CBOR_MAJOR_TYPE_SIMPLE,  // The major type for
-                                                          // floats and doubles
-                                 uSize,                   // min size / tells
-                                                          // encoder to do it right
-                                 uNum,                    // Bytes of the floating
-                                                          // point number as a uint
-                                 UsefulOutBuf_GetEndPosition(&(me->OutBuf))); // end position for append
-      
-      me->uError = Nesting_Increment(&(me->nesting), 1);
-   }
-}
-
-
-void QCBOREncode_AddDouble_2(QCBOREncodeContext *me, const char *szLabel, int64_t nLabel, double dNum)
-{
-   const IEEE754_union uNum = IEEE754_DoubleToSmallest(dNum);
-   
-   QCBOREncode_AddType7_2(me, szLabel, nLabel, uNum.uSize, uNum.uValue);
-}
-
-
-
 
 /*
  Public functions to finish and get the encoded result. See header qcbor.h
  */
 QCBORError QCBOREncode_Finish(QCBOREncodeContext *me, UsefulBufC *pEncodedCBOR)
 {
-   if(me->uError)
+   QCBORError uReturn = me->uError;
+   
+   if(uReturn != QCBOR_SUCCESS) {
       goto Done;
+   }
    
    if (Nesting_IsInNest(&(me->nesting))) {
-      me->uError = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
+      uReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
       goto Done;
    }
    
@@ -571,17 +535,20 @@
       // And of course UsefulBuf will never overrun the input buffer given
       // to it. No complex analysis of the error handling in this file is
       // needed to know that is true. Just read the UsefulBuf code.
-      me->uError = QCBOR_ERR_BUFFER_TOO_SMALL;
+      uReturn = QCBOR_ERR_BUFFER_TOO_SMALL;
       goto Done;
    }
 
    *pEncodedCBOR = UsefulOutBuf_OutUBuf(&(me->OutBuf));
    
 Done:
-   return me->uError;
+   return uReturn;
 }
 
 
+/*
+ Public functions to finish and get the encoded result. See header qcbor.h
+ */
 QCBORError QCBOREncode_FinishGetSize(QCBOREncodeContext *me, size_t *puEncodedLen)
 {
    UsefulBufC Enc;
@@ -596,3 +563,54 @@
 }
 
 
+
+
+/*
+ Notes on the code
+ 
+ CBOR Major Type     Public Function
+ 0                   QCBOREncode_AddUInt64
+ 0, 1                QCBOREncode_AddUInt64, QCBOREncode_AddInt64
+ 2, 3                QCBOREncode_AddBuffer, Also QCBOREncode_OpenMapOrArray
+ 4, 5                QCBOREncode_OpenMapOrArray
+ 6                   QCBOREncode_AddTag
+ 7                   QCBOREncode_AddDouble, QCBOREncode_AddSimple
+ 
+ Object code sizes on X86 with LLVM compiler and -Os (Nov 27, 2018)
+ 
+ _QCBOREncode_Init   84
+ _QCBOREncode_AddUInt64   76
+ _QCBOREncode_AddInt64   87
+ _QCBOREncode_AddBuffer   131
+ _QCBOREncode_AddSimple   30
+ _AppendType7   83
+ _QCBOREncode_OpenMapOrArray   89
+ _QCBOREncode_CloseMapOrArray   181
+ _InsertEncodedTypeAndNumber   480
+ _QCBOREncode_Finish   72
+ 
+ Total is about 1.4KB (including FinishGetSize and AddTag and AddDouble)
+ 
+ _InsertEncodedTypeAndNumber is large because a lot of UsefulBuf
+ code inlines into it including the conversion to network byte
+ order. This could be optimized to at least half the size, but
+ code would probably not be quite as clean.
+ 
+ _QCBOREncode_CloseMapOrArray is larger because it has a lot
+ of nesting tracking to do and much of Nesting_ inlines
+ into it. It probably can't be reduced much.
+ 
+ If the error returned by Nesting_Increment() can be ignored
+ because the limit is so high and the consequence of exceeding
+ is proved to be inconsequential, then a lot of if(me->uError)
+ instance can be removed, saving some code.
+ 
+ */
+
+
+
+
+
+
+
+
diff --git a/test/float_tests.c b/test/float_tests.c
index 091dc5c..2b472f3 100644
--- a/test/float_tests.c
+++ b/test/float_tests.c
@@ -316,6 +316,10 @@
 {
     UsefulBuf_MAKE_STACK_UB(EncodedHalfsMem, 420);
     
+#define QCBOREncode_AddDoubleAsSmallestToMap QCBOREncode_AddDoubleToMap
+#define QCBOREncode_AddDoubleAsSmallestToMapN QCBOREncode_AddDoubleToMapN
+
+    
     QCBOREncodeContext EC;
     QCBOREncode_Init(&EC, EncodedHalfsMem);
     // These are mostly from https://en.wikipedia.org/wiki/Half-precision_floating-point_format
diff --git a/test/qcbor_encode_tests.c b/test/qcbor_encode_tests.c
index 395e43a..d87b4e4 100644
--- a/test/qcbor_encode_tests.c
+++ b/test/qcbor_encode_tests.c
@@ -49,7 +49,7 @@
 
 //#define PRINT_FUNCTIONS_FOR_DEBUGGINGXX
 
-#if  PRINT_FUNCTIONS_FOR_DEBUGGINGXX
+#ifdef  PRINT_FUNCTIONS_FOR_DEBUGGINGXX
 #include <stdio.h>
 
 // ifdef these out to not have compiler warnings
@@ -468,6 +468,7 @@
 
 int AllAddMethodsTest()
 {
+   // TODO: this test should be broken down into several so it is more managable. Tags and labels could be more sensible
    QCBOREncodeContext ECtx;
    int nReturn = 0;
    
@@ -475,11 +476,13 @@
    
    QCBOREncode_OpenArray(&ECtx);
 
-   // Non-map ints
+   // Some ints that are tagged and have strings preceeding them (not labels becase it is not a map)
+   QCBOREncode_AddSZString(&ECtx, "UINT62");
    QCBOREncode_AddTag(&ECtx, 100);
-   QCBOREncode_AddUInt64_2(&ECtx, "UINT62", QCBOR_NO_INT_LABEL, 89989909);
+   QCBOREncode_AddUInt64(&ECtx, 89989909);
+   QCBOREncode_AddSZString(&ECtx, "INT64");
    QCBOREncode_AddTag(&ECtx, 76);
-   QCBOREncode_AddInt64_2(&ECtx, "INT64", QCBOR_NO_INT_LABEL, 77689989909);
+   QCBOREncode_AddInt64(&ECtx, 77689989909);
    QCBOREncode_AddUInt64(&ECtx,0);
    QCBOREncode_AddInt64(&ECtx, -44);
 
@@ -496,7 +499,7 @@
    
    // Epoch date with labels
    QCBOREncode_OpenMap(&ECtx);
-   QCBOREncode_AddDateEpoch_2(&ECtx, "LongLiveDenisRitchie", QCBOR_NO_INT_LABEL, 1400000000);
+   QCBOREncode_AddDateEpochToMap(&ECtx, "LongLiveDenisRitchie", 1400000000);
    QCBOREncode_AddDateEpochToMap(&ECtx, "time()", 1477263730);
    QCBOREncode_AddDateEpochToMapN(&ECtx, -1969, 1477263222);
    QCBOREncode_CloseMap(&ECtx);
@@ -506,9 +509,10 @@
 
    // binary blobs in maps
    QCBOREncode_OpenMap(&ECtx);
+   QCBOREncode_AddSZString(&ECtx, "binbin");
    QCBOREncode_AddTag(&ECtx, 100000);
-   QCBOREncode_AddBytes_2(&ECtx, "binbin", QCBOR_NO_INT_LABEL, ((UsefulBufC) {(uint8_t []){0x00}, 1}));
-   QCBOREncode_AddBytesToMap(&ECtx, "blabel", ((UsefulBufC){(uint8_t []){0x01, 0x02, 0x03}, 3}));
+   QCBOREncode_AddBytes(&ECtx, ((UsefulBufC) {(uint8_t []){0x00}, 1}));
+   QCBOREncode_AddBytesToMap(&ECtx, "blabel", ((UsefulBufC) {(uint8_t []){0x01, 0x02, 0x03}, 3}));
    QCBOREncode_AddBytesToMapN(&ECtx, 0, ((UsefulBufC){(uint8_t []){0x04, 0x02, 0x03, 0xfe}, 4}));
    QCBOREncode_CloseMap(&ECtx);
    
@@ -523,9 +527,10 @@
    // text blobs in maps
    QCBOREncode_OpenMap(&ECtx);
    QCBOREncode_AddTextToMap(&ECtx, "#####", UsefulBuf_FROM_SZ_LITERAL("foo bar foo foo"));
-   QCBOREncode_AddTextToMap(&ECtx, "____", UsefulBuf_FROM_SZ_LITERAL("foo bar")); // TODO _2?
+   QCBOREncode_AddTextToMap(&ECtx, "____", UsefulBuf_FROM_SZ_LITERAL("foo bar"));
+   QCBOREncode_AddSZString(&ECtx, "()()()");
    QCBOREncode_AddTag(&ECtx, 1000);
-   QCBOREncode_AddSZString_2(&ECtx, "()()()", QCBOR_NO_INT_LABEL, "rab rab oof");
+   QCBOREncode_AddSZString(&ECtx, "rab rab oof");
    QCBOREncode_AddTextToMapN(&ECtx,22, UsefulBuf_FROM_SZ_LITERAL("foo foo foo foo"));
    QCBOREncode_AddSZStringToMap(&ECtx, "^^", "oooooooof");
    QCBOREncode_AddSZStringToMapN(&ECtx, 99, "ffffoooooooof");
@@ -549,9 +554,10 @@
    // true / false ...
    QCBOREncode_AddSimple(&ECtx, CBOR_SIMPLEV_UNDEF);
    QCBOREncode_OpenMap(&ECtx);
+   QCBOREncode_AddSZString(&ECtx, "dare");
    QCBOREncode_AddTag(&ECtx, 66);
-   QCBOREncode_AddSimple_2(&ECtx, "dare", QCBOR_NO_INT_LABEL, CBOR_SIMPLEV_TRUE);
-   QCBOREncode_AddSimpleToMap(&ECtx, "uu", CBOR_SIMPLEV_FALSE);
+   QCBOREncode_AddBool(&ECtx, true);
+   QCBOREncode_AddBoolToMap(&ECtx, "uu", false);
    QCBOREncode_AddSimpleToMapN(&ECtx, 737634, CBOR_SIMPLEV_NULL);
    QCBOREncode_CloseMap(&ECtx);
    
@@ -561,40 +567,46 @@
 
    // opening arrays in a map
    QCBOREncode_OpenMap(&ECtx);
+   QCBOREncode_AddSZString(&ECtx, "label and tagged empty array");
    QCBOREncode_AddTag(&ECtx, 1093);
-   QCBOREncode_OpenArray_2(&ECtx, "label and tagged empty array", QCBOR_NO_INT_LABEL);
+   QCBOREncode_OpenArray(&ECtx);
    QCBOREncode_CloseArray(&ECtx);
    QCBOREncode_OpenArrayInMap(&ECtx, "alabl");
    QCBOREncode_CloseArray(&ECtx);
    QCBOREncode_OpenArrayInMapN(&ECtx, 42);
    QCBOREncode_CloseArray(&ECtx); 
    QCBOREncode_CloseMap(&ECtx);
-   
+ 
    // opening maps with labels and tagging
    QCBOREncode_OpenMap(&ECtx);
    QCBOREncode_OpenMapInMap(&ECtx, "in a map");
    QCBOREncode_OpenMapInMapN(&ECtx, 5556);
+   QCBOREncode_AddSZString(&ECtx, "in a in a in a");
    QCBOREncode_AddTag(&ECtx, 9087);
-   QCBOREncode_OpenMap_2(&ECtx, "in a in a in a", QCBOR_NO_INT_LABEL);
+   QCBOREncode_OpenMap(&ECtx);
    QCBOREncode_CloseMap(&ECtx);
    QCBOREncode_CloseMap(&ECtx);
    QCBOREncode_CloseMap(&ECtx);
    QCBOREncode_CloseMap(&ECtx);
    
+
    // Extended simple values (these are not standard...)
    QCBOREncode_OpenMap(&ECtx);
+   QCBOREncode_AddSZString(&ECtx, "s1");
    QCBOREncode_AddTag(&ECtx, 88);
-   QCBOREncode_AddType7_2(&ECtx, "s1", QCBOR_NO_INT_LABEL, 0, 255);
-   QCBOREncode_AddType7_2(&ECtx, "s2", QCBOR_NO_INT_LABEL, 0, 0);
+   QCBOREncode_AddSimple(&ECtx, 255);
+   QCBOREncode_AddSimpleToMap(&ECtx, "s2", 0);
+   QCBOREncode_AddSZString(&ECtx, "s3");
    QCBOREncode_AddTag(&ECtx, 88);
-   QCBOREncode_AddType7_2(&ECtx, "s3", QCBOR_NO_INT_LABEL, 0, 33);
+   QCBOREncode_AddSimple(&ECtx, 33);
+   QCBOREncode_AddInt64(&ECtx, 88378374); // label before tag
    QCBOREncode_AddTag(&ECtx, 88);
-   QCBOREncode_AddType7_2(&ECtx, NULL, 88378374, 0, 255);
+   QCBOREncode_AddSimple(&ECtx, 255);
+   QCBOREncode_AddInt64(&ECtx, 89); // label before tag
    QCBOREncode_AddTag(&ECtx, 88);
-   QCBOREncode_AddType7_2(&ECtx, NULL, 89, 0, 19);
+   QCBOREncode_AddSimple(&ECtx, 19);
    QCBOREncode_CloseMap(&ECtx);
    
-   
    // UUIDs
    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);
@@ -604,7 +616,6 @@
    QCBOREncode_AddBinaryUUIDToMapN(&ECtx, 99, XXUUID);
    QCBOREncode_CloseMap(&ECtx);
    
-   
    // Bool
    QCBOREncode_AddBool(&ECtx, true);
    QCBOREncode_AddBool(&ECtx, false);
@@ -1653,7 +1664,7 @@
    
    for(int i = 0; i < (BSTR_TEST_DEPTH-2)/3; i++) {
       QCBOREncode_OpenMap(&EC);
-      QCBOREncode_BstrWrapMapN(&EC, i+0x20);
+      QCBOREncode_BstrWrapInMapN(&EC, i+0x20);
       QCBOREncode_OpenArray(&EC);
       QCBOREncode_AddUInt64(&EC, i+0x10);
    }
@@ -1798,7 +1809,7 @@
    
    // top level array for cose sign1, 18 is the tag for COSE sign
    QCBOREncode_AddTag(&EC, 18); // TODO: replace with constant
-   QCBOREncode_OpenArray_2(&EC, NULL, QCBOR_NO_INT_LABEL); // TODO: _2
+   QCBOREncode_OpenArray(&EC);
    
    // Add protected headers
    QCBOREncode_AddBytes(&EC, ProtectedHeaders);