Lots of progress on indefinite lengths; refactor decoder to get of weird semi-recursion
diff --git a/src/UsefulBuf.c b/src/UsefulBuf.c
index 323e173..3aa6406 100644
--- a/src/UsefulBuf.c
+++ b/src/UsefulBuf.c
@@ -93,6 +93,18 @@
    return((UsefulBufC){Dest.ptr, Src.len});
 }
 
+
+UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
+{
+    if(Src.len > Dest.len - uOffset) {
+        return NULLUsefulBufC;
+    }
+    
+    memcpy(Dest.ptr + uOffset, Src.ptr, Src.len);
+    
+    return((UsefulBufC){Dest.ptr, Src.len});
+}
+
 /*
    Public function -- see UsefulBuf.h
  */
@@ -170,6 +182,7 @@
     
     // The following check fails on ThreadX
 #if 0
+    // TODO: fix this for new way of doing storage
     // Sanity check on the pointer and size to be sure we are not
     // passed a buffer that goes off the end of the address space.
     // Given this test, we know that all unsigned lengths less than
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 7e441cd..eccd469 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -93,15 +93,30 @@
    return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]);
 }
 
+inline static int DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
+{
+   if(!DecodeNesting_IsNested(pNesting)) {
+      return 0;
+   }
+   
+   return pNesting->pCurrent->uCount == UINT16_MAX;
+}
+
 inline static int DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
 {
-   if(!DecodeNesting_IsNested(pNesting))
+   if(!DecodeNesting_IsNested(pNesting)) {
       return 0;
+   }
    
    return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
 }
 
