homogenous arrays starting to work
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index b3301c7..223cc7f 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -5919,3 +5919,209 @@
 }
 
 #endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
+
+
+
+/* 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,
+                                uint8_t             uTagRequirement,
+                                uint32_t           *pInts,
+                                size_t             *pSize)
+{
+   QCBORItem item;
+   QCBORDecode_VGetNext(pMe, &item);
+
+   if(item.uDataType != QCBOR_TYPE_BYTE_STRING ||
+      !QCBORDecode_IsTagged(pMe, &item, 99)) { // TODO: correct tag number
+      pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+      return;
+   }
+
+   if(item.val.string.len % 4 != 0) {
+      pMe->uLastError = 99; // TODO: figure out error
+      return;
+   }
+
+   *pSize = item.val.string.len / 4;
+
+   /* may have to swap if endianness doesn't match */
+   pInts = (uint32_t *) &(item.val.string.ptr);
+}
+
+
+void QCBORDecode_GetUint32ArrayLE(QCBORDecodeContext *pMe,
+                                uint8_t             uTagRequirement,
+                                uint32_t           *pInts,
+                                size_t             *pSize)
+{
+   QCBORItem item;
+   QCBORDecode_GetNext(pMe, &item);
+
+   // TODO: check type
+   // TODO: check size is a multiple of 4
+
+   *pSize = item.val.string.len / 4;
+
+   // TODO: must swap all the ints
+
+   pInts = (uint32_t *) &(item.val.string.ptr);
+
+
+}
+
+
+
+
+
+static QCBORError
+CheckTagList(uint64_t uTag, const uint64_t *puTagList)
+{
+   for(size_t i = 0; puTagList[i] != CBOR_TAG_INVALID64; i++) {
+      if(uTag == puTagList[i]) {
+         return QCBOR_SUCCESS;
+      }
+   }
+   return QCBOR_ERR_UNEXPECTED_TYPE;
+}
+
+
+QCBORError CheckTagRequirement2(QCBORDecodeContext *pMe,
+                                uint8_t uTagRequirement,
+                                const uint64_t *puTagNumbers,
+                                const uint8_t *puContentTypes,
+                                const QCBORItem *pItem)
+{
+   /* In this checker, the tags of interest are never mapped
+    to QCBOR_TYPEs. */
+
+   /* Check the content type first. If that is wrong, then this fails
+    no matter what. */
+   QCBORError uReturn = CheckTypeList(pItem->uDataType, puContentTypes);
+   if(uReturn != QCBOR_SUCCESS) {
+      return uReturn;
+   }
+
+   uReturn = CheckTagList(QCBORDecode_GetNthTag(pMe, pItem, 0), puTagNumbers);
+
+   const int nTagReq = uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
+   switch(nTagReq) {
+      case QCBOR_TAG_REQUIREMENT_TAG:
+         if(uReturn != QCBOR_SUCCESS) {
+            goto Done;
+         }
+         break;
+
+      case QCBOR_TAG_REQUIREMENT_NOT_A_TAG:
+         if(uReturn == QCBOR_SUCCESS) {
+            uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
+            goto Done;
+         }
+         break;
+
+      case QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG:
+         break;
+   }
+
+   if(!(uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS)) {
+      /* Additional tags are prohibited. */
+      int nAdditionalIndex = 0;
+      if(uReturn == QCBOR_SUCCESS) {
+         nAdditionalIndex++;
+      }
+      if(pItem->uTags[0] != CBOR_TAG_INVALID16) {
+         uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
+      }
+   }
+   uReturn = QCBOR_SUCCESS;
+
+Done:
+   return uReturn;
+}
+
+
+
+
+void QCBORDecode_GetHomogenousArray(QCBORDecodeContext *pMe,
+                                    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};
+
+
+   QCBORError uError = CheckTagRequirement2(pMe,
+                                            uTagRequirement,
+                                            puAllowedTags,
+                                            puAllowedContents,
+                                            &item);
+   if(uError) {
+      pMe->uLastError = (uint8_t)uError;
+      goto Done;
+   }
+
+   const uint8_t uIntNestLevel = item.uNextNestLevel;
+
+   size_t uIntCount = 0;
+   do {
+      QCBORDecode_GetNext(pMe, &item);
+      if(item.uDataType != uType) {
+         pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+         goto Done;
+      }
+
+      /* A good compiler should not generate much code here since
+       since it is just a copy of either 8 or 16 bytes for the
+       cases. */
+      switch (uType) {
+         case QCBOR_TYPE_INT64:
+            if(array.pnInt64s) {
+               array.pnInt64s[uIntCount] = item.val.int64;
+            }
+            break;
+
+         case QCBOR_TYPE_UINT64:
+            if(array.puUInt64s) {
+               array.puUInt64s[uIntCount] = item.val.int64;
+            }
+            break;
+
+         case QCBOR_TYPE_DOUBLE:
+              if(array.pDoubles) {
+                 array.pDoubles[uIntCount] = item.val.dfnum;
+              }
+              break;
+
+         case QCBOR_TYPE_TEXT_STRING:
+         case QCBOR_TYPE_BYTE_STRING:
+              if(array.pStrings) {
+                 array.pStrings[uIntCount] = item.val.string;
+              }
+              break;
+      }
+      uIntCount++;
+
+      if(uIntCount >= nInArrayCount) {
+         pMe->uLastError = QCBOR_ERR_BUFFER_TOO_SMALL;
+         goto Done;
+      }
+
+   } while(item.uNextNestLevel >= uIntNestLevel);
+
+
+   *pnOutArrayCount = uIntCount;
+
+Done:
+   return;
+}
+
diff --git a/src/qcbor_encode.c b/src/qcbor_encode.c
index 59c420b..55d51f6 100644
--- a/src/qcbor_encode.c
+++ b/src/qcbor_encode.c
@@ -950,3 +950,195 @@
 
    return nReturn;
 }
