Clean up some tag decoding
diff --git a/inc/qcbor/qcbor_common.h b/inc/qcbor/qcbor_common.h
index 6180240..521ef6e 100644
--- a/inc/qcbor/qcbor_common.h
+++ b/inc/qcbor/qcbor_common.h
@@ -174,15 +174,17 @@
     (https://tools.ietf.org/html/rfc5870) and WGS-84. No API is
     provided for this tag. */
 #define CBOR_TAG_GEO_COORD    103
-
-/** Binary MIME */
+/** Binary MIME.*/
 #define CBOR_TAG_BINARY_MIME 257
-
 /** The magic number, self-described CBOR. No API is provided for this
     tag. */
 #define CBOR_TAG_CBOR_MAGIC 55799
 
-#define CBOR_TAG_NONE  UINT64_MAX
+/** Three different values for invalid tag from the CBOR tags registry */
+#define CBOR_TAG_INVALID16 0xffff
+#define CBOR_TAG_INVALID32 0xffffffff
+#define CBOR_TAG_INVALID64 0xffffffffffffffff
+
 
 
 /*
@@ -300,7 +302,9 @@
        item. */
    QCBOR_ERR_BAD_BREAK = 19,
 
-   /** During decoding, too many tags in the caller-configured tag
+   /** More than @ref QCBOR_MAX_TAGS_PER_ITEM tags encounterd for a CBOR ITEM.
+      @ref QCBOR_MAX_TAGS_PER_ITEM is a limit of this implementation.
+      During decoding, too many tags in the caller-configured tag
        list, or not enough space in @ref QCBORTagListOut. */
    QCBOR_ERR_TOO_MANY_TAGS = 20,
 
@@ -352,9 +356,9 @@
     QCBOR_ERR_NOT_ENTERED = 31,
 
     /** A callback indicates processing should not continue for some non-CBOR reason */
-    QCBOR_ERR_CALLBACK_FAIL = 32,
-    
-    /* This is stored in uint8_t in places; never add values > 255 */
+    QCBOR_ERR_CALLBACK_FAIL = 32
+
+    /* This is stored in uint8_t; never add values > 255 */
 } QCBORError;
 
 
diff --git a/inc/qcbor/qcbor_decode.h b/inc/qcbor/qcbor_decode.h
index 282ffde..5da7ba3 100644
--- a/inc/qcbor/qcbor_decode.h
+++ b/inc/qcbor/qcbor_decode.h
@@ -936,6 +936,34 @@
 
 
 /**
+ @brief Returns the tag values for an item.
+
+ @param[in] pCtx    The decoder context.
+ @param[in] pItem The CBOR item to get the tag for.
+ @param[in] uIndex The index of the tag to get.
+
+ @returns The actual nth tag value.
+
+ Up to \ref QCBOR_MAX_TAGS_PER_ITEM are recorded for a decoded CBOR item. If there
+ are more than this, the \ref QCBOR_ERR_TOO_MANY_TAGS error is returned
+ by QCBORDecode_GetNext() and other. This is a limit of this implementation,
+ not of CBOR.
+
+ The 0th tag (@c uIndex 0) is the one that occurs closest to the data item.
+ Tags nest, so the nth tag applies to what ever type
+ is a result of applying the (n-1) tag.
+
+ To reduce memory used by a QCBORItem, this implementation maps
+ all tags larger than UINT16_MAX. This function does the unmapping.
+
+ This returns \ref CBOR_TAG_INVALID16 on all errors or if the nth tag is requested and
+ there is no nth tag. If there are no tags on the item, then
+ requesting the 0th tag will return \ref CBOR_TAG_INVALID16.
+ */
+uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pCtx, const QCBORItem *pItem, unsigned int uIndex);
+
+
+/**
  @brief Check whether all the bytes have been decoded and maps and arrays closed.
 
  @param[in]  pCtx  The context to check.
@@ -1885,32 +1913,8 @@
    return 0;
 }
 
-#define FOFOO (0xffff - 1024)
 
-/*
- Returns the tag values for an item.
 
- The 0th tag is the one that occurs closest to the data item.
- Tags nest, so the nth tag applies to what ever type
- is a result of applying the (n-1) tag.
-
- This returns 0xffff on all errors or if the nth tag is requested and
- there is no nth tag. If there are no tags on the item, then
- requesting the 0th tag will return 0xffff.
-
- */
-static inline uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe, const QCBORItem *pItem, unsigned int uIndex)
-{
-   if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
-      return 0xffff; // TODO constant for standard bad tag value
-   }
-
-   if(pItem->uTags[uIndex] > FOFOO) {
-      return pItem->uTags[uIndex];
-   } else {
-      return pMe->auMappedTags[pItem->uTags[uIndex] - FOFOO];
-   }
-}
 
 static inline QCBORError QCBORDecode_GetError(QCBORDecodeContext *pMe)
 {
diff --git a/inc/qcbor/qcbor_private.h b/inc/qcbor/qcbor_private.h
index 02cbf86..c96740f 100644
--- a/inc/qcbor/qcbor_private.h
+++ b/inc/qcbor/qcbor_private.h
@@ -70,6 +70,10 @@
  */
 #define QCBOR_NUM_MAPPED_TAGS 4
 
+#define QCBOR_MAX_NUM_MAPPED_TAGS 1024
+
+#define QCBOR_LAST_UNMAPPED_TAG (CBOR_TAG_INVALID16 - QCBOR_MAX_NUM_MAPPED_TAGS)
+
 /*
  PRIVATE DATA STRUCTURE
 
diff --git a/src/qcbor_decode.c b/src/qcbor_decode.c
index 3913e7e..f58c6c3 100644
--- a/src/qcbor_decode.c
+++ b/src/qcbor_decode.c
@@ -397,7 +397,7 @@
    me->uDecodeMode = (uint8_t)nDecodeMode;
    DecodeNesting_Init(&(me->nesting));
    for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
-      me->auMappedTags[i] = 0xffff;
+      me->auMappedTags[i] = CBOR_TAG_INVALID16;
    }
 }
 
@@ -942,7 +942,10 @@
    // Stack usage: int/ptr: 3 -- 24
    QCBORError nReturn;
 
-   uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {0xffff, 0xffff, 0xffff, 0xffff};
+   uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
+                                               CBOR_TAG_INVALID16,
+                                               CBOR_TAG_INVALID16,
+                                               CBOR_TAG_INVALID16};
 
    // Loop fetching items until the item fetched is not a tag
    for(;;) {
@@ -960,20 +963,20 @@
       // 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) {
+         if(auTags[uTagIndex] == CBOR_TAG_INVALID16) {
             break;
          }
       }
       if(uTagIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
-         return 99; // TODO error code
+         return QCBOR_ERR_TOO_MANY_TAGS;
       }
 
       // Is the tag > 16 bits?
-      if(pDecodedItem->val.uTagV > 0xffff) {
+      if(pDecodedItem->val.uTagV > CBOR_TAG_INVALID16) {
          size_t uTagMapIndex;
          // Is there room in the tag map?
          for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
-            if(me->auMappedTags[uTagMapIndex] == 0xffff) {
+            if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
                break;
             }
             if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
@@ -1678,7 +1681,7 @@
          nReturn = DecodeUUID(pDecodedItem);
          break;
             
-         case 0xffff:
+         case CBOR_TAG_INVALID16:
          // The end of the tag list or no tags
          // Successful exit from the loop.
          goto Done;
@@ -1733,7 +1736,7 @@
    if(pTags != NULL) {
       pTags->uNumUsed = 0;
       for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++) {
-         if(pDecodedItem->uTags[i] == 0xffff) {
+         if(pDecodedItem->uTags[i] == CBOR_TAG_INVALID16) {
             break;
          }
          if(pTags->uNumUsed >= pTags->uNumAllocated) {
@@ -1799,7 +1802,7 @@
                          uint64_t           uTag)
 {
    for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM; i++ ) {
-      if(pItem->uTags[i] == 0xffff) {
+      if(pItem->uTags[i] == CBOR_TAG_INVALID16) {
          break;
       }
       if(ConvertTag(me, pItem->uTags[i]) == uTag) {
@@ -1838,6 +1841,22 @@
 }
 
 
+/*
+Public function, see header qcbor/qcbor_decode.h file
+*/
+uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe, const QCBORItem *pItem, unsigned int uIndex)
+{
+   if(uIndex > QCBOR_MAX_TAGS_PER_ITEM) {
+      return CBOR_TAG_INVALID16;
+   } else if(pItem->uTags[uIndex] <= QCBOR_LAST_UNMAPPED_TAG) {
+      return pItem->uTags[uIndex];
+   } else if(pItem->uTags[uIndex] < QCBOR_NUM_MAPPED_TAGS + QCBOR_LAST_UNMAPPED_TAG) {
+      return pMe->auMappedTags[pItem->uTags[uIndex] - QCBOR_LAST_UNMAPPED_TAG];
+   } else {
+      return CBOR_TAG_INVALID16;
+   }
+}
+
 
 /*