new tags design is working
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index c832816..749327b 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -337,139 +337,6 @@
 
 
 
-/*
- This list of built-in tags. Only add tags here that are
- clearly established and useful. Once a tag is added here
- it can't be taken out as that would break backwards compatibility.
- There are only 48 slots available forever.
- */
-static const uint16_t spBuiltInTagMap[] = {
-   CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_SIX
-   CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_SIX
-   CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_SIX
-   CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_SIX
-   CBOR_TAG_DECIMAL_FRACTION, // See TAG_MAPPER_FIRST_SIX
-   CBOR_TAG_BIGFLOAT, // See TAG_MAPPER_FIRST_SIX
-   CBOR_TAG_COSE_ENCRYPTO,
-   CBOR_TAG_COSE_MAC0,
-   CBOR_TAG_COSE_SIGN1,
-   CBOR_TAG_ENC_AS_B64URL,
-   CBOR_TAG_ENC_AS_B64,
-   CBOR_TAG_ENC_AS_B16,
-   CBOR_TAG_CBOR,
-   CBOR_TAG_URI,
-   CBOR_TAG_B64URL,
-   CBOR_TAG_B64,
-   CBOR_TAG_REGEX,
-   CBOR_TAG_MIME,
-   CBOR_TAG_BIN_UUID,
-   CBOR_TAG_CWT,
-   CBOR_TAG_ENCRYPT,
-   CBOR_TAG_MAC,
-   CBOR_TAG_SIGN,
-   CBOR_TAG_GEO_COORD,
-   CBOR_TAG_CBOR_MAGIC
-};
-
-// This is used in a bit of cleverness in GetNext_TaggedItem() to
-// keep code size down and switch for the internal processing of
-// these types. This will break if the first six items in
-// spBuiltInTagMap don't have values 0,1,2,3,4,5. That is the
-// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3....
-#define QCBOR_TAGFLAG_DATE_STRING      (0x01LL << CBOR_TAG_DATE_STRING)
-#define QCBOR_TAGFLAG_DATE_EPOCH       (0x01LL << CBOR_TAG_DATE_EPOCH)
-#define QCBOR_TAGFLAG_POS_BIGNUM       (0x01LL << CBOR_TAG_POS_BIGNUM)
-#define QCBOR_TAGFLAG_NEG_BIGNUM       (0x01LL << CBOR_TAG_NEG_BIGNUM)
-#define QCBOR_TAGFLAG_DECIMAL_FRACTION (0x01LL << CBOR_TAG_DECIMAL_FRACTION)
-#define QCBOR_TAGFLAG_BIGFLOAT         (0x01LL << CBOR_TAG_BIGFLOAT)
-
-#define TAG_MAPPER_FIRST_SIX (QCBOR_TAGFLAG_DATE_STRING       |\
-                               QCBOR_TAGFLAG_DATE_EPOCH       |\
-                               QCBOR_TAGFLAG_POS_BIGNUM       |\
-                               QCBOR_TAGFLAG_NEG_BIGNUM       |\
-                               QCBOR_TAGFLAG_DECIMAL_FRACTION |\
-                               QCBOR_TAGFLAG_BIGFLOAT)
-
-#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING      |\
-                               QCBOR_TAGFLAG_DATE_EPOCH       |\
-                               QCBOR_TAGFLAG_POS_BIGNUM       |\
-                               QCBOR_TAGFLAG_NEG_BIGNUM)
-
-#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
-#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
-#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
-
-static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
-{
-   if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
-      /*
-       This is a cross-check to make sure the above array doesn't
-       accidentally get made too big.  In normal conditions the above
-       test should optimize out as all the values are known at compile
-       time.
-       */
-      return -1;
-   }
-
-   if(uTag > UINT16_MAX) {
-      // This tag map works only on 16-bit tags
-      return -1;
-   }
-
-   for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
-      if(spBuiltInTagMap[nTagBitIndex] == uTag) {
-         return nTagBitIndex;
-      }
-   }
-   return -1; // Indicates no match
-}
-
-static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
-{
-   for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
-      if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
-         return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
-      }
-   }
-
-   return -1; // Indicates no match
-}
-
-/*
-  Find the tag bit index for a given tag value, or error out
-
- This and the above functions could probably be optimized and made
- clearer and neater.
- */
-static QCBORError
-TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap,
-                 uint64_t uTag,
-                 uint8_t *puTagBitIndex)
-{
-   int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
-   if(nTagBitIndex >= 0) {
-      // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
-      *puTagBitIndex = (uint8_t)nTagBitIndex;
-      return QCBOR_SUCCESS;
-   }
-
-   if(pCallerConfiguredTagMap) {
-      if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
-         return QCBOR_ERR_TOO_MANY_TAGS;
-      }
-      nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
-      if(nTagBitIndex >= 0) {
-         // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
-
-         *puTagBitIndex = (uint8_t)nTagBitIndex;
-         return QCBOR_SUCCESS;
-      }
-   }
-
-   return QCBOR_ERR_BAD_OPT_TAG;
-}
-
-
 
 /*===========================================================================
    QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
@@ -530,6 +397,9 @@
    // passed it will just act as if the default normal mode of 0 was set.
    me->uDecodeMode = (uint8_t)nDecodeMode;
    DecodeNesting_Init(&(me->nesting));
+   for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
+      me->auMappedTags[i] = 0xffff;
+   }
 }
 
 
@@ -553,7 +423,7 @@
 void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
                                             const QCBORTagListIn *pTagList)
 {
-   me->pCallerConfiguredTagList = pTagList;
+   // This does nothing now. It is retained for backwards compatibility
 }
 
 
@@ -1053,21 +923,27 @@
 }
 
 
+uint64_t ConvertTag(QCBORDecodeContext *me, uint16_t uTagVal) {
+   if(uTagVal < 0xfff0) {
+      return uTagVal;
+   } else {
+      // TODO constant and error check
+      int x = uTagVal - 0xfff0;
+      return me->auMappedTags[x];
+   }
+}
+
 /*
  Gets all optional tag data items preceding a data item that is not an
  optional tag and records them as bits in the tag map.
  */
 static QCBORError