+
+
+
+static inline void UsefulOutBuf_InsertUint32LE(UsefulOutBuf *pMe,
+                                             uint32_t uInteger32,
+                                             size_t uPos)
+{
+   /* See UsefulOutBuf_InsertUint64() for comments on this code */
+
+    /* htonl is not used (but it is used for outputting BE)
+
+   htonl will swap if CPU is little endian and do nothing if it is big endian
+
+     The opposite is needed.
+
+     Could use htonl and then always swap the result, but
+     that doesn't seem any better than the default
+     shift and swap that always works.
+
+
+     */
+
+   const void *pBytes;
+
+#if defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
+   pBytes = &uInteger32;
+
+#elif defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
+   uint32_t uTmp = __builtin_bswap32(uInteger32);
+
+   pBytes = &uTmp;
+
+#else
+   uint8_t aTmp[4];
+
+   aTmp[0] = (uint8_t)((uInteger32 & 0xff) >> 24);
+   aTmp[1] = (uint8_t)((uInteger32 & 0xff00) >> 16);
+   aTmp[2] = (uint8_t)((uInteger32 & 0xff0000) >> 8);
+   aTmp[3] = (uint8_t)(uInteger32 & 0xff000000);
+
+   pBytes = aTmp;
+#endif
+
+   UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
+}
+
+void
+QCBOREncode_AddUint32ArrayLittleEndian(QCBOREncodeContext *pMe,
+                                         const uint32_t      array[],
+                                         size_t              uArrayLen)
+{
+   QCBOREncode_AddTag(pMe, 84); // TODO: the correct tag
+
+   const size_t uNumBytes = uArrayLen * sizeof(uint32_t);
+
+   AppendCBORHead(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, uNumBytes, 0);
+
+   for(size_t n = 0; n < uArrayLen; n++) {
+      UsefulOutBuf_InsertUint32LE(&(pMe->OutBuf), array[n], 99); // TODO: correct position
+   }
+}
+
+void
+QCBOREncode_AddUint32ArrayBigEndian(QCBOREncodeContext *pMe,
+                                         const uint32_t      array[],
+                                         size_t              uArrayLen)
+{
+   QCBOREncode_AddTag(pMe, 84); // TODO: the correct tag
+
+   const size_t uNumBytes = uArrayLen * sizeof(uint32_t);
+
+   AppendCBORHead(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, uNumBytes, 0);
+
+   for(size_t n = 0; n < uArrayLen; n++) {
+      UsefulOutBuf_AppendUint32(&(pMe->OutBuf), array[n]);
+   }
+}
+
+
+// Note that this will produce an array of major type 0 and 1,
+// but that is what is necessary to have an array of positive
+// and negative integers. The types allowed for a homogeneous
+// array are caller-defined, not strictly by CBOR major type
+// or such, so this is just fine.
+void
+QCBOREncode_AddArrayOfInts(QCBOREncodeContext *pMe,
+                           uint8_t             uTagRequirement,
+                           const int64_t      *puInts,
+                           size_t              uNumInts)
+{
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_HOMOGENEOUS_ARRAY);
+   }
+   QCBOREncode_OpenArray(pMe);
+
+   for(size_t i = 0; i < uNumInts; i++) {
+      QCBOREncode_AddInt64(pMe, puInts[i]);
+   }
+   QCBOREncode_CloseArray(pMe);
+}
+
+
+void
+QCBOREncode_AddArrayOfUInts(QCBOREncodeContext *pMe,
+                            uint8_t             uTagRequirement,
+                            const uint64_t     *puInts,
+                            size_t              uNumInts)
+{
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_HOMOGENEOUS_ARRAY);
+   }
+   QCBOREncode_OpenArray(pMe);
+
+   for(size_t i = 0; i < uNumInts; i++) {
+      QCBOREncode_AddUInt64(pMe, puInts[i]);
+   }
+   QCBOREncode_CloseArray(pMe);
+}
+
+
+void
+QCBOREncode_AddArrayOfDoubles(QCBOREncodeContext *pMe,
+                              uint8_t             uTagRequirement,
+                              const double       *pdDoubles,
+                              size_t              uNumDoubles)
+{
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_HOMOGENEOUS_ARRAY);
+   }
+   QCBOREncode_OpenArray(pMe);
+
+   for(size_t i = 0; i < uNumDoubles; i++) {
+      QCBOREncode_AddDouble(pMe, pdDoubles[i]);
+   }
+   QCBOREncode_CloseArray(pMe);
+}
+
+
+void
+QCBOREncode_AddArrayOfByteStrings(QCBOREncodeContext *pMe,
+                                  uint8_t             uTagRequirement,
+                                  const UsefulBufC   *pStrings,
+                                  size_t              uNumStrings)
+{
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_HOMOGENEOUS_ARRAY);
+   }
+   QCBOREncode_OpenArray(pMe);
+
+   for(size_t i = 0; i < uNumStrings; i++) {
+      QCBOREncode_AddBytes(pMe, pStrings[i]);
+   }
+   QCBOREncode_CloseArray(pMe);
+}
+
+void
+QCBOREncode_AddArrayOfTextStrings(QCBOREncodeContext *pMe,
+                                  uint8_t             uTagRequirement,
+                                  const UsefulBufC   *pStrings,
+                                  size_t              uNumStrings)
+{
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_HOMOGENEOUS_ARRAY);
+   }
+   QCBOREncode_OpenArray(pMe);
+
+   for(size_t i = 0; i < uNumStrings; i++) {
+      QCBOREncode_AddText(pMe, pStrings[i]);
+   }
+   QCBOREncode_CloseArray(pMe);
+}
+
+
+void
+QCBOREncode_AddArrayOSZStrings(QCBOREncodeContext *pMe,
+                               uint8_t             uTagRequirement,
+                               const char        **pStrings,
+                               size_t              uNumStrings)
+{
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_HOMOGENEOUS_ARRAY);
+   }
+   QCBOREncode_OpenArray(pMe);
+
+   for(size_t i = 0; i < uNumStrings; i++) {
+      QCBOREncode_AddSZString(pMe, pStrings[i]);
+   }
+   QCBOREncode_CloseArray(pMe);
+}
+
+
+