-inline static void DecodeNesting_Decrement(QCBORDecodeNesting *pNesting, uint8_t uDataType)
+inline static void DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
+{
+   pNesting->pCurrent--;
+}
+
+inline static void DecodeNesting_Decrement(QCBORDecodeNesting *pNesting)
 {
    if(!DecodeNesting_IsNested(pNesting)) {
       return;  // at top level where there is no tracking
@@ -109,7 +124,7 @@
    
    // Decrement
    pNesting->pCurrent->uCount--;
-   
+
    // Pop up nesting levels if the counts at the levels is zero
    while(0 == pNesting->pCurrent->uCount && DecodeNesting_IsNested(pNesting)) {
       pNesting->pCurrent--;
@@ -167,6 +182,15 @@
 
 
 /*
+ Public function, see header file
+ */
+void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx, const QCBORStringAllocator *pAllocator)
+{
+    pCtx->pStringAllocator = (void *)pAllocator;
+}
+
+
+/*
  This decodes the fundamental part of a CBOR data item, the type and number
  
  This is the Counterpart to InsertEncodedTypeAndNumber().
@@ -175,6 +199,11 @@
  also results in the conversion for floats in addition to that for
  lengths, tags and integer values.
  
+ This returns:
+   pnMajorType -- the major type for the item
+   puNumber -- the "number" which is used a the value for integers, tags and floats and length for strings and arrays
+   puAdditionalInfo -- Pass this along to know what kind of float or if length is indefinite
+ 
  */
 inline static int DecodeTypeAndNumber(UsefulInputBuf *pUInBuf, int *pnMajorType, uint64_t *puNumber, uint8_t *puAdditionalInfo)
 {
@@ -188,8 +217,7 @@
    const uint8_t uAdditionalInfo = InitialByte & 0x1f;
    
    // Get the integer that follows the major type. Do not know if this is a length, value, float or tag at this point
-   // Also convert from network byte order. Call ntohxx on simple variables in case they are macros that
-   // reference their argument multiple times.
+   // Also convert from network byte order.
    uint64_t uTmpValue;
    switch(uAdditionalInfo) {
          
@@ -212,11 +240,14 @@
       case ADDINFO_RESERVED1: // reserved by CBOR spec
       case ADDINFO_RESERVED2: // reserved by CBOR spec
       case ADDINFO_RESERVED3: // reserved by CBOR spec
-      case LEN_IS_INDEFINITE: // indefinite types not supported (yet)
          nReturn = QCBOR_ERR_UNSUPPORTED;
          goto Done;
+
+      case LEN_IS_INDEFINITE:
+         // Fall through to see what happens: TODO: check this.
          
       default:
+         // This is when the "number" is in the additional info
          uTmpValue = uAdditionalInfo;
          break;
    }
@@ -300,6 +331,10 @@
 #error QCBOR_TYPE_UNDEF macro value wrong
 #endif
 
+#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
+#error QCBOR_TYPE_BREAK macro value wrong
+#endif
+
 #if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
 #error QCBOR_TYPE_DOUBLE macro value wrong
 #endif
@@ -324,7 +359,6 @@
       case ADDINFO_RESERVED1:  // 28
       case ADDINFO_RESERVED2:  // 29
       case ADDINFO_RESERVED3:  // 30
-      case CBOR_SIMPLE_BREAK:  // 31
          nReturn = QCBOR_ERR_UNSUPPORTED;
          break;
            
@@ -343,6 +377,7 @@
       case CBOR_SIMPLEV_TRUE:  // 21
       case CBOR_SIMPLEV_NULL:  // 22
       case CBOR_SIMPLEV_UNDEF: // 23
+      case CBOR_SIMPLE_BREAK:  // 31
          break; // nothing to do
          
       case CBOR_SIMPLEV_ONEBYTE: // 24
@@ -370,7 +405,7 @@
 /*
  Decode text and byte strings
  */
-inline static int DecodeBytes(int nMajorType, uint64_t uNumber, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
+inline static int DecodeBytesOld(int nMajorType, uint64_t uNumber, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
 {
    const void *pBytes = UsefulInputBuf_GetBytes(pUInBuf, uNumber);
    
@@ -385,6 +420,30 @@
    return nReturn;
 }
 
+inline static int DecodeBytes(QCBORStringAllocator *pAlloc, int nMajorType, uint64_t uNumber, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
+{
+    UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uNumber);
+   
+   int nReturn = QCBOR_ERR_HIT_END;
+   
+   if(!UsefulBuf_IsNULLC(Bytes)) {
+      if(pAlloc) {
+         UsefulBuf NewMem = pAlloc->fAllocate(pAlloc->pAllocaterContext, NULL, uNumber);
+         if(UsefulBuf_IsNULL(NewMem)) {
+            pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
+         } else {
+            // TODO: failure
+         }
+      } else {
+         pDecodedItem->val.string = Bytes;
+      }
+      pDecodedItem->uDataType  = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
+      nReturn = QCBOR_SUCCESS;
+   }
+   
+   return nReturn;
+}
+
 
 /*
  Mostly just assign the right data type for the date string.
@@ -453,21 +512,203 @@
 }
 
 
+
+
+// Make sure the constants align as this is assumed by the GetAnItem() implementation
+#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
+#error QCBOR_TYPE_ARRAY value not lined up with major type
+#endif
+#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
+#error QCBOR_TYPE_MAP value not lined up with major type
+#endif
+
 /*
- Decode the optional tagging that preceeds the real data value. There could be lots of them.
+ This gets a single data item and decodes it including preceding optional tagging. This does not
+ deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
+ maps are handled at the next level up in GetNext().
+ 
+ Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
+    a few forms of invalid encoded CBOR
  */
-static int GetAnItem(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, int bCalledFromDecodeOptional);
+
+static int GetNext_Item(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, QCBORStringAllocator *pAlloc)
+{
+   int nReturn;
+   
+   // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
+   // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
+   int      uMajorType;
+   uint64_t uNumber;
+   uint8_t  uAdditionalInfo;
+   
+   nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
+   
+   // Error out here if we got into trouble on the type and number.
+   // The code after this will not work if the type and number is not good.
+   if(nReturn)
+      goto Done;
+   
+   pDecodedItem->uTagBits = 0;
+   pDecodedItem->uTag     = 0;
+   pDecodedItem->uAllocated = 0;
+   
+   // At this point the major type and the value are valid. We've got the type and the number that
+   // starts every CBOR data item.
+   switch (uMajorType) {
+      case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
+      case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
+         nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
+         break;
+         
+      case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
+      case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
+         if(uAdditionalInfo == LEN_IS_INDEFINITE) {
+            pDecodedItem->uDataType  = (uMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
+            pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX}; // TODO: SIZE_MAX this is OK, right?
+         } else {
+            nReturn = DecodeBytes(pAlloc, uMajorType, uNumber, pUInBuf, pDecodedItem);
+         }
+         break;
+         
+      case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
+      case CBOR_MAJOR_TYPE_MAP:   // Major type 5
+         // Record the number of items in the array or map
+         if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
+            nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
+            goto Done;
+         }
+         if(uAdditionalInfo == LEN_IS_INDEFINITE) {
+            pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length; TODO: a better way?
+         } else {
+            pDecodedItem->val.uCount = (uint16_t)uNumber; // type conversion OK because of check above
+         }
+         pDecodedItem->uDataType  = uMajorType; // C preproc #if above makes sure constants align
+         break;
+         
+      case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
+         pDecodedItem->uTag      = uNumber;
+         pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
+         break;
+         
+      case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
+         nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
+         break;
+         
+      default: // Should never happen because DecodeTypeAndNumber() should never return > 7
+         nReturn = QCBOR_ERR_UNSUPPORTED;
+         break;
+   }
+   
+Done:
+   return nReturn;
+}
+
+
+
+/*
+ This layer deals with indefinite length strings
+ 
+ */
+static int GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
+{
+   int nReturn;
+   QCBORStringAllocator *pAlloc =  (QCBORStringAllocator *)me->pStringAllocator;
+   
+   nReturn = GetNext_Item(&(me->InBuf), pDecodedItem, me->bStringAllocateAll ? pAlloc: NULL);
+   if(nReturn) {
+      goto Done;
+   }
+   
+   // To reduce code size by removing support for indefinite length strings, the
+   // code in this function from here down can be eliminated. Run tests to be sure
+   // all is OK if you remove this.
+   if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
+      nReturn = QCBOR_ERR_BAD_BREAK;
+      goto Done;
+   }
+   
+   if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING && pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
+      goto Done; // no need to do any work here on non-string types
+   }
+   
+   if(pDecodedItem->val.string.len != SIZE_MAX) { // TODO: is this right? Is there a better way to mark this?
+      goto Done; // length is not indefinite, so no work to do
+   }
+   
+   if(pAlloc == NULL) {
+      // can't do indefinite length strings without an allocator
+      nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
+      goto Done;
+   }
+   
+   // There is an indefinite length string to work on...
+   const uint8_t uStringType = pDecodedItem->uDataType;
+   
+   // Loop getting segments of indefinite string
+   UsefulBufC FullString = NULLUsefulBufC;
+   for(;;) {
+      // Get item for next segment
+      QCBORItem Item;
+      nReturn = GetNext_Item(&(me->InBuf), &Item, NULL); // Never alloc segments of indefinite length strings
+      if(nReturn) {
+         // Error getting the next segment
+         break;
+      }
+      
+      // See if it is marker at end of indefinite length string
+      if(Item.uDataType == QCBOR_TYPE_BREAK) {
+         // SUCCESS!!!
+         pDecodedItem->val.string = FullString;
+         pDecodedItem->uAllocated = 1;
+         break;
+      }
+      
+      // Match data type of segment to type at beginning
+      if(Item.uDataType != uStringType) {
+         nReturn = QCBOR_ERR_INDEFINITE_STRING_SEG;
+         break;
+      }
+      
+      // Expand the buffer so it can fit
+      UsefulBuf NewMem = (*pAlloc->fAllocate)(pAlloc->pAllocaterContext, (void *)FullString.ptr, FullString.len + Item.val.string.len);
+      if(UsefulBuf_IsNULL(NewMem)) {
+         nReturn = QCBOR_ERR_STRING_ALLOC;
+         break;
+      }
+      
+      // Copy data to the end of it.
+      FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, Item.val.string);
+   }
+   
+Done:
+   if(nReturn && FullString.ptr) {
+      // Getting item failed, clean up the allocated memory
+      (pAlloc->fFree)(pAlloc->pAllocaterContext, (void *)FullString.ptr); // TODO unconst construct
+   }
+   
+   return nReturn;
+}
+
 
 /*
  Returns an error if there was something wrong with the optional item or it couldn't
  be handled.
  */
-static int DecodeOptional(UsefulInputBuf *pUInBuf, uint64_t uInputTag, QCBORItem *pDecodedItem)
+static int GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
 {
-   int      nReturn = QCBOR_SUCCESS;
+   int nReturn;
+   
+   nReturn = GetNext_FullItem(me, pDecodedItem);
+   if(nReturn) {
+      goto Done;
+   }
+   
+   if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
+      goto Done;
+   }
    
    uint64_t uTagFlags = 0; // accumulate the tags in the form of flags
-   uint64_t uTagToProcess = uInputTag; // First process tag passed in
+   uint64_t uTagToProcess = pDecodedItem->uTag; // First process tag passed in
    
    QCBORItem Item;
    
@@ -478,11 +719,11 @@
          uTagFlags |= QCBOR_TAGFLAG_CBOR_MAGIC;
       }
       /* This code ignores the all but the first tag of value
-         greater than 63. Ignoring tags that are not understoof
-         is allowed by the standard. Multiple tags are 
-         presumably rare. */
+       greater than 63. Ignoring tags that are not understoof
+       is allowed by the standard. Multiple tags are
+       presumably rare. */
       
