Tidy up decode-related headers (#280)

Check and reduce some dependency between decode headers

Rename qcbor_decode to qcbor_main_decode to be more clear and help with header backwards compatibility 

Fix a header include backwards compatibility to v1 issue

Fix long lines and trailing spaces


Co-authored-by: Laurence Lundblade <lgl@securitytheory.com>
diff --git a/inc/qcbor/UsefulBuf.h b/inc/qcbor/UsefulBuf.h
index 1ed558b..80b5c78 100644
--- a/inc/qcbor/UsefulBuf.h
+++ b/inc/qcbor/UsefulBuf.h
@@ -1471,7 +1471,7 @@
  *
  * @return  0 for equality, positive if uStart1 is lexographically larger,
  *          negative if uStart2 is lexographically larger.
- * 
+ *
  * This looks into bytes that have been output at the offsets @c start1
  * and @c start2. It compares bytes at those two starting points until
  * they are not equal or @c uLen1 or @c uLen2 is reached. If the
@@ -1894,7 +1894,7 @@
  * @param[in] uLen2     Length of second range of bytes.
  *
  * This returns the same as UsefulBuf_Compare().
- * 
+ *
  * If the offset or the length plus offset or a range extends outside
  * the input buffer, that range of bytes will be considered greater
  * than the other string. If both are outside this is considered a
diff --git a/inc/qcbor/qcbor_common.h b/inc/qcbor/qcbor_common.h
index affdd9b..fdc5d3a 100644
--- a/inc/qcbor/qcbor_common.h
+++ b/inc/qcbor/qcbor_common.h
@@ -1,4 +1,6 @@
 /* ==========================================================================
+ * qcbor_common -- Common definitions for encding and decoding.
+ *
  * Copyright (c) 2016-2018, The Linux Foundation.
  * Copyright (c) 2018-2024, Laurence Lundblade.
  * Copyright (c) 2021, Arm Limited.
@@ -30,6 +32,7 @@
  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * ========================================================================= */
+
 #ifndef qcbor_common_h
 #define qcbor_common_h
 
@@ -433,8 +436,9 @@
    QCBOR_ERR_TAGS_DISABLED = 51,
 
    // TODO: maybe reduce number of conformance codes to not use up unrecoverable errors
-   
-   /** Decoded CBOR is does not conform to preferred serialization. The CBOR head's argument is not encoded in shortest form, or indefinite lengths are used.*/
+
+   /** Decoded CBOR is does not conform to preferred serialization. The CBOR head's argument is not
+    * encoded in shortest form, or indefinite lengths are used. */
    QCBOR_ERR_PREFERRED_CONFORMANCE = 52,
 
    /** Decoded CBOR does not conform to CDE. This occurs when a map is not sorted. Other
@@ -569,7 +573,7 @@
    /** An unconsumed tag number was encountered. */
    QCBOR_ERR_UNEXPECTED_TAG_NUMBER = 89, // TODO: rid of this in favor of below?
 
-   /** In QCBOR v2, tag numbers must be processed by QCBORDecode_GetNextTagNumber(). 
+   /** In QCBOR v2, tag numbers must be processed by QCBORDecode_GetNextTagNumber().
     * See @ref QCBOR_DECODE_CONFIG_UNPROCESSED_TAG_NUMBERS. */
    QCBOR_ERR_UNPROCESSED_TAG_NUMBER = 90,
 
diff --git a/inc/qcbor/qcbor_decode.h b/inc/qcbor/qcbor_decode.h
index 2f7a118..3dee9b6 100644
--- a/inc/qcbor/qcbor_decode.h
+++ b/inc/qcbor/qcbor_decode.h
@@ -1,1529 +1,20 @@
-/* ===========================================================================
- * Copyright (c) 2016-2018, The Linux Foundation.
- * Copyright (c) 2018-2024, Laurence Lundblade.
- * Copyright (c) 2021, Arm Limited.
- * All rights reserved.
+/* ==========================================================================
+ * qcbor_decode.h -- Backwards compatibility to v1 qcbor_decode.h
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- *       copyright notice, this list of conditions and the following
- *       disclaimer in the documentation and/or other materials provided
- *       with the distribution.
- *     * Neither the name of The Linux Foundation nor the names of its
- *       contributors, nor the name "Laurence Lundblade" may be used to
- *       endorse or promote products derived from this software without
- *       specific prior written permission.
+ * Copyright (c) 2024, Laurence Lundblade. All rights reserved.
  *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- * ========================================================================= */
-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * See BSD-3-Clause license in file named "LICENSE"
+ *
+ * Created on 12/1/24.
+ * ========================================================================== */
 
 #ifndef qcbor_decode_h
 #define qcbor_decode_h
 
-
-#include "qcbor/qcbor_common.h"
-#include "qcbor/qcbor_private.h"
-#include <stdbool.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#if 0
-} /* Keep editor indention formatting happy */
-#endif
-#endif
-
-
-/**
- * @file qcbor_decode.h
- *
- * @anchor BasicDecode
- * # QCBOR Basic Decode
- *
- * This section discusses decoding assuming familiarity with the
- * general description of this encoder-decoder in section @ref
- * Overview.
- *
- * Encoded CBOR has a tree structure where the leaf nodes are
- * non-aggregate types like integers and strings and the intermediate
- * nodes are either arrays or maps. Fundamentally, CBOR decoding is a
- * pre-order traversal of this tree with CBOR sequences a minor
- * exception. Calling QCBORDecode_GetNext() repeatedly will perform
- * this. QCBOR maintains an internal traversal cursor. It is possible
- * to decode any CBOR by only calling QCBORDecode_GetNext(), though
- * this doesn't take advantage of many QCBOR features.
- *
- * QCBORDecode_GetNext() returns a 56 byte structure called
- * @ref QCBORItem that describes the decoded item including:
- * - The data itself, integer, string, floating-point number...
- * - The label if present
- * - Unprocessed tags
- * - Nesting level
- * - Allocation type (primarily of interest for indefinite length strings)
- *
- * For strings, this structure contains a pointer and length back into
- * the original data.
- *
- * Most of the tags that QCBOR supports directly are decoded into a
- * representation in @ref QCBORItem.
- *
- * A string allocator must be used when decoding indefinite length
- * strings. See QCBORDecode_SetMemPool() or
- * QCBORDecode_SetUpAllocator(). @ref QCBORItem indicates if a string
- * was allocated with the string allocator.
- *
- * This pre-order traversal gives natural decoding of arrays where the
- * array members are taken in order. Maps can be decoded this way too,
- * but the @ref SpiffyDecode APIs that allow searching maps by label
- * are often more convenient.
- *
- * @anchor v2-Tag-Decoding
- *
- * RFC 7049 called tags "optional". This was a mistake. They specify
- * critical type information that can't be ignored by decoders.
- *
- * QCBOR v1 always returns the tag numbers on an item
- * in QCBORItem and leaves it up to the caller to check.
- * Probably most callers don't know this and never added
- * the check. There decode implementations are tolerant
- * of random tag numbers and they shouldn't be.
- *
- * QCBOR v2 requires tags numbers to be processed by
- * QCBORDecode_GetNextTagNumber(). If they are not
- * an error will be returned.
- *
- * This new behavior saves the caller from having to do this check
- * (that they probably didn't know they neeeded).  It is much more
- * correct behavior.
- *
- * This behavior is not backwards compatible with v1. The v1 behavior
- * can be restored with @ref QCBOR_DECODE_ALLOW_UNPROCESSED_TAG_NUMBERS.
- * However, the v2 behavior is more correct, so this configuration
- * should not be used.
- *
- * @anchor Decode-Errors-Overview
- * # Decode Errors Overview
- *
- * The simplest way to handle decoding errors is to make use of the
- * internal error tracking. The only error code check necessary is
- * at the end when QCBORDecode_Finish() is called. To do this:
- *
- * - Use QCBORDecode_VGetNext(), QCBORDecode_VPeekNext()
- *  and any or all of the functions in qcbor_spiffy_decode.h. Don't use
- *  QCBORDecode_GetNext() or QCBORDecode_PeekNext().
- * - Call QCBORDecode_Finish() and check its return code.
- * - Do not reference any decoded data until after
- *    QCBORDecode_Finish() returns success.
- *
- * Once an encoding error has been encountered, the error state is
- * entered and further decoding function calls will do nothing.  It is
- * safe to continue calling decoding functions after an error. No
- * error checking is necessary making the code to decode a protocol
- * simpler.  The two exceptions are QCBORDecode_GetNext() and
- * QCBORDecode_PeekNext() which will try to decode even if the decoder
- * is in the error state. Use QCBORDecode_VGetNext() and
- * QCBORDecode_VPeekNext() instead.
- *
- * While some protocols are simple enough to be decoded this way, many
- * aren’t because the data items earlier in the protocol determine how
- * later data items are to be decoded. In that case it is necessary to
- * call QCBORDecode_GetError() to know the earlier items were
- * successfully decoded before examining their value or type.
- *
- * The internal decode error state can be reset by reinitializing the
- * decoder or calling QCBORDecode_GetErrorAndReset(). Code calling
- * QCBOR may take advantage of the internal error state to halt
- * futher decoding and propagate errors it detects using
- * QCBORDecode_SetError().
- *
- * It is only useful to reset the error state by calling
- * QCBORDecode_GetErrorAndReset() on recoverable errors. Examples of
- * recoverable errors are a map entry not being found or integer
- * overflow or underflow during conversion. Examples of unrecoverable
- * errors are hitting the end of the input and array or map nesting
- * beyond the limits of the implementation. See
- * QCBORDecode_IsUnrecoverableError().Trying to reset and decode after
- * an unrecoverable error will usually just lead to another error.
- *
- * It is possible to use QCBORDecode_GetNext() and
- * QCBORDecode_PeekNext() to decode an entire protocol. However, that is
- * usually more work, more code and less convenient than using spiffy
- * decode functions.
- *
- * It is also possible to mix the use of QCBORDecode_GetNext() with
- * QCBORDecode_VGetNext() and the spiffy decode functions, but
- * QCBORDecode_GetError() must be called and return QCBOR_SUCCESS before
- * QCBORDecode_GetNext() is called.
- *
- * The effect of a decoding error on the traversal cursor position
- * varies by the decoding method called. It is unaffected by spiffy
- * decode methods that get items by map label.
- * QCBORDecode_GetInt64InMapN() is an example of this. The traversal
- * cursor will be advanced by most other decode methods even when
- * there is a decode error, often leaving it in an indeterminate
- * position. If it is necessary to continue to decoding after an
- * error, QCBORDecode_Rewind() can be used to reset it to a known-good
- * position.
- *
- * When using spiffy decode methods to get an item by label from a map
- * the whole map is internally traversed including nested arrays and
- * maps. If there is any unrecoverable error during that traversal,
- * the retrieval by label will fail. The unrecoverable error will be
- * returned even if it is not because the item being sought is in
- * error. Recoverable errors will be ignored unless they are on the
- * item being sought, in which case the unrecoverable error will be
- * returned. Unrecoverable errors are those indicated by
- * QCBORDecode_IsUnrecoverableError().
- *
- * @anchor Disabilng-Tag-Decoding
- * # Disabilng Tag Decoding
- *
- * TODO: update this
- * If QCBOR_DISABLE_TAGS is defined, all code for decoding tags will
- * be omitted reducing the core decoder, QCBORDecode_VGetNext(), by
- * about 400 bytes. If a tag number is encountered in the decoder
- * input the unrecoverable error @ref QCBOR_ERR_TAGS_DISABLED will be
- * returned.  No input with tags can be decoded.
- *
- * Decode functions like QCBORDecode_GetEpochDate() and
- * QCBORDecode_GetDecimalFraction() that can decode the tag content
- * even if the tag number is absent are still available.  Typically
- * they won't be linked in because of dead stripping. The
- * @c uTagRequirement parameter has no effect, but if it is
- * @ref QCBOR_TAG_REQUIREMENT_TAG, @ref QCBOR_ERR_TAGS_DISABLED
- * will be set.
- */
-
-
-/**
- *  These are the decode configuration flags that can be or'd together
- *  and passed to QCBORDecode_Init().
- */
-typedef enum {
-   /** Normal decoding with no flags set. */
-   QCBOR_DECODE_MODE_NORMAL = 0,
-
-   /** Required map labels to be strings. If not @ref  QCBOR_ERR_MAP_LABEL_TYPE
-    * occurs. */
-   QCBOR_DECODE_MODE_MAP_STRINGS_ONLY = 0x01,
-
-   /** Causes maps to be treated as special arrays so all types of map
-    * labels can be decoded..  They will be returned with special
-    * @c uDataType @ref QCBOR_TYPE_MAP_AS_ARRAY and @c uCount, the
-    * number of items, will be double what it would be for a normal
-    * map because the labels are also counted. This mode is useful for
-    * decoding CBOR that has labels that are not integers or
-    * strings. Each map entry is decoded with two Get() calls, one for
-    * the label and one for the value. QCBORItem.label is never filled
-    * in. */
-   QCBOR_DECODE_MODE_MAP_AS_ARRAY = 0x02,
-
-   /** Makes QCBOR v2 tag decoding compatible with QCBOR v1. The error
-    *  @ref QCBOR_ERR_UNPROCESSED_TAG_NUMBER is not returned.  See
-    *  @ref v2-Tag-Decoding and QCBORDecode_CompatibilityV1().
-    */
-   QCBOR_DECODE_ALLOW_UNPROCESSED_TAG_NUMBERS = 0x04,
-
-   /** Error out on indefinite length strings, arrays and maps. */
-   QCBOR_DECODE_NO_INDEF_LENGTH = 0x08,
-
-   /** Error out if integers or floats are encoded as
-    *  non-preferred. */
-   QCBOR_DECODE_ONLY_PREFERRED_NUMBERS = 0x10,
-
-   /** If big numbers that will fit into normal integers are
-    *  encountered error XXX will occur. This is to comply with big
-    *  number preferred serialization. */
-   QCBOR_DECODE_ONLY_PREFERRED_BIG_NUMBERS = 0x20,
-
-   /** If maps are not sorted, error @ref QCBOR_ERR_UNSORTED
-    *  occurs. This is makes map decoding take more CPU time, but that
-    *  is probably only of consequence with big maps on small CPUs. */
-   QCBOR_DECODE_ONLY_SORTED_MAPS = 0x40,
-
-   /** If whole number floats are present (they are not encoded as
-    * integers), error @ref QCBOR_ERR_DCBOR_CONFORMANCE occurs. This
-    * is as required for dCBOR.
-    */
-   QCBOR_DECODE_ONLY_REDUCED_FLOATS = 0x80,
-
-   /** dCBOR allows only the simple types true, false and NULL
-    * This enforces that.
-    */
-   QCBOR_DECODE_DISALLOW_DCBOR_SIMPLES = 0x100,
-
-   /**
-    * This checks that the input is encoded with preferred
-    * serialization. The checking is performed as each item is
-    * decoded. If no QCBORDecode_GetXxx() is called for an item,
-    * there's no check on that item. Preferred serialization was first
-    * defined in section 4.1 of RFC 8949, but is more sharply in
-    * draft-ietf-cbor-cde. Summarizing, the requirements are: the use
-    * of definite-length encoding only, integers, including string
-    * lengths and tags, must be in shortest form, and floating-point
-    * numbers must be reduced to shortest form all the way to
-    * half-precision. */
-   QCBOR_DECODE_MODE_PREFERRED = QCBOR_DECODE_NO_INDEF_LENGTH |
-                                 QCBOR_DECODE_ONLY_PREFERRED_NUMBERS |
-                                 QCBOR_DECODE_ONLY_PREFERRED_BIG_NUMBERS,
-
-   /** This checks that maps in the input are sorted by label as
-    * described in RFC 8949 section 4.2.1.  This also performs
-    * duplicate label checking.  This mode adds considerable CPU-time
-    * expense to decoding, though it is probably only of consequence
-    * for large inputs on slow CPUs.
-    *
-    * This also performs all the checks that
-    * @ref QCBOR_DECODE_MODE_PREFERRED does. */
-   QCBOR_DECODE_MODE_CDE = QCBOR_DECODE_MODE_PREFERRED |
-                           QCBOR_DECODE_ONLY_SORTED_MAPS,
-
-   /** This requires integer-float unification. It performs all the checks that
-    * @ref QCBOR_DECODE_MODE_CDE does. */
-   QCBOR_DECODE_MODE_DCBOR = QCBOR_DECODE_MODE_CDE |
-                             QCBOR_DECODE_ONLY_REDUCED_FLOATS |
-                             QCBOR_DECODE_DISALLOW_DCBOR_SIMPLES,
-
-} QCBORDecodeMode;
-
-
-
-/**
- * The maximum size of input to the decoder. Slightly less than
- * @c UINT32_MAX to make room for some special indicator values.
- */
-#define QCBOR_MAX_DECODE_INPUT_SIZE (UINT32_MAX - 2)
-
-/**
- * The maximum number of tags that may occur on an individual nested
- * item. Typically 4.
- */
-#define QCBOR_MAX_TAGS_PER_ITEM QCBOR_MAX_TAGS_PER_ITEM1
-
-
-
-/* Do not renumber these. Code depends on some of these values. */
-/** The data type is unknown, unset or invalid. */
-#define QCBOR_TYPE_NONE           0
-
-/** Never used in QCBORItem. Used by functions that match QCBOR types. */
-#define QCBOR_TYPE_ANY            1
-
-/** Type for an integer that decoded either between @c INT64_MIN and
- *  @c INT32_MIN or @c INT32_MAX and @c INT64_MAX. Data is in member
- *  @c val.int64. See also \ref QCBOR_TYPE_65BIT_NEG_INT */
-#define QCBOR_TYPE_INT64          2
-
-/** Type for an integer that decoded to a more than @c INT64_MAX and
- *  @c UINT64_MAX.  Data is in member @c val.uint64. */
-#define QCBOR_TYPE_UINT64         3
-
-/** Type for an array. See comments on @c val.uCount. */
-#define QCBOR_TYPE_ARRAY          4
-
-/** Type for a map. See comments on @c val.uCount. */
-#define QCBOR_TYPE_MAP            5
-
-/** Type for a buffer full of bytes. Data is in @c val.string. */
-#define QCBOR_TYPE_BYTE_STRING    6
-
-/** Type for a UTF-8 string. It is not NULL-terminated. See
- *  QCBOREncode_AddText() for a discussion of line endings in CBOR. Data
- *  is in @c val.string.  */
-#define QCBOR_TYPE_TEXT_STRING    7
-
-/** Type for a positive big number. Data is in @c val.bignum, a
- *  pointer and a length. See QCBORDecode_StringsTagCB()
- *  and @ref CBOR_TAG_POS_BIGNUM. */
-#define QCBOR_TYPE_POSBIGNUM      9
-
-/** Type for a negative big number. Data is in @c val.bignum, a
- *  pointer and a length. Type 1 integers in the range of [-2^64,
- *  -2^63 - 1] are returned in this type.  One must be subtracted from
- *  what is returned to get the actual value. This is because of the
- *  way CBOR negative numbers are represented. QCBOR doesn't do this
- *  because it can't be done without storage allocation and QCBOR
- *  avoids storage allocation for the most part.  For example, if 1 is
- *  subtraced from a negative big number that is the two bytes 0xff
- *  0xff, the result would be 0x01 0x00 0x00, one byte longer than
- *  what was received. See QCBORDecode_StringsTagCB(). and
- *  @ref  CBOR_TAG_NEG_BIGNUM. */
-#define QCBOR_TYPE_NEGBIGNUM     10
-
-/** Type for [RFC 3339] (https://tools.ietf.org/html/rfc3339) date
- *  string, possibly with time zone. Data is in @c val.string . Note this
- *  was previously in @c val.dateString, however this is the same as
- *  val.string being the same type in same union. val.dateString will
- *  be deprecated.. */
-#define QCBOR_TYPE_DATE_STRING   11
-
-/** Type for integer seconds since Jan 1970 + floating-point
- *  fraction. Data is in @c val.epochDate */
-#define QCBOR_TYPE_DATE_EPOCH    12
-
-/** The CBOR major type "simple" has a small integer value indicating
- *  what it is. The standard CBOR simples are true, false, null, undef
- *  (values 20-23) and float-point numbers (values 25-27).  The values
- *  0-19 and 32-255 are unassigned and may be used if registered with
- *  in the IANA Simple Values Registry.  If these unassigned simple
- *  values occur in the input they will be decoded as this.  The value
- *  is in @c val.uSimple. */
-#define QCBOR_TYPE_UKNOWN_SIMPLE 13
-
-/** A decimal fraction made of decimal exponent and integer mantissa.
- *  See @ref expAndMantissa and QCBOREncode_AddTDecimalFraction(). */
-#define QCBOR_TYPE_DECIMAL_FRACTION            14
-
-/** A decimal fraction made of decimal exponent and positive big
- *  number mantissa. See @ref expAndMantissa and
- *  QCBOREncode_AddTDecimalFractionBigMantissa(). */
-#define QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM 15
-
-/** A decimal fraction made of decimal exponent and negative big
- *  number mantissa. See @ref expAndMantissa and
- *  QCBOREncode_AddTDecimalFractionBigMantissa(). */
-#define QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM 16
-
-/** A decimal fraction made of decimal exponent and positive
- * uint64_t . See QCBOREncode_AddTDecimalFractionBigMantissa(). */
-#define QCBOR_TYPE_DECIMAL_FRACTION_POS_U64    79
-
-/** A decimal fraction made of decimal exponent and negative big
- *  number mantissa. See @ref expAndMantissa and
- *  QCBOREncode_AddTDecimalFractionBigMantissa(). */
-#define QCBOR_TYPE_DECIMAL_FRACTION_NEG_U64    80
-
-/** A floating-point number made of base-2 exponent and integer
- *  mantissa.  See @ref expAndMantissa and
- *  QCBOREncode_AddTBigFloat(). */
-#define QCBOR_TYPE_BIGFLOAT                    17
-
-/** A floating-point number made of base-2 exponent and positive big
- *  number mantissa.  See @ref expAndMantissa and
- *  QCBOREncode_AddTBigFloatBigMantissa(). */
-// TODO: rename to BIGMANTISSA?
-#define QCBOR_TYPE_BIGFLOAT_POS_BIGNUM         18
-
-/** A floating-point number made of base-2 exponent and negative big
- *  number mantissa.  See @ref expAndMantissa and
- *  QCBOREncode_AddTBigFloatBigMantissa(). */
-#define QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM         19
-
-/** A floating-point number made of base-2 exponent and positive big
- *  number mantissa.  See @ref expAndMantissa and
- *  QCBOREncode_AddTBigFloatBigMantissa(). */
-// TODO: rename to U64MANTISSA
-#define QCBOR_TYPE_BIGFLOAT_POS_U64            82
-
-/** A floating-point number made of base-2 exponent and negative big
- *  number mantissa.  See @ref expAndMantissa and
- *  QCBOREncode_AddTBigFloatBigMantissa(). */
-#define QCBOR_TYPE_BIGFLOAT_NEG_U64            83
-
-/** Type for the simple value false. */
-#define QCBOR_TYPE_FALSE         20
-
-/** Type for the simple value true. */
-#define QCBOR_TYPE_TRUE          21
-
-/** Type for the simple value null. */
-#define QCBOR_TYPE_NULL          22
-
-/** Type for the simple value undef. */
-#define QCBOR_TYPE_UNDEF         23
-
-/** Type for a floating-point number. Data is in @c val.fnum. */
-#define QCBOR_TYPE_FLOAT         26
-
-/** Type for a double floating-point number. Data is in @c val.dfnum. */
-#define QCBOR_TYPE_DOUBLE        27
-
-/** Special type for integers between -2^63 - 1 to -2^64 that
- * can't be returned as @ref QCBOR_TYPE_INT64 because they don't fit
- * in an int64_t. The value is returned in @c val.uint64, but this
- * isn't the number transmitted. Do this arithmatic (carefully to
- * avoid over/underflow) to get the value transmitted: - val.uint64 - 1.
- * See QCBOREncode_AddNegativeUInt64() for a longer explanation
- * and warning. */
-#define QCBOR_TYPE_65BIT_NEG_INT 28
-
-#define QCBOR_TYPE_BREAK         31 /* Used internally; never returned */
-
-/** For @ref QCBOR_DECODE_MODE_MAP_AS_ARRAY decode mode, a map that is
- *  being traversed as an array. See QCBORDecode_Init() */
-#define QCBOR_TYPE_MAP_AS_ARRAY  32
-
-/** Encoded CBOR that is wrapped in a byte string. Often used when the
- *  CBOR is to be hashed for signing or HMAC. See also @ref
- *  QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE. Data is in @c val.string. */
-#define QBCOR_TYPE_WRAPPED_CBOR  36
-
-/** A URI as defined in RFC 3986.  Data is in @c val.string. */
-#define QCBOR_TYPE_URI           44
-
-/** Text is base64 URL encoded in RFC 4648.  The base64 encoding is
- *  NOT removed. Data is in @c val.string. */
-#define QCBOR_TYPE_BASE64URL     45
-
-/** Text is base64 encoded in RFC 4648.  The base64 encoding is NOT
- *  removed. Data is in @c val.string. */
-#define QCBOR_TYPE_BASE64        46
-
-/** PERL-compatible regular expression. Data is in @c val.string. */
-#define QCBOR_TYPE_REGEX         47
-
-/** Non-binary MIME per RFC 2045.  See also @ref
- *  QCBOR_TYPE_BINARY_MIME. Data is in @c val.string. */
-#define QCBOR_TYPE_MIME          48
-
-/** Binary UUID per RFC 4122.  Data is in @c val.string. */
-#define QCBOR_TYPE_UUID          49
-
-/** A CBOR sequence per RFC 8742. See also @ ref
- *  QBCOR_TYPE_WRAPPED_CBOR.  Data is in @c val.string. */
-#define QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE  75
-
-/** Binary MIME per RFC 2045. See also @ref QCBOR_TYPE_MIME. Data is
- *  in @c val.string. */
-#define QCBOR_TYPE_BINARY_MIME   76
-
-/** Type for [RFC 8943](https://tools.ietf.org/html/rfc8943) date
- *  string, a date with no time or time zone info. Data is in
- *  @c val.string */
-#define QCBOR_TYPE_DAYS_STRING   77
-
-/** Type for integer days since Jan 1 1970 described in
- *  [RFC 8943](https://tools.ietf.org/html/rfc8943). Data is in
- *  @c val.epochDays */
-#define QCBOR_TYPE_DAYS_EPOCH    78
-
-/* 79, 80, 82, 83 is used above for decimal fraction and big float */
-
-
-#define QCBOR_TYPE_TAG_NUMBER 127 /* Used internally; never returned */
-
-/** Start of user-defined data types. The range is mainly for user-defined tag content
- * decoders. See QCBORTagContentCallBack */
-#define QCBOR_TYPE_START_USER_DEFINED 128
-
-/** End of user-defined data types. */
-#define QCBOR_TYPE_END_USER_DEFINED 255
-
-
-/**
- * The largest value in @c utags that is unmapped and can be used without
- * mapping it through QCBORDecode_GetNthTagNumber().
- */
-#define QCBOR_LAST_UNMAPPED_TAG (CBOR_TAG_INVALID16 - QCBOR_NUM_MAPPED_TAGS - 1)
-
-
-/**
- * @anchor expAndMantissa
- *
- * This holds the value for big floats and decimal fractions, as an
- * exponent and mantissa.  For big floats the base for exponentiation
- * is 2. For decimal fractions it is 10. Whether an instance is a big
- * float or decimal fraction is known by context, usually by @c uDataType
- * in @ref QCBORItem which might be @ref QCBOR_TYPE_DECIMAL_FRACTION,
- * @ref QCBOR_TYPE_BIGFLOAT, ...
- *
- * The mantissa may be an @c int64_t or a big number. This is again
- * determined by context, usually @c uDataType in @ref QCBORItem which
- * might be @ref QCBOR_TYPE_DECIMAL_FRACTION,
- * @ref QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, ...  The sign of the
- * big number also comes from the context
- * (@ref QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
- * @ref QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM,...).
- *
- * @c bigNum is big endian or network byte order. The most significant
- * byte is first.
- *
- * When @c Mantissa is @c int64_t, it represents the true value of the
- * mantissa with the offset of 1 for CBOR negative values
- * applied. When it is a negative big number
- * (@ref QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM or
- * @ref QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM), the offset of 1 has NOT been
- * applied (doing so requires somewhat complex big number arithmetic
- * and may increase the length of the big number). To get the correct
- * value @c bigNum must be incremented by one before use.
- *
- * Also see QCBOREncode_AddTDecimalFraction(),
- * QCBOREncode_AddTBigFloat(), QCBOREncode_AddTDecimalFractionBigNum()
- * and QCBOREncode_AddTBigFloatBigNum().
- */
-typedef struct  {
-   int64_t nExponent;
-   union {
-      int64_t    nInt;
-      uint64_t   uInt;
-      UsefulBufC bigNum;
-   } Mantissa;
-} QCBORExpAndMantissa;
-
-
-/**
- * This holds a decoded data item. It is returned by the
- * QCBORDecode_GetNext(), the principle decoding function.
- * It holds the type, value, label, tags and other details
- * of the decoded data item.
- *
- * This is typically 56 bytes on 64-bit CPUs and 52 bytes on 32-bit
- * CPUs (the CPU and the system's ABI determine this size).
- */
-typedef struct _QCBORItem {
-   /** Tells what element of the @c val union to use. One of @ref
-    *  QCBOR_TYPE_INT64, @ref QCBOR_TYPE_ARRAY, ...*/
-   uint8_t  uDataType;
-
-   /** Tells what element of the @c label union to use. One of
-    *  @ref QCBOR_TYPE_INT64, @ref QCBOR_TYPE_BYTE_STRING, ...*/
-   uint8_t  uLabelType;
-
-   /** Holds the nesting depth for arrays and map. 0 is the top level
-    *  with no arrays or maps entered. */
-   uint8_t  uNestingLevel;
-
-   /** Holds the nesting level of the next item after this one.  If
-    *  less than @c uNestingLevel, this item was the last one in an
-    *  arry or map and it closed out at least one nesting level. */
-   uint8_t  uNextNestLevel;
-
-   /** 1 if a @c val that is a string is allocated with string
-    * allocator, 0 if not. Always 0 unless an allocator has been set
-    * up by calling QCBORDecode_SetMemPool() or
-    * QCBORDecode_SetUpAllocator(). */
-   uint8_t  uDataAlloc;
-
-   /** 1 if a @c label that is a string is allocated with string
-    * allocator, 0 if not. Always 0 unless an allocator has been set
-    * up by calling QCBORDecode_SetMemPool() or
-    * QCBORDecode_SetUpAllocator(). */
-   uint8_t  uLabelAlloc;
-
-   /** The union holding the item's value. Select union member based
-    *  on @c uDataType. */
-   union {
-      /** The value for @c uDataType @ref QCBOR_TYPE_INT64. */
-      int64_t     int64;
-      /** The value for @c uDataType @ref QCBOR_TYPE_UINT64. */
-      uint64_t    uint64;
-      /** The value for @c uDataType @ref QCBOR_TYPE_BYTE_STRING and
-       *  @ref QCBOR_TYPE_TEXT_STRING. Also
-       *  for many tags whose content is a string such @ref QCBOR_TYPE_DAYS_STRING
-       *  and @ref QCBOR_TYPE_URI. */
-      UsefulBufC  string;
-      /** The "value" for @c uDataType @ref QCBOR_TYPE_ARRAY or @ref
-       *  QCBOR_TYPE_MAP, the number of items in the array or map.  It
-       *  is @c UINT16_MAX when decoding indefinite-lengths maps and
-       *  arrays. Detection of the end of a map or array is best done
-       *  with @c uNestLevel and @c uNextNestLevel so as to work for
-       *  both definite and indefinite length maps and arrays. */
-      uint16_t    uCount;
-#ifndef USEFULBUF_DISABLE_ALL_FLOAT
-      /** The value for @c uDataType @ref QCBOR_TYPE_DOUBLE. */
-      double      dfnum;
-      /** The value for @c uDataType @ref QCBOR_TYPE_FLOAT. */
-      float       fnum;
-#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
-      /** The value for @c uDataType @ref QCBOR_TYPE_DATE_EPOCH, the
-       *  number of seconds after or before Jan 1, 1970. This has a
-       *  range of 500 billion years. Floating-point dates are
-       *  converted to this integer + fractional value. If the input
-       *  value is beyond the 500 billion-year range (e.g., +/i
-       *  infinity, large floating point values, NaN)
-       *  @ref QCBOR_ERR_DATE_OVERFLOW will be returned. If the input
-       *  is floating-point and QCBOR has been compiled with
-       *  floating-point disabled, one of the various floating-point
-       *  disabled errors will be returned. */
-      struct {
-         int64_t  nSeconds;
-#ifndef USEFULBUF_DISABLE_ALL_FLOAT
-         double   fSecondsFraction;
-#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
-      } epochDate;
-
-      /** The value for @c uDataType @ref QCBOR_TYPE_DAYS_EPOCH -- the
-       *  number of days before or after Jan 1, 1970. */
-      int64_t     epochDays;
-
-      /** The value for @c uDataType @ref QCBOR_TYPE_POSBIGNUM and
-       * @ref QCBOR_TYPE_NEGBIGNUM.  */
-      UsefulBufC  bigNum;
-
-      /** See @ref QCBOR_TYPE_UKNOWN_SIMPLE */
-      uint8_t     uSimple;
-
-#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
-      QCBORExpAndMantissa expAndMantissa;
-#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
-
-      uint64_t    uTagNumber; /* Used internally during decoding */
-
-      /* For use by user-defined tag content handlers */
-      uint8_t     userDefined[24];
-   } val;
-
-   /** Union holding the different label types selected based on @c uLabelType */
-   union {
-      /** The label for @c uLabelType for @ref QCBOR_TYPE_INT64 */
-      int64_t     int64;
-#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
-      /** The label for @c uLabelType for @ref QCBOR_TYPE_UINT64 */
-      uint64_t    uint64;
-      /** The label for @c uLabelType @ref QCBOR_TYPE_BYTE_STRING and
-       *  @ref QCBOR_TYPE_TEXT_STRING */
-      UsefulBufC  string;
-#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
-   } label;
-
-#ifndef QCBOR_DISABLE_TAGS
-   /**
-    * PRIVATE MEMBER
-    * Use  QCBORDecode_GetNthTagNumber() to retrieve tag numbers on an item.
-    * Also see @ref Tags-Overview.
-    *
-    * In QCBOR v1 this was named uTags and was in the reverse order.
-    * It wasn't explicitly described as private, but was implicitly private.
-    */
-   QCBORMappedTagNumbers auTagNumbers;
-#endif
-} QCBORItem;
-
-/**
- * An array or map's length is indefinite when it has this value.
- */
-#define QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH UINT16_MAX
-
-
-
-
-/**
- * @brief Prototype for the implementation of a string allocator.
- *
- * @param[in] pAllocateCxt Pointer to context for the particular
- *                         allocator implementation. Its contents
- *                         depend on how a particular string allocator
- *                         works. Typically, it will contain a pointer
- *                         to the memory pool and some booking keeping
- *                         data.
- *
- * @param[in] pOldMem      Points to some memory previously allocated
- *                         that is either to be freed or to be
- *                         reallocated to be larger. It is @c NULL for
- *                         new allocations and when called as the
- *                         destructor.
- *
- * @param[in] uNewSize     Size of memory to be allocated or new size
- *                         for a chunk being reallocated. Zero when
- *                         called to free memory or when called as the
- *                         destructor.
- *
- * @return Either the allocated buffer is returned, or
- *         @ref NULLUsefulBufC. @ref NULLUsefulBufC is returned on a
- *         failed allocation and in the two cases where there is
- *         nothing to return.
- *
- * This function must be implemented for a custom string
- * allocator. See QCBORDecode_SetUpAllocator().
- *
- * This is not needed if the built-in string allocator available
- * through QCBORDecode_SetMemPool() is used.
- *
- * After being set up by a call to QCBORDecode_SetUpAllocator(),
- * this is called back in four modes:
- *
- * - allocate: @c uNewSize is the amount to allocate. @c pOldMem is
- *  @c NULL.
- *
- * - free: @c uNewSize is 0. @c pOldMem points to the memory to be
- * freed.  When the decoder calls this, it will always be for the most
- * recent block that was either allocated or reallocated.
- *
- * - reallocate: @c pOldMem is the block to reallocate. @c uNewSize is
- * its new size.  When the decoder calls this, it will always be for the
- * most recent block that was either allocated or reallocated.
- *
- * - destruct: @c pOldMem is @c NULL and @c uNewSize is 0. This is
- * called when the decoding is complete by
- * QCBORDecode_Finish(). Usually, the strings allocated by a string
- * allocator are in use after the decoding is completed so this
- * usually will not free those strings. Many string allocators will
- * not need to do anything in this mode.
- *
- * The strings allocated by this will have @c uDataAlloc set to true
- * in the @ref QCBORItem when they are returned. The user of the
- * strings will have to free them. How they free them, depends on the
- * design of the string allocator.
- */
-typedef UsefulBuf (* QCBORStringAllocate)(void   *pAllocateCxt,
-                                          void   *pOldMem,
-                                          size_t  uNewSize);
-
-
-/**
- * For the built-in string allocator available via
- * QCBORDecode_SetMemPool(), this is the size overhead needed
- * internally.  The amount of memory available for decoded strings is
- * the size of the buffer given to QCBORDecode_SetMemPool() less this
- * amount.
- *
- * This doesn't apply to custom string allocators, only to the one
- * available via QCBORDecode_SetMemPool().
- */
-#define QCBOR_DECODE_MIN_MEM_POOL_SIZE 8
-
-
-
-
-/**
- * QCBORDecodeContext holds the context for decoding CBOR.  It is
- * about 300 bytes, so it can go on the stack.  The contents are
- * opaque, and the caller should not access any internal items.  A
- * context may be re-used serially as long as it is re initialized.
- */
-typedef struct _QCBORDecodeContext QCBORDecodeContext;
-
-
-/**
- * Initialize the CBOR decoder context.
- *
- * @param[in] pCtx          The context to initialize.
- * @param[in] EncodedCBOR   The buffer with CBOR encoded bytes to be decoded.
- * @param[in] uConfigFlags  See @ref QCBORDecodeMode.
- *
- * Initialize the decoder context with the encoded CBOR to be decoded.
- *
- * For typical use, @c uConfigFlags is zero (@ref QCBOR_DECODE_MODE_NORMAL).
- * See configuration flags that can be or'd defined in @ref QCBORDecodeMode.
- *
- * If indefinite-length strings are to be decoded, then
- * QCBORDecode_SetMemPool() or QCBORDecode_SetUpAllocator() must be
- * additionally called to set up a string allocator.
- */
-void
-QCBORDecode_Init(QCBORDecodeContext *pCtx, UsefulBufC EncodedCBOR, QCBORDecodeMode uConfigFlags);
-
-
-/**
- * @brief Set up the MemPool string allocator for indefinite-length strings.
- *
- * @param[in] pCtx         The decode context.
- * @param[in] MemPool      The pointer and length of the memory pool.
- * @param[in] bAllStrings  If true, all strings, even of definite
- *                         length, will be allocated with the string
- *                         allocator.
- *
- * @return Error if the MemPool was greater than @c UINT32_MAX
- *         or less than @ref QCBOR_DECODE_MIN_MEM_POOL_SIZE.
- *
- * Indefinite-length strings (text and byte) cannot be decoded unless
- * there is a string allocator configured. MemPool is a simple
- * built-in string allocator that allocates bytes from a memory pool
- * handed to it by calling this function.  The memory pool is just a
- * pointer and length for some block of memory that is to be used for
- * string allocation. It can come from the stack, heap or other.
- *
- * The memory pool must be @ref QCBOR_DECODE_MIN_MEM_POOL_SIZE plus
- * space for all the strings allocated.  There is no overhead per
- * string allocated. A conservative way to size this buffer is to make
- * it the same size as the CBOR being decoded plus @ref
- * QCBOR_DECODE_MIN_MEM_POOL_SIZE.
- *
- * This memory pool is used for all indefinite-length strings that are
- * text strings or byte strings, including strings used as labels.
- *
- * The pointers to strings in @ref QCBORItem will point into the
- * memory pool set here. They do not need to be individually
- * freed. Just discard the buffer when they are no longer needed.
- *
- * If @c bAllStrings is set, then the size will be the overhead plus
- * the space to hold **all** strings, definite and indefinite-length,
- * value or label. The advantage of this is that after the decode is
- * complete, the original memory holding the encoded CBOR does not
- * need to remain valid.
- *
- * This simple allocator is not hard linked to the QCBOR decoder.
- * Assuming dead-stripping of unused symbols is being performed, this
- * simple allocator will not be linked in unless
- * QCBORDecode_SetMemPool() is called.
- *
- * See also QCBORDecode_SetUpAllocator() to set up a custom allocator
- * if this one isn't sufficient.
- */
-QCBORError
-QCBORDecode_SetMemPool(QCBORDecodeContext *pCtx,
-                       UsefulBuf           MemPool,
-                       bool                bAllStrings);
-
-
-/**
- * @brief Sets up a custom string allocator for indefinite-length strings
- *
- * @param[in] pCtx                 The decoder context to set up an
- *                                 allocator for.
- * @param[in] pfAllocateFunction   Pointer to function that will be
- *                                 called by QCBOR for allocations and
- *                                 frees.
- * @param[in] pAllocateContext     Context passed to @c
- *                                 pfAllocateFunction.
- * @param[in] bAllStrings          If true, all strings, even of definite
- *                                 length, will be allocated with the
- *                                 string allocator.
- *
- * Indefinite-length strings (text and byte) cannot be decoded unless
- * a string allocator is configured. QCBORDecode_SetUpAllocator()
- * allows the caller to configure an external string allocator
- * implementation if the internal string allocator is
- * unsuitable. See QCBORDecode_SetMemPool() to configure the internal
- * allocator.
- *
- * The string allocator configured here is a custom one designed
- * and implemented by the caller.  See @ref QCBORStringAllocate for
- * the requirements for a string allocator implementation.
- *
- * A malloc-based string external allocator can be obtained by calling
- * @c QCBORDecode_MakeMallocStringAllocator(). It will return a
- * function and pointer that can be given here as @c pAllocatorFunction
- * and @c pAllocatorContext. It uses standard @c malloc() so @c free()
- * must be called on all strings marked by @c uDataAlloc @c == @c 1 or
- * @c uLabelAlloc @c == @c 1 in @ref QCBORItem. Note this is in a
- * separate GitHub repository.
- */
-void
-QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx,
-                           QCBORStringAllocate pfAllocateFunction,
-                           void               *pAllocateContext,
-                           bool                bAllStrings);
-
-
-/**
- * @brief Get the next item (integer, byte string, array...) in the
- * preorder traversal of the CBOR tree.
- *
- * @param[in]  pCtx          The decoder context.
- * @param[out] pDecodedItem  The decoded CBOR item.
- *
- * @c pDecodedItem is filled from the decoded item. Generally, the
- * following data is returned in the structure:
- *
- * - @c uDataType which indicates which member of the @c val union the
- *   data is in. This decoder figures out the type based on the CBOR
- *   major type, the CBOR "additionalInfo", the CBOR optional tags and
- *   the value of the integer.
- *
- * - The value of the item, which might be an integer, a pointer and a
- *   length, the count of items in an array, a floating-point number or
- *   other.
- *
- * - The nesting level for maps and arrays.
- *
- * - The label for an item in a map, which may be a text or byte string
- *   or an integer.
- *
- * - The unprocessed tag numbers for which the item is the tag content.
- *
- * See @ref QCBORItem for all the details about what is returned.
- *
- * This function handles arrays and maps. When an array or map is
- * first encountered a @ref QCBORItem will be returned with major type
- * @ref QCBOR_TYPE_ARRAY or @ref QCBOR_TYPE_MAP.  @c
- * QCBORItem.val.uNestLevel gives the nesting level of the opening of
- * the array or map. When the next item is fetched, it will be the
- * first one in the array or map and its @c QCBORItem.val.uNestLevel
- * will be one more than that of the opening of the array or map.
- *
- * Nesting level 0 is the top-most nesting level. The first item
- * decoded always has nesting level 0. A map or array at the top level
- * has nesting level 0 and the members of the array or map have
- * nesting level 1.
- *
- * Here is an example of how the nesting level is reported for a CBOR
- * sequence with no arrays or maps at all.
- *
- * @code
- * Data Item           Nesting Level
- * integer                     0
- * byte string                 0
- * @endcode
- *
- * Here is an example of how the nesting level is reported for a CBOR
- * sequence with a simple array and some top-level items.
- *
- * @code
- * Data Item           Nesting Level
- * integer                     0
- * array with 2 items          0
- *    byte string              1
- *    byte string              1
- * integer                     0
- * @endcode
- *
- * Here's a more complex example that is not a CBOR sequence
- *
- * @code
- * Data Item           Nesting Level
- * map with 4 items            0
- *    text string              1
- *    array with 3 integers    1
- *       integer               2
- *       integer               2
- *       integer               2
- *    text string              1
- *    byte string              1
- * @endcode
- *
- * In @ref QCBORItem, @c uNextNestLevel is the nesting level for the
- * next call to QCBORDecode_VGetNext(). It indicates if any maps or
- * arrays were closed out during the processing of the just-fetched
- * @ref QCBORItem. This processing includes a look-ahead for any
- * breaks that close out indefinite-length arrays or maps. This value
- * is needed to be able to understand the hierarchical structure. If
- * @c uNextNestLevel is not equal to @c uNestLevel the end of the
- * current map or array has been encountered. This works for both
- * definite and indefinite-length arrays so it is the best way to find the
- * end of a map or array. Alternatively, for definite-length arrays,
- * @c QCBORItem.val.uCount contains the number of items in the
- * array. For indefinite-length arrays, @c QCBORItem.val.uCount
- * is @c UINT16_MAX.
- *
- * See extensive discussion in @ref Tag-Decoding.
- *
- * See [Decode Error Overview](#Decode-Errors-Overview).
- *
- * If a decoding error occurs or previously occured, @c uDataType and
- * @c uLabelType will be set to @ref QCBOR_TYPE_NONE. If there is no
- * need to know the specific error, it is sufficient to check for @ref
- * QCBOR_TYPE_NONE.
- *
- * Errors fall in several categories:
- *
- * - Not well-formed errors are those where there is something
- *   syntactically and fundamentally wrong with the CBOR being
- *   decoded. Decoding should stop completely.
- *
- * - Invalid CBOR is well-formed, but still not correct. It is
- *   probably best to stop decoding, but not necessary.
- *
- * - This implementation has some size limits. They should rarely be
- *   encountered. If they are it may because something is wrong with
- *   the CBOR, for example an array size is incorrect.
- *
- * - There are a few CBOR constructs that are not handled without some
- *   extra configuration. These are indefinite length strings and maps
- *   with labels that are not strings or integers. See
- *   QCBORDecode_Init().  Also, the QCBOR library may have been
- *   compiled with some features disabled to reduce code size and this
- *   can result in some errors.
- *
- * - Resource exhaustion. This only occurs when a string allocator is
- *   configured to handle indefinite-length strings as other than
- *   that, this implementation does no dynamic memory allocation.
- *
- * x
- * | __Not well-formed errors__  ||
- * | @ref QCBOR_ERR_HIT_END                 | Partial data item; need more input bytes to complete decoding |
- * | @ref QCBOR_ERR_UNSUPPORTED             | Input contains CBOR with reserved additional info values |
- * | @ref QCBOR_ERR_BAD_TYPE_7              | Simple value encoded as two-byte integer rather than one |
- * | @ref QCBOR_ERR_BAD_BREAK               | Break occured outside an indefinite-length map or such |
- * | @ref QCBOR_ERR_BAD_INT                 | Length of integer is bad |
- * | @ref QCBOR_ERR_INDEFINITE_STRING_CHUNK | One of the chunks in indefinite-length string is the wrong type |
- * | __Invalid CBOR__  ||
- * | @ref QCBOR_ERR_NO_MORE_ITEMS        | Need more input data items to decode |
- * | @ref QCBOR_ERR_BAD_EXP_AND_MANTISSA | The structure of a big float or big number is invalid |
- * | @ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT | The content of a tag is of the wrong type |
- * | __Implementation Limits__  ||
- * | @ref QCBOR_ERR_INT_OVERFLOW                  | Input integer smaller than INT64_MIN |
- * | @ref QCBOR_ERR_ARRAY_DECODE_TOO_LONG         | Array or map has more elements than can be handled |
- * | @ref QCBOR_ERR_DATE_OVERFLOW                 | Date larger than can be handled |
- * | @ref QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP | Nesting deeper than can be handled |
- * | @ref QCBOR_ERR_STRING_TOO_LONG               | Encountered a string longer than size_t can hold less 4 bytes |
- * | @ref QCBOR_ERR_TOO_MANY_TAGS                 | Tag nesting deeper than limit, typically 4 |
- * | __Configuration errors__  ||
- * | @ref QCBOR_ERR_NO_STRING_ALLOCATOR        | Encountered indefinite-length string with no allocator configured |
- * | @ref QCBOR_ERR_MAP_LABEL_TYPE             | A map label that is not a string on an integer |
- * | @ref QCBOR_ERR_HALF_PRECISION_DISABLED    | Half-precision input, but disabled in QCBOR library |
- * | @ref QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED  | Indefinite-length input, but disabled in QCBOR library |
- * | @ref QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED | Indefinite-length input, but disabled in QCBOR library |
- * | @ref QCBOR_ERR_ALL_FLOAT_DISABLED             | Library compiled with floating-point support turned off. |
- * | __Resource exhaustion errors__  ||
- * | @ref QCBOR_ERR_STRING_ALLOCATE | The string allocator is unable to allocate more memory |
- */
-void
-QCBORDecode_VGetNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
-
-
-/**
- * @brief Preorder traversal like QCBORDecode_VGetNext() without use
- * of internal error state.
- *
- * @param[in]  pCtx          The decoder context.
- * @param[out] pDecodedItem  The decoded CBOR item.
- *
- * @return See error table of decoding errors set by QCBORDecode_VGetNext().
- *
- * This is the same as QCBORDecode_VGetNext() except it
- * doesn't set the internal decoding error and will attempt to decode
- * even if the decoder is in the error state.
- */
-QCBORError
-QCBORDecode_GetNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
-
-
-/**
- * @brief Get the next item, fully consuming it if it is a map or array.
- *
- * @param[in]  pCtx          The decoder context.
- * @param[out] pDecodedItem  The decoded CBOR item.
- *
- * @c pItem returned is the same as QCBORDecode_VGetNext(). If the
- * item is an array or map, the entire contents of the array or map
- * will be consumed leaving the cursor after the array or map.
- *
- * If an array or map is being consumed by this, an error will occur
- * if any of the items in the array or map are in error.
- *
- * If the item is a tag the contents of which is an array or map, like
- * a big float, @c pItem will identify it as such and the contents
- * will be consumed, but the validity of the tag won't be checked
- * other than for being well-formed.
- *
- * In order to go back to decode the contents of an array or map
- * consumed by this, the decoder must be rewound using
- * QCBORDecode_Rewind().
- */
-void
-QCBORDecode_VGetNextConsume(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
-
-
-/**
- * @brief Get the next data item without consuming it.
- *
- * @param[in]  pCtx          The decoder context.
- * @param[out] pDecodedItem  The decoded CBOR item.
- *
- * This is the same as QCBORDecode_VGetNext() but does not consume the
- * data item. This only looks ahead one item. Calling it repeatedly
- * will just return the same item over and over.
- *
- * This uses about 200 bytes of stack, far more than anything else
- * here in qcbor_decode.h because it saves a copy of most of the
- * decode context temporarily.
- *
- * This is useful for looking ahead to determine the type of a data
- * item to know which type-specific spiffy decode function to call or
- * decoding protocols where the types of later data items
- * depending on type of earlier ones.
- *
- * The error must be retrieved with QCBORDecode_GetError() and checked
- * to know the peek was successful before referencing the contents of
- * @c pDecodedItem.
- */
-void
-QCBORDecode_VPeekNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
-
-
-/**
- * @brief Get the next data item without consuming it without use
- * of internal error state.
- *
- * @param[in]  pCtx          The decoder context.
- * @param[out] pDecodedItem  The decoded CBOR item.
- *
- * This is the same as QCBORDecode_VPeekNext() except it doesn't set
- * the internal decoding error and will attempt to decode even if the
- * decoder is in the error state.
- */
-QCBORError
-QCBORDecode_PeekNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
-
-
-/**
- * @brief Get the current traversal cursort offset in the input CBOR.
- *
- * @param[in]  pCtx   The decoder context.
- *
- * @returns The traversal cursor offset or @c UINT32_MAX.
-
- * The position returned is always the start of the next item that
- * would be next decoded with QCBORDecode_VGetNext(). The cursor
- * returned may be at the end of the input in which case the next call
- * to QCBORDecode_VGetNext() will result in the @ref
- * QCBOR_ERR_NO_MORE_ITEMS. See also QCBORDecode_AtEnd().
- *
- * If the decoder is in error state from previous decoding,
- * @c UINT32_MAX is returned.
- *
- * When decoding map items, the position returned is always of the
- * label, never the value.
- *
- * For indefinite-length arrays and maps, the break byte is consumed
- * when the last item in the array or map is consumed so the cursor is
- * at the next item to be decoded as expected.
- *
- * There are some special rules for the traversal cursor when fetching
- * map items by label. See the description of @SpiffyDecode.
- *
- * When traversal is bounded because an array or map has been entered
- * (e.g., QCBORDecode_EnterMap()) and all items in the array or map
- * have been consumed, the position returned will be of the item
- * outside of the array or map. The array or map must be exited before
- * QCBORDecode_VGetNext() will decode it.
- *
- * In many cases the position returned will be in the middle of
- * an array or map. It will not be possible to start decoding at
- * that location with another instance of the decoder and go to
- * the end. It is not valid CBOR. If the input is a CBOR sequence
- * and the position is not in the moddle of an array or map
- * then it is possible to decode to the end.
- *
- * There is no corresponding seek method because it is too complicated
- * to restore the internal decoder state that tracks nesting.
- */
-static uint32_t
-QCBORDecode_Tell(QCBORDecodeContext *pCtx);
-
-
-/**
- * @brief Tell whether cursor is at end of the input.
- *
- * @param[in] pCtx   The decoder context.
- *
- * @returns Error code possibly indicating end of input.
- *
- * This returns the same as QCBORDecode_GetError() except that @ref
- * QCBOR_ERR_NO_MORE_ITEMS is returned if the travseral cursor is at
- * the end of the CBOR input bytes (not the end of an entered array or
- * map).
- */
-QCBORError
-QCBORDecode_EndCheck(QCBORDecodeContext *pCtx);
-
-
-
-/**
- * @brief Check that a decode completed successfully.
- *
- * @param[in]  pCtx  The context to check.
- *
- * @returns The internal tracked decode error or @ref QCBOR_SUCCESS.
- *
- * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
- *
- * This should always be called at the end of a decode to determine if
- * it completed successfully.  For some protocols, checking the return
- * value here may be the only error check necessary.
- *
- * This returns the internal tracked error if the decoder is in the
- * error state, the same one returned by QCBORDecode_GetError().  This
- * performs final checks at the end of the decode, and may also return
- * @ref QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN
- * or @ref QCBOR_ERR_EXTRA_BYTES.
- *
- * This calls the destructor for the string allocator, if one is in
- * use. Because of this, It can't be called multiple times like
- * QCBORDecode_PartialFinish().
- *
- * Some CBOR protocols use a CBOR sequence defined in [RFC 8742]
- * (https://tools.ietf.org/html/rfc8742). A CBOR sequence typically
- * doesn't start out with a map or an array. The end of the CBOR is
- * determined in some other way, perhaps by external framing, or by
- * the occurrence of some particular CBOR data item or such. The
- * buffer given to decode must start out with valid CBOR, but it can
- * have extra bytes at the end that are not CBOR or CBOR that is to be
- * ignored.
- *
- * QCBORDecode_Finish() should still be called when decoding CBOR
- * sequences to check that the input decoded was well-formed. If the
- * input was well-formed and there are extra bytes at the end @ref
- * QCBOR_ERR_EXTRA_BYTES will be returned.  This can be considered a
- * successful decode.  See also QCBORDecode_PartialFinish().
- */
-QCBORError
-QCBORDecode_Finish(QCBORDecodeContext *pCtx);
-
-
-/**
- * @brief Return number of bytes consumed so far.
- *
- * @param[in]  pCtx        The context to check.
- * @param[out] puConsumed  The number of bytes consumed so far.
- *                          May be @c NULL.
- *
- * @returns The same as QCBORDecode_Finish();
- *
- * This is primarily for partially decoding CBOR sequences. It is the
- * same as QCBORDecode_Finish() except it returns the number of bytes
- * consumed and doesn't call the destructor for the string allocator
- * (See @ref QCBORDecode_SetMemPool()).
- *
- * When this is called before all input bytes are consumed, @ref
- * QCBOR_ERR_EXTRA_BYTES will be returned as QCBORDecode_Finish()
- * does. For typical use of this, that particular error is disregarded.
- *
- * Decoding with the same @ref QCBORDecodeContext can continue after
- * calling this and this may be called many times.
- *
- * Another way to resume decoding is to call QCBORDecode_Init() with the
- * bytes not decoded, but this only works on CBOR sequences when the
- * decoding stopped with no open arrays, maps or byte strings.
- */
-QCBORError
-QCBORDecode_PartialFinish(QCBORDecodeContext *pCtx, size_t *puConsumed);
-
-
-/**
- * @brief  Retrieve the undecoded input buffer.
- *
- * @param[in]  pCtx  The decode context.
- *
- * @return The input that was given to QCBORDecode_Init().
- *
- * A simple convenience method, should it be useful to get the original input back.
- */
-static UsefulBufC
-QCBORDecode_RetrieveUndecodedInput(QCBORDecodeContext *pCtx);
-
-
-/**
- * @brief Get the decoding error.
- *
- * @param[in] pCtx    The decoder context.
- * @return            The decoding error.
- *
- * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
- *
- * The returns the tracked internal error code. All decoding functions
- * set the internal error except QCBORDecode_GetNext() and
- * QCBORDecode_PeekNext().
- *
- * For many protocols it is only necessary to check the return code
- * from QCBORDecode_Finish() at the end of all the decoding.  It is
- * unnecessary to call this.
- *
- * For some protocols, the decoding sequence depends on the types,
- * values or labels of data items. If so, this must be called before
- * using decoded values to know the decode was a success and the
- * type, value and label is valid.
- *
- * Some errors, like integer conversion overflow, date string format
- * may not affect the flow of a protocol. The protocol decoder may
- * wish to proceed even if they occur. In that case
- * QCBORDecode_GetAndResetError() may be called after these data items
- * are fetched.
- */
-static QCBORError
-QCBORDecode_GetError(QCBORDecodeContext *pCtx);
-
-
-/**
- * @brief Get and reset the decoding error.
- *
- * @param[in] pCtx    The decoder context.
- * @returns The decoding error.
- *
- * This returns the same as QCBORDecode_GetError() and also resets the
- * error state to @ref QCBOR_SUCCESS.
- */
-static QCBORError
-QCBORDecode_GetAndResetError(QCBORDecodeContext *pCtx);
-
-
-/**
- * @brief Whether an error indicates non-well-formed CBOR.
- *
- * @param[in] uErr    The QCBOR error code.
- * @return @c true if the error code indicates non-well-formed CBOR.
- */
-static bool
-QCBORDecode_IsNotWellFormedError(QCBORError uErr);
-
-
-/**
- * @brief Whether a decoding error is recoverable.
- *
- * @param[in] uErr    The QCBOR error code.
- * @return @c true if the error code indicates and uncrecoverable error.
- *
- * When an error is unrecoverable, no further decoding of the input is
- * possible.  CBOR is a compact format with almost no redundancy so
- * errors like incorrect lengths or array counts are
- * unrecoverable. Unrecoverable errors also occur when implementation
- * limits such as the limit on array and map nesting are encountered.
- * When the built-in decoding of a tag like an epoch date encounters
- * an error such as a data item of an unexpected type, this is also an
- * unrecoverable error because the internal decoding doesn't try to
- * decode everything in the tag.
- *
- * The unrecoverable errors are a range of the errors in
- * @ref QCBORError.
- */
-static bool
-QCBORDecode_IsUnrecoverableError(QCBORError uErr);
-
-
-/**
- * @brief Manually set error condition, or set user-defined error.
- *
- * @param[in] pCtx    The decoder context.
- * @param[in] uError  The error code to set.
- *
- * Once set, none of the QCBORDecode methods will do anything and the
- * error code set will stay until cleared with
- * QCBORDecode_GetAndResetError().  A user-defined error can be set
- * deep in some decoding layers to short-circuit further decoding
- * and propagate up.
- *
- * When the error condition is set, QCBORDecode_VGetNext() will always
- * return an item with data and label type as @ref QCBOR_TYPE_NONE.
- *
- * The main intent of this is to set a user-defined error code in the
- * range of @ref QCBOR_ERR_FIRST_USER_DEFINED to
- * @ref QCBOR_ERR_LAST_USER_DEFINED, but it is OK to set QCBOR-defined
- * error codes too.
- */
-static void
-QCBORDecode_SetError(QCBORDecodeContext *pCtx, QCBORError uError);
-
-
-
-
-/* ========================================================================= *
- *    BEGINNING OF DEPRECATED FUNCTIONS                                      *
- *                                                                           *
- *    There is no plan to remove these in future versions.                   *
- *    They just have been replaced by something better.                      *
- * ========================================================================= */
-
-/**
- * @brief Configure CBOR decoder context for QCBOR v1 compatibility (deprecated).
- *
- * @param[in] pCtx  The context to configure.
- *
- * This performs two actions to make QCBOR v2 decoding compatible with v1.
- *
- * First, it sets @ref QCBOR_DECODE_ALLOW_UNPROCESSED_TAG_NUMBERS
- * which causes no error to be returned when un processed tag numbers
- * are encountered.
- *
- * Second, it installs all the same tag content handlers that were hardwired in v1.
- *    QCBORDecode_InstallTagDecoders(pMe, QCBORDecode_TagDecoderTablev1, NULL);
- *
- * This is listed as deprecated even though it is new in QCBOR v2
- * because it recommended that v1 mode not be used because the tag
- * number processing is too loose. See @ref v2-Tag-Decoding.
- *
- * This links in a fair bit of object code for all the tag content
- * handlers that were always present in v1. To get the v1 behavior
- * without the object code for the tag content handlers, pass
- * @ref QCBOR_DECODE_ALLOW_UNPROCESSED_TAG_NUMBERS to
- * QCBORDecode_Init().
- */
-void
-QCBORDecode_CompatibilityV1(QCBORDecodeContext *pCtx);
-
-
-/* ========================================================================= *
- *    END OF DEPRECATED FUNCTIONS                                            *
- * ========================================================================= */
-
-
-
-
-/* ========================================================================= *
- *    BEGINNING OF PRIVATE INLINE IMPLEMENTATION                             *
- * ========================================================================= */
-
-static inline uint32_t
-QCBORDecode_Tell(QCBORDecodeContext *pMe)
-{
-   if(pMe->uLastError) {
-      return UINT32_MAX;
-   }
-
-   /* Cast is safe because decoder input size is restricted. */
-   return (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
-}
-
-static inline UsefulBufC
-QCBORDecode_RetrieveUndecodedInput(QCBORDecodeContext *pMe)
-{
-   return UsefulInputBuf_RetrieveUndecodedInput(&(pMe->InBuf));
-}
-
-static inline QCBORError
-QCBORDecode_GetError(QCBORDecodeContext *pMe)
-{
-    return (QCBORError)pMe->uLastError;
-}
-
-static inline QCBORError
-QCBORDecode_GetAndResetError(QCBORDecodeContext *pMe)
-{
-    const QCBORError uReturn = (QCBORError)pMe->uLastError;
-    pMe->uLastError = QCBOR_SUCCESS;
-    return uReturn;
-}
-
-static inline bool
-QCBORDecode_IsNotWellFormedError(const QCBORError uErr)
-{
-   if(uErr >= QCBOR_START_OF_NOT_WELL_FORMED_ERRORS &&
-      uErr <= QCBOR_END_OF_NOT_WELL_FORMED_ERRORS) {
-      return true;
-   } else {
-      return false;
-   }
-}
-
-static inline bool
-QCBORDecode_IsUnrecoverableError(const QCBORError uErr)
-{
-   if(uErr >= QCBOR_START_OF_UNRECOVERABLE_DECODE_ERRORS &&
-      uErr <= QCBOR_END_OF_UNRECOVERABLE_DECODE_ERRORS) {
-      return true;
-   } else {
-      return false;
-   }
-}
-
-
-static inline void
-QCBORDecode_SetError(QCBORDecodeContext *pMe, QCBORError uError)
-{
-   pMe->uLastError = (uint8_t)uError;
-}
-
-/* ======================================================================== *
- *    END OF PRIVATE INLINE IMPLEMENTATION                                  *
- * ======================================================================== */
-
-
-/* A few cross checks on size constants and special value lengths */
-#if  QCBOR_MAP_OFFSET_CACHE_INVALID < QCBOR_MAX_DECODE_INPUT_SIZE
-#error QCBOR_MAP_OFFSET_CACHE_INVALID is too large
-#endif
-
-#if QCBOR_NON_BOUNDED_OFFSET < QCBOR_MAX_DECODE_INPUT_SIZE
-#error QCBOR_NON_BOUNDED_OFFSET is too large
-#endif
-
-#ifdef __cplusplus
-}
-#endif
+#include "qcbor/qcbor_main_decode.h"
+#include "qcbor/qcbor_tag_decode.h"
+#include "qcbor/qcbor_number_decode.h"
 
 #endif /* qcbor_decode_h */
diff --git a/inc/qcbor/qcbor_encode.h b/inc/qcbor/qcbor_encode.h
index 93b9b03..e37b654 100644
--- a/inc/qcbor/qcbor_encode.h
+++ b/inc/qcbor/qcbor_encode.h
@@ -31,7 +31,6 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * ========================================================================= */
 
-
 #ifndef qcbor_encode_h
 #define qcbor_encode_h
 
diff --git a/inc/qcbor/qcbor_main_decode.h b/inc/qcbor/qcbor_main_decode.h
new file mode 100644
index 0000000..40cc78f
--- /dev/null
+++ b/inc/qcbor/qcbor_main_decode.h
@@ -0,0 +1,1611 @@
+/* ===========================================================================
+ * qcbor_main_decode.h -- The main CBOR decoder.
+ *
+ * Copyright (c) 2016-2018, The Linux Foundation.
+ * Copyright (c) 2018-2024, Laurence Lundblade.
+ * Copyright (c) 2021, Arm Limited.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors, nor the name "Laurence Lundblade" may be used to
+ *       endorse or promote products derived from this software without
+ *       specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ========================================================================= */
+
+#ifndef qcbor_main_decode_h
+#define qcbor_main_decode_h
+
+
+#include "qcbor/qcbor_common.h"
+#include "qcbor/qcbor_private.h"
+#include <stdbool.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+} /* Keep editor indention formatting happy */
+#endif
+#endif
+
+
+/**
+ * @file qcbor_main_decode.h
+ *
+ * @anchor BasicDecode
+ * # QCBOR Basic Decode
+ *
+ * This section discusses decoding assuming familiarity with the
+ * general description of this encoder-decoder in section @ref
+ * Overview.
+ *
+ * Encoded CBOR has a tree structure where the leaf nodes are
+ * non-aggregate types like integers and strings and the intermediate
+ * nodes are either arrays or maps. Fundamentally, CBOR decoding is a
+ * pre-order traversal of this tree with CBOR sequences a minor
+ * exception. Calling QCBORDecode_GetNext() repeatedly will perform
+ * this. QCBOR maintains an internal traversal cursor. It is possible
+ * to decode any CBOR by only calling QCBORDecode_GetNext(), though
+ * this doesn't take advantage of many QCBOR features.
+ *
+ * QCBORDecode_GetNext() returns a 56 byte structure called
+ * @ref QCBORItem that describes the decoded item including:
+ * - The data itself, integer, string, floating-point number...
+ * - The label if present
+ * - Unprocessed tags
+ * - Nesting level
+ * - Allocation type (primarily of interest for indefinite length strings)
+ *
+ * For strings, this structure contains a pointer and length back into
+ * the original data.
+ *
+ * Most of the tags that QCBOR supports directly are decoded into a
+ * representation in @ref QCBORItem.
+ *
+ * A string allocator must be used when decoding indefinite length
+ * strings. See QCBORDecode_SetMemPool() or
+ * QCBORDecode_SetUpAllocator(). @ref QCBORItem indicates if a string
+ * was allocated with the string allocator.
+ *
+ * This pre-order traversal gives natural decoding of arrays where the
+ * array members are taken in order. Maps can be decoded this way too,
+ * but the @ref SpiffyDecode APIs that allow searching maps by label
+ * are often more convenient.
+ *
+ * @anchor v2-Tag-Decoding
+ *
+ * RFC 7049 called tags "optional". This was a mistake. They specify
+ * critical type information that can't be ignored by decoders.
+ *
+ * QCBOR v1 always returns the tag numbers on an item
+ * in QCBORItem and leaves it up to the caller to check.
+ * Probably most callers don't know this and never added
+ * the check. There decode implementations are tolerant
+ * of random tag numbers and they shouldn't be.
+ *
+ * QCBOR v2 requires tags numbers to be processed by
+ * QCBORDecode_GetNextTagNumber(). If they are not
+ * an error will be returned.
+ *
+ * This new behavior saves the caller from having to do this check
+ * (that they probably didn't know they neeeded).  It is much more
+ * correct behavior.
+ *
+ * This behavior is not backwards compatible with v1. The v1 behavior
+ * can be restored with @ref QCBOR_DECODE_ALLOW_UNPROCESSED_TAG_NUMBERS.
+ * However, the v2 behavior is more correct, so this configuration
+ * should not be used.
+ *
+ * @anchor Decode-Errors-Overview
+ * # Decode Errors Overview
+ *
+ * The simplest way to handle decoding errors is to make use of the
+ * internal error tracking. The only error code check necessary is
+ * at the end when QCBORDecode_Finish() is called. To do this:
+ *
+ * - Use QCBORDecode_VGetNext(), QCBORDecode_VPeekNext()
+ *  and any or all of the functions in qcbor_spiffy_decode.h. Don't use
+ *  QCBORDecode_GetNext() or QCBORDecode_PeekNext().
+ * - Call QCBORDecode_Finish() and check its return code.
+ * - Do not reference any decoded data until after
+ *    QCBORDecode_Finish() returns success.
+ *
+ * Once an encoding error has been encountered, the error state is
+ * entered and further decoding function calls will do nothing.  It is
+ * safe to continue calling decoding functions after an error. No
+ * error checking is necessary making the code to decode a protocol
+ * simpler.  The two exceptions are QCBORDecode_GetNext() and
+ * QCBORDecode_PeekNext() which will try to decode even if the decoder
+ * is in the error state. Use QCBORDecode_VGetNext() and
+ * QCBORDecode_VPeekNext() instead.
+ *
+ * While some protocols are simple enough to be decoded this way, many
+ * aren’t because the data items earlier in the protocol determine how
+ * later data items are to be decoded. In that case it is necessary to
+ * call QCBORDecode_GetError() to know the earlier items were
+ * successfully decoded before examining their value or type.
+ *
+ * The internal decode error state can be reset by reinitializing the
+ * decoder or calling QCBORDecode_GetErrorAndReset(). Code calling
+ * QCBOR may take advantage of the internal error state to halt
+ * futher decoding and propagate errors it detects using
+ * QCBORDecode_SetError().
+ *
+ * It is only useful to reset the error state by calling
+ * QCBORDecode_GetErrorAndReset() on recoverable errors. Examples of
+ * recoverable errors are a map entry not being found or integer
+ * overflow or underflow during conversion. Examples of unrecoverable
+ * errors are hitting the end of the input and array or map nesting
+ * beyond the limits of the implementation. See
+ * QCBORDecode_IsUnrecoverableError().Trying to reset and decode after
+ * an unrecoverable error will usually just lead to another error.
+ *
+ * It is possible to use QCBORDecode_GetNext() and
+ * QCBORDecode_PeekNext() to decode an entire protocol. However, that is
+ * usually more work, more code and less convenient than using spiffy
+ * decode functions.
+ *
+ * It is also possible to mix the use of QCBORDecode_GetNext() with
+ * QCBORDecode_VGetNext() and the spiffy decode functions, but
+ * QCBORDecode_GetError() must be called and return QCBOR_SUCCESS before
+ * QCBORDecode_GetNext() is called.
+ *
+ * The effect of a decoding error on the traversal cursor position
+ * varies by the decoding method called. It is unaffected by spiffy
+ * decode methods that get items by map label.
+ * QCBORDecode_GetInt64InMapN() is an example of this. The traversal
+ * cursor will be advanced by most other decode methods even when
+ * there is a decode error, often leaving it in an indeterminate
+ * position. If it is necessary to continue to decoding after an
+ * error, QCBORDecode_Rewind() can be used to reset it to a known-good
+ * position.
+ *
+ * When using spiffy decode methods to get an item by label from a map
+ * the whole map is internally traversed including nested arrays and
+ * maps. If there is any unrecoverable error during that traversal,
+ * the retrieval by label will fail. The unrecoverable error will be
+ * returned even if it is not because the item being sought is in
+ * error. Recoverable errors will be ignored unless they are on the
+ * item being sought, in which case the unrecoverable error will be
+ * returned. Unrecoverable errors are those indicated by
+ * QCBORDecode_IsUnrecoverableError().
+ *
+ * @anchor Disabilng-Tag-Decoding
+ * # Disabilng Tag Decoding
+ *
+ * TODO: update this
+ * If QCBOR_DISABLE_TAGS is defined, all code for decoding tags will
+ * be omitted reducing the core decoder, QCBORDecode_VGetNext(), by
+ * about 400 bytes. If a tag number is encountered in the decoder
+ * input the unrecoverable error @ref QCBOR_ERR_TAGS_DISABLED will be
+ * returned.  No input with tags can be decoded.
+ *
+ * Decode functions like QCBORDecode_GetEpochDate() and
+ * QCBORDecode_GetDecimalFraction() that can decode the tag content
+ * even if the tag number is absent are still available.  Typically
+ * they won't be linked in because of dead stripping. The
+ * @c uTagRequirement parameter has no effect, but if it is
+ * @ref QCBOR_TAG_REQUIREMENT_TAG, @ref QCBOR_ERR_TAGS_DISABLED
+ * will be set.
+ */
+
+
+/**
+ *  These are the decode configuration flags that can be or'd together
+ *  and passed to QCBORDecode_Init().
+ */
+typedef enum {
+   /** Normal decoding with no flags set. */
+   QCBOR_DECODE_MODE_NORMAL = 0,
+
+   /** Required map labels to be strings. If not @ref  QCBOR_ERR_MAP_LABEL_TYPE
+    * occurs. */
+   QCBOR_DECODE_MODE_MAP_STRINGS_ONLY = 0x01,
+
+   /** Causes maps to be treated as special arrays so all types of map
+    * labels can be decoded..  They will be returned with special
+    * @c uDataType @ref QCBOR_TYPE_MAP_AS_ARRAY and @c uCount, the
+    * number of items, will be double what it would be for a normal
+    * map because the labels are also counted. This mode is useful for
+    * decoding CBOR that has labels that are not integers or
+    * strings. Each map entry is decoded with two Get() calls, one for
+    * the label and one for the value. QCBORItem.label is never filled
+    * in. */
+   QCBOR_DECODE_MODE_MAP_AS_ARRAY = 0x02,
+
+   /** Makes QCBOR v2 tag decoding compatible with QCBOR v1. The error
+    *  @ref QCBOR_ERR_UNPROCESSED_TAG_NUMBER is not returned.  See
+    *  @ref v2-Tag-Decoding and QCBORDecode_CompatibilityV1().
+    */
+   QCBOR_DECODE_ALLOW_UNPROCESSED_TAG_NUMBERS = 0x04,
+
+   /** Error out on indefinite length strings, arrays and maps. */
+   QCBOR_DECODE_NO_INDEF_LENGTH = 0x08,
+
+   /** Error out if integers or floats are encoded as
+    *  non-preferred. */
+   QCBOR_DECODE_ONLY_PREFERRED_NUMBERS = 0x10,
+
+   /** If big numbers that will fit into normal integers are
+    *  encountered error XXX will occur. This is to comply with big
+    *  number preferred serialization. */
+   QCBOR_DECODE_ONLY_PREFERRED_BIG_NUMBERS = 0x20,
+
+   /** If maps are not sorted, error @ref QCBOR_ERR_UNSORTED
+    *  occurs. This is makes map decoding take more CPU time, but that
+    *  is probably only of consequence with big maps on small CPUs. */
+   QCBOR_DECODE_ONLY_SORTED_MAPS = 0x40,
+
+   /** If whole number floats are present (they are not encoded as
+    * integers), error @ref QCBOR_ERR_DCBOR_CONFORMANCE occurs. This
+    * is as required for dCBOR.
+    */
+   QCBOR_DECODE_ONLY_REDUCED_FLOATS = 0x80,
+
+   /** dCBOR allows only the simple types true, false and NULL
+    * This enforces that.
+    */
+   QCBOR_DECODE_DISALLOW_DCBOR_SIMPLES = 0x100,
+
+   /**
+    * This checks that the input is encoded with preferred
+    * serialization. The checking is performed as each item is
+    * decoded. If no QCBORDecode_GetXxx() is called for an item,
+    * there's no check on that item. Preferred serialization was first
+    * defined in section 4.1 of RFC 8949, but is more sharply in
+    * draft-ietf-cbor-cde. Summarizing, the requirements are: the use
+    * of definite-length encoding only, integers, including string
+    * lengths and tags, must be in shortest form, and floating-point
+    * numbers must be reduced to shortest form all the way to
+    * half-precision. */
+   QCBOR_DECODE_MODE_PREFERRED = QCBOR_DECODE_NO_INDEF_LENGTH |
+                                 QCBOR_DECODE_ONLY_PREFERRED_NUMBERS |
+                                 QCBOR_DECODE_ONLY_PREFERRED_BIG_NUMBERS,
+
+   /** This checks that maps in the input are sorted by label as
+    * described in RFC 8949 section 4.2.1.  This also performs
+    * duplicate label checking.  This mode adds considerable CPU-time
+    * expense to decoding, though it is probably only of consequence
+    * for large inputs on slow CPUs.
+    *
+    * This also performs all the checks that
+    * @ref QCBOR_DECODE_MODE_PREFERRED does. */
+   QCBOR_DECODE_MODE_CDE = QCBOR_DECODE_MODE_PREFERRED |
+                           QCBOR_DECODE_ONLY_SORTED_MAPS,
+
+   /** This requires integer-float unification. It performs all the checks that
+    * @ref QCBOR_DECODE_MODE_CDE does. */
+   QCBOR_DECODE_MODE_DCBOR = QCBOR_DECODE_MODE_CDE |
+                             QCBOR_DECODE_ONLY_REDUCED_FLOATS |
+                             QCBOR_DECODE_DISALLOW_DCBOR_SIMPLES,
+
+} QCBORDecodeMode;
+
+
+
+/**
+ * The maximum size of input to the decoder. Slightly less than
+ * @c UINT32_MAX to make room for some special indicator values.
+ */
+#define QCBOR_MAX_DECODE_INPUT_SIZE (UINT32_MAX - 2)
+
+/**
+ * The maximum number of tags that may occur on an individual nested
+ * item. Typically 4.
+ */
+#define QCBOR_MAX_TAGS_PER_ITEM QCBOR_MAX_TAGS_PER_ITEM1
+
+
+
+/* Do not renumber these. Code depends on some of these values. */
+/** The data type is unknown, unset or invalid. */
+#define QCBOR_TYPE_NONE           0
+
+/** Never used in QCBORItem. Used by functions that match QCBOR types. */
+#define QCBOR_TYPE_ANY            1
+
+/** Type for an integer that decoded either between @c INT64_MIN and
+ *  @c INT32_MIN or @c INT32_MAX and @c INT64_MAX. Data is in member
+ *  @c val.int64. See also \ref QCBOR_TYPE_65BIT_NEG_INT */
+#define QCBOR_TYPE_INT64          2
+
+/** Type for an integer that decoded to a more than @c INT64_MAX and
+ *  @c UINT64_MAX.  Data is in member @c val.uint64. */
+#define QCBOR_TYPE_UINT64         3
+
+/** Type for an array. See comments on @c val.uCount. */
+#define QCBOR_TYPE_ARRAY          4
+
+/** Type for a map. See comments on @c val.uCount. */
+#define QCBOR_TYPE_MAP            5
+
+/** Type for a buffer full of bytes. Data is in @c val.string. */
+#define QCBOR_TYPE_BYTE_STRING    6
+
+/** Type for a UTF-8 string. It is not NULL-terminated. See
+ *  QCBOREncode_AddText() for a discussion of line endings in CBOR. Data
+ *  is in @c val.string.  */
+#define QCBOR_TYPE_TEXT_STRING    7
+
+/** Type for a positive big number. Data is in @c val.bignum, a
+ *  pointer and a length. See QCBORDecode_StringsTagCB()
+ *  and @ref CBOR_TAG_POS_BIGNUM. */
+#define QCBOR_TYPE_POSBIGNUM      9
+
+/** Type for a negative big number. Data is in @c val.bignum, a
+ *  pointer and a length. Type 1 integers in the range of [-2^64,
+ *  -2^63 - 1] are returned in this type.  One must be subtracted from
+ *  what is returned to get the actual value. This is because of the
+ *  way CBOR negative numbers are represented. QCBOR doesn't do this
+ *  because it can't be done without storage allocation and QCBOR
+ *  avoids storage allocation for the most part.  For example, if 1 is
+ *  subtraced from a negative big number that is the two bytes 0xff
+ *  0xff, the result would be 0x01 0x00 0x00, one byte longer than
+ *  what was received. See QCBORDecode_StringsTagCB(). and
+ *  @ref  CBOR_TAG_NEG_BIGNUM. */
+#define QCBOR_TYPE_NEGBIGNUM     10
+
+/** Type for [RFC 3339] (https://tools.ietf.org/html/rfc3339) date
+ *  string, possibly with time zone. Data is in @c val.string . Note this
+ *  was previously in @c val.dateString, however this is the same as
+ *  val.string being the same type in same union. val.dateString will
+ *  be deprecated.. */
+#define QCBOR_TYPE_DATE_STRING   11
+
+/** Type for integer seconds since Jan 1970 + floating-point
+ *  fraction. Data is in @c val.epochDate */
+#define QCBOR_TYPE_DATE_EPOCH    12
+
+/** The CBOR major type "simple" has a small integer value indicating
+ *  what it is. The standard CBOR simples are true, false, null, undef
+ *  (values 20-23) and float-point numbers (values 25-27).  The values
+ *  0-19 and 32-255 are unassigned and may be used if registered with
+ *  in the IANA Simple Values Registry.  If these unassigned simple
+ *  values occur in the input they will be decoded as this.  The value
+ *  is in @c val.uSimple. */
+#define QCBOR_TYPE_UKNOWN_SIMPLE 13
+
+/** A decimal fraction made of decimal exponent and integer mantissa.
+ *  See @ref expAndMantissa and QCBOREncode_AddTDecimalFraction(). */
+#define QCBOR_TYPE_DECIMAL_FRACTION            14
+
+/** A decimal fraction made of decimal exponent and positive big
+ *  number mantissa. See @ref expAndMantissa and
+ *  QCBOREncode_AddTDecimalFractionBigMantissa(). */
+#define QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM 15
+
+/** A decimal fraction made of decimal exponent and negative big
+ *  number mantissa. See @ref expAndMantissa and
+ *  QCBOREncode_AddTDecimalFractionBigMantissa(). */
+#define QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM 16
+
+/** A decimal fraction made of decimal exponent and positive
+ * uint64_t . See QCBOREncode_AddTDecimalFractionBigMantissa(). */
+#define QCBOR_TYPE_DECIMAL_FRACTION_POS_U64    79
+
+/** A decimal fraction made of decimal exponent and negative big
+ *  number mantissa. See @ref expAndMantissa and
+ *  QCBOREncode_AddTDecimalFractionBigMantissa(). */
+#define QCBOR_TYPE_DECIMAL_FRACTION_NEG_U64    80
+
+/** A floating-point number made of base-2 exponent and integer
+ *  mantissa.  See @ref expAndMantissa and
+ *  QCBOREncode_AddTBigFloat(). */
+#define QCBOR_TYPE_BIGFLOAT                    17
+
+/** A floating-point number made of base-2 exponent and positive big
+ *  number mantissa.  See @ref expAndMantissa and
+ *  QCBOREncode_AddTBigFloatBigMantissa(). */
+// TODO: rename to BIGMANTISSA?
+#define QCBOR_TYPE_BIGFLOAT_POS_BIGNUM         18
+
+/** A floating-point number made of base-2 exponent and negative big
+ *  number mantissa.  See @ref expAndMantissa and
+ *  QCBOREncode_AddTBigFloatBigMantissa(). */
+#define QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM         19
+
+/** A floating-point number made of base-2 exponent and positive big
+ *  number mantissa.  See @ref expAndMantissa and
+ *  QCBOREncode_AddTBigFloatBigMantissa(). */
+// TODO: rename to U64MANTISSA
+#define QCBOR_TYPE_BIGFLOAT_POS_U64            82
+
+/** A floating-point number made of base-2 exponent and negative big
+ *  number mantissa.  See @ref expAndMantissa and
+ *  QCBOREncode_AddTBigFloatBigMantissa(). */
+#define QCBOR_TYPE_BIGFLOAT_NEG_U64            83
+
+/** Type for the simple value false. */
+#define QCBOR_TYPE_FALSE         20
+
+/** Type for the simple value true. */
+#define QCBOR_TYPE_TRUE          21
+
+/** Type for the simple value null. */
+#define QCBOR_TYPE_NULL          22
+
+/** Type for the simple value undef. */
+#define QCBOR_TYPE_UNDEF         23
+
+/** Type for a floating-point number. Data is in @c val.fnum. */
+#define QCBOR_TYPE_FLOAT         26
+
+/** Type for a double floating-point number. Data is in @c val.dfnum. */
+#define QCBOR_TYPE_DOUBLE        27
+
+/** Special type for integers between -2^63 - 1 to -2^64 that
+ * can't be returned as @ref QCBOR_TYPE_INT64 because they don't fit
+ * in an int64_t. The value is returned in @c val.uint64, but this
+ * isn't the number transmitted. Do this arithmatic (carefully to
+ * avoid over/underflow) to get the value transmitted: - val.uint64 - 1.
+ * See QCBOREncode_AddNegativeUInt64() for a longer explanation
+ * and warning. */
+#define QCBOR_TYPE_65BIT_NEG_INT 28
+
+#define QCBOR_TYPE_BREAK         31 /* Used internally; never returned */
+
+/** For @ref QCBOR_DECODE_MODE_MAP_AS_ARRAY decode mode, a map that is
+ *  being traversed as an array. See QCBORDecode_Init() */
+#define QCBOR_TYPE_MAP_AS_ARRAY  32
+
+/** Encoded CBOR that is wrapped in a byte string. Often used when the
+ *  CBOR is to be hashed for signing or HMAC. See also @ref
+ *  QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE. Data is in @c val.string. */
+#define QBCOR_TYPE_WRAPPED_CBOR  36
+
+/** A URI as defined in RFC 3986.  Data is in @c val.string. */
+#define QCBOR_TYPE_URI           44
+
+/** Text is base64 URL encoded in RFC 4648.  The base64 encoding is
+ *  NOT removed. Data is in @c val.string. */
+#define QCBOR_TYPE_BASE64URL     45
+
+/** Text is base64 encoded in RFC 4648.  The base64 encoding is NOT
+ *  removed. Data is in @c val.string. */
+#define QCBOR_TYPE_BASE64        46
+
+/** PERL-compatible regular expression. Data is in @c val.string. */
+#define QCBOR_TYPE_REGEX         47
+
+/** Non-binary MIME per RFC 2045.  See also @ref
+ *  QCBOR_TYPE_BINARY_MIME. Data is in @c val.string. */
+#define QCBOR_TYPE_MIME          48
+
+/** Binary UUID per RFC 4122.  Data is in @c val.string. */
+#define QCBOR_TYPE_UUID          49
+
+/** A CBOR sequence per RFC 8742. See also @ ref
+ *  QBCOR_TYPE_WRAPPED_CBOR.  Data is in @c val.string. */
+#define QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE  75
+
+/** Binary MIME per RFC 2045. See also @ref QCBOR_TYPE_MIME. Data is
+ *  in @c val.string. */
+#define QCBOR_TYPE_BINARY_MIME   76
+
+/** Type for [RFC 8943](https://tools.ietf.org/html/rfc8943) date
+ *  string, a date with no time or time zone info. Data is in
+ *  @c val.string */
+#define QCBOR_TYPE_DAYS_STRING   77
+
+/** Type for integer days since Jan 1 1970 described in
+ *  [RFC 8943](https://tools.ietf.org/html/rfc8943). Data is in
+ *  @c val.epochDays */
+#define QCBOR_TYPE_DAYS_EPOCH    78
+
+/* 79, 80, 82, 83 is used above for decimal fraction and big float */
+
+
+#define QCBOR_TYPE_TAG_NUMBER 127 /* Used internally; never returned */
+
+/** Start of user-defined data types. The range is mainly for user-defined tag content
+ * decoders. See QCBORTagContentCallBack */
+#define QCBOR_TYPE_START_USER_DEFINED 128
+
+/** End of user-defined data types. */
+#define QCBOR_TYPE_END_USER_DEFINED 255
+
+
+/**
+ * The largest value in @c utags that is unmapped and can be used without
+ * mapping it through QCBORDecode_GetNthTagNumber().
+ */
+#define QCBOR_LAST_UNMAPPED_TAG (CBOR_TAG_INVALID16 - QCBOR_NUM_MAPPED_TAGS - 1)
+
+
+/**
+ * @anchor expAndMantissa
+ *
+ * This holds the value for big floats and decimal fractions, as an
+ * exponent and mantissa.  For big floats the base for exponentiation
+ * is 2. For decimal fractions it is 10. Whether an instance is a big
+ * float or decimal fraction is known by context, usually by @c uDataType
+ * in @ref QCBORItem which might be @ref QCBOR_TYPE_DECIMAL_FRACTION,
+ * @ref QCBOR_TYPE_BIGFLOAT, ...
+ *
+ * The mantissa may be an @c int64_t or a big number. This is again
+ * determined by context, usually @c uDataType in @ref QCBORItem which
+ * might be @ref QCBOR_TYPE_DECIMAL_FRACTION,
+ * @ref QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM, ...  The sign of the
+ * big number also comes from the context
+ * (@ref QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
+ * @ref QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM,...).
+ *
+ * @c bigNum is big endian or network byte order. The most significant
+ * byte is first.
+ *
+ * When @c Mantissa is @c int64_t, it represents the true value of the
+ * mantissa with the offset of 1 for CBOR negative values
+ * applied. When it is a negative big number
+ * (@ref QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM or
+ * @ref QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM), the offset of 1 has NOT been
+ * applied (doing so requires somewhat complex big number arithmetic
+ * and may increase the length of the big number). To get the correct
+ * value @c bigNum must be incremented by one before use.
+ *
+ * Also see QCBOREncode_AddTDecimalFraction(),
+ * QCBOREncode_AddTBigFloat(), QCBOREncode_AddTDecimalFractionBigNum()
+ * and QCBOREncode_AddTBigFloatBigNum().
+ */
+typedef struct  {
+   int64_t nExponent;
+   union {
+      int64_t    nInt;
+      uint64_t   uInt;
+      UsefulBufC bigNum;
+   } Mantissa;
+} QCBORExpAndMantissa;
+
+
+
+/**
+ * This holds a decoded data item. It is returned by the
+ * QCBORDecode_GetNext(), the principle decoding function.
+ * It holds the type, value, label, tags and other details
+ * of the decoded data item.
+ *
+ * This is typically 56 bytes on 64-bit CPUs and 52 bytes on 32-bit
+ * CPUs (the CPU and the system's ABI determine this size).
+ */
+typedef struct _QCBORItem {
+   /** Tells what element of the @c val union to use. One of @ref
+    *  QCBOR_TYPE_INT64, @ref QCBOR_TYPE_ARRAY, ...*/
+   uint8_t  uDataType;
+
+   /** Tells what element of the @c label union to use. One of
+    *  @ref QCBOR_TYPE_INT64, @ref QCBOR_TYPE_BYTE_STRING, ...*/
+   uint8_t  uLabelType;
+
+   /** Holds the nesting depth for arrays and map. 0 is the top level
+    *  with no arrays or maps entered. */
+   uint8_t  uNestingLevel;
+
+   /** Holds the nesting level of the next item after this one.  If
+    *  less than @c uNestingLevel, this item was the last one in an
+    *  arry or map and it closed out at least one nesting level. */
+   uint8_t  uNextNestLevel;
+
+   /** 1 if a @c val that is a string is allocated with string
+    * allocator, 0 if not. Always 0 unless an allocator has been set
+    * up by calling QCBORDecode_SetMemPool() or
+    * QCBORDecode_SetUpAllocator(). */
+   uint8_t  uDataAlloc;
+
+   /** 1 if a @c label that is a string is allocated with string
+    * allocator, 0 if not. Always 0 unless an allocator has been set
+    * up by calling QCBORDecode_SetMemPool() or
+    * QCBORDecode_SetUpAllocator(). */
+   uint8_t  uLabelAlloc;
+
+   /** The union holding the item's value. Select union member based
+    *  on @c uDataType. */
+   union {
+      /** The value for @c uDataType @ref QCBOR_TYPE_INT64. */
+      int64_t     int64;
+      /** The value for @c uDataType @ref QCBOR_TYPE_UINT64. */
+      uint64_t    uint64;
+      /** The value for @c uDataType @ref QCBOR_TYPE_BYTE_STRING and
+       *  @ref QCBOR_TYPE_TEXT_STRING. Also
+       *  for many tags whose content is a string such @ref QCBOR_TYPE_DAYS_STRING
+       *  and @ref QCBOR_TYPE_URI. */
+      UsefulBufC  string;
+      /** The "value" for @c uDataType @ref QCBOR_TYPE_ARRAY or @ref
+       *  QCBOR_TYPE_MAP, the number of items in the array or map.  It
+       *  is @c UINT16_MAX when decoding indefinite-lengths maps and
+       *  arrays. Detection of the end of a map or array is best done
+       *  with @c uNestLevel and @c uNextNestLevel so as to work for
+       *  both definite and indefinite length maps and arrays. */
+      uint16_t    uCount;
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+      /** The value for @c uDataType @ref QCBOR_TYPE_DOUBLE. */
+      double      dfnum;
+      /** The value for @c uDataType @ref QCBOR_TYPE_FLOAT. */
+      float       fnum;
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+      /** The value for @c uDataType @ref QCBOR_TYPE_DATE_EPOCH, the
+       *  number of seconds after or before Jan 1, 1970. This has a
+       *  range of 500 billion years. Floating-point dates are
+       *  converted to this integer + fractional value. If the input
+       *  value is beyond the 500 billion-year range (e.g., +/i
+       *  infinity, large floating point values, NaN)
+       *  @ref QCBOR_ERR_DATE_OVERFLOW will be returned. If the input
+       *  is floating-point and QCBOR has been compiled with
+       *  floating-point disabled, one of the various floating-point
+       *  disabled errors will be returned. */
+      struct {
+         int64_t  nSeconds;
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+         double   fSecondsFraction;
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+      } epochDate;
+
+      /** The value for @c uDataType @ref QCBOR_TYPE_DAYS_EPOCH -- the
+       *  number of days before or after Jan 1, 1970. */
+      int64_t     epochDays;
+
+      /** The value for @c uDataType @ref QCBOR_TYPE_POSBIGNUM and
+       * @ref QCBOR_TYPE_NEGBIGNUM.  */
+      UsefulBufC  bigNum;
+
+      /** See @ref QCBOR_TYPE_UKNOWN_SIMPLE */
+      uint8_t     uSimple;
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+      QCBORExpAndMantissa expAndMantissa;
+#endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
+
+      uint64_t    uTagNumber; /* Used internally during decoding */
+
+      /* For use by user-defined tag content handlers */
+      uint8_t     userDefined[24];
+   } val;
+
+   /** Union holding the different label types selected based on @c uLabelType */
+   union {
+      /** The label for @c uLabelType for @ref QCBOR_TYPE_INT64 */
+      int64_t     int64;
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+      /** The label for @c uLabelType for @ref QCBOR_TYPE_UINT64 */
+      uint64_t    uint64;
+      /** The label for @c uLabelType @ref QCBOR_TYPE_BYTE_STRING and
+       *  @ref QCBOR_TYPE_TEXT_STRING */
+      UsefulBufC  string;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+   } label;
+
+#ifndef QCBOR_DISABLE_TAGS
+   /**
+    * PRIVATE MEMBER
+    * Use  QCBORDecode_GetNthTagNumber() to retrieve tag numbers on an item.
+    * Also see @ref Tags-Overview.
+    *
+    * In QCBOR v1 this was named uTags and was in the reverse order.
+    * It wasn't explicitly described as private, but was implicitly private.
+    */
+   QCBORMappedTagNumbers auTagNumbers;
+#endif
+} QCBORItem;
+
+/**
+ * An array or map's length is indefinite when it has this value.
+ */
+#define QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH UINT16_MAX
+
+
+
+
+/**
+ * @brief Prototype for the implementation of a string allocator.
+ *
+ * @param[in] pAllocateCxt Pointer to context for the particular
+ *                         allocator implementation. Its contents
+ *                         depend on how a particular string allocator
+ *                         works. Typically, it will contain a pointer
+ *                         to the memory pool and some booking keeping
+ *                         data.
+ *
+ * @param[in] pOldMem      Points to some memory previously allocated
+ *                         that is either to be freed or to be
+ *                         reallocated to be larger. It is @c NULL for
+ *                         new allocations and when called as the
+ *                         destructor.
+ *
+ * @param[in] uNewSize     Size of memory to be allocated or new size
+ *                         for a chunk being reallocated. Zero when
+ *                         called to free memory or when called as the
+ *                         destructor.
+ *
+ * @return Either the allocated buffer is returned, or
+ *         @ref NULLUsefulBufC. @ref NULLUsefulBufC is returned on a
+ *         failed allocation and in the two cases where there is
+ *         nothing to return.
+ *
+ * This function must be implemented for a custom string
+ * allocator. See QCBORDecode_SetUpAllocator().
+ *
+ * This is not needed if the built-in string allocator available
+ * through QCBORDecode_SetMemPool() is used.
+ *
+ * After being set up by a call to QCBORDecode_SetUpAllocator(),
+ * this is called back in four modes:
+ *
+ * - allocate: @c uNewSize is the amount to allocate. @c pOldMem is
+ *  @c NULL.
+ *
+ * - free: @c uNewSize is 0. @c pOldMem points to the memory to be
+ * freed.  When the decoder calls this, it will always be for the most
+ * recent block that was either allocated or reallocated.
+ *
+ * - reallocate: @c pOldMem is the block to reallocate. @c uNewSize is
+ * its new size.  When the decoder calls this, it will always be for the
+ * most recent block that was either allocated or reallocated.
+ *
+ * - destruct: @c pOldMem is @c NULL and @c uNewSize is 0. This is
+ * called when the decoding is complete by
+ * QCBORDecode_Finish(). Usually, the strings allocated by a string
+ * allocator are in use after the decoding is completed so this
+ * usually will not free those strings. Many string allocators will
+ * not need to do anything in this mode.
+ *
+ * The strings allocated by this will have @c uDataAlloc set to true
+ * in the @ref QCBORItem when they are returned. The user of the
+ * strings will have to free them. How they free them, depends on the
+ * design of the string allocator.
+ */
+typedef UsefulBuf (* QCBORStringAllocate)(void   *pAllocateCxt,
+                                          void   *pOldMem,
+                                          size_t  uNewSize);
+
+
+/**
+ * For the built-in string allocator available via
+ * QCBORDecode_SetMemPool(), this is the size overhead needed
+ * internally.  The amount of memory available for decoded strings is
+ * the size of the buffer given to QCBORDecode_SetMemPool() less this
+ * amount.
+ *
+ * This doesn't apply to custom string allocators, only to the one
+ * available via QCBORDecode_SetMemPool().
+ */
+#define QCBOR_DECODE_MIN_MEM_POOL_SIZE 8
+
+
+
+
+/**
+ * QCBORDecodeContext holds the context for decoding CBOR.  It is
+ * about 300 bytes, so it can go on the stack.  The contents are
+ * opaque, and the caller should not access any internal items.  A
+ * context may be re-used serially as long as it is re initialized.
+ */
+typedef struct _QCBORDecodeContext QCBORDecodeContext;
+
+
+/**
+ * Initialize the CBOR decoder context.
+ *
+ * @param[in] pCtx          The context to initialize.
+ * @param[in] EncodedCBOR   The buffer with CBOR encoded bytes to be decoded.
+ * @param[in] uConfigFlags  See @ref QCBORDecodeMode.
+ *
+ * Initialize the decoder context with the encoded CBOR to be decoded.
+ *
+ * For typical use, @c uConfigFlags is zero (@ref QCBOR_DECODE_MODE_NORMAL).
+ * See configuration flags that can be or'd defined in @ref QCBORDecodeMode.
+ *
+ * If indefinite-length strings are to be decoded, then
+ * QCBORDecode_SetMemPool() or QCBORDecode_SetUpAllocator() must be
+ * additionally called to set up a string allocator.
+ */
+void
+QCBORDecode_Init(QCBORDecodeContext *pCtx, UsefulBufC EncodedCBOR, QCBORDecodeMode uConfigFlags);
+
+
+/**
+ * @brief Set up the MemPool string allocator for indefinite-length strings.
+ *
+ * @param[in] pCtx         The decode context.
+ * @param[in] MemPool      The pointer and length of the memory pool.
+ * @param[in] bAllStrings  If true, all strings, even of definite
+ *                         length, will be allocated with the string
+ *                         allocator.
+ *
+ * @return Error if the MemPool was greater than @c UINT32_MAX
+ *         or less than @ref QCBOR_DECODE_MIN_MEM_POOL_SIZE.
+ *
+ * Indefinite-length strings (text and byte) cannot be decoded unless
+ * there is a string allocator configured. MemPool is a simple
+ * built-in string allocator that allocates bytes from a memory pool
+ * handed to it by calling this function.  The memory pool is just a
+ * pointer and length for some block of memory that is to be used for
+ * string allocation. It can come from the stack, heap or other.
+ *
+ * The memory pool must be @ref QCBOR_DECODE_MIN_MEM_POOL_SIZE plus
+ * space for all the strings allocated.  There is no overhead per
+ * string allocated. A conservative way to size this buffer is to make
+ * it the same size as the CBOR being decoded plus @ref
+ * QCBOR_DECODE_MIN_MEM_POOL_SIZE.
+ *
+ * This memory pool is used for all indefinite-length strings that are
+ * text strings or byte strings, including strings used as labels.
+ *
+ * The pointers to strings in @ref QCBORItem will point into the
+ * memory pool set here. They do not need to be individually
+ * freed. Just discard the buffer when they are no longer needed.
+ *
+ * If @c bAllStrings is set, then the size will be the overhead plus
+ * the space to hold **all** strings, definite and indefinite-length,
+ * value or label. The advantage of this is that after the decode is
+ * complete, the original memory holding the encoded CBOR does not
+ * need to remain valid.
+ *
+ * This simple allocator is not hard linked to the QCBOR decoder.
+ * Assuming dead-stripping of unused symbols is being performed, this
+ * simple allocator will not be linked in unless
+ * QCBORDecode_SetMemPool() is called.
+ *
+ * See also QCBORDecode_SetUpAllocator() to set up a custom allocator
+ * if this one isn't sufficient.
+ */
+QCBORError
+QCBORDecode_SetMemPool(QCBORDecodeContext *pCtx,
+                       UsefulBuf           MemPool,
+                       bool                bAllStrings);
+
+
+/**
+ * @brief Sets up a custom string allocator for indefinite-length strings
+ *
+ * @param[in] pCtx                 The decoder context to set up an
+ *                                 allocator for.
+ * @param[in] pfAllocateFunction   Pointer to function that will be
+ *                                 called by QCBOR for allocations and
+ *                                 frees.
+ * @param[in] pAllocateContext     Context passed to @c
+ *                                 pfAllocateFunction.
+ * @param[in] bAllStrings          If true, all strings, even of definite
+ *                                 length, will be allocated with the
+ *                                 string allocator.
+ *
+ * Indefinite-length strings (text and byte) cannot be decoded unless
+ * a string allocator is configured. QCBORDecode_SetUpAllocator()
+ * allows the caller to configure an external string allocator
+ * implementation if the internal string allocator is
+ * unsuitable. See QCBORDecode_SetMemPool() to configure the internal
+ * allocator.
+ *
+ * The string allocator configured here is a custom one designed
+ * and implemented by the caller.  See @ref QCBORStringAllocate for
+ * the requirements for a string allocator implementation.
+ *
+ * A malloc-based string external allocator can be obtained by calling
+ * @c QCBORDecode_MakeMallocStringAllocator(). It will return a
+ * function and pointer that can be given here as @c pAllocatorFunction
+ * and @c pAllocatorContext. It uses standard @c malloc() so @c free()
+ * must be called on all strings marked by @c uDataAlloc @c == @c 1 or
+ * @c uLabelAlloc @c == @c 1 in @ref QCBORItem. Note this is in a
+ * separate GitHub repository.
+ */
+void
+QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx,
+                           QCBORStringAllocate pfAllocateFunction,
+                           void               *pAllocateContext,
+                           bool                bAllStrings);
+
+
+/**
+ * @brief Get the next item (integer, byte string, array...) in the
+ * preorder traversal of the CBOR tree.
+ *
+ * @param[in]  pCtx          The decoder context.
+ * @param[out] pDecodedItem  The decoded CBOR item.
+ *
+ * @c pDecodedItem is filled from the decoded item. Generally, the
+ * following data is returned in the structure:
+ *
+ * - @c uDataType which indicates which member of the @c val union the
+ *   data is in. This decoder figures out the type based on the CBOR
+ *   major type, the CBOR "additionalInfo", the CBOR optional tags and
+ *   the value of the integer.
+ *
+ * - The value of the item, which might be an integer, a pointer and a
+ *   length, the count of items in an array, a floating-point number or
+ *   other.
+ *
+ * - The nesting level for maps and arrays.
+ *
+ * - The label for an item in a map, which may be a text or byte string
+ *   or an integer.
+ *
+ * - The unprocessed tag numbers for which the item is the tag content.
+ *
+ * See @ref QCBORItem for all the details about what is returned.
+ *
+ * This function handles arrays and maps. When an array or map is
+ * first encountered a @ref QCBORItem will be returned with major type
+ * @ref QCBOR_TYPE_ARRAY or @ref QCBOR_TYPE_MAP.  @c
+ * QCBORItem.val.uNestLevel gives the nesting level of the opening of
+ * the array or map. When the next item is fetched, it will be the
+ * first one in the array or map and its @c QCBORItem.val.uNestLevel
+ * will be one more than that of the opening of the array or map.
+ *
+ * Nesting level 0 is the top-most nesting level. The first item
+ * decoded always has nesting level 0. A map or array at the top level
+ * has nesting level 0 and the members of the array or map have
+ * nesting level 1.
+ *
+ * Here is an example of how the nesting level is reported for a CBOR
+ * sequence with no arrays or maps at all.
+ *
+ * @code
+ * Data Item           Nesting Level
+ * integer                     0
+ * byte string                 0
+ * @endcode
+ *
+ * Here is an example of how the nesting level is reported for a CBOR
+ * sequence with a simple array and some top-level items.
+ *
+ * @code
+ * Data Item           Nesting Level
+ * integer                     0
+ * array with 2 items          0
+ *    byte string              1
+ *    byte string              1
+ * integer                     0
+ * @endcode
+ *
+ * Here's a more complex example that is not a CBOR sequence
+ *
+ * @code
+ * Data Item           Nesting Level
+ * map with 4 items            0
+ *    text string              1
+ *    array with 3 integers    1
+ *       integer               2
+ *       integer               2
+ *       integer               2
+ *    text string              1
+ *    byte string              1
+ * @endcode
+ *
+ * In @ref QCBORItem, @c uNextNestLevel is the nesting level for the
+ * next call to QCBORDecode_VGetNext(). It indicates if any maps or
+ * arrays were closed out during the processing of the just-fetched
+ * @ref QCBORItem. This processing includes a look-ahead for any
+ * breaks that close out indefinite-length arrays or maps. This value
+ * is needed to be able to understand the hierarchical structure. If
+ * @c uNextNestLevel is not equal to @c uNestLevel the end of the
+ * current map or array has been encountered. This works for both
+ * definite and indefinite-length arrays so it is the best way to find the
+ * end of a map or array. Alternatively, for definite-length arrays,
+ * @c QCBORItem.val.uCount contains the number of items in the
+ * array. For indefinite-length arrays, @c QCBORItem.val.uCount
+ * is @c UINT16_MAX.
+ *
+ * See extensive discussion in @ref Tag-Decoding.
+ *
+ * See [Decode Error Overview](#Decode-Errors-Overview).
+ *
+ * If a decoding error occurs or previously occured, @c uDataType and
+ * @c uLabelType will be set to @ref QCBOR_TYPE_NONE. If there is no
+ * need to know the specific error, it is sufficient to check for @ref
+ * QCBOR_TYPE_NONE.
+ *
+ * Errors fall in several categories:
+ *
+ * - Not well-formed errors are those where there is something
+ *   syntactically and fundamentally wrong with the CBOR being
+ *   decoded. Decoding should stop completely.
+ *
+ * - Invalid CBOR is well-formed, but still not correct. It is
+ *   probably best to stop decoding, but not necessary.
+ *
+ * - This implementation has some size limits. They should rarely be
+ *   encountered. If they are it may because something is wrong with
+ *   the CBOR, for example an array size is incorrect.
+ *
+ * - There are a few CBOR constructs that are not handled without some
+ *   extra configuration. These are indefinite length strings and maps
+ *   with labels that are not strings or integers. See
+ *   QCBORDecode_Init().  Also, the QCBOR library may have been
+ *   compiled with some features disabled to reduce code size and this
+ *   can result in some errors.
+ *
+ * - Resource exhaustion. This only occurs when a string allocator is
+ *   configured to handle indefinite-length strings as other than
+ *   that, this implementation does no dynamic memory allocation.
+ *
+ * x
+ * | __Not well-formed errors__  ||
+ * | @ref QCBOR_ERR_HIT_END                 | Partial data item; need more input bytes to complete decoding |
+ * | @ref QCBOR_ERR_UNSUPPORTED             | Input contains CBOR with reserved additional info values |
+ * | @ref QCBOR_ERR_BAD_TYPE_7              | Simple value encoded as two-byte integer rather than one |
+ * | @ref QCBOR_ERR_BAD_BREAK               | Break occured outside an indefinite-length map or such |
+ * | @ref QCBOR_ERR_BAD_INT                 | Length of integer is bad |
+ * | @ref QCBOR_ERR_INDEFINITE_STRING_CHUNK | One of the chunks in indefinite-length string is the wrong type |
+ * | __Invalid CBOR__  ||
+ * | @ref QCBOR_ERR_NO_MORE_ITEMS        | Need more input data items to decode |
+ * | @ref QCBOR_ERR_BAD_EXP_AND_MANTISSA | The structure of a big float or big number is invalid |
+ * | @ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT | The content of a tag is of the wrong type |
+ * | __Implementation Limits__  ||
+ * | @ref QCBOR_ERR_INT_OVERFLOW                  | Input integer smaller than INT64_MIN |
+ * | @ref QCBOR_ERR_ARRAY_DECODE_TOO_LONG         | Array or map has more elements than can be handled |
+ * | @ref QCBOR_ERR_DATE_OVERFLOW                 | Date larger than can be handled |
+ * | @ref QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP | Nesting deeper than can be handled |
+ * | @ref QCBOR_ERR_STRING_TOO_LONG               | Encountered a string longer than size_t can hold less 4 bytes |
+ * | @ref QCBOR_ERR_TOO_MANY_TAGS                 | Tag nesting deeper than limit, typically 4 |
+ * | __Configuration errors__  ||
+ * | @ref QCBOR_ERR_NO_STRING_ALLOCATOR        | Encountered indefinite-length string with no allocator configured |
+ * | @ref QCBOR_ERR_MAP_LABEL_TYPE             | A map label that is not a string on an integer |
+ * | @ref QCBOR_ERR_HALF_PRECISION_DISABLED    | Half-precision input, but disabled in QCBOR library |
+ * | @ref QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED  | Indefinite-length input, but disabled in QCBOR library |
+ * | @ref QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED | Indefinite-length input, but disabled in QCBOR library |
+ * | @ref QCBOR_ERR_ALL_FLOAT_DISABLED             | Library compiled with floating-point support turned off. |
+ * | __Resource exhaustion errors__  ||
+ * | @ref QCBOR_ERR_STRING_ALLOCATE | The string allocator is unable to allocate more memory |
+ */
+void
+QCBORDecode_VGetNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
+
+
+/**
+ * @brief Preorder traversal like QCBORDecode_VGetNext() without use
+ * of internal error state.
+ *
+ * @param[in]  pCtx          The decoder context.
+ * @param[out] pDecodedItem  The decoded CBOR item.
+ *
+ * @return See error table of decoding errors set by QCBORDecode_VGetNext().
+ *
+ * This is the same as QCBORDecode_VGetNext() except it
+ * doesn't set the internal decoding error and will attempt to decode
+ * even if the decoder is in the error state.
+ */
+QCBORError
+QCBORDecode_GetNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
+
+
+/**
+ * @brief Get the next item, fully consuming it if it is a map or array.
+ *
+ * @param[in]  pCtx          The decoder context.
+ * @param[out] pDecodedItem  The decoded CBOR item.
+ *
+ * @c pItem returned is the same as QCBORDecode_VGetNext(). If the
+ * item is an array or map, the entire contents of the array or map
+ * will be consumed leaving the cursor after the array or map.
+ *
+ * If an array or map is being consumed by this, an error will occur
+ * if any of the items in the array or map are in error.
+ *
+ * If the item is a tag the contents of which is an array or map, like
+ * a big float, @c pItem will identify it as such and the contents
+ * will be consumed, but the validity of the tag won't be checked
+ * other than for being well-formed.
+ *
+ * In order to go back to decode the contents of an array or map
+ * consumed by this, the decoder must be rewound using
+ * QCBORDecode_Rewind().
+ */
+void
+QCBORDecode_VGetNextConsume(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
+
+
+/**
+ * @brief Get the next data item without consuming it.
+ *
+ * @param[in]  pCtx          The decoder context.
+ * @param[out] pDecodedItem  The decoded CBOR item.
+ *
+ * This is the same as QCBORDecode_VGetNext() but does not consume the
+ * data item. This only looks ahead one item. Calling it repeatedly
+ * will just return the same item over and over.
+ *
+ * This uses about 200 bytes of stack, far more than anything else
+ * here in qcbor_main_decode.h because it saves a copy of most of the
+ * decode context temporarily.
+ *
+ * This is useful for looking ahead to determine the type of a data
+ * item to know which type-specific spiffy decode function to call or
+ * decoding protocols where the types of later data items
+ * depending on type of earlier ones.
+ *
+ * The error must be retrieved with QCBORDecode_GetError() and checked
+ * to know the peek was successful before referencing the contents of
+ * @c pDecodedItem.
+ */
+void
+QCBORDecode_VPeekNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
+
+
+/**
+ * @brief Get the next data item without consuming it without use
+ * of internal error state.
+ *
+ * @param[in]  pCtx          The decoder context.
+ * @param[out] pDecodedItem  The decoded CBOR item.
+ *
+ * This is the same as QCBORDecode_VPeekNext() except it doesn't set
+ * the internal decoding error and will attempt to decode even if the
+ * decoder is in the error state.
+ */
+QCBORError
+QCBORDecode_PeekNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
+
+
+/**
+ * @brief Get the current traversal cursort offset in the input CBOR.
+ *
+ * @param[in]  pCtx   The decoder context.
+ *
+ * @returns The traversal cursor offset or @c UINT32_MAX.
+
+ * The position returned is always the start of the next item that
+ * would be next decoded with QCBORDecode_VGetNext(). The cursor
+ * returned may be at the end of the input in which case the next call
+ * to QCBORDecode_VGetNext() will result in the @ref
+ * QCBOR_ERR_NO_MORE_ITEMS. See also QCBORDecode_AtEnd().
+ *
+ * If the decoder is in error state from previous decoding,
+ * @c UINT32_MAX is returned.
+ *
+ * When decoding map items, the position returned is always of the
+ * label, never the value.
+ *
+ * For indefinite-length arrays and maps, the break byte is consumed
+ * when the last item in the array or map is consumed so the cursor is
+ * at the next item to be decoded as expected.
+ *
+ * There are some special rules for the traversal cursor when fetching
+ * map items by label. See the description of @SpiffyDecode.
+ *
+ * When traversal is bounded because an array or map has been entered
+ * (e.g., QCBORDecode_EnterMap()) and all items in the array or map
+ * have been consumed, the position returned will be of the item
+ * outside of the array or map. The array or map must be exited before
+ * QCBORDecode_VGetNext() will decode it.
+ *
+ * In many cases the position returned will be in the middle of
+ * an array or map. It will not be possible to start decoding at
+ * that location with another instance of the decoder and go to
+ * the end. It is not valid CBOR. If the input is a CBOR sequence
+ * and the position is not in the moddle of an array or map
+ * then it is possible to decode to the end.
+ *
+ * There is no corresponding seek method because it is too complicated
+ * to restore the internal decoder state that tracks nesting.
+ */
+static uint32_t
+QCBORDecode_Tell(QCBORDecodeContext *pCtx);
+
+
+/**
+ * @brief Tell whether cursor is at end of the input.
+ *
+ * @param[in] pCtx   The decoder context.
+ *
+ * @returns Error code possibly indicating end of input.
+ *
+ * This returns the same as QCBORDecode_GetError() except that @ref
+ * QCBOR_ERR_NO_MORE_ITEMS is returned if the travseral cursor is at
+ * the end of the CBOR input bytes (not the end of an entered array or
+ * map).
+ */
+QCBORError
+QCBORDecode_EndCheck(QCBORDecodeContext *pCtx);
+
+
+
+/**
+ * @brief Check that a decode completed successfully.
+ *
+ * @param[in]  pCtx  The context to check.
+ *
+ * @returns The internal tracked decode error or @ref QCBOR_SUCCESS.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * This should always be called at the end of a decode to determine if
+ * it completed successfully.  For some protocols, checking the return
+ * value here may be the only error check necessary.
+ *
+ * This returns the internal tracked error if the decoder is in the
+ * error state, the same one returned by QCBORDecode_GetError().  This
+ * performs final checks at the end of the decode, and may also return
+ * @ref QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN
+ * or @ref QCBOR_ERR_EXTRA_BYTES.
+ *
+ * This calls the destructor for the string allocator, if one is in
+ * use. Because of this, It can't be called multiple times like
+ * QCBORDecode_PartialFinish().
+ *
+ * Some CBOR protocols use a CBOR sequence defined in [RFC 8742]
+ * (https://tools.ietf.org/html/rfc8742). A CBOR sequence typically
+ * doesn't start out with a map or an array. The end of the CBOR is
+ * determined in some other way, perhaps by external framing, or by
+ * the occurrence of some particular CBOR data item or such. The
+ * buffer given to decode must start out with valid CBOR, but it can
+ * have extra bytes at the end that are not CBOR or CBOR that is to be
+ * ignored.
+ *
+ * QCBORDecode_Finish() should still be called when decoding CBOR
+ * sequences to check that the input decoded was well-formed. If the
+ * input was well-formed and there are extra bytes at the end @ref
+ * QCBOR_ERR_EXTRA_BYTES will be returned.  This can be considered a
+ * successful decode.  See also QCBORDecode_PartialFinish().
+ */
+QCBORError
+QCBORDecode_Finish(QCBORDecodeContext *pCtx);
+
+
+/**
+ * @brief Return number of bytes consumed so far.
+ *
+ * @param[in]  pCtx        The context to check.
+ * @param[out] puConsumed  The number of bytes consumed so far.
+ *                          May be @c NULL.
+ *
+ * @returns The same as QCBORDecode_Finish();
+ *
+ * This is primarily for partially decoding CBOR sequences. It is the
+ * same as QCBORDecode_Finish() except it returns the number of bytes
+ * consumed and doesn't call the destructor for the string allocator
+ * (See @ref QCBORDecode_SetMemPool()).
+ *
+ * When this is called before all input bytes are consumed, @ref
+ * QCBOR_ERR_EXTRA_BYTES will be returned as QCBORDecode_Finish()
+ * does. For typical use of this, that particular error is disregarded.
+ *
+ * Decoding with the same @ref QCBORDecodeContext can continue after
+ * calling this and this may be called many times.
+ *
+ * Another way to resume decoding is to call QCBORDecode_Init() with the
+ * bytes not decoded, but this only works on CBOR sequences when the
+ * decoding stopped with no open arrays, maps or byte strings.
+ */
+QCBORError
+QCBORDecode_PartialFinish(QCBORDecodeContext *pCtx, size_t *puConsumed);
+
+
+/**
+ * @brief  Retrieve the undecoded input buffer.
+ *
+ * @param[in]  pCtx  The decode context.
+ *
+ * @return The input that was given to QCBORDecode_Init().
+ *
+ * A simple convenience method, should it be useful to get the original input back.
+ */
+static UsefulBufC
+QCBORDecode_RetrieveUndecodedInput(QCBORDecodeContext *pCtx);
+
+
+/**
+ * @brief Get the decoding error.
+ *
+ * @param[in] pCtx    The decoder context.
+ * @return            The decoding error.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * The returns the tracked internal error code. All decoding functions
+ * set the internal error except QCBORDecode_GetNext() and
+ * QCBORDecode_PeekNext().
+ *
+ * For many protocols it is only necessary to check the return code
+ * from QCBORDecode_Finish() at the end of all the decoding.  It is
+ * unnecessary to call this.
+ *
+ * For some protocols, the decoding sequence depends on the types,
+ * values or labels of data items. If so, this must be called before
+ * using decoded values to know the decode was a success and the
+ * type, value and label is valid.
+ *
+ * Some errors, like integer conversion overflow, date string format
+ * may not affect the flow of a protocol. The protocol decoder may
+ * wish to proceed even if they occur. In that case
+ * QCBORDecode_GetAndResetError() may be called after these data items
+ * are fetched.
+ */
+static QCBORError
+QCBORDecode_GetError(QCBORDecodeContext *pCtx);
+
+
+/**
+ * @brief Get and reset the decoding error.
+ *
+ * @param[in] pCtx    The decoder context.
+ * @returns The decoding error.
+ *
+ * This returns the same as QCBORDecode_GetError() and also resets the
+ * error state to @ref QCBOR_SUCCESS.
+ */
+static QCBORError
+QCBORDecode_GetAndResetError(QCBORDecodeContext *pCtx);
+
+
+/**
+ * @brief Whether an error indicates non-well-formed CBOR.
+ *
+ * @param[in] uErr    The QCBOR error code.
+ * @return @c true if the error code indicates non-well-formed CBOR.
+ */
+static bool
+QCBORDecode_IsNotWellFormedError(QCBORError uErr);
+
+
+/**
+ * @brief Whether a decoding error is recoverable.
+ *
+ * @param[in] uErr    The QCBOR error code.
+ * @return @c true if the error code indicates and uncrecoverable error.
+ *
+ * When an error is unrecoverable, no further decoding of the input is
+ * possible.  CBOR is a compact format with almost no redundancy so
+ * errors like incorrect lengths or array counts are
+ * unrecoverable. Unrecoverable errors also occur when implementation
+ * limits such as the limit on array and map nesting are encountered.
+ * When the built-in decoding of a tag like an epoch date encounters
+ * an error such as a data item of an unexpected type, this is also an
+ * unrecoverable error because the internal decoding doesn't try to
+ * decode everything in the tag.
+ *
+ * The unrecoverable errors are a range of the errors in
+ * @ref QCBORError.
+ */
+static bool
+QCBORDecode_IsUnrecoverableError(QCBORError uErr);
+
+
+/**
+ * @brief Manually set error condition, or set user-defined error.
+ *
+ * @param[in] pCtx    The decoder context.
+ * @param[in] uError  The error code to set.
+ *
+ * Once set, none of the QCBORDecode methods will do anything and the
+ * error code set will stay until cleared with
+ * QCBORDecode_GetAndResetError().  A user-defined error can be set
+ * deep in some decoding layers to short-circuit further decoding
+ * and propagate up.
+ *
+ * When the error condition is set, QCBORDecode_VGetNext() will always
+ * return an item with data and label type as @ref QCBOR_TYPE_NONE.
+ *
+ * The main intent of this is to set a user-defined error code in the
+ * range of @ref QCBOR_ERR_FIRST_USER_DEFINED to
+ * @ref QCBOR_ERR_LAST_USER_DEFINED, but it is OK to set QCBOR-defined
+ * error codes too.
+ */
+static void
+QCBORDecode_SetError(QCBORDecodeContext *pCtx, QCBORError uError);
+
+
+
+
+/* ========================================================================= *
+ *    BEGINNING OF DEPRECATED FUNCTIONS                                      *
+ *                                                                           *
+ *    There is no plan to remove these in future versions.                   *
+ *    They just have been replaced by something better.                      *
+ * ========================================================================= */
+
+/**
+ * @brief Configure CBOR decoder context for QCBOR v1 compatibility (deprecated).
+ *
+ * @param[in] pCtx  The context to configure.
+ *
+ * This performs two actions to make QCBOR v2 decoding compatible with v1.
+ *
+ * First, it sets @ref QCBOR_DECODE_ALLOW_UNPROCESSED_TAG_NUMBERS
+ * which causes no error to be returned when un processed tag numbers
+ * are encountered.
+ *
+ * Second, it installs all the same tag content handlers that were hardwired in v1.
+ *    QCBORDecode_InstallTagDecoders(pMe, QCBORDecode_TagDecoderTablev1, NULL);
+ *
+ * This is listed as deprecated even though it is new in QCBOR v2
+ * because it recommended that v1 mode not be used because the tag
+ * number processing is too loose. See @ref v2-Tag-Decoding.
+ *
+ * This links in a fair bit of object code for all the tag content
+ * handlers that were always present in v1. To get the v1 behavior
+ * without the object code for the tag content handlers, pass
+ * @ref QCBOR_DECODE_ALLOW_UNPROCESSED_TAG_NUMBERS to
+ * QCBORDecode_Init().
+ */
+void
+QCBORDecode_CompatibilityV1(QCBORDecodeContext *pCtx);
+
+
+/* ========================================================================= *
+ *    END OF DEPRECATED FUNCTIONS                                            *
+ * ========================================================================= */
+
+
+
+
+/* ========================================================================= *
+ *    BEGINNING OF PRIVATE AND INLINE IMPLEMENTATION                             *
+ * ========================================================================= */
+
+/* Semi-private function. See qcbor_decode.c */
+QCBORError
+QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
+                                      QCBORItem          *pDecodedItem);
+
+/* Semi-private function. See qcbor_decode.c */
+void
+QCBORDecode_Private_GetItemInMapNoCheckSZ(QCBORDecodeContext *pMe,
+                                          const char         *szLabel,
+                                          const uint8_t       uQcborType,
+                                          QCBORItem          *pItem,
+                                          size_t             *puOffset);
+
+/* Semi-private function. See qcbor_decode.c */
+void
+QCBORDecode_Private_GetItemInMapNoCheckN(QCBORDecodeContext *pMe,
+                                         const int64_t       nLabel,
+                                         const uint8_t       uQcborType,
+                                         QCBORItem          *pItem,
+                                         size_t             *puOffset);
+
+
+/* Semi-private function. See qcbor_main_decode.c */
+uint64_t
+QCBORDecode_Private_UnMapTagNumber(const QCBORDecodeContext *pMe,
+                                   const uint16_t            uMappedTagNumber);
+
+/* Semi-private function. See qcbor_main_decode.c */
+QCBORError
+QCBORDecode_Private_ConsumeItem(QCBORDecodeContext *pMe,
+                                const QCBORItem    *pItemToConsume,
+                                bool               *pbBreak,
+                                uint8_t            *puNextNestLevel);
+
+/* Semi-private function. See qcbor_main_decode.c */
+QCBORError
+QCBORDecode_Private_GetItemChecks(QCBORDecodeContext *pMe,
+                                  QCBORError          uErr,
+                                  const size_t        uOffset,
+                                  QCBORItem          *pDecodedItem);
+
+/* Semi-private function. See qcbor_decode.c */
+QCBORError
+QCBORDecode_Private_NestLevelAscender(QCBORDecodeContext *pMe,
+                                      bool                bMarkEnd,
+                                      bool               *pbBreak);
+
+
+static inline uint32_t
+QCBORDecode_Tell(QCBORDecodeContext *pMe)
+{
+   if(pMe->uLastError) {
+      return UINT32_MAX;
+   }
+
+   /* Cast is safe because decoder input size is restricted. */
+   return (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
+}
+
+static inline UsefulBufC
+QCBORDecode_RetrieveUndecodedInput(QCBORDecodeContext *pMe)
+{
+   return UsefulInputBuf_RetrieveUndecodedInput(&(pMe->InBuf));
+}
+
+static inline QCBORError
+QCBORDecode_GetError(QCBORDecodeContext *pMe)
+{
+    return (QCBORError)pMe->uLastError;
+}
+
+static inline QCBORError
+QCBORDecode_GetAndResetError(QCBORDecodeContext *pMe)
+{
+    const QCBORError uReturn = (QCBORError)pMe->uLastError;
+    pMe->uLastError = QCBOR_SUCCESS;
+    return uReturn;
+}
+
+static inline bool
+QCBORDecode_IsNotWellFormedError(const QCBORError uErr)
+{
+   if(uErr >= QCBOR_START_OF_NOT_WELL_FORMED_ERRORS &&
+      uErr <= QCBOR_END_OF_NOT_WELL_FORMED_ERRORS) {
+      return true;
+   } else {
+      return false;
+   }
+}
+
+static inline bool
+QCBORDecode_IsUnrecoverableError(const QCBORError uErr)
+{
+   if(uErr >= QCBOR_START_OF_UNRECOVERABLE_DECODE_ERRORS &&
+      uErr <= QCBOR_END_OF_UNRECOVERABLE_DECODE_ERRORS) {
+      return true;
+   } else {
+      return false;
+   }
+}
+
+
+static inline void
+QCBORDecode_SetError(QCBORDecodeContext *pMe, QCBORError uError)
+{
+   pMe->uLastError = (uint8_t)uError;
+}
+
+
+static inline void
+QCBORDecode_Private_SaveTagNumbers(QCBORDecodeContext *pMe, const QCBORItem *pItem)
+{
+#ifndef QCBOR_DISABLE_TAGS
+   memcpy(pMe->auLastTags, pItem->auTagNumbers, sizeof(pItem->auTagNumbers));
+#else /* ! QCBOR_DISABLE_TAGS */
+   (void)pMe;
+   (void)pItem;
+#endif /* ! QCBOR_DISABLE_TAGS */
+}
+
+
+static inline void
+QCBORDecode_Private_GetAndTell(QCBORDecodeContext *pMe, QCBORItem *Item, size_t *uOffset)
+{
+#ifndef QCBOR_DISABLE_TAGS
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   *uOffset = QCBORDecode_Tell(pMe);
+#else /* ! QCBOR_DISABLE_TAGS */
+   *uOffset = SIZE_MAX;
+
+#endif /* ! QCBOR_DISABLE_TAGS */
+   pMe->uLastError = (uint8_t)QCBORDecode_Private_GetNextTagContent(pMe, Item);
+}
+
+
+/* ======================================================================== *
+ *    END OF PRIVATE INLINE IMPLEMENTATION                                  *
+ * ======================================================================== */
+
+
+
+
+/* A few cross checks on size constants and special value lengths */
+#if  QCBOR_MAP_OFFSET_CACHE_INVALID < QCBOR_MAX_DECODE_INPUT_SIZE
+#error QCBOR_MAP_OFFSET_CACHE_INVALID is too large
+#endif
+
+#if QCBOR_NON_BOUNDED_OFFSET < QCBOR_MAX_DECODE_INPUT_SIZE
+#error QCBOR_NON_BOUNDED_OFFSET is too large
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* qcbor_main_decode_h */
diff --git a/inc/qcbor/qcbor_number_decode.h b/inc/qcbor/qcbor_number_decode.h
index 8c525ec..6972671 100644
--- a/inc/qcbor/qcbor_number_decode.h
+++ b/inc/qcbor/qcbor_number_decode.h
@@ -14,7 +14,7 @@
 #define qcbor_number_decode_h
 
 
-#include "qcbor/qcbor_decode.h"
+#include "qcbor/qcbor_main_decode.h"
 
 
 #ifdef __cplusplus
@@ -27,7 +27,7 @@
 
 
 /**
- * @file qcbor_number
+ * @file qcbor_number_decode.h
  */
 
 /** Conversion will proceed if the CBOR item to be decoded is an
@@ -1035,21 +1035,21 @@
 
 void
 QCBORDecode_GetTBigFloatBigMantissaInMapN(QCBORDecodeContext *pCtx,
-                                          int64_t             nLabel,
-                                          uint8_t             uTagRequirement,
-                                          UsefulBuf           MantissaBuffer,
-                                          UsefulBufC         *pMantissa,
-                                          bool               *pbMantissaIsNegative,
-                                          int64_t            *pnExponent);
+                                          int64_t      nLabel,
+                                          uint8_t      uTagRequirement,
+                                          UsefulBuf    MantissaBuffer,
+                                          UsefulBufC  *pMantissa,
+                                          bool        *pbMantissaIsNegative,
+                                          int64_t     *pnExponent);
 
 void
 QCBORDecode_GetTBigFloatBigMantissaInMapSZ(QCBORDecodeContext *pCtx,
-                                           const char         *szLabel,
-                                           uint8_t             uTagRequirement,
-                                           UsefulBuf           MantissaBuffer,
-                                           UsefulBufC         *pMantissa,
-                                           bool               *pbMantissaIsNegative,
-                                           int64_t            *pnExponent);
+                                           const char  *szLabel,
+                                           uint8_t      uTagRequirement,
+                                           UsefulBuf    MantissaBuffer,
+                                           UsefulBufC  *pMantissa,
+                                           bool        *pbMantissaIsNegative,
+                                           int64_t     *pnExponent);
 
 
 /**
@@ -1090,21 +1090,21 @@
 
 void
 QCBORDecode_GetTBigFloatBigMantissaRawInMapN(QCBORDecodeContext *pCtx,
-                                             int64_t             nLabel,
-                                             uint8_t             uTagRequirement,
-                                             UsefulBuf           MantissaBuffer,
-                                             UsefulBufC         *pMantissa,
-                                             bool               *pbMantissaIsNegative,
-                                             int64_t            *pnExponent);
+                                             int64_t      nLabel,
+                                             uint8_t      uTagRequirement,
+                                             UsefulBuf    MantissaBuffer,
+                                             UsefulBufC  *pMantissa,
+                                             bool        *pbMantissaIsNegative,
+                                             int64_t     *pnExponent);
 
 void
 QCBORDecode_GetTBigFloatBigMantissaRawInMapSZ(QCBORDecodeContext *pCtx,
-                                              const char         *szLabel,
-                                              uint8_t             uTagRequirement,
-                                              UsefulBuf           MantissaBuffer,
-                                              UsefulBufC         *pMantissa,
-                                              bool               *pbMantissaIsNegative,
-                                              int64_t            *pnExponent);
+                                              const char  *szLabel,
+                                              uint8_t      uTagRequirement,
+                                              UsefulBuf    MantissaBuffer,
+                                              UsefulBufC  *pMantissa,
+                                              bool        *pbMantissaIsNegative,
+                                              int64_t     *pnExponent);
 
 #endif /* ! QCBOR_DISABLE_EXP_AND_MANTISSA */
 
@@ -1315,7 +1315,7 @@
                                   bool               *pbMantissaIsNegative,
                                   int64_t            *pnExponent);
 
