| /* ========================================================================== |
| * 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_private_h |
| #define qcbor_private_h |
| |
| |
| #include <stdint.h> |
| #include "UsefulBuf.h" |
| #include "qcbor/qcbor_common.h" |
| |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #if 0 |
| } // Keep editor indention formatting happy |
| #endif |
| #endif |
| |
| |
| /* This was originally defined as QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA, |
| * but this is inconsistent with all the other QCBOR_DISABLE_ |
| * #defines, so the name was changed and this was added for backwards |
| * compatibility |
| */ |
| #ifdef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA |
| #define QCBOR_DISABLE_EXP_AND_MANTISSA |
| #endif |
| |
| /* If USEFULBUF_DISABLE_ALL_FLOATis defined then define |
| * QCBOR_DISABLE_FLOAT_HW_USE and QCBOR_DISABLE_PREFERRED_FLOAT |
| */ |
| #ifdef USEFULBUF_DISABLE_ALL_FLOAT |
| #ifndef QCBOR_DISABLE_FLOAT_HW_USE |
| #define QCBOR_DISABLE_FLOAT_HW_USE |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| #ifndef QCBOR_DISABLE_PREFERRED_FLOAT |
| #define QCBOR_DISABLE_PREFERRED_FLOAT |
| #endif /* QCBOR_DISABLE_PREFERRED_FLOAT */ |
| #endif /* USEFULBUF_DISABLE_ALL_FLOAT */ |
| |
| |
| /* |
| * Convenience macro for selecting the proper return value in case floating |
| * point feature(s) are disabled. |
| * |
| * The macros: |
| * |
| * FLOAT_ERR_CODE_NO_FLOAT(x) Can be used when disabled floating point should |
| * result error, and all other cases should return |
| * 'x'. |
| * |
| * The below macros always return QCBOR_ERR_ALL_FLOAT_DISABLED when all |
| * floating point is disabled. |
| * |
| * FLOAT_ERR_CODE_NO_HALF_PREC(x) Can be used when disabled preferred float |
| * results in error, and all other cases should |
| * return 'x'. |
| * FLOAT_ERR_CODE_NO_FLOAT_HW(x) Can be used when disabled hardware floating |
| * point results in error, and all other cases |
| * should return 'x'. |
| * FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) Can be used when either disabled |
| * preferred float or disabling |
| * hardware floating point results |
| * in error, and all other cases |
| * should return 'x'. |
| */ |
| #ifdef USEFULBUF_DISABLE_ALL_FLOAT |
| #define FLOAT_ERR_CODE_NO_FLOAT(x) QCBOR_ERR_ALL_FLOAT_DISABLED |
| #define FLOAT_ERR_CODE_NO_HALF_PREC(x) QCBOR_ERR_ALL_FLOAT_DISABLED |
| #define FLOAT_ERR_CODE_NO_FLOAT_HW(x) QCBOR_ERR_ALL_FLOAT_DISABLED |
| #define FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) QCBOR_ERR_ALL_FLOAT_DISABLED |
| #else /* USEFULBUF_DISABLE_ALL_FLOAT*/ |
| #define FLOAT_ERR_CODE_NO_FLOAT(x) x |
| #ifdef QCBOR_DISABLE_PREFERRED_FLOAT |
| #define FLOAT_ERR_CODE_NO_HALF_PREC(x) QCBOR_ERR_HALF_PRECISION_DISABLED |
| #define FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) QCBOR_ERR_HALF_PRECISION_DISABLED |
| #else /* QCBOR_DISABLE_PREFERRED_FLOAT */ |
| #define FLOAT_ERR_CODE_NO_HALF_PREC(x) x |
| #ifdef QCBOR_DISABLE_FLOAT_HW_USE |
| #define FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) QCBOR_ERR_HW_FLOAT_DISABLED |
| #else |
| #define FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) x |
| #endif |
| #endif /* QCBOR_DISABLE_PREFERRED_FLOAT */ |
| #ifdef QCBOR_DISABLE_FLOAT_HW_USE |
| #define FLOAT_ERR_CODE_NO_FLOAT_HW(x) QCBOR_ERR_HW_FLOAT_DISABLED |
| #else /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| #define FLOAT_ERR_CODE_NO_FLOAT_HW(x) x |
| #endif /* QCBOR_DISABLE_FLOAT_HW_USE */ |
| #endif /*USEFULBUF_DISABLE_ALL_FLOAT*/ |
| |
| |
| /* |
| * These are special values for the AdditionalInfo bits that are part of |
| * the first byte. Mostly they encode the length of the data item. |
| */ |
| #define LEN_IS_ONE_BYTE 24 |
| #define LEN_IS_TWO_BYTES 25 |
| #define LEN_IS_FOUR_BYTES 26 |
| #define LEN_IS_EIGHT_BYTES 27 |
| #define ADDINFO_RESERVED1 28 |
| #define ADDINFO_RESERVED2 29 |
| #define ADDINFO_RESERVED3 30 |
| #define LEN_IS_INDEFINITE 31 |
| |
| |
| /* |
| * 24 is a special number for CBOR. Integers and lengths |
| * less than it are encoded in the same byte as the major type. |
| */ |
| #define CBOR_TWENTY_FOUR 24 |
| |
| |
| /* |
| * Values for the 5 bits for items of major type 7 |
| */ |
| #define CBOR_SIMPLEV_FALSE 20 |
| #define CBOR_SIMPLEV_TRUE 21 |
| #define CBOR_SIMPLEV_NULL 22 |
| #define CBOR_SIMPLEV_UNDEF 23 |
| #define CBOR_SIMPLEV_ONEBYTE 24 |
| #define HALF_PREC_FLOAT 25 |
| #define SINGLE_PREC_FLOAT 26 |
| #define DOUBLE_PREC_FLOAT 27 |
| #define CBOR_SIMPLE_BREAK 31 |
| #define CBOR_SIMPLEV_RESERVED_START CBOR_SIMPLEV_ONEBYTE |
| #define CBOR_SIMPLEV_RESERVED_END CBOR_SIMPLE_BREAK |
| |
| |
| /* The largest offset to the start of an array or map. It is slightly |
| * less than UINT32_MAX so the error condition can be tested on 32-bit |
| * machines. UINT32_MAX comes from uStart in QCBORTrackNesting being |
| * a uin32_t. |
| * |
| * This will cause trouble on a machine where size_t is less than 32-bits. |
| * |
| * TODO: make this public? |
| */ |
| #define QCBOR_MAX_ARRAY_OFFSET (UINT32_MAX - 100) |
| |
| |
| /* The number of tags that are 16-bit or larger that can be handled |
| * in a decode. |
| */ |
| #define QCBOR_NUM_MAPPED_TAGS 4 |
| |
| /* The number of tags (of any size) recorded for an individual item. */ |
| #define QCBOR_MAX_TAGS_PER_ITEM1 4 |
| |
| |
| |
| |
| /* |
| * PRIVATE DATA STRUCTURE |
| * |
| * Holds the data for tracking array and map nesting during |
| * encoding. Pairs up with the Nesting_xxx functions to make an |
| * "object" to handle nesting encoding. |
| * |
| * uStart is a uint32_t instead of a size_t to keep the size of this |
| * struct down so it can be on the stack without any concern. It |
| * would be about double if size_t was used instead. |
| * |
| * Size approximation (varies with CPU/compiler): |
| * 64-bit machine: (15 + 1) * (4 + 2 + 1 + 1 pad) + 8 = 136 bytes |
| * 32-bit machine: (15 + 1) * (4 + 2 + 1 + 1 pad) + 4 = 132 bytes |
| */ |
| typedef struct __QCBORTrackNesting { |
| /* PRIVATE DATA STRUCTURE */ |
| struct { |
| /* See QCBOREncode_OpenMapOrArray() for details on how this works */ |
| uint32_t uStart; /* uStart is the position where the array starts */ |
| uint16_t uCount; /* Number of items in the arrary or map; counts items |
| * in a map, not pairs of items */ |
| uint8_t uMajorType; /* Indicates if item is a map or an array */ |
| } pArrays[QCBOR_MAX_ARRAY_NESTING+1], /* stored state for nesting levels */ |
| *pCurrentNesting; /* the current nesting level */ |
| } QCBORTrackNesting; |
| |
| |
| /* |
| * PRIVATE DATA STRUCTURE |
| * |
| * Context / data object for encoding some CBOR. Used by all encode |
| * functions to form a public "object" that does the job of encdoing. |
| * |
| * Size approximation (varies with CPU/compiler): |
| * 64-bit machine: 27 + 1 (+ 4 padding) + 136 = 32 + 136 = 168 bytes |
| * 32-bit machine: 15 + 1 + 132 = 148 bytes |
| */ |
| typedef struct _QCBOREncodeContext QCBORPrivateEncodeContext; |
| |
| |
| /* These are in order of increasing strictness. Order is relied upon in |
| * implementation. */ |
| #define QCBOR_ENCODE_MODE_ANY 0 |
| #define QCBOR_ENCODE_MODE_PREFERRED 1 |
| #define QCBOR_ENCODE_MODE_CDE 2 |
| #define QCBOR_ENCODE_MODE_DCBOR 3 |
| |
| |
| struct _QCBOREncodeContext { |
| /* PRIVATE DATA STRUCTURE */ |
| UsefulOutBuf OutBuf; /* Pointer to output buffer, its length and |
| * position in it. */ |
| uint8_t uError; /* Error state, always from QCBORError enum */ |
| uint8_t uMode; /* @ref QCBOR_ENCODE_MODE_PREFERRED or related */ |
| uint8_t uAllow; /* @ref QCBOR_ENCODE_ALLOW_NAN_PAYLOAD, ... */ |
| void (*pfnCloseMap)(QCBORPrivateEncodeContext *); /* Use of function |
| * pointer explained in QCBOREncode_SerializationCDE() */ |
| QCBORTrackNesting nesting; /* Keep track of array and map nesting */ |
| }; |
| |
| |
| /* |
| * PRIVATE DATA STRUCTURE |
| * |
| * Holds the data for array and map nesting for decoding work. This |
| * structure and the DecodeNesting_Xxx() functions in qcbor_decode.c |
| * form an "object" that does the work for arrays and maps. All access |
| * to this structure is through DecodeNesting_Xxx() functions. |
| * |
| * 64-bit machine size |
| * 128 = 16 * 8 for the two unions |
| * 64 = 16 * 4 for the uLevelType, 1 byte padded to 4 bytes for alignment |
| * 16 = 16 bytes for two pointers |
| * 208 TOTAL |
| * |
| * 32-bit machine size is 200 bytes |
| */ |
| typedef struct __QCBORDecodeNesting { |
| /* PRIVATE DATA STRUCTURE */ |
| struct nesting_decode_level { |
| /* |
| * This keeps tracking info for each nesting level. There are two |
| * main types of levels: |
| * 1) Byte count tracking. This is for the top level input CBOR |
| * which might be a single item or a CBOR sequence and byte |
| * string wrapped encoded CBOR. |
| * 2) Item count tracking. This is for maps and arrays. |
| * |
| * uLevelType has value QCBOR_TYPE_BYTE_STRING for 1) and |
| * QCBOR_TYPE_MAP or QCBOR_TYPE_ARRAY or QCBOR_TYPE_MAP_AS_ARRAY |
| * for 2). |
| * |
| * Item count tracking is either for definite or indefinite-length |
| * maps/arrays. For definite lengths, the total count and items |
| * unconsumed are tracked. For indefinite-length, uTotalCount is |
| * QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH (UINT16_MAX) and |
| * there is no per-item count of members. For indefinite-length |
| * maps and arrays, uCountCursor is UINT16_MAX if not consumed |
| * and zero if it is consumed in the pre-order |
| * traversal. Additionally, if entered in bounded mode, |
| * uCountCursor is QCBOR_COUNT_INDICATES_ZERO_LENGTH to indicate |
| * it is empty. |
| * |
| * This also records whether a level is bounded or not. All |
| * byte-count tracked levels (the top-level sequence and |
| * bstr-wrapped CBOR) are bounded implicitly. Maps and arrays |
| * may or may not be bounded. They are bounded if they were |
| * Entered() and not if they were traversed with GetNext(). They |
| * are marked as bounded by uStartOffset not being @c UINT32_MAX. |
| */ |
| /* |
| * If uLevelType can put in a separately indexed array, the |
| * union/struct will be 8 bytes rather than 9 and a lot of |
| * wasted padding for alignment will be saved. |
| */ |
| uint8_t uLevelType; |
| union { |
| struct { |
| #define QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH UINT16_MAX |
| #define QCBOR_COUNT_INDICATES_ZERO_LENGTH UINT16_MAX-1 |
| uint16_t uCountTotal; |
| uint16_t uCountCursor; |
| #define QCBOR_NON_BOUNDED_OFFSET UINT32_MAX |
| /* The start of the array or map in bounded mode so |
| * the input can be rewound for GetInMapXx() by label. */ |
| uint32_t uStartOffset; |
| } ma; /* for maps and arrays */ |
| struct { |
| /* The end of the input before the bstr was entered so that |
| * it can be restored when the bstr is exited. */ |
| uint32_t uSavedEndOffset; |
| /* The beginning of the bstr so that it can be rewound. */ |
| uint32_t uBstrStartOffset; |
| } bs; /* for top-level sequence and bstr-wrapped CBOR */ |
| } u; |
| } pLevels[QCBOR_MAX_ARRAY_NESTING+1], |
| *pCurrent, |
| *pCurrentBounded; |
| /* |
| * pCurrent is for item-by-item pre-order traversal. |
| * |
| * pCurrentBounded points to the current bounding level or is NULL |
| * if there isn't one. |
| * |
| * pCurrent must always be below pCurrentBounded as the pre-order |
| * traversal is always bounded by the bounding level. |
| * |
| * When a bounded level is entered, the pre-order traversal is set |
| * to the first item in the bounded level. When a bounded level is |
| * exited, the pre-order traversl is set to the next item after the |
| * map, array or bstr. This may be more than one level up, or even |
| * the end of the input CBOR. |
| */ |
| } QCBORDecodeNesting; |
| |
| |
| typedef struct { |
| /* PRIVATE DATA STRUCTURE */ |
| void *pAllocateCxt; |
| UsefulBuf (* pfAllocator)(void *pAllocateCxt, void *pOldMem, size_t uNewSize); |
| } QCBORInternalAllocator; |
| |
| |
| /* |
| * PRIVATE DATA STRUCTURE |
| * |
| * The decode context. This data structure plus the public |
| * QCBORDecode_xxx functions form an "object" that does CBOR decoding. |
| * |
| * Size approximation (varies with CPU/compiler): |
| * 64-bit machine: 32 + 1 + 1 + 6 bytes padding + 72 + 16 + 8 + 8 = 144 bytes |
| * 32-bit machine: 16 + 1 + 1 + 2 bytes padding + 68 + 8 + 8 + 4 = 108 bytes |
| */ |
| struct _QCBORDecodeContext { |
| /* PRIVATE DATA STRUCTURE */ |
| UsefulInputBuf InBuf; |
| |
| QCBORDecodeNesting nesting; |
| |
| /* If a string allocator is configured for indefinite-length |
| * strings, it is configured here. |
| */ |
| QCBORInternalAllocator StringAllocator; |
| |
| /* These are special for the internal MemPool allocator. They are |
| * not used otherwise. We tried packing these in the MemPool |
| * itself, but there are issues with memory alignment. |
| */ |
| uint32_t uMemPoolSize; |
| uint32_t uMemPoolFreeOffset; |
| |
| /* A cached offset to the end of the current map 0 if no value is |
| * cached. |
| */ |
| #define QCBOR_MAP_OFFSET_CACHE_INVALID UINT32_MAX |
| uint32_t uMapEndOffsetCache; |
| |
| uint8_t uDecodeMode; |
| uint8_t bStringAllocateAll; |
| uint8_t uLastError; /* QCBORError stuffed into a uint8_t */ |
| |
| /* See MapTagNumber() for description of how tags are mapped. */ |
| uint64_t auMappedTags[QCBOR_NUM_MAPPED_TAGS]; |
| |
| uint16_t uLastTags[QCBOR_MAX_TAGS_PER_ITEM1]; |
| }; |
| |
| |
| /* Used internally in the impementation here Must not conflict with |
| * any of the official CBOR types |
| */ |
| #define CBOR_MAJOR_NONE_TYPE_RAW 9 |
| #define CBOR_MAJOR_NONE_TAG_LABEL_REORDER 10 |
| #define CBOR_MAJOR_NONE_TYPE_OPEN_BSTR 12 |
| |
| |
| /* Add this to types to indicate they are to be encoded as indefinite lengths */ |
| #define QCBOR_INDEFINITE_LEN_TYPE_MODIFIER 0x80 |
| #define CBOR_MAJOR_NONE_TYPE_ARRAY_INDEFINITE_LEN \ |
| CBOR_MAJOR_TYPE_ARRAY + QCBOR_INDEFINITE_LEN_TYPE_MODIFIER |
| #define CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN \ |
| CBOR_MAJOR_TYPE_MAP + QCBOR_INDEFINITE_LEN_TYPE_MODIFIER |
| #define CBOR_MAJOR_NONE_TYPE_SIMPLE_BREAK \ |
| CBOR_MAJOR_TYPE_SIMPLE + QCBOR_INDEFINITE_LEN_TYPE_MODIFIER |
| |
| |
| /* Value of QCBORItem.val.string.len when the string length is |
| * indefinite. Used temporarily in the implementation and never |
| * returned in the public interface. |
| */ |
| #define QCBOR_STRING_LENGTH_INDEFINITE SIZE_MAX |
| |
| |
| /* The number of elements in a C array of a particular type */ |
| #define C_ARRAY_COUNT(array, type) (sizeof(array)/sizeof(type)) |
| |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* qcbor_private_h */ |