-GetNext_TaggedItem(QCBORDecodeContext *me,
-                   QCBORItem *pDecodedItem,
-                   QCBORTagListOut *pTags)
+GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
 {
    // Stack usage: int/ptr: 3 -- 24
    QCBORError nReturn;
-   uint64_t  uTagBits = 0;
-   if(pTags) {
-      pTags->uNumUsed = 0;
-   }
+
+   uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {0xffff, 0xffff, 0xffff, 0xffff};
 
    // Loop fetching items until the item fetched is not a tag
    for(;;) {
@@ -1078,36 +954,44 @@
 
       if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
          // Successful exit from loop; maybe got some tags, maybe not
-         pDecodedItem->uTagBits = uTagBits;
+         memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
          break;
       }
 
-      uint8_t uTagBitIndex;
-      // Tag was mapped, tag was not mapped, error with tag list
-      switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
-
-         case QCBOR_SUCCESS:
-            // Successfully mapped the tag
-            uTagBits |= 0x01ULL << uTagBitIndex;
+      // Is there room for the tag in the tags list?
+      size_t uTagIndex;
+      for(uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
+         if(auTags[uTagIndex] == 0xffff) {
             break;
-
-         case QCBOR_ERR_BAD_OPT_TAG:
-            // Tag is not recognized. Do nothing
-            break;
-
-         default:
-            // Error Condition
-            goto Done;
+         }
+      }
+      if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
+         return 99; // TODO error code
       }
 
-      if(pTags) {
-         // Caller wants all tags recorded in the provided buffer
-         if(pTags->uNumUsed >= pTags->uNumAllocated) {
-            nReturn = QCBOR_ERR_TOO_MANY_TAGS;
-            goto Done;
+      // Is the tag > 16 bits?
+      if(pDecodedItem->val.uTagV > 0xffff) {
+         size_t uTagMapIndex;
+         // Is there room in the tag map?
+         for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
+            if(me->auMappedTags[uTagMapIndex] == 0xffff) {
+               break;
+            }
+            if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
+               break;
+            }
          }
-         pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
-         pTags->uNumUsed++;
+         if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
+            // No room for the tag
+            return 97; // TODO error code
+         }
+
+         // Cover the case where tag is new and were it is already in the map
+         me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
+         auTags[uTagIndex] = (uint16_t)(uTagMapIndex + 0xfff0); // TODO proper constant and cast
+
+      } else {
+         auTags[uTagIndex] = (uint16_t)pDecodedItem->val.uTagV;
       }
    }
 
@@ -1121,12 +1005,10 @@
  items into one QCBORItem.
  */
 static inline QCBORError
-GetNext_MapEntry(QCBORDecodeContext *me,
-                 QCBORItem *pDecodedItem,
-                 QCBORTagListOut *pTags)
+GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
 {
    // Stack use: int/ptr 1, QCBORItem  -- 56
-   QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
+   QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
    if(nReturn)
       goto Done;
 
@@ -1144,7 +1026,7 @@
          // Save label in pDecodedItem and get the next which will
          // be the real data
          QCBORItem LabelItem = *pDecodedItem;
-         nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
+         nReturn = GetNext_TaggedItem(me, pDecodedItem);
          if(nReturn)
             goto Done;
 
@@ -1199,9 +1081,8 @@
  Public function, see header qcbor/qcbor_decode.h file
  TODO: correct this comment
  */
-QCBORError QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me,
-                                         QCBORItem *pDecodedItem,
-                                         QCBORTagListOut *pTags)
+static QCBORError
+QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
 {
    // Stack ptr/int: 2, QCBORItem : 64
 
@@ -1229,7 +1110,7 @@
       goto Done;
    }
 
-   nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
+   nReturn = GetNext_MapEntry(me, pDecodedItem);
    if(nReturn) {
       goto Done;
    }
@@ -1345,7 +1226,7 @@
    }
    const UsefulBufC Temp    = pDecodedItem->val.string;
    pDecodedItem->val.bigNum = Temp;
-   const bool bIsPosBigNum = (bool)(pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM);
+   const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
    pDecodedItem->uDataType  = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
                                                      : QCBOR_TYPE_NEGBIGNUM);
    return QCBOR_SUCCESS;
@@ -1353,6 +1234,19 @@
 
 
 /*
+ Mostly just assign the right data type for the bignum.
+ */
+inline static QCBORError DecodeUUID(QCBORItem *pDecodedItem)
+{
+   if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
+      return QCBOR_ERR_BAD_OPT_TAG;
+   }
+   pDecodedItem->uDataType = QCBOR_TYPE_UUID;
+   return QCBOR_SUCCESS;
+}
+
+
+/*
  The epoch formatted date. Turns lots of different forms of encoding
  date into uniform one
  */
@@ -1454,7 +1348,7 @@
 
    // --- Get the exponent ---
    QCBORItem exponentItem;
-   nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem, NULL);
+   nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
    if(nReturn != QCBOR_SUCCESS) {
       goto Done;
    }
@@ -1525,59 +1419,58 @@
  Public function, see header qcbor/qcbor_decode.h file
  */
 QCBORError
-QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
-                            QCBORItem *pDecodedItem,
-                            QCBORTagListOut *pTags)
+QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
 {
    QCBORError nReturn;
 
-   nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem, pTags);
+   nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
    if(nReturn != QCBOR_SUCCESS) {
       goto Done;
    }
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
-#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_SIX
-#else
-#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_FOUR
-#endif
+   for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
+      switch(pDecodedItem->uTags[i] ) {
+         case 0xffff:
+         // The end of the tag list or no tags
+         // Successful exit from the loop.
+         goto Done;
 
-   // Only pay attention to tags this code knows how to decode.
-   switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_XXX) {
-      case 0:
-         // No tags at all or none we know about. Nothing to do.
-         // This is the pass-through path of this function
-         // that will mostly be taken when decoding any item.
-         break;
-
-      case QCBOR_TAGFLAG_DATE_STRING:
+         case CBOR_TAG_DATE_STRING:
          nReturn = DecodeDateString(pDecodedItem);
          break;
 
-      case QCBOR_TAGFLAG_DATE_EPOCH:
+         case CBOR_TAG_DATE_EPOCH:
          nReturn = DecodeDateEpoch(pDecodedItem);
          break;
 
-      case QCBOR_TAGFLAG_POS_BIGNUM:
-      case QCBOR_TAGFLAG_NEG_BIGNUM:
+         case CBOR_TAG_POS_BIGNUM:
+         case CBOR_TAG_NEG_BIGNUM:
          nReturn = DecodeBigNum(pDecodedItem);
          break;
 
-#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
-      case QCBOR_TAGFLAG_DECIMAL_FRACTION:
-      case QCBOR_TAGFLAG_BIGFLOAT:
+   #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+         case CBOR_TAG_DECIMAL_FRACTION:
+         case CBOR_TAG_BIGFLOAT:
          // For aggregate tagged types, what goes into pTags is only collected
          // from the surrounding data item, not the contents, so pTags is not
          // passed on here.
 
          nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
          break;
-#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+   #endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
 
-      default:
-         // Encountering some mixed-up CBOR like something that
-         // is tagged as both a string and integer date.
-         nReturn = QCBOR_ERR_BAD_OPT_TAG;
+         case CBOR_TAG_BIN_UUID:
+         nReturn = DecodeUUID(pDecodedItem);
+
+         default:
+         // A tag that is not understood
+         // A successful exit from the loop
+         goto Done;
+
+      }
+      if(nReturn != QCBOR_SUCCESS) {
+         goto Done;
+      }
    }
 
 Done:
@@ -1589,12 +1482,48 @@
 }
 
 
+QCBORError QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
+{
+   const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
+
+   QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
+
+   UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
+
+   return uErr;
+}
+
+
 /*
  Public function, see header qcbor/qcbor_decode.h file
  */
-QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
+QCBORError
+QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
+                            QCBORItem *pDecodedItem,
+                            QCBORTagListOut *pTags)
 {
-   return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
+   QCBORError nReturn;
+
+   nReturn = QCBORDecode_GetNext(me, pDecodedItem);
+   if(nReturn != QCBOR_SUCCESS) {
+      return nReturn;
+   }
+
+   if(pTags != NULL) {
+      pTags->uNumUsed = 0;
+      for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
+         if(pDecodedItem->uTags[i] == 0xffff) {
+            break;
+         }
+         if(pTags->uNumUsed >= pTags->uNumAllocated) {
+            return QCBOR_ERR_TOO_MANY_TAGS;
+         }
+         pTags->puTags[pTags->uNumUsed] = ConvertTag(me, pDecodedItem->uTags[i]);
+         pTags->uNumUsed++;
+      }
+   }
+
+   return QCBOR_SUCCESS;
 }
 
 
@@ -1648,17 +1577,16 @@
                          const QCBORItem *pItem,
                          uint64_t uTag)
 {
-   const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
-
-   uint8_t uTagBitIndex;
-   // Do not care about errors in pCallerConfiguredTagMap here. They are
-   // caught during GetNext() before this is called.
-   if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
-      return 0;
+   for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
+      if(pItem->uTags[i] == 0xffff) {
+         break;
+      }
+      if(ConvertTag(me, pItem->uTags[i]) == uTag) {
+         return 1;
+      }
    }
 
-   const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
-   return (uTagBit & pItem->uTagBits) != 0;
+   return 0;
 }
 
 
@@ -2054,6 +1982,7 @@
    
    uint64_t uFound = 0;
 
+   /* Iterate over items in the map / array */
    do {
       /* Remember offset because sometims we have to return it */
       const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
@@ -2076,6 +2005,7 @@
                nReturn = QCBOR_ERR_DUPLICATE_LABEL;
                goto Done;
             }
+            /* Also try to match its type */
             if(!MatchType(Item, *pIterator)) {
                nReturn = QCBOR_ERR_UNEXPECTED_TYPE;
                goto Done;
@@ -2129,6 +2059,13 @@
 }
 
 
+// TODO: implement this 
+QCBORError QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx, QCBORItem *pItemList, void *pCallbackCtx, pfItemCallback pfCB)
+{
+   return 0;
+}
+
+
 void QCBORDecode_ExitMapMode(QCBORDecodeContext *pMe, uint8_t uType)
 {
    size_t uEndOffset;