big change with the new tag decoding -- unlimited number of tags, better handling of custom tags
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 831843c..b944eb6 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -204,6 +204,126 @@
 
 
 
+/*
+ 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_FOUR
+   CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_FOUR
+   CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_FOUR
+   CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_FOUR
+   CBOR_TAG_FRACTION,
+   CBOR_TAG_BIGFLOAT,
+   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 four items in
+// spBuiltInTagMap don't have values 0,1,2,3. 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 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 int 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;
+}
+
+
+
 
 /*
  Public function, see header file
@@ -224,10 +344,15 @@
  */
 void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx, const QCBORStringAllocator *pAllocator, bool bAllocAll)
 {
-    pCtx->pStringAllocator = (void *)pAllocator;
+   pCtx->pStringAllocator = (void *)pAllocator;
    pCtx->bStringAllocateAll = bAllocAll;
 }
 
+void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me, const QCBORTagListIn *pTagList)
+{
+   me->pCallerConfiguredTagList = pTagList;
+}
+
 
 /*
  This decodes the fundamental part of a CBOR data item, the type and number
@@ -246,6 +371,7 @@
  */
 inline static int DecodeTypeAndNumber(UsefulInputBuf *pUInBuf, int *pnMajorType, uint64_t *puNumber, uint8_t *puAdditionalInfo)
 {
+   // Stack usage: int/ptr 5 -- 40
    int nReturn;
    
    // Get the initial byte that every CBOR data item has
@@ -323,6 +449,7 @@
  */
 inline static int DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
 {
+   // Stack usage: int/ptr 1 -- 8
    int nReturn = QCBOR_SUCCESS;
    
    if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
@@ -385,6 +512,7 @@
 
 inline static int DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
 {
+   // Stack usage: 0
    int nReturn = QCBOR_SUCCESS;
    
    // uAdditionalInfo is 5 bits from the initial byte
@@ -443,6 +571,7 @@
  */
 inline static int DecodeBytes(const QCBORStringAllocator *pAlloc, int nMajorType, uint64_t uStrLen, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
 {
+   // Stack usage: UsefulBuf 2, int/ptr 1  40
    int nReturn = QCBOR_SUCCESS;
    
    UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, uStrLen);
@@ -474,15 +603,16 @@
 /*
  Mostly just assign the right data type for the date string.
  */
-inline static int DecodeDateString(QCBORItem Item, QCBORItem *pDecodedItem)
+inline static int DecodeDateString(QCBORItem *pDecodedItem)
 {
-   if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) {
+   // Stack Use: UsefulBuf 1 16
+   if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
       return QCBOR_ERR_BAD_OPT_TAG;
    }
-   pDecodedItem->val.dateString = Item.val.string;
-   pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
-   pDecodedItem->uTagBits = Item.uTagBits;
-   pDecodedItem->uTag = Item.uTag;
+   
+   UsefulBufC Temp              = pDecodedItem->val.string;
+   pDecodedItem->val.dateString = Temp;
+   pDecodedItem->uDataType      = QCBOR_TYPE_DATE_STRING;
    return QCBOR_SUCCESS;
 }
 
@@ -490,15 +620,15 @@
 /*
  Mostly just assign the right data type for the bignum.
  */
-inline static int DecodeBigNum(QCBORItem Item, QCBORItem *pDecodedItem, uint64_t uTagFlags)
+inline static int DecodeBigNum(QCBORItem *pDecodedItem)
 {
-   if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
+   // Stack Use: UsefulBuf 1  -- 16
+   if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
       return QCBOR_ERR_BAD_OPT_TAG;
    }
-   pDecodedItem->val.bigNum     = Item.val.string;
-   pDecodedItem->uDataType      = uTagFlags & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
-   pDecodedItem->uTagBits       = Item.uTagBits;
-   pDecodedItem->uTag           = Item.uTag;
+   UsefulBufC Temp          = pDecodedItem->val.string;
+   pDecodedItem->val.bigNum = Temp;
+   pDecodedItem->uDataType  = pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM; // TODO: check this
    return QCBOR_SUCCESS;
 }
 
@@ -506,51 +636,46 @@
 /*
  The epoch formatted date. Turns lots of different forms of encoding date into uniform one
  */
-static int DecodeDateEpoch(QCBORItem Item, QCBORItem *pDecodedItem)
+static int DecodeDateEpoch(QCBORItem *pDecodedItem)
 {
+   // Stack usage: 1
    int nReturn = QCBOR_SUCCESS;
    
-   pDecodedItem->uTagBits                       = Item.uTagBits;
-   pDecodedItem->uTag                           = Item.uTag;
-   pDecodedItem->uDataType                      = QCBOR_TYPE_DATE_EPOCH;
    pDecodedItem->val.epochDate.fSecondsFraction = 0;
+   double d = pDecodedItem->val.dfnum; // Might not use this, but keeps code flow neater below
    
-   switch (Item.uDataType) {
+   switch (pDecodedItem->uDataType) {
          
       case QCBOR_TYPE_INT64:
-         pDecodedItem->val.epochDate.nSeconds = Item.val.int64;
+         pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
          break;
          
       case QCBOR_TYPE_UINT64:
-         if(Item.val.uint64 > INT64_MAX) {
-            nReturn = QCBOR_ERR_DATE_OVERFLOW; 
+         if(pDecodedItem->val.uint64 > INT64_MAX) {
+            nReturn = QCBOR_ERR_DATE_OVERFLOW;
             goto Done;
          }
-         pDecodedItem->val.epochDate.nSeconds = Item.val.uint64;
+         pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.uint64;
          break;
          
       case QCBOR_TYPE_FLOAT:
-         // TODO: can we save code by widening a float to a double here? Then drop into double-handling code
-         if(Item.val.fnum > INT64_MAX) {
-            nReturn = QCBOR_ERR_DATE_OVERFLOW;
-            goto Done;
-         }
-         pDecodedItem->val.epochDate.nSeconds = Item.val.fnum;
-         pDecodedItem->val.epochDate.fSecondsFraction = Item.val.fnum - pDecodedItem->val.epochDate.nSeconds;
-         break;
-
+         d = pDecodedItem->val.fnum;
+         // Fall through
+         
       case QCBOR_TYPE_DOUBLE:
-         if(Item.val.dfnum > INT64_MAX) {
+         if(d > INT64_MAX) {
             nReturn = QCBOR_ERR_DATE_OVERFLOW;
             goto Done;
          }
-         pDecodedItem->val.epochDate.nSeconds = Item.val.dfnum;
-         pDecodedItem->val.epochDate.fSecondsFraction = Item.val.dfnum - pDecodedItem->val.epochDate.nSeconds;
+         pDecodedItem->val.epochDate.nSeconds = d; // Float to integer conversion happening here.
+         pDecodedItem->val.epochDate.fSecondsFraction = d - pDecodedItem->val.epochDate.nSeconds;
          break;
          
       default:
          nReturn = QCBOR_ERR_BAD_OPT_TAG;
+         goto Done;
    }
+   pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
    
 Done:
    return nReturn;
@@ -577,6 +702,7 @@
  */
 static int GetNext_Item(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, const QCBORStringAllocator *pAlloc)
 {
+   // Stack usage: int/ptr 3 -- 24
    int nReturn;
    
    // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
@@ -628,7 +754,7 @@
          break;
          
       case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
-         pDecodedItem->uTag      = uNumber;
+         pDecodedItem->val.uTagV = uNumber;
          pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
          break;
          
@@ -654,8 +780,9 @@
  
  Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
  */
-static int GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
+static inline int GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
 {
+   // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem  -- 96
    int nReturn;
    QCBORStringAllocator *pAlloc = (QCBORStringAllocator *)me->pStringAllocator;
    UsefulBufC FullString = NULLUsefulBufC;
@@ -692,7 +819,7 @@
    // Loop getting segments of indefinite string
    for(;;) {
       // Get item for next segment
-      QCBORItem StringSegmentItem;
+      QCBORItem StringSegmentItem; // TODO: rename segment to chunk to line up with new RFC
       // NULL passed to never string alloc segments of indefinite length strings
       nReturn = GetNext_Item(&(me->InBuf), &StringSegmentItem, NULL);
       if(nReturn) {
@@ -742,86 +869,74 @@
  Returns an error if there was something wrong with the optional item or it couldn't
  be handled.
  */
-static int GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
+static int GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
 {
-   int nReturn;
-   
-   // TODO: optimize loop below so there is only one call to GetNext_FullItem?
-   nReturn = GetNext_FullItem(me, pDecodedItem);
-   if(nReturn) {
-      goto Done;
+   // Stack usage: int/ptr: 3 -- 24
+   int       nReturn;
+   uint64_t  uTagBits = 0;
+   if(pTags) {
+      pTags->uNumUsed = 0;
    }
-   
-   if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
-      goto Done;
-   }
-   
-   uint64_t uTagFlags = 0; // accumulate the tags in the form of flags
-   uint64_t uTagToProcess = pDecodedItem->uTag; // First process tag passed in
-   
-   QCBORItem Item;
-   
-   do {
-      if(uTagToProcess < 63) { // 63 is the number of bits in a uint64 - 1
-         uTagFlags |= 0x01LL << uTagToProcess;
-      } else if(uTagToProcess == CBOR_TAG_CBOR_MAGIC) {
-         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. */
-      
-      nReturn = GetNext_FullItem(me, &Item);
+
+   for(;;) {
+      nReturn = GetNext_FullItem(me, pDecodedItem);
       if(nReturn) {
-         // Bail out of the whole item fetch on any sort of error here
-         goto Done;
+         goto Done; // Error out of the loop
       }
       
-      if(Item.uDataType != QCBOR_TYPE_OPTTAG) {
+      if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
+         // Successful exit from loop; maybe got some tags, maybe not
+         pDecodedItem->uTagBits = uTagBits;
          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;
+            break;
+            
+         case QCBOR_ERR_BAD_OPT_TAG:
+            // Tag is not recognized. Do nothing
+            break;
+            
+         default:
+            // Error Condition
+            goto Done;
+      }
       
-      uTagToProcess = Item.uTag;
-   } while (1);
+      if(pTags) {
+         // Caller wants all tags recorded in the provided buffer
+         if(pTags->uNumUsed >= pTags->uNumAllocated) {
+            nReturn = QCBOR_ERR_TOO_MANY_TAGS;
+            goto Done;
+         }
+         pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
+         pTags->uNumUsed++;
+      }
+   }
    
-   
-   /*
-    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.
-    
-    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?
-    */
-   
-   Item.uTagBits = uTagFlags;
-   Item.uTag = uTagToProcess;
-   
-   switch(uTagFlags & (QCBOR_TAGFLAG_DATE_STRING | QCBOR_TAGFLAG_DATE_EPOCH | QCBOR_TAGFLAG_POS_BIGNUM |QCBOR_TAGFLAG_NEG_BIGNUM)) {
+   switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_FOUR) {
       case 0:
-         // No tags we know about. Pass them up
-         *pDecodedItem = Item;
+         // No tags at all or none we know about. Nothing to do.
+         // This is part of the pass-through path of this function
+         // that will mostly be taken when decoding any item.
          break;
          
       case QCBOR_TAGFLAG_DATE_STRING:
-         nReturn = DecodeDateString(Item, pDecodedItem);
+         nReturn = DecodeDateString(pDecodedItem);
          break;
          
       case QCBOR_TAGFLAG_DATE_EPOCH:
-         nReturn = DecodeDateEpoch(Item, pDecodedItem);
+         nReturn = DecodeDateEpoch(pDecodedItem);
          break;
          
       case QCBOR_TAGFLAG_POS_BIGNUM:
       case QCBOR_TAGFLAG_NEG_BIGNUM:
-         nReturn = DecodeBigNum(Item, pDecodedItem, uTagFlags);
+         nReturn = DecodeBigNum(pDecodedItem);
          break;
          
       default:
@@ -838,13 +953,15 @@
 /*
  This layer takes care of map entries. It combines the label and data items into one QCBORItem.
  */
-static inline int GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
+static inline int GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
 {
-   int nReturn = GetNext_TaggedItem(me, pDecodedItem);
+   // Stack use: int/ptr 1, QCBORItem  -- 56
+   int nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
    if(nReturn)
       goto Done;
    
    if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
+      // Break can't be a map entry
       goto Done;
    }
    
@@ -854,7 +971,7 @@
       
       // Get the next item which will be the real data; Item will be the label
       QCBORItem LabelItem = *pDecodedItem;
-      nReturn = GetNext_TaggedItem(me, pDecodedItem);
+      nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
       if(nReturn)
          goto Done;
       
@@ -881,6 +998,7 @@
       } else {
          // label is not an int or a string. It is an arrray
          // or a float or such and this implementation doesn't handle that.
+         // Also, tags on labels are ignored.
          nReturn = QCBOR_ERR_MAP_LABEL_TYPE ;
          goto Done;
       }
@@ -894,13 +1012,15 @@
 /*
  Public function, see header qcbor.h file
  */
-int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
+int QCBORDecode_GetNextWithTags(QCBORDecodeContext *me, QCBORItem *pDecodedItem, QCBORTagListOut *pTags)
 {
+   // Stack ptr/int: 2, QCBORItem : 64
+
    // The public entry point for fetching and parsing the next QCBORItem.
    // All the CBOR parsing work is here and in subordinate calls.
    int nReturn;
    
-   nReturn = GetNext_MapEntry(me, pDecodedItem);
+   nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
    if(nReturn) {
       goto Done;
    }
@@ -974,6 +1094,12 @@
 }
 
 
+int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
+{
+   return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
+}
+
+
 /*
  Decoding items is done in 5 layered functions, one calling the
  next one down. If a layer has no work to do for a particular item
@@ -1003,12 +1129,34 @@
  item in CBOR, the thing with an initial byte containing
  the major type.
  
+ Roughly this takes 300 bytes of stack for vars. Need to
+ evaluate this more carefully and correctly.
+ 
  */
 
 
 /*
  Public function, see header qcbor.h file
  */
+int QCBORDecode_IsTagged(QCBORDecodeContext *me, 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;
+   }
+   
+   const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
+   return (uTagBit & pItem->uTagBits) != 0;
+}
+
+
+/*
+ Public function, see header qcbor.h file
+ */
 int QCBORDecode_Finish(QCBORDecodeContext *me)
 {
    int nReturn = QCBOR_SUCCESS;