checkpoint work on arrays
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 223cc7f..d7b3958 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -5922,34 +5922,145 @@
 
 
 
-/* The one that matches the endianness should return without copying
- The other either has to copy or has to swap by violating const-ness.
- If copying, the caller has to know. If violating const-ness, then
-the caller only knows that const-ness is violated. */
 
-void QCBORDecode_GetUint32ArrayBE(QCBORDecodeContext *pMe,
+
+
+typedef enum {
+   QCBOR_IS_BIG_ENDIAN = 0,
+   QCBOR_IS_LITTLE_ENDIAN = 1,
+   QCBOR_UNKNOWN_ENDIAN = 2
+} QCBOREndianness;
+
+void QCBORDecode_GetUint32Array(QCBORDecodeContext *pMe,
                                 uint8_t             uTagRequirement,
-                                uint32_t           *pInts,
-                                size_t             *pSize)
+                                uint32_t          **puUIntsDecoded,
+                                size_t             *puSizeDecoded,
+                                QCBOREndianness    *puEndianness)
 {
-   QCBORItem item;
-   QCBORDecode_VGetNext(pMe, &item);
+   QCBORItem Item;
+   QCBORDecode_VGetNext(pMe, &Item);
 
-   if(item.uDataType != QCBOR_TYPE_BYTE_STRING ||
-      !QCBORDecode_IsTagged(pMe, &item, 99)) { // TODO: correct tag number
+   if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
       pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
       return;
    }
 
-   if(item.val.string.len % 4 != 0) {
-      pMe->uLastError = 99; // TODO: figure out error
+   const TagSpecification TagSpec =
+      {
+         uTagRequirement,
+         {CBOR_TAG_UINT32_BIG_ENDIAN_ARRAY, CBOR_TAG_UINT32_LITTLE_ENDIAN_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
+   if(pMe->uLastError) {
       return;
    }
 
-   *pSize = item.val.string.len / 4;
+   if(QCBORDecode_IsTagged(pMe, &Item, CBOR_TAG_UINT32_BIG_ENDIAN_ARRAY)) {
+      *puEndianness = QCBOR_IS_BIG_ENDIAN;
+   } else if(QCBORDecode_IsTagged(pMe, &Item, CBOR_TAG_UINT32_LITTLE_ENDIAN_ARRAY)) {
+      *puEndianness = QCBOR_IS_LITTLE_ENDIAN;
+   } else {
+      *puEndianness = QCBOR_UNKNOWN_ENDIAN;
+   }
 
-   /* may have to swap if endianness doesn't match */
-   pInts = (uint32_t *) &(item.val.string.ptr);
+
+   if(Item.val.string.len % sizeof(uint32_t) != 0) {
+      pMe->uLastError = QCBOR_ERR_INPUT_SIZE_MULTIPLE;
+      return;
+   }
+
+   *puSizeDecoded = Item.val.string.len / sizeof(uint32_t);
+
+   *puUIntsDecoded = (uint32_t *)(Item.val.string.ptr);
+}
+
+
+
+
+
+// positive values are QCBOR error codes
+#define PERFORM_SWAP -1
+#define DO_NOT_SWAP 0
+static int
+ShallWeSwap(QCBOREndianRequirement uSwapRequirement, QCBOREndianness uEndianness)
+{
+   /* Asked to always swap */
+   if(uSwapRequirement == QCBOR_ENDIAN_SWAP) {
+      return PERFORM_SWAP;
+   }
+
+   /* Asked to never swap */
+   if(uSwapRequirement == QCBOR_ENDIAN_NO_SWAP) {
+      return DO_NOT_SWAP;
+   }
+
+   /* The following use cases require the input endianness to be known */
+   if(uEndianness == QCBOR_UNKNOWN_ENDIAN) {
+      return QCBOR_ERR_INPUT_ENDIANNESS_UNKNOWN;
+   }
+
+   QCBOREndianRequirement uOutput = uSwapRequirement;
+   if(uOutput == QCBOR_ENDIAN_MATCH_ENDIANNESS) {
+#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
+      uOutput = QCBOR_ENDIAN_BIG_ENDIAN;
+#else
+      uOutput = QCBOR_ENDIAN_LITTLE_ENDIAN;
+#endif
+   }
+
+   if((QCBOREndianness)uOutput != uEndianness) {
+      return PERFORM_SWAP;
+   } else {
+      return DO_NOT_SWAP;
+   }
+}
+
+
+void QCBORDecode_GetUint32ArrayCopy(QCBORDecodeContext    *pMe,
+                                    uint8_t                uTagRequirement,
+                                    QCBOREndianRequirement uSwapRequirement,
+                                    size_t                 uBufferSize,
+                                    uint32_t              *puUIntsBuffer,
+                                    size_t                *puReturnedSize)
+{
+   size_t           uReceivedArraySize;
+   uint32_t        *puReceivedArray;
+   QCBOREndianness  uEndianness;
+
+   QCBORDecode_GetUint32Array(pMe,
+                              uTagRequirement,
+                             &puReceivedArray,
+                             &uReceivedArraySize,
+                             &uEndianness);
+   if(pMe->uLastError) {
+      return;
+   }
+
+
+   if(uBufferSize < uReceivedArraySize) {
+      /* Given buffer is too small */
+      pMe->uLastError = QCBOR_ERR_BUFFER_TOO_SMALL;
+      return;
+   }
+
+   memcpy(puUIntsBuffer, puReceivedArray, uReceivedArraySize * sizeof(uint32_t));
+
+   int nSwapRequest = ShallWeSwap(uSwapRequirement, uEndianness);
+
+   if(nSwapRequest > 0) {
+      /* Error figuring out whether to swap or not. */
+      pMe->uLastError = (uint8_t)nSwapRequest;
+      return;
+   }
+
+   if(nSwapRequest == PERFORM_SWAP) {
+      for(size_t i = 0; i < uReceivedArraySize; i++) {
+         const uint32_t uArrayElement = USEFUL_SWAP32(puUIntsBuffer[i]);
+         puUIntsBuffer[i] = uArrayElement;
+      }
+   }
 }
 
 
@@ -5966,7 +6077,15 @@
 
    *pSize = item.val.string.len / 4;
 
-   // TODO: must swap all the ints
+#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
+   /* Must swap all the unsigned integers */
+   uint32_t *pUIntStart = item.val.string.ptr;
+   uint32_t *pUIntEnd   = pUIntStart + *pSize;
+   for(uint32_t *pUInt = pUIntStart; pUInt < pUIntEnd; pUInt++) {
+      const uint32_t u = USEFUL_SWAP32(*pUInt);
+      *pUInt = u;
+   }
+#endif
 
    pInts = (uint32_t *) &(item.val.string.ptr);
 
@@ -6043,18 +6162,14 @@
 }
 
 
-
-
-void QCBORDecode_GetHomogenousArray(QCBORDecodeContext *pMe,
+void ProcessHomogenousArray(QCBORDecodeContext *pMe,
+                            const QCBORItem *pItem,
                                     uint8_t             uTagRequirement,
                                     uint8_t             uType,
                                     size_t              nInArrayCount,
                                     union QCBORHomogenousArray array,
                                     size_t             *pnOutArrayCount)
 {
-   QCBORItem item;
-   QCBORDecode_GetNext(pMe, &item);
-
    const uint64_t puAllowedTags[] = {CBOR_TAG_HOMOGENEOUS_ARRAY, CBOR_TAG_INVALID64};
 
    const uint8_t puAllowedContents[] = {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE};
@@ -6064,13 +6179,15 @@
                                             uTagRequirement,
                                             puAllowedTags,
                                             puAllowedContents,
-                                            &item);
+                                            pItem);
    if(uError) {
       pMe->uLastError = (uint8_t)uError;
       goto Done;
    }
 
-   const uint8_t uIntNestLevel = item.uNextNestLevel;
+   const uint8_t uIntNestLevel = pItem->uNextNestLevel;
+   QCBORItem item;
+
 
    size_t uIntCount = 0;
    do {
@@ -6125,3 +6242,80 @@
    return;
 }
 
+
+void QCBORDecode_GetHomogenousArray(QCBORDecodeContext *pMe,
+                                    uint8_t             uTagRequirement,
+                                    uint8_t             uType,
+                                    size_t              nInArrayCount,
+                                    union QCBORHomogenousArray array,
+                                    size_t             *pnOutArrayCount)
+{
+   QCBORItem item;
+   QCBORDecode_VGetNext(pMe, &item);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   ProcessHomogenousArray(pMe,
+                          &item,
+                          uTagRequirement,
+                          uType,
+                          nInArrayCount,
+                          array,
+                          pnOutArrayCount);
+}
+
+void QCBORDecode_GetHomogenousArrayInMapN(QCBORDecodeContext *pMe,
+                                          int64_t             nLabel,
+                                          uint8_t             uTagRequirement,
+                                          uint8_t             uType,
+                                          size_t              nInArrayCount,
+                                          union QCBORHomogenousArray array,
+                                          size_t             *pnOutArrayCount)
+{
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   ProcessHomogenousArray(pMe,
+                          &Item,
+                          uTagRequirement,
+                          uType,
+                          nInArrayCount,
+                          array,
+                          pnOutArrayCount);
+}
+
+
+void QCBORDecode_GetHomogenousArrayInMapSZ(QCBORDecodeContext *pMe,
+                                           const char          *szLabel,
+                                           uint8_t             uTagRequirement,
+                                           uint8_t             uType,
+                                           size_t              nInArrayCount,
+                                           union QCBORHomogenousArray array,
+                                           size_t             *pnOutArrayCount)
+{
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   ProcessHomogenousArray(pMe,
+                          &Item,
+                          uTagRequirement,
+                          uType,
+                          nInArrayCount,
+                          array,
+                          pnOutArrayCount);
+}