-      nReturn = GetAnItem(pUInBuf, &Item, 1);
+      nReturn = GetNext_FullItem(me, &Item);
       if(nReturn) {
          // Bail out of the whole item fetch on any sort of error here
          goto Done;
@@ -494,22 +735,22 @@
       
       uTagToProcess = Item.uTag;
    } while (1);
-
+   
    
    /*
-     CBOR allows multiple tags on a data item. It also defines
-     a number of standard tag values, most of which are 
-     less than 64.  This code can deal with multiple tag
-     values that are less than 64 and the last tag of multiple
-     if the value is more than 64. Or said another way
-     if there is one tag with a value >64 this code works. 
+    CBOR allows multiple tags on a data item. It also defines
+    a number of standard tag values, most of which are
+    less than 64.  This code can deal with multiple tag
+    values that are less than 64 and the last tag of multiple
+    if the value is more than 64. Or said another way
+    if there is one tag with a value >64 this code works.
     
-     The assumption is that multiple tag values > 64 are rare.
+    The assumption is that multiple tag values > 64 are rare.
     
-     At this point in this code. uTagFlags has all the flags
-     < 64 and uTagToProcess has the last tag.
+    At this point in this code. uTagFlags has all the flags
+    < 64 and uTagToProcess has the last tag.
     
-     Does this deal with multiple tags on an item we process?
+    Does this deal with multiple tags on an item we process?
     */
    
    Item.uTagBits = uTagFlags;