-/* Deprecated. Use QCBORDecode_GetTDecimalFractionBigMantissaRawInMapN() instead */
+/* Deprecated. Use QCBORDecode_GetTDecimalFractionBigMantissaRawInMapN() */
 static void
 QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pCtx,
                                         int64_t             nLabel,
@@ -1325,7 +1325,7 @@
                                         bool               *pbIsNegative,
                                         int64_t            *pnExponent);
 
-/* Deprecated. Use QCBORDecode_GetTDecimalFractionBigMantissaRawInMapSZ() instead. */
+/* Deprecated. Use QCBORDecode_GetTDecimalFractionBigMantissaRawInMapSZ() */
 static void
 QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pCtx,
                                          const char         *szLabel,
@@ -1397,19 +1397,18 @@
 
 
 /* ========================================================================= *
- *    BEGINNING OF PRIVATE INLINE IMPLEMENTATION                             *
+ *    BEGINNING OF PRIVATE AND INLINE IMPLEMENTATION                             *
  * ========================================================================= */
 
 
-/* Semi-private funcion used by public inline functions. See qcbor_number_decode.c */
+/* Semi-private. See qcbor_number_decode.c */
 void
 QCBORDecode_Private_GetUInt64Convert(QCBORDecodeContext *pCtx,
                                      uint32_t            uConvertTypes,
                                      uint64_t           *puValue,
                                      QCBORItem          *pItem);
 
-
-/* Semi-private funcion used by public inline functions. See qcbor_number_decode.c */
+/* Semi-private. See qcbor_number_decode.c */
 void
 QCBORDecode_Private_GetUInt64ConvertInMapN(QCBORDecodeContext *pCtx,
                                            int64_t             nLabel,
@@ -1417,8 +1416,7 @@
                                            uint64_t           *puValue,
                                            QCBORItem          *pItem);
 
-
-/* Semi-private funcion used by public inline functions. See qcbor_number_decode.c */
+/* Semi-private. See qcbor_number_decode.c */
 void
 QCBORDecode_Private_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pCtx,
                                             const char         *szLabel,
@@ -1426,14 +1424,14 @@
                                             uint64_t           *puValue,
                                             QCBORItem          *pItem);
 
-/* Semi-private funcion used by public inline functions. See qcbor_number_decode.c */
+/* Semi-private. See qcbor_number_decode.c */
 void
 QCBORDecode_Private_GetInt64Convert(QCBORDecodeContext *pCtx,
                                     uint32_t            uConvertTypes,
                                     int64_t            *pnValue,
                                     QCBORItem          *pItem);
 
-/* Semi-private funcion used by public inline functions. See qcbor_number_decode.c */
+/* Semi-private. See qcbor_number_decode.c */
 void
 QCBORDecode_Private_GetInt64ConvertInMapN(QCBORDecodeContext *pCtx,
                                           int64_t             nLabel,
@@ -1441,7 +1439,7 @@
                                           int64_t            *pnValue,
                                           QCBORItem          *pItem);
 
-/* Semi-private funcion used by public inline functions. See qcbor_number_decode.c */
+/* Semi-private. See qcbor_number_decode.c */
 void
 QCBORDecode_Private_GetInt64ConvertInMapSZ(QCBORDecodeContext *pCtx,
                                            const char         *szLabel,
@@ -1451,14 +1449,14 @@
 
 
 #ifndef USEFULBUF_DISABLE_ALL_FLOAT
-/* Semi-private funcion used by public inline functions. See qcbor_number_decode.c */
+/* Semi-private. See qcbor_number_decode.c */
 void
 QCBORDecode_Private_GetDoubleConvert(QCBORDecodeContext *pCtx,
                                      uint32_t            uConvertTypes,
                                      double             *pValue,
                                      QCBORItem          *pItem);
 
-/* Semi-private funcion used by public inline functions. See qcbor_number_decode.c */
+/* Semi-private. See qcbor_number_decode.c */
 void
 QCBORDecode_Private_GetDoubleConvertInMapN(QCBORDecodeContext *pCtx,
                                            int64_t             nLabel,
@@ -1466,7 +1464,7 @@
                                            double             *pdValue,
                                            QCBORItem          *pItem);
 
-/* Semi-private funcion used by public inline functions. See qcbor_number_decode.c */
+/* Semi-private. See qcbor_number_decode.c */
 void
 QCBORDecode_Private_GetDoubleConvertInMapSZ(QCBORDecodeContext *pCtx,
                                             const char         *szLabel,
@@ -1476,7 +1474,7 @@
 #endif /* ! USEFULBUF_DISABLE_ALL_FLOAT */
 
 
-/* Semi-private funcion used by public inline functions. See qcbor_tag_decode.c */
+/* Semi-private. See qcbor_number_decode.c */
 void
 QCBORDecode_Private_GetTaggedString(QCBORDecodeContext  *pMe,
                                     uint8_t              uTagRequirement,
@@ -1485,7 +1483,7 @@
                                     UsefulBufC          *pBstr);
 
 
-/* Semi-private funcion used by public inline functions. See qcbor_tag_decode.c */
+/* Semi-private. See qcbor_number_decode.c */
 void
 QCBORDecode_Private_GetTaggedStringInMapN(QCBORDecodeContext  *pMe,
                                           const int64_t        nLabel,
@@ -1495,7 +1493,7 @@
                                           UsefulBufC          *pString);
 
 
-/* Semi-private funcion used by public inline functions. See qcbor_tag_decode.c */
+/* Semi-private. See qcbor_number_decode.c */
 void
 QCBORDecode_Private_GetTaggedStringInMapSZ(QCBORDecodeContext  *pMe,
                                            const char          *szLabel,
@@ -1739,7 +1737,11 @@
                             UsefulBufC         *pBigNumber,
                             bool               *pbIsNegative)
 {
-   QCBORDecode_GetTBigNumberRawInMapN(pMe, nLabel, uTagRequirement, pBigNumber, pbIsNegative);
+   QCBORDecode_GetTBigNumberRawInMapN(pMe,
+                                      nLabel,
+                                      uTagRequirement,
+                                      pBigNumber,
+                                      pbIsNegative);
 }
 
 static inline void /* Deprecated */
@@ -1749,7 +1751,11 @@
                              UsefulBufC         *pBigNumber,
                              bool               *pbIsNegative)
 {
-   QCBORDecode_GetTBigNumberRawInMapSZ(pMe, szLabel, uTagRequirement, pBigNumber, pbIsNegative);
+   QCBORDecode_GetTBigNumberRawInMapSZ(pMe,
+                                       szLabel,
+                                       uTagRequirement,
+                                       pBigNumber,
+                                       pbIsNegative);
 }
 
 #ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
@@ -1759,7 +1765,10 @@
                                int64_t            *pnMantissa,
                                int64_t            *pnExponent)
 {
-   QCBORDecode_GetTDecimalFraction(pMe, uTagRequirement, pnMantissa, pnExponent);
+   QCBORDecode_GetTDecimalFraction(pMe,
+                                   uTagRequirement,
+                                   pnMantissa,
+                                   pnExponent);
 }
 
 static inline void /* Deprecated */
@@ -1769,7 +1778,11 @@
                                      int64_t            *pnMantissa,
                                      int64_t            *pnExponent)
 {
-   QCBORDecode_GetTDecimalFractionInMapN(pMe, nLabel, uTagRequirement, pnMantissa, pnExponent);
+   QCBORDecode_GetTDecimalFractionInMapN(pMe,
+                                         nLabel,
+                                         uTagRequirement,
+                                         pnMantissa,
+                                         pnExponent);
 }
 
 static inline void /* Deprecated */
@@ -1779,7 +1792,11 @@
                                       int64_t            *pnMantissa,
                                       int64_t            *pnExponent)
 {
-   QCBORDecode_GetTDecimalFractionInMapSZ(pMe, szLabel, uTagRequirement, pnMantissa, pnExponent);
+   QCBORDecode_GetTDecimalFractionInMapSZ(pMe,
+                                          szLabel,
+                                          uTagRequirement,
+                                          pnMantissa,
+                                          pnExponent);
 }
 
 
@@ -1791,7 +1808,12 @@
                                   bool               *pbMantissaIsNegative,
                                   int64_t            *pnExponent)
 {
-   QCBORDecode_GetTDecimalFractionBigMantissaRaw(pMe, uTagRequirement, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
+   QCBORDecode_GetTDecimalFractionBigMantissaRaw(pMe,
+                                                 uTagRequirement,
+                                                 MantissaBuffer,
+                                                 pMantissa,
+                                                 pbMantissaIsNegative,
+                                                 pnExponent);
 }
 
 static inline void /* Deprecated */
@@ -1821,7 +1843,13 @@
                                          bool               *pbMantissaIsNegative,
                                          int64_t            *pnExponent)
 {
-   QCBORDecode_GetTDecimalFractionBigMantissaRawInMapSZ(pMe, szLabel, uTagRequirement, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
+   QCBORDecode_GetTDecimalFractionBigMantissaRawInMapSZ(pMe,
+                                                        szLabel,
+                                                        uTagRequirement,
+                                                        MantissaBuffer,
+                                                        pMantissa,
+                                                        pbMantissaIsNegative,
+                                                        pnExponent);
 
 }
 
@@ -1841,7 +1869,11 @@
                               int64_t            *pnMantissa,
                               int64_t            *pnExponent)
 {
-   QCBORDecode_GetTBigFloatInMapN(pMe, nLabel, uTagRequirement, pnMantissa, pnExponent);
+   QCBORDecode_GetTBigFloatInMapN(pMe,
+                                  nLabel,
+                                  uTagRequirement,
+                                  pnMantissa,
+                                  pnExponent);
 }
 
 static inline void /* Deprecated */
@@ -1851,7 +1883,11 @@
                                int64_t            *pnMantissa,
                                int64_t            *pnExponent)
 {
-   QCBORDecode_GetTBigFloatInMapSZ(pMe, szLabel, uTagRequirement, pnMantissa, pnExponent);
+   QCBORDecode_GetTBigFloatInMapSZ(pMe,
+                                   szLabel,
+                                   uTagRequirement,
+                                   pnMantissa,
+                                   pnExponent);
 }
 
 static inline void /* Deprecated */
diff --git a/inc/qcbor/qcbor_private.h b/inc/qcbor/qcbor_private.h
index c6266a1..9abbb8b 100644
--- a/inc/qcbor/qcbor_private.h
+++ b/inc/qcbor/qcbor_private.h
@@ -1,4 +1,6 @@
 /* ==========================================================================
+ * qcbor_private -- Non-public data structures for encding and decoding.
+ *
  * Copyright (c) 2016-2018, The Linux Foundation.
  * Copyright (c) 2018-2024, Laurence Lundblade.
  * Copyright (c) 2021, Arm Limited.
@@ -31,7 +33,6 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * ========================================================================= */
 
-
 #ifndef qcbor_private_h
 #define qcbor_private_h
 
@@ -384,7 +385,7 @@
    uint32_t uDecodeMode;
    uint8_t  bStringAllocateAll;
    uint8_t  uLastError;  /* QCBORError stuffed into a uint8_t */
-   uint8_t  bAllowAllLabels; /* Used internally only, not an external feature yet */
+   uint8_t  bAllowAllLabels; /* Used internally only, not external yet */
 
    /* See MapTagNumber() for description of how tags are mapped. */
    uint64_t auMappedTags[QCBOR_NUM_MAPPED_TAGS];
diff --git a/inc/qcbor/qcbor_spiffy_decode.h b/inc/qcbor/qcbor_spiffy_decode.h
index 26902d7..e4a1594 100644
--- a/inc/qcbor/qcbor_spiffy_decode.h
+++ b/inc/qcbor/qcbor_spiffy_decode.h
@@ -10,11 +10,12 @@
  *
  * Forked from qcbor_decode.h on 7/23/2020
  * ========================================================================== */
+
 #ifndef qcbor_spiffy_decode_h
 #define qcbor_spiffy_decode_h
 
-
-#include "qcbor/qcbor_decode.h"
+#include "qcbor/qcbor_spiffy_decode.h"
+#include "qcbor/qcbor_number_decode.h" /* For v1 compatibility, not dependency */
 
 
 #ifdef __cplusplus
@@ -801,7 +802,6 @@
                                   QCBORItem          *pItem,
                                   UsefulBufC         *pEncodedCBOR);
 
-
 /* Semi-private funcion used by public inline functions. See qcbor_decode.c */
 void
 QCBORDecode_Private_SearchAndGetArrayOrMap(QCBORDecodeContext *pCtx,
@@ -810,6 +810,33 @@
                                            UsefulBufC         *pEncodedCBOR);
 
 
+/* Semi-private data structure */
+typedef struct {
+   void               *pCBContext;
+   QCBORItemCallback   pfCallback;
+} MapSearchCallBack;
+
+/* Semi-private data structure */
+typedef struct {
+   size_t   uStartOffset;
+   uint16_t uItemCount;
+} MapSearchInfo;
+
+/* Semi-private function. See qcbor_spiffy_decode.c */
+QCBORError
+QCBORDecode_Private_MapSearch(QCBORDecodeContext *pMe,
+                              QCBORItem          *pItemArray,
+                              MapSearchInfo      *pInfo,
+                              MapSearchCallBack  *pCallBack);
+
+
+/* Semi-private function. See qcbor_spiffy_decode.c */
+QCBORError
+QCBORDecode_Private_ExitBoundedLevel(QCBORDecodeContext *pMe,
+                                     const uint32_t      uEndOffset);
+
+
+
 
 static inline void
 QCBORDecode_EnterMap(QCBORDecodeContext *pMe, QCBORItem *pItem) {
diff --git a/inc/qcbor/qcbor_tag_decode.h b/inc/qcbor/qcbor_tag_decode.h
index 7f92a48..74128e1 100644
--- a/inc/qcbor/qcbor_tag_decode.h
+++ b/inc/qcbor/qcbor_tag_decode.h
@@ -13,7 +13,8 @@
 #ifndef qcbor_tag_decode_h
 #define qcbor_tag_decode_h
 
-#include "qcbor/qcbor_decode.h"
+#include "qcbor/qcbor_main_decode.h"
+
 
 #ifdef __cplusplus
 extern "C" {
@@ -848,7 +849,7 @@
  * decoder will get @ref QCBOR_TYPE_POSBIGNUM instead of a tag number and
  * a byte string.
  */
-typedef QCBORError (QCBORTagContentCallBack)(QCBORDecodeContext *pCtx, 
+typedef QCBORError (QCBORTagContentCallBack)(QCBORDecodeContext *pCtx,
                                              void               *pTagDecodersContext,
                                              uint64_t            uTagNumber,
                                              QCBORItem          *pItem);
@@ -1114,7 +1115,7 @@
 
 
 /* ========================================================================= *
- *    BEGINNING OF PRIVATE INLINE IMPLEMENTATION                             *
+ *    BEGINNING OF PRIVATE AND INLINE IMPLEMENTATION                             *
  * ========================================================================= */
 
 /* Semi-private used by public inline functions. See qcbor_tag_decode.c */
@@ -1143,7 +1144,25 @@
                                            uint64_t             uTagNumber,
                                            UsefulBufC          *pString);
 
+/* Semi-private function. See qcbor_tag_decode.c */
+void
+QCBORDecode_Private_ProcessTagItemMulti(QCBORDecodeContext      *pMe,
+                                        QCBORItem               *pItem,
+                                        const uint8_t            uTagRequirement,
+                                        const uint8_t            uQCBORTypes[],
+                                        const uint64_t           uTagNumbers[],
+                                        QCBORTagContentCallBack *pfCB,
+                                        size_t                   uOffset);
 
+/* Semi-private function. See qcbor_tag_decode.c */
+void
+QCBORDecode_Private_ProcessTagItem(QCBORDecodeContext      *pMe,
+                                   QCBORItem               *pItem,
+                                   const uint8_t            uTagRequirement,
+                                   const uint8_t            uQCBORTypes[],
+                                   const uint64_t           uTagNumber,
+                                   QCBORTagContentCallBack *pfCB,
+                                   size_t                   uOffset);
 
 
 #ifndef QCBOR_DISABLE_TAGS