checkpoint work on arrays
diff --git a/inc/qcbor/UsefulBuf.h b/inc/qcbor/UsefulBuf.h
index 990191a..2974adf 100644
--- a/inc/qcbor/UsefulBuf.h
+++ b/inc/qcbor/UsefulBuf.h
@@ -1580,6 +1580,18 @@
 static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
 
 
+// TODO: document this; maybe add tests...
+#if defined(USEFULBUF_CONFIG_BSWAP)
+#define USEFUL_SWAP32(integer) \
+   __builtin_bswap32(integer);
+#else
+#define USEFUL_SWAP32(integer) \
+   ((integer & 0xff) >> 24) + \
+   ((integer & 0xff00) >> 16) + \
+   ((integer & 0xff0000) >> 8) + \
+    (integer & 0xff000000)
+#endif
+
 
 
 /*----------------------------------------------------------
@@ -1789,6 +1801,7 @@
 }
 
 
+
 static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
                                              uint16_t uInteger16,
                                              size_t uPos)
@@ -1836,20 +1849,21 @@
    uint32_t uTmp = htonl(uInteger32);
    pBytes = &uTmp;
 
-#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
-   uint32_t uTmp = __builtin_bswap32(uInteger32);
-
+#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
+   uint32_t uTmp = XSWAP(uInteger32);
    pBytes = &uTmp;
 
 #else
-   uint8_t aTmp[4];
 
-   aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
-   aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
-   aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
-   aTmp[3] = (uint8_t)(uInteger32 & 0xff);
+   uint32_t uTmp =
+   ((uInteger32 & 0xff) >> 24) + \
+   ((uInteger32 & 0xff00) >> 16) + \
+   ((uInteger32 & 0xff0000) >> 8) + \
+   (uInteger32 & 0xff000000);
 
-   pBytes = aTmp;
+   pBytes = &uTmp;
+
+
 #endif
 
    UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
diff --git a/inc/qcbor/qcbor_common.h b/inc/qcbor/qcbor_common.h
index a7c33e0..b1a2e96 100644
--- a/inc/qcbor/qcbor_common.h
+++ b/inc/qcbor/qcbor_common.h
@@ -197,6 +197,16 @@
     tag. */
 #define CBOR_TAG_CBOR_SEQUENCE 63
 
+#define CBOR_TAG_UINT8_ARRAY 64
+
+#define CBOR_TAG_UINT16_BIG_ENDIAN_ARRAY 65
+#define CBOR_TAG_UINT32_BIG_ENDIAN_ARRAY 66
+#define CBOR_TAG_UINT64_BIG_ENDIAN_ARRAY 67
+
+#define CBOR_TAG_UINT16_LITTLE_ENDIAN_ARRAY 69
+#define CBOR_TAG_UINT32_LITTLE_ENDIAN_ARRAY 70
+#define CBOR_TAG_UINT64_LITTLE_ENDIAN_ARRAY 71
+
 
 #define CBOR_TAG_ENCRYPT       96
 /** Not Decoded by QCBOR. Tag for COSE format MAC. See [RFC 8152, COSE]
@@ -505,6 +515,14 @@
        indefinite length map or array in the input CBOR. */
    QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED = 44,
 
+   /** The input CBOR needs to be a multiple of 2, 4 or 8 bytes and it is not. */
+   QCBOR_ERR_INPUT_SIZE_MULTIPLE = 45,
+
+   /** The input CBOR  is not a tag indicating endianness and the input endianness
+    needs to be know to proceed. */
+   QCBOR_ERR_INPUT_ENDIANNESS_UNKNOWN = 45,
+
+
    /* This is stored in uint8_t; never add values > 255 */
 } QCBORError;
 
diff --git a/inc/qcbor/qcbor_encode.h b/inc/qcbor/qcbor_encode.h
index 6ac004e..c25fbc5 100644
--- a/inc/qcbor/qcbor_encode.h
+++ b/inc/qcbor/qcbor_encode.h
@@ -503,9 +503,9 @@
  */
 void QCBOREncode_AddInt64(QCBOREncodeContext *pCtx, int64_t nNum);
 
-static void QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t uNum);
+static void QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t nNum);
 
-static void QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t uNum);
+static void QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t nNum);
 
 
 /**
@@ -1957,6 +1957,79 @@
                                   uint64_t  uNumber);
 
 
+
+
+
+/**
+ @brief Encode a "homogeneous" array of signed integers.
+
+ @param[in] pCtx  The encoding context.
+ @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+                             @ref QCBOR_ENCODE_AS_BORROWED.
+ @param[in] pnNum  The array of integers to output.
+ @param[in] uNumInts  The number of integers in \c pnNum.
+
+ This encodes a homogeneous array of signed integers as described in section 3.2 in [RFC 8746](https://tools.ietf.org/html/rfc8746).
+
+ To encode the actual integers, this just opens an array, adds all the integers
+ and closes the array as one might expect. The only thing unusual is the
+ encoding of this as a tag.
+
+ If \c uTagRequirement is @ref QCBOR_ENCODE_AS_TAG then
+ this is encoded as the homogenous array tag, which means the array
+ is preceded by the tag number \ref CBOR_TAG_HOMOGENEOUS_ARRAY.
+
+ If \c uTagRequirement is @ref QCBOR_ENCODE_AS_BORROWED then
+ there is no tag number and this is the straight forward encoding of an
+ array of integers. This is "borrowed" because the definition of a homogenous
+ array is as a tag.
+
+ This uses QCBOREncode_AddInt64() to encode the integers so
+ preferred encoding in the shortest form is used and this will encode
+ with either major type 0 or 1 depending on whether each integer is
+ positive or negative.
+*/
+void
+QCBOREncode_AddArrayOfInt64s(QCBOREncodeContext *pCtx,
+                             uint8_t             uTagRequirement,
+                             const int64_t       pnNum[],
+                             size_t              uNumInts);
+
+
+void
+QCBOREncode_AddArrayOfUInt64s(QCBOREncodeContext *pMe,
+                              uint8_t             uTagRequirement,
+                              const uint64_t      puInts[],
+                              size_t              uNumUInts);
+
+
+void
+QCBOREncode_AddArrayOfDoubles(QCBOREncodeContext *pMe,
+                              uint8_t             uTagRequirement,
+                              const double        pdDoubles[],
+                              size_t              uNumDoubles);
+
+
+void
+QCBOREncode_AddArrayOfByteStrings(QCBOREncodeContext *pMe,
+                                  uint8_t             uTagRequirement,
+                                  const UsefulBufC    pStrings[],
+                                  size_t              uNumStrings);
+
+
+void
+QCBOREncode_AddArrayOfTextStrings(QCBOREncodeContext *pMe,
+                                  uint8_t             uTagRequirement,
+                                  const UsefulBufC    pStrings[],
+                                  size_t              uNumStrings);
+
+
+void
+QCBOREncode_AddArrayOfSZStrings(QCBOREncodeContext *pMe,
+                                uint8_t             uTagRequirement,
+                                const char         *pStrings[],
+                                size_t              uNumStrings);
+
 /*
 Definitely need to have two functions, one for BE and one for LE.
  Since we have to say what format to output. There is no wire format.
@@ -1968,19 +2041,16 @@
 use correct tag.
 
 
-
+There are going to be about 20 functions here for
+ all the different integer types.
 
 
  */
 
 
-void
-QCBOREncode_AddArrayOfInts(QCBOREncodeContext *pMe,
-                           uint8_t             uTagRequirement,
-                           const int64_t      *puInts,
-                           size_t              uNumInts);
 
-void QCBOREncode_AddUint32ArrayBigEndian(QCBOREncodeContext *pCtx,
+
+void QCBOREncode_AddTypedArrayOfUInt32BigEndian(QCBOREncodeContext *pCtx,
                                          const uint32_t      array[],
                                          size_t              uArrayLen);
 
@@ -2156,18 +2226,18 @@
 
 
 static inline void
-QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pMe, const char *szLabel, int64_t uNum)
+QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pMe, const char *szLabel, int64_t nNum)
 {
    // Use _AddBuffer() because _AddSZString() is defined below, not above
    QCBOREncode_AddBuffer(pMe, CBOR_MAJOR_TYPE_TEXT_STRING, UsefulBuf_FromSZ(szLabel));
-   QCBOREncode_AddInt64(pMe, uNum);
+   QCBOREncode_AddInt64(pMe, nNum);
 }
 
 static inline void
-QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pMe, int64_t nLabel, int64_t uNum)
+QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pMe, int64_t nLabel, int64_t nNum)
 {
    QCBOREncode_AddInt64(pMe, nLabel);
-   QCBOREncode_AddInt64(pMe, uNum);
+   QCBOREncode_AddInt64(pMe, nNum);
 }
 
 
diff --git a/inc/qcbor/qcbor_spiffy_decode.h b/inc/qcbor/qcbor_spiffy_decode.h
index a18c3c6..424b5ae 100644
--- a/inc/qcbor/qcbor_spiffy_decode.h
+++ b/inc/qcbor/qcbor_spiffy_decode.h
@@ -1700,6 +1700,176 @@
 
 
 
+/**
+ @brief Get a "homgeneous" array of 64-bit integers
+
+ @param[in] pCtx   The decode context.
+
+ This decodes was is called the "homogenous array" tag in RFC xxxx.
+  The input must be a normal CBOR array where every item
+ in the array is CBOR item of major type 0 or 1.
+
+ See also QCBORDecode_GetTypedArrayOfInt64s() for an alternate encoding of 64-bit integers that is
+ more compact in some cases, but is NOT endian neutral.
+
+*/
+static void
+QCBORDecode_GetArrayOfInt64(QCBORDecodeContext *pCtx,
+                            uint8_t             uTagRequirement,
+                            size_t              nInArrayCount,
+                            int64_t            *pnInt64s,
+                            size_t             *pnOutArrayCount);
+
+static void
+QCBORDecode_GetArrayOfInt64InMapN(QCBORDecodeContext *pCtx,
+                                  int64_t             nLabel,
+                                  uint8_t             uTagRequirement,
+                                  size_t              nInArrayCount,
+                                  int64_t            *pnInt64s,
+                                  size_t             *pnOutArrayCount);
+
+static void
+QCBORDecode_GetArrayOfInt64InMapSZ(QCBORDecodeContext *pCtx,
+                                   const char         *szLabel,
+                                   uint8_t             uTagRequirement,
+                                   size_t              nInArrayCount,
+                                   int64_t            *pnInt64s,
+                                   size_t             *pnOutArrayCount);
+
+
+
+static void inline
+QCBORDecode_GetArrayOfUInt64(QCBORDecodeContext *pCtx,
+                             uint8_t             uTagRequirement,
+                             size_t              nInArrayCount,
+                             int64_t            *puUInt64s,
+                             size_t             *pnOutArrayCount);
+
+
+static void inline
+QCBORDecode_GetArrayOfTextStrings(QCBORDecodeContext *pCtx,
+                                  uint8_t             uTagRequirement,
+                                  size_t              nInArrayCount,
+                                  UsefulBufC         *pStrings,
+                                  size_t             *pnOutArrayCount);
+
+static void inline
+QCBORDecode_GetArrayOfByteStrings(QCBORDecodeContext *pCtx,
+                                  uint8_t             uTagRequirement,
+                                  size_t              nInArrayCount,
+                                  UsefulBufC         *pStrings,
+                                  size_t             *pnOutArrayCount);
+
+
+static void inline
+QCBORDecode_GetArrayOfDoubles(QCBORDecodeContext *pCtx,
+                              uint8_t             uTagRequirement,
+                              size_t              nInArrayCount,
+                              double             *pDoubles,
+                              size_t             *pnOutArrayCount);
+
+
+
+#define IS_BIG_ENDIAN   0
+#define IS_LITTLE_ENDIAN 1
+#define ENDIAN_UNKNOWN 2
+
+/**
+ @brief Get a "typed" array of 64-bit integers
+
+ @param[in] pCtx   The decode context.
+
+ This decodes was is called the "type array" tag in RFC xxxx.
+ The CBOR to be decoded is a byte string where every 8 bytes are interpreted as
+ as signed 64-bit integer.
+
+ Unlike everything else in CBOR, the integers are NOT in network byte
+ order. The sender may have encoded them as big or little endian. The point
+ of doing this is to be able to more-efficiently send large arrays of integers
+ between implementing end-points that need and support this. This
+ avoids any copying or byte swapping of the integers saving both
+ memory and CPU cycles.
+
+ The array may be a CBOR tag or not. \c uTagRequrement instructs the
+ decoder as to whether it will decode as a tag.
+
+ If encoded CBOR is a tag, it will be known whether what was sent
+ was big or little endian and returned in \c uEndianness. If it
+ is not a tag, then the knowledge of the endianess has to come from
+ else where. Perhaps it is part of the particular protocol that all
+ type arrays are to be of a particular endianness.
+*/
+void QCBORDecode_GetTypedArrayOfInt64s(QCBORDecodeContext *pCtx,
+                                       uint8_t             uTagRequirement,
+                                       uint64_t           **pInts,
+                                       size_t             *pSize,
+                                       uint8_t            *uEndianess); // TODO: constants for endianness
+/**
+  * This specifies the enianness processing that should be done for a few
+ * methods for array decoding that are configurable this way.
+ *
+ * Note that the endianness of the input must be known for some
+ * of these to work. Somtimes the input CBOR is not a tag
+ * and the endianness is not know.
+ */
+typedef enum {
+   /** The output is to be big endian. The input must be a tag indicating its endianness for this to work. */
+   QCBOR_ENDIAN_BIG_ENDIAN = 0,
+   /** The output is to be little endian. The input must be a tag indicating its endianness for this to work. */
+   QCBOR_ENDIAN_LITTLE_ENDIAN = 1,
+   /** A swap will always be performed. It is up to the caller to know the input endianness. */
+   QCBOR_ENDIAN_SWAP = 2,
+   /** A swap will never be performed. It is up to the caller to know the input endianness. */
+   QCBOR_ENDIAN_NO_SWAP = 3,
+   /** Swapping will be performed if necessary to make the output the correct endianness. The input must be a tag indicating its endianness for this to work. */
+   QCBOR_ENDIAN_MATCH_ENDIANNESS = 4,
+} QCBOREndianRequirement;
+
+
+
+/**
+ @brief Get an "typed" array of 64-bit integers with copying and swapping
+
+ @param[in] pCtx   The decode context.
+
+This decodes the same data type as QCBORDecode_GetTypedArrayOfInt64s().
+ Additionaly, it copies the array to a supplied buffer and does byte swapping
+ for endianness as instructed.
+
+ The received array may or may not have indication of its endianness.
+
+
+
+ The possible swapping options are:
+   - big endian; the input must have indication of its endianness for this to work
+      - little endianess
+ - swap; the endianness will always be swapped regardless of what of the input is marked
+ - no swap; there will be no swapping regardless of how the input is marked
+ - match configured endianness of machine
+*/
+void QCBORDecode_GetTypedArrayOfInt64sCopy(QCBORDecodeContext *pCtx,
+                                           uint8_t             uTagRequirement,
+                                           QCBOREndianRequirement uSwapRequirement,
+                                           size_t              uSize,
+                                           uint64_t          **pInts,
+                                           size_t             *pSize);
+
+
+
+void QCBORDecode_GetUInt32Array(QCBORDecodeContext *pCtx,
+                                uint8_t             uTagRequirement,
+                                uint32_t           **pInts,
+                                size_t             *pSize);
+
+
+void QCBORDecode_GetUint32ArrayCopy(QCBORDecodeContext *pCtx,
+                                    uint8_t             uTagRequirement,
+                                    QCBOREndianRequirement  uSwapRequirement,
+                                    size_t              uSize,
+                                    uint32_t           *pInts,
+                                    size_t             *pSize);
+
+
 /* ===========================================================================
    BEGINNING OF PRIVATE INLINE IMPLEMENTATION
    ========================================================================== */
@@ -2585,7 +2755,10 @@
 
 
 
-
+/**
+ * Semi-private data structure to hold the pointer into which to copy
+ * a decoded homogeneous array.
+ */
 union QCBORHomogenousArray {
    int64_t    *pnInt64s;
    int64_t    *puUInt64s;
@@ -2593,7 +2766,33 @@
    UsefulBufC *pStrings;
 };
 
-void QCBORDecode_GetHomogenousArray(QCBORDecodeContext *pMe,
+/**
+ * Semi-private method to decode a homogeneous array
+ *
+ * @param[in] pCtx   The decode context.
+ * @param[in] uTagRequirement   One of @c QCBOR_TAG_REQUIREMENT_XXX
+ * @param[in] uType                      The QCBOR type of the array elements.
+ * @param[in] nInArrayCount  The size in number of elements of @c array passed in.
+ * @param[in,out] array  The buffer into which the array is decoded.
+ * @param[out] pnOutArrayCount The number of elements in @c array that were filled in.
+ *
+ * This decodes the next item as a homogenous array where all the elements in the
+ * array can be decoded as the QCBOR_TYPE passed in as @c uType. The type
+ * must be one of @ref  QCBOR_TYPE_INT64, @ref QCBOR_TYPE_UINT64,
+ * @ref QCBOR_TYPE_DOUBLE, @ref QCBOR_TYPE_TEXT_STRING or
+ * @ref QCBOR_TYPE_BYTE_STRING. Note that for QCBOR_TYPE_INT64
+ * the members in the array can be of either major type 0 or 1.
+ *
+ * The buffer into which the array is decoded is in the @ref QCBORHomogenousArray
+ * union. The size of the buffer must be @c nInArrayCount times the size of the
+ * data type. The number of elements decoded is returned in @c pnOutArrayCount.
+ *
+ * @c array may be NULL in which case the array will be decoded and
+ * @c pnOutArrayCount will be filled in, but note that input will be consumed.
+ * To actually get the decoded array values QCBORDecode_Rewind() will have to
+ * be used and it goes back to the start of an entered enclosing array or map.
+ */
+void QCBORDecode_GetHomogenousArray(QCBORDecodeContext *pCtx,
                                     uint8_t             uTagRequirement,
                                     uint8_t             uType,
                                     size_t              nInArrayCount,
@@ -2601,6 +2800,22 @@
                                     size_t             *pnOutArrayCount);
 
 
+void QCBORDecode_GetHomogenousArrayInMapN(QCBORDecodeContext *pMe,
+                                          int64_t             nLabel,
+                                          uint8_t             uTagRequirement,
+                                          uint8_t             uType,
+                                          size_t              nInArrayCount,
+                                          union QCBORHomogenousArray array,
+                                          size_t             *pnOutArrayCount);
+
+void QCBORDecode_GetHomogenousArrayInMapSZ(QCBORDecodeContext *pMe,
+                                           const char          *szLabel,
+                                           uint8_t             uTagRequirement,
+                                           uint8_t             uType,
+                                           size_t              nInArrayCount,
+                                           union QCBORHomogenousArray array,
+                                           size_t             *pnOutArrayCount);
+
 static void inline
 QCBORDecode_GetArrayOfInt64(QCBORDecodeContext *pMe,
                             uint8_t             uTagRequirement,
@@ -2622,6 +2837,50 @@
 
 
 static void inline
+QCBORDecode_GetArrayOfInt64InMapN(QCBORDecodeContext *pMe,
+                                 int64_t             nLabel,
+                            uint8_t             uTagRequirement,
+                            size_t              nInArrayCount,
+                            int64_t            *pnInt64s,
+                            size_t             *pnOutArrayCount)
+{
+   union QCBORHomogenousArray array;
+
+   array.pnInt64s = pnInt64s;
+
+   QCBORDecode_GetHomogenousArrayInMapN(pMe,
+                                        nLabel,
+                                        uTagRequirement,
+                                        QCBOR_TYPE_INT64,
+                                        nInArrayCount,
+                                        array,
+                                        pnOutArrayCount);
+}
+
+static void inline
+QCBORDecode_GetArrayOfInt64InMapSZ(QCBORDecodeContext *pMe,
+                                   const char         *szLabel,
+                                   uint8_t             uTagRequirement,
+                                   size_t              nInArrayCount,
+                                   int64_t            *pnInt64s,
+                                   size_t             *pnOutArrayCount)
+{
+   union QCBORHomogenousArray array;
+
+   array.pnInt64s = pnInt64s;
+
+   QCBORDecode_GetHomogenousArrayInMapSZ(pMe,
+                                         szLabel,
+                                         uTagRequirement,
+                                         QCBOR_TYPE_INT64,
+                                         nInArrayCount,
+                                         array,
+                                         pnOutArrayCount);
+}
+
+
+
+static void inline
 QCBORDecode_GetArrayOfUInt64(QCBORDecodeContext *pMe,
                              uint8_t             uTagRequirement,
                              size_t              nInArrayCount,