@@ -538,93 +779,6 @@
          // Encountering some mixed up CBOR like something that
          // is tagged as both a string and integer date.
          nReturn = QCBOR_ERR_BAD_OPT_TAG ;
-      }
-
-Done:
-   return nReturn;
-}
-
-
-
-// Make sure the constants align as this is assumed by the GetAnItem() implementation
-#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
-#error QCBOR_TYPE_ARRAY value not lined up with major type
-#endif
-#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
-#error QCBOR_TYPE_MAP value not lined up with major type
-#endif
-
-/*
- This gets a single data item and decodes it including preceding optional tagging. This does not
- deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
- maps are handled at the next level up in GetNext().
- 
- Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
-    a few forms of invalid encoded CBOR
- */
-
-static int GetAnItem(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, int bCalledFromDecodeOptional)
-{
-   int nReturn;
-   
-   // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
-   // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
-   int      uMajorType;
-   uint64_t uNumber;
-   uint8_t  uAdditionalInfo;
-   
-   nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
-   
-   // Error out here if we got into trouble on the type and number.
-   // The code after this will not work if the type and number is not good.
-   if(nReturn)
-      goto Done;
-   
-   pDecodedItem->uTagBits = 0;
-   pDecodedItem->uTag     = 0;
-   
-   // At this point the major type and the value are valid. We've got the type and the number that
-   // starts every CBOR data item.
-   switch (uMajorType) {
-      case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
-      case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
-         nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
-         break;
-         
-      case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
-      case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
-         nReturn = DecodeBytes(uMajorType, uNumber, pUInBuf, pDecodedItem);
-         break;
-         
-      case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
-      case CBOR_MAJOR_TYPE_MAP:   // Major type 5
-         // Record the number of items in the array or map
-         if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
-            nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
-            goto Done;
-         }
-         pDecodedItem->val.uCount = uNumber; // type conversion OK because of check above
-         pDecodedItem->uDataType  = uMajorType; // C preproc #if above makes sure constants align
-         break;
-         
-      case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
-         pDecodedItem->uTag      = uNumber;
-         pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
-         if(!bCalledFromDecodeOptional) {
-            // There can be a more than one optional tag in front of an actual data item
-            // they are all handled by looping in DecodeOptional which calls back here
-            // this test avoids infinite recursion.
-            nReturn = DecodeOptional(pUInBuf, uNumber, pDecodedItem);
-         }
-         break;
-         
-      case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
-         nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
-         break;
-         
-      default: // Should never happen because DecodeTypeAndNumber() should never return > 7
-         nReturn = QCBOR_ERR_UNSUPPORTED;
-         break;
    }
    
 Done:
@@ -633,18 +787,11 @@
 
 
 /*
- Public function, see header qcbor.h file
+ This layer takes care of map entries. It combines the label and data items into one item.
  */
-int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
+static inline int GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
 {
-   int nReturn;
-   
-   if(!UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
-      nReturn = QCBOR_ERR_HIT_END;
-      goto Done;
-   }
-   
-   nReturn = GetAnItem(&(me->InBuf), pDecodedItem, 0);
+   int nReturn = GetNext_TaggedItem(me, pDecodedItem);
    if(nReturn)
       goto Done;
    
@@ -654,7 +801,7 @@
       
       // Get the next item which will be the real data; Item will be the label
       QCBORItem LabelItem = *pDecodedItem;
-      nReturn = GetAnItem(&(me->InBuf), pDecodedItem, 0);
+      nReturn = GetNext_TaggedItem(me, pDecodedItem); // TODO: test indefinite length string labels
       if(nReturn)
          goto Done;
       
@@ -666,7 +813,7 @@
          // It's not a string and we only want strings, probably for easy translation to JSON
          nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
          goto Done;
-     } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
+      } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
          pDecodedItem->label.int64 = LabelItem.val.int64;
          pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
       } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
@@ -683,6 +830,58 @@
       }
    }
    
+Done:
+   return nReturn;
+}
+
+
+/*
+ Public function, see header qcbor.h file
+ */
+/*
+ Decoding items is done in layers:
+ - This top layer takes care of tracking for decsending into and
+   ascending out of maps and arrays  GetNext()
+ - The next layer takes care of map entries that are made up
+   of a label and a data item. They are returned as one. GetNextMap() GetNext_MapEntry()
+ - The next layer takes care of tagging and tagged types  GetNext_TaggedItem()
+ - The next layer takes care of indefinite length strings GetFullItem()  GetNext_FullItem()
+ - The next layer does the main decoding of the non-compound GetAnItem()  GetNext_Item()
+   items, all the different types of them
+ 
+ */
+int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
+{
+   int nReturn;
+   
+   if(!UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
+      nReturn = QCBOR_ERR_HIT_END;
+      goto Done;
+   }
+   
+   nReturn = GetNext_MapEntry(me, pDecodedItem);
+   if(nReturn) {
+      goto Done;
+   }
+   
+   // Handle any breaks that are closing out arrays or maps
+   while(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
+      if(!DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
+         nReturn = QCBOR_ERR_BAD_BREAK;
+         goto Done;
+      }
+      
+      // Close out and ascend
+      DecodeNesting_Ascend(&(me->nesting));
+      
+      nReturn = GetNext_MapEntry(me, pDecodedItem);
+      if(nReturn) {
+         goto Done;
+      }
+   }
+   
+   // Now have the next item that is not a break. The one that is going to be returned
+
    // Record the nesting level for this data item
    pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
    
@@ -691,8 +890,11 @@
       nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem->uDataType, pDecodedItem->val.uCount);
    } else {
       // Track number of items in maps and arrays and ascend nesting if all are consumed
-      // Note that an empty array or map is like a integer or string in effect here
-      DecodeNesting_Decrement(&(me->nesting), pDecodedItem->uDataType);
+      // Note that an empty array or map is like an integer or string in effect here
+      // No counting is done for indefinite length arrays
+      if(!DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
+         DecodeNesting_Decrement(&(me->nesting));
+      }
    }
    
 Done:
@@ -705,19 +907,59 @@
  */
 int QCBORDecode_Finish(QCBORDecodeContext *me)
 {
-   return UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) ? QCBOR_ERR_EXTRA_BYTES : QCBOR_SUCCESS;
+   int nReturn = QCBOR_SUCCESS;
+   
+   // Consume any breaks ending indefinite length arrays or maps here
+   // Definite length arrays and maps get closed off above when they
+   // the last item in them is consumed; they are not handled here.
+   while(DecodeNesting_GetLevel(&(me->nesting))) {
+      QCBORItem Item;
+      GetNext_Item(&(me->InBuf), &Item, false);
+      if(Item.uDataType != QCBOR_TYPE_BREAK) {
+         nReturn = QCBOR_ERR_EXTRA_BYTES;
+         break;
+      }
+      DecodeNesting_Ascend(&(me->nesting));
+   }
+   
+   // Call the desctructor for the string allocator if there is one
+   if(me->pStringAllocator) {
+      QCBORStringAllocator *pAllocator = (QCBORStringAllocator *)me->pStringAllocator;
+      if(pAllocator->fDestructor) {
+         (pAllocator->fDestructor)(pAllocator->pAllocaterContext);
+      }
+   }
+   
+   if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
+      nReturn = QCBOR_ERR_EXTRA_BYTES;
+   }
+   
+   return nReturn;
 }
 
 
 
+/*
+ 
+ Use the 64-bit map. 48 8-bit tags built in, 1 16 bit tag, 15 64-bit tags can be assigned as of interest
+ 
+ There is a tag map.
+ 
+ TODO: how does tinyCBOR do it?
+ 
+ 
+ 
+ 
+ 
+ */
+
+
 /* 
  
 Decoder errors handled in this file
  
  - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
- 
- - indefinite length, currently not supported QCBOR_ERR_UNSUPPORTED
- 
+  
  - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
  
  - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
@@ -738,3 +980,70 @@
  
  */
 
+
+
+typedef struct {
+   QCBORStringAllocator  StringAllocator;
+   uint8_t              *pStart;
+   uint8_t              *pEnd;
+   uint8_t              *pFree;
+} MemPool;
+
+
+/*
+ Code Reviewers: THIS FUNCTION DOES POINTER MATH
+ */
+static UsefulBuf MemPool_Alloc(void *ctx, void *pMem, size_t uNewSize)
+{
+   MemPool *me = (MemPool *)ctx;
+   void *pReturn = NULL;
+   
+   if(pMem) {
+      // Realloc case
+      // TODO: review this pointer math
+      if((uint8_t *)pMem + uNewSize <= me->pEnd && (uint8_t *)pMem > me->pStart) {
+         me->pFree = pMem + uNewSize;
+         pReturn = pMem;
+      }
+   } else {
+      // New chunk case
+      if(me->pFree + uNewSize <= me->pEnd) {
+         pReturn = me->pFree;
+         me->pFree += uNewSize;
+      }
+   }
+   
+   return (UsefulBuf){pReturn, uNewSize};
+}
+
+
+static void MemPool_Free(void *ctx, void *pOldMem)
+{
+   MemPool *me = (MemPool *)ctx;
+   me->pFree = pOldMem;
+}
+
+
+void QCBORDecode_SetMemPool(QCBORDecodeContext *me, UsefulBuf Pool, bool bAllStrings)
+{
+   if(Pool.len < sizeof(MemPool)+1) {
+      return; // Failure will happen when first string needs to be allocated
+   }
+   
+   MemPool *pMP = (MemPool *)Pool.ptr;
+   
+   pMP->StringAllocator.fAllocate   = MemPool_Alloc;
+   pMP->StringAllocator.fFree       = MemPool_Free;
+   pMP->StringAllocator.fDestructor = NULL;
+   
+   pMP->pStart = Pool.ptr + sizeof(MemPool);
+   pMP->pFree  = pMP->pStart;
+   pMP->pEnd   = Pool.ptr + Pool.len;
+   pMP->StringAllocator.pAllocaterContext = pMP;
+   
+   me->pStringAllocator = pMP;
+   me->bStringAllocateAll = bAllStrings;
+}
+
+
+
diff --git a/src/qcbor_decode_malloc.c b/src/qcbor_decode_malloc.c
new file mode 100644
index 0000000..4e405e0
--- /dev/null
+++ b/src/qcbor_decode_malloc.c
@@ -0,0 +1,65 @@
+//
+//  qcbor_decode_malloc.c
+//  QCBOR
+//
+//  Created by Laurence Lundblade on 10/1/18.
+//  Copyright © 2018 Laurence Lundblade. All rights reserved.
+//
+
+#include "qcbor.h"
+#include <stdlib.h> // for realloc and free
+
+static UsefulBuf MemMallocAlloc(void *ctx, void *pOldMem, size_t uNewSize)
+{
+    void *pNewMem = realloc(pOldMem, uNewSize);
+    return (UsefulBuf){pNewMem, uNewSize};
+}
+
+static void MemMallocFree(void *ctx, void *old)
+{
+    free(old);
+}
+
+static void MemMallocDestructor(void *ctx)
+{
+    free(ctx);
+}
+
+
+QCBORStringAllocator *QCBORDecode_MakeMallocStringAllocator()
+{
+    QCBORStringAllocator *pAllocaterContext = malloc(sizeof(QCBORStringAllocator));
+    if(pAllocaterContext) {
+        pAllocaterContext->fAllocate   = MemMallocAlloc;
+        pAllocaterContext->fFree       = MemMallocFree;
+        pAllocaterContext->fDestructor = MemMallocDestructor;
+    }
+    
+    return pAllocaterContext;
+}
+
+
+/*
+void QCBORDecodeMalloc_Init(QCBORDecodeContext *me, UsefulBufC EncodedCBOR, int8_t nDecodeMode)
+{
+    QCBORDecode_Init(me, EncodedCBOR, nDecodeMode);
+    
+    QCBORStringAllocator *pAllocaterContext = malloc(sizeof(QCBORStringAllocator));
+    
+    pAllocaterContext->fAllocate = MemMalloc;
+    pAllocaterContext->fFree = MemFree;
+    
+    QCBORDecode_SetUpAllocator(me, pAllocaterContext);
+}
+
+
+int QCBORDecodeMalloc_Finish(QCBORDecodeContext *me)
+{
+    const QCBORStringAllocator *pAllocator = QCBORDecode_GetAllocator(me);
+    
+    free((void *)pAllocator); // TODO: better way to cast away const here
+    return QCBORDecode_Finish(me);
+} */
+
+
+