blob: fa55190b4b3cf7330449377e51fa3e7f1533efbc [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladeee851742020-01-08 08:37:05 -08003 Copyright (c) 2018-2020, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundbladeee851742020-01-08 08:37:05 -080033/*==============================================================================
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070034 FILE: qcbor_decode.c
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080035
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070036 DESCRIPTION: This file contains the implementation of QCBOR.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080037
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070038 EDIT HISTORY FOR FILE:
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080039
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070040 This section contains comments describing changes made to the module.
41 Notice that changes are listed in reverse chronological order.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080042
Laurence Lundbladeee851742020-01-08 08:37:05 -080043 when who what, where, why
44 -------- ---- ---------------------------------------------------
Laurence Lundblade06350ea2020-01-27 19:32:40 -080045 01/28/2020 llundblade Refine integer signedness to quiet static analysis.
Laurence Lundbladec5fef682020-01-25 11:38:45 -080046 01/25/2020 llundblade Cleaner handling of too-long encoded string input.
47 01/25/2020 llundblade Refine use of integer types to quiet static analysis
48 01/08/2020 llundblade Documentation corrections & improved code formatting
Laurence Lundbladeee851742020-01-08 08:37:05 -080049 12/30/19 llundblade Add support for decimal fractions and bigfloats.
50 11/07/19 llundblade Fix long long conversion to double compiler warning
51 09/07/19 llundblade Fix bug decoding empty arrays and maps
52 07/31/19 llundblade Decode error fixes for some not-well-formed CBOR
53 07/31/19 llundblade New error code for better end of data handling
54 02/17/19 llundblade Fixed: QCBORItem.u{Data|Label}Alloc when
55 bAllStrings set
56 02/16/19 llundblade Redesign MemPool to fix memory access alignment bug
57 01/10/19 llundblade Clever type and argument decoder; 250 bytes smaller
58 11/9/18 llundblade Error codes are now enums.
59 11/2/18 llundblade Simplify float decoding and align with preferred
60 float encoding
61 10/31/18 llundblade Switch to one license that is almost BSD-3.
62 10/28/18 llundblade Reworked tag decoding
63 10/15/18 llundblade Indefinite length maps and arrays supported
64 10/8/18 llundblade Indefinite length strings supported
65 02/04/17 llundbla Work on CPUs that don's require pointer alignment
66 by making use of changes in UsefulBuf
67 03/01/17 llundbla More data types; decoding improvements and fixes
68 11/13/16 llundbla Integrate most TZ changes back into github version.
69 09/30/16 gkanike Porting to TZ.
70 03/15/16 llundbla Initial Version.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080071
Laurence Lundbladeee851742020-01-08 08:37:05 -080072 =============================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070073
74#include "qcbor.h"
Laurence Lundblade12d32c52018-09-19 11:25:27 -070075#include "ieee754.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070076
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070077
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053078/*
79 This casts away the const-ness of a pointer, usually so it can be
80 freed or realloced.
81 */
82#define UNCONST_POINTER(ptr) ((void *)(ptr))
83
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070084
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070085
Laurence Lundbladeee851742020-01-08 08:37:05 -080086/*===========================================================================
87 DecodeNesting -- Functions for tracking array/map nesting when decoding
88
89 See qcbor.h for definition of the object used here: QCBORDecodeNesting
90 ===========================================================================*/
91
92inline static int
93IsMapOrArray(uint8_t uDataType)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070094{
95 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
96}
97
Laurence Lundbladeee851742020-01-08 08:37:05 -080098inline static int
99DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700100{
101 return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]);
102}
103
Laurence Lundbladeee851742020-01-08 08:37:05 -0800104inline static int
105DecodeNesting_IsIndefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700106{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700107 return pNesting->pCurrent->uCount == UINT16_MAX;
108}
109
Laurence Lundbladeee851742020-01-08 08:37:05 -0800110inline static uint8_t
111DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800112{
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800113 // Check in DecodeNesting_Descend and never having
114 // QCBOR_MAX_ARRAY_NESTING > 255 gaurantee cast is safe
115 return (uint8_t)(pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]));
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800116}
117
Laurence Lundbladeee851742020-01-08 08:37:05 -0800118inline static int
119DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700120{
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700121 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700122 return 0;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700123 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800124
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700125 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
126}
127
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800128// Process a break. This will either ascend the nesting or error out
Laurence Lundbladeee851742020-01-08 08:37:05 -0800129inline static QCBORError
130DecodeNesting_BreakAscend(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700131{
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800132 // breaks must always occur when there is nesting
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700133 if(!DecodeNesting_IsNested(pNesting)) {
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800134 return QCBOR_ERR_BAD_BREAK;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700135 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800136
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800137 // breaks can only occur when the map/array is indefinite length
138 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
139 return QCBOR_ERR_BAD_BREAK;
140 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800141
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800142 // if all OK, the break reduces the level of nesting
143 pNesting->pCurrent--;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800144
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800145 return QCBOR_SUCCESS;
146}
147
Laurence Lundbladeee851742020-01-08 08:37:05 -0800148// Called on every single item except breaks including open of a map/array
149inline static void
150DecodeNesting_DecrementCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800151{
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700152 while(DecodeNesting_IsNested(pNesting)) {
153 // Not at the top level, so there is decrementing to be done.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800154
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800155 if(!DecodeNesting_IsIndefiniteLength(pNesting)) {
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700156 // Decrement the current nesting level if it is not indefinite.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +0800157 pNesting->pCurrent->uCount--;
158 }
Laurence Lundblade9916b1b2019-09-07 22:33:25 -0700159
160 if(pNesting->pCurrent->uCount != 0) {
161 // Did not close out an array or map, so nothing further
162 break;
163 }
164
165 // Closed out an array or map so level up
166 pNesting->pCurrent--;
167
168 // Continue with loop to see if closing out this doesn't close out more
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700169 }
170}
171
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800172// Called on every map/array
Laurence Lundbladeee851742020-01-08 08:37:05 -0800173inline static QCBORError
174DecodeNesting_Descend(QCBORDecodeNesting *pNesting, QCBORItem *pItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700175{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700176 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800177
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800178 if(pItem->val.uCount == 0) {
179 // Nothing to do for empty definite lenth arrays. They are just are
180 // effectively the same as an item that is not a map or array
181 goto Done;
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530182 // Empty indefinite length maps and arrays are handled elsewhere
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800183 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800184
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800185 // Error out if arrays is too long to handle
186 if(pItem->val.uCount != UINT16_MAX && pItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700187 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
188 goto Done;
189 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800190
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800191 // Error out if nesting is too deep
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700192 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
193 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
194 goto Done;
195 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800196
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800197 // The actual descend
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700198 pNesting->pCurrent++;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800199
Laurence Lundblade3a760b02018-10-08 13:46:03 +0800200 // Record a few details for this nesting level
201 pNesting->pCurrent->uMajorType = pItem->uDataType;
202 pNesting->pCurrent->uCount = pItem->val.uCount;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800203
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700204Done:
205 return nReturn;;
206}
207
Laurence Lundbladeee851742020-01-08 08:37:05 -0800208inline static void
209DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700210{
211 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
212}
213
214
215
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700216/*
217 This list of built-in tags. Only add tags here that are
218 clearly established and useful. Once a tag is added here
219 it can't be taken out as that would break backwards compatibility.
220 There are only 48 slots available forever.
221 */
222static const uint16_t spBuiltInTagMap[] = {
Laurence Lundblade59289e52019-12-30 13:44:37 -0800223 CBOR_TAG_DATE_STRING, // See TAG_MAPPER_FIRST_SIX
224 CBOR_TAG_DATE_EPOCH, // See TAG_MAPPER_FIRST_SIX
225 CBOR_TAG_POS_BIGNUM, // See TAG_MAPPER_FIRST_SIX
226 CBOR_TAG_NEG_BIGNUM, // See TAG_MAPPER_FIRST_SIX
227 CBOR_TAG_DECIMAL_FRACTION, // See TAG_MAPPER_FIRST_SIX
228 CBOR_TAG_BIGFLOAT, // See TAG_MAPPER_FIRST_SIX
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700229 CBOR_TAG_COSE_ENCRYPTO,
230 CBOR_TAG_COSE_MAC0,
231 CBOR_TAG_COSE_SIGN1,
232 CBOR_TAG_ENC_AS_B64URL,
233 CBOR_TAG_ENC_AS_B64,
234 CBOR_TAG_ENC_AS_B16,
235 CBOR_TAG_CBOR,
236 CBOR_TAG_URI,
237 CBOR_TAG_B64URL,
238 CBOR_TAG_B64,
239 CBOR_TAG_REGEX,
240 CBOR_TAG_MIME,
241 CBOR_TAG_BIN_UUID,
242 CBOR_TAG_CWT,
243 CBOR_TAG_ENCRYPT,
244 CBOR_TAG_MAC,
245 CBOR_TAG_SIGN,
246 CBOR_TAG_GEO_COORD,
247 CBOR_TAG_CBOR_MAGIC
248};
249
250// This is used in a bit of cleverness in GetNext_TaggedItem() to
251// keep code size down and switch for the internal processing of
Laurence Lundblade59289e52019-12-30 13:44:37 -0800252// these types. This will break if the first six items in
253// spBuiltInTagMap don't have values 0,1,2,3,4,5. That is the
254// mapping is 0 to 0, 1 to 1, 2 to 2 and 3 to 3....
255#define QCBOR_TAGFLAG_DATE_STRING (0x01LL << CBOR_TAG_DATE_STRING)
256#define QCBOR_TAGFLAG_DATE_EPOCH (0x01LL << CBOR_TAG_DATE_EPOCH)
257#define QCBOR_TAGFLAG_POS_BIGNUM (0x01LL << CBOR_TAG_POS_BIGNUM)
258#define QCBOR_TAGFLAG_NEG_BIGNUM (0x01LL << CBOR_TAG_NEG_BIGNUM)
259#define QCBOR_TAGFLAG_DECIMAL_FRACTION (0x01LL << CBOR_TAG_DECIMAL_FRACTION)
260#define QCBOR_TAGFLAG_BIGFLOAT (0x01LL << CBOR_TAG_BIGFLOAT)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700261
Laurence Lundblade59289e52019-12-30 13:44:37 -0800262#define TAG_MAPPER_FIRST_SIX (QCBOR_TAGFLAG_DATE_STRING |\
263 QCBOR_TAGFLAG_DATE_EPOCH |\
264 QCBOR_TAGFLAG_POS_BIGNUM |\
265 QCBOR_TAGFLAG_NEG_BIGNUM |\
266 QCBOR_TAGFLAG_DECIMAL_FRACTION |\
267 QCBOR_TAGFLAG_BIGFLOAT)
268
269#define TAG_MAPPER_FIRST_FOUR (QCBOR_TAGFLAG_DATE_STRING |\
270 QCBOR_TAGFLAG_DATE_EPOCH |\
271 QCBOR_TAGFLAG_POS_BIGNUM |\
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700272 QCBOR_TAGFLAG_NEG_BIGNUM)
273
274#define TAG_MAPPER_TOTAL_TAG_BITS 64 // Number of bits in a uint64_t
275#define TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS) // 48
276#define TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS (TAG_MAPPER_TOTAL_TAG_BITS - QCBOR_MAX_CUSTOM_TAGS ) // 48
277
278static inline int TagMapper_LookupBuiltIn(uint64_t uTag)
279{
280 if(sizeof(spBuiltInTagMap)/sizeof(uint16_t) > TAG_MAPPER_MAX_SIZE_BUILT_IN_TAGS) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800281 /*
282 This is a cross-check to make sure the above array doesn't
283 accidentally get made too big. In normal conditions the above
284 test should optimize out as all the values are known at compile
285 time.
286 */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700287 return -1;
288 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800289
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700290 if(uTag > UINT16_MAX) {
291 // This tag map works only on 16-bit tags
292 return -1;
293 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800294
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700295 for(int nTagBitIndex = 0; nTagBitIndex < (int)(sizeof(spBuiltInTagMap)/sizeof(uint16_t)); nTagBitIndex++) {
296 if(spBuiltInTagMap[nTagBitIndex] == uTag) {
297 return nTagBitIndex;
298 }
299 }
300 return -1; // Indicates no match
301}
302
303static inline int TagMapper_LookupCallerConfigured(const QCBORTagListIn *pCallerConfiguredTagMap, uint64_t uTag)
304{
305 for(int nTagBitIndex = 0; nTagBitIndex < pCallerConfiguredTagMap->uNumTags; nTagBitIndex++) {
306 if(pCallerConfiguredTagMap->puTags[nTagBitIndex] == uTag) {
307 return nTagBitIndex + TAG_MAPPER_CUSTOM_TAGS_BASE_INDEX;
308 }
309 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800310
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700311 return -1; // Indicates no match
312}
313
314/*
315 Find the tag bit index for a given tag value, or error out
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800316
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700317 This and the above functions could probably be optimized and made
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800318 clearer and neater.
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700319 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800320static QCBORError
321TagMapper_Lookup(const QCBORTagListIn *pCallerConfiguredTagMap,
322 uint64_t uTag,
323 uint8_t *puTagBitIndex)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700324{
325 int nTagBitIndex = TagMapper_LookupBuiltIn(uTag);
326 if(nTagBitIndex >= 0) {
327 // Cast is safe because TagMapper_LookupBuiltIn never returns > 47
328 *puTagBitIndex = (uint8_t)nTagBitIndex;
329 return QCBOR_SUCCESS;
330 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800331
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700332 if(pCallerConfiguredTagMap) {
333 if(pCallerConfiguredTagMap->uNumTags > QCBOR_MAX_CUSTOM_TAGS) {
334 return QCBOR_ERR_TOO_MANY_TAGS;
335 }
336 nTagBitIndex = TagMapper_LookupCallerConfigured(pCallerConfiguredTagMap, uTag);
337 if(nTagBitIndex >= 0) {
338 // Cast is safe because TagMapper_LookupBuiltIn never returns > 63
339
340 *puTagBitIndex = (uint8_t)nTagBitIndex;
341 return QCBOR_SUCCESS;
342 }
343 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800344
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700345 return QCBOR_ERR_BAD_OPT_TAG;
346}
347
348
349
Laurence Lundbladeee851742020-01-08 08:37:05 -0800350/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800351 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
352
353 The following four functions are pretty wrappers for invocation of
354 the string allocator supplied by the caller.
355
Laurence Lundbladeee851742020-01-08 08:37:05 -0800356 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800357
Laurence Lundbladeee851742020-01-08 08:37:05 -0800358static inline void
359StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800360{
361 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
362}
363
Laurence Lundbladeee851742020-01-08 08:37:05 -0800364// StringAllocator_Reallocate called with pMem NULL is
365// equal to StringAllocator_Allocate()
366static inline UsefulBuf
367StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
368 void *pMem,
369 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800370{
371 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
372}
373
Laurence Lundbladeee851742020-01-08 08:37:05 -0800374static inline UsefulBuf
375StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800376{
377 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
378}
379
Laurence Lundbladeee851742020-01-08 08:37:05 -0800380static inline void
381StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800382{
383 if(pMe->pfAllocator) {
384 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
385 }
386}
387
388
389
Laurence Lundbladeee851742020-01-08 08:37:05 -0800390/*===========================================================================
391 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700392
Laurence Lundbladeee851742020-01-08 08:37:05 -0800393 See qcbor.h for definition of the object used here: QCBORDecodeContext
394 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700395/*
396 Public function, see header file
397 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800398void QCBORDecode_Init(QCBORDecodeContext *me,
399 UsefulBufC EncodedCBOR,
400 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700401{
402 memset(me, 0, sizeof(QCBORDecodeContext));
403 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800404 // Don't bother with error check on decode mode. If a bad value is
405 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700406 me->uDecodeMode = nDecodeMode;
407 DecodeNesting_Init(&(me->nesting));
408}
409
410
411/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700412 Public function, see header file
413 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800414void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
415 QCBORStringAllocate pfAllocateFunction,
416 void *pAllocateContext,
417 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700418{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800419 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
420 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
421 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700422}
423
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800424
425/*
426 Public function, see header file
427 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800428void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *me,
429 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700430{
431 me->pCallerConfiguredTagList = pTagList;
432}
433
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700434
435/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800436 This decodes the fundamental part of a CBOR data item, the type and
437 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800438
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700439 This is the Counterpart to InsertEncodedTypeAndNumber().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800440
Laurence Lundbladeee851742020-01-08 08:37:05 -0800441 This does the network->host byte order conversion. The conversion
442 here also results in the conversion for floats in addition to that
443 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800444
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700445 This returns:
446 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800447
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800448 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800449 tags and floats and length for strings and arrays
450
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800451 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800452 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800453
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800454 The int type is preferred to uint8_t for some variables as this
455 avoids integer promotions, can reduce code size and makes
456 static analyzers happier.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700457 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800458inline static QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
459 int *pnMajorType,
460 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800461 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700462{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700463 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800464
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700465 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800466 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800467
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700468 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800469 const int nTmpMajorType = nInitialByte >> 5;
470 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800471
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800472 // Where the number or argument accumulates
473 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800474
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800475 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800476 // Need to get 1,2,4 or 8 additional argument bytes Map
477 // LEN_IS_ONE_BYTE.. LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800478 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800479
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800480 // Loop getting all the bytes in the argument
481 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800482 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800483 // This shift and add gives the endian conversion
484 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
485 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800486 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800487 // The reserved and thus-far unused additional info values
488 nReturn = QCBOR_ERR_UNSUPPORTED;
489 goto Done;
490 } else {
491 // Less than 24, additional info is argument or 31, an indefinite length
492 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800493 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700494 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800495
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700496 if(UsefulInputBuf_GetError(pUInBuf)) {
497 nReturn = QCBOR_ERR_HIT_END;
498 goto Done;
499 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800500
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700501 // All successful if we got here.
502 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800503 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800504 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800505 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800506
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700507Done:
508 return nReturn;
509}
510
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800511
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700512/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800513 CBOR doesn't explicitly specify two's compliment for integers but all
514 CPUs use it these days and the test vectors in the RFC are so. All
515 integers in the CBOR structure are positive and the major type
516 indicates positive or negative. CBOR can express positive integers
517 up to 2^x - 1 where x is the number of bits and negative integers
518 down to 2^x. Note that negative numbers can be one more away from
519 zero than positive. Stdint, as far as I can tell, uses two's
520 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800521
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700522 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800523 used carefully here, and in particular why it isn't used in the interface.
524 Also see
525 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
526
527 Int is used for values that need less than 16-bits and would be subject
528 to integer promotion and complaining by static analyzers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700529 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800530inline static QCBORError
531DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700532{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700533 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800534
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700535 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
536 if (uNumber <= INT64_MAX) {
537 pDecodedItem->val.int64 = (int64_t)uNumber;
538 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800539
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700540 } else {
541 pDecodedItem->val.uint64 = uNumber;
542 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800543
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700544 }
545 } else {
546 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800547 // CBOR's representation of negative numbers lines up with the
548 // two-compliment representation. A negative integer has one
549 // more in range than a positive integer. INT64_MIN is
550 // equal to (-INT64_MAX) - 1.
551 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700552 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800553
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700554 } else {
555 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000556 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700557 nReturn = QCBOR_ERR_INT_OVERFLOW;
558 }
559 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800560
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700561 return nReturn;
562}
563
564// Make sure #define value line up as DecodeSimple counts on this.
565#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
566#error QCBOR_TYPE_FALSE macro value wrong
567#endif
568
569#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
570#error QCBOR_TYPE_TRUE macro value wrong
571#endif
572
573#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
574#error QCBOR_TYPE_NULL macro value wrong
575#endif
576
577#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
578#error QCBOR_TYPE_UNDEF macro value wrong
579#endif
580
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700581#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
582#error QCBOR_TYPE_BREAK macro value wrong
583#endif
584
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700585#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
586#error QCBOR_TYPE_DOUBLE macro value wrong
587#endif
588
589#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
590#error QCBOR_TYPE_FLOAT macro value wrong
591#endif
592
593/*
594 Decode true, false, floats, break...
595 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800596inline static QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800597DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700598{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700599 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800600
Laurence Lundbladeee851742020-01-08 08:37:05 -0800601 // uAdditionalInfo is 5 bits from the initial byte compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800602 // above make sure uAdditionalInfo values line up with uDataType values.
603 // DecodeTypeAndNumber never returns a major type > 1f so cast is safe
604 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800605
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800606 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800607 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
608 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800609
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700610 case HALF_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700611 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
612 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700613 break;
Laurence Lundbladecc2ed342018-09-22 17:29:55 -0700614 case SINGLE_PREC_FLOAT:
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700615 pDecodedItem->val.dfnum = (double)UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
616 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700617 break;
618 case DOUBLE_PREC_FLOAT:
619 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700620 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700621 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800622
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700623 case CBOR_SIMPLEV_FALSE: // 20
624 case CBOR_SIMPLEV_TRUE: // 21
625 case CBOR_SIMPLEV_NULL: // 22
626 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700627 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700628 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800629
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700630 case CBOR_SIMPLEV_ONEBYTE: // 24
631 if(uNumber <= CBOR_SIMPLE_BREAK) {
632 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700633 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700634 goto Done;
635 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800636 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700637 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800638
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700639 default: // 0-19
640 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800641 /*
642 DecodeTypeAndNumber will make uNumber equal to
643 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
644 safe because the 2, 4 and 8 byte lengths of uNumber are in
645 the double/float cases above
646 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700647 pDecodedItem->val.uSimple = (uint8_t)uNumber;
648 break;
649 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800650
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700651Done:
652 return nReturn;
653}
654
655
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700656/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530657 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700658 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800659inline static QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
660 int nMajorType,
661 uint64_t uStrLen,
662 UsefulInputBuf *pUInBuf,
663 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700664{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700665 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800666
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800667 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
668 // This check makes the casts to size_t below safe.
669
670 // 4 bytes less than the largest sizeof() so this can be tested by
671 // putting a SIZE_MAX length in the CBOR test input (no one will
672 // care the limit on strings is 4 bytes shorter).
673 if(uStrLen > SIZE_MAX-4) {
674 nReturn = QCBOR_ERR_STRING_TOO_LONG;
675 goto Done;
676 }
677
678 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530679 if(UsefulBuf_IsNULLC(Bytes)) {
680 // Failed to get the bytes for this string item
681 nReturn = QCBOR_ERR_HIT_END;
682 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700683 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530684
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800685 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530686 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800687 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530688 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700689 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530690 goto Done;
691 }
692 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800693 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530694 } else {
695 // Normal case with no string allocator
696 pDecodedItem->val.string = Bytes;
697 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800698 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800699 // Cast because ternary operator causes promotion to integer
700 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
701 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800702
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530703Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700704 return nReturn;
705}
706
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700707
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800708
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700709
710
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700711
712
Laurence Lundbladeee851742020-01-08 08:37:05 -0800713// Make sure the constants align as this is assumed by
714// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700715#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
716#error QCBOR_TYPE_ARRAY value not lined up with major type
717#endif
718#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
719#error QCBOR_TYPE_MAP value not lined up with major type
720#endif
721
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700722/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800723 This gets a single data item and decodes it including preceding
724 optional tagging. This does not deal with arrays and maps and nesting
725 except to decode the data item introducing them. Arrays and maps are
726 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800727
Laurence Lundbladeee851742020-01-08 08:37:05 -0800728 Errors detected here include: an array that is too long to decode,
729 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700730 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800731static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
732 QCBORItem *pDecodedItem,
733 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700734{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700735 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800736
Laurence Lundbladeee851742020-01-08 08:37:05 -0800737 /*
738 Get the major type and the number. Number could be length of more
739 bytes or the value depending on the major type nAdditionalInfo is
740 an encoding of the length of the uNumber and is needed to decode
741 floats and doubles
742 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800743 int nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700744 uint64_t uNumber;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800745 int nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800746
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700747 memset(pDecodedItem, 0, sizeof(QCBORItem));
748
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800749 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800750
Laurence Lundbladeee851742020-01-08 08:37:05 -0800751 // Error out here if we got into trouble on the type and number. The
752 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700753 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700754 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700755 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800756
Laurence Lundbladeee851742020-01-08 08:37:05 -0800757 // At this point the major type and the value are valid. We've got
758 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800759 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700760 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
761 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800762 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700763 nReturn = QCBOR_ERR_BAD_INT;
764 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800765 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700766 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700767 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800768
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700769 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
770 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800771 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
772 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
773 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
774 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530775 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700776 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800777 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700778 }
779 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800780
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700781 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
782 case CBOR_MAJOR_TYPE_MAP: // Major type 5
783 // Record the number of items in the array or map
784 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
785 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
786 goto Done;
787 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800788 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530789 pDecodedItem->val.uCount = UINT16_MAX; // Indicate indefinite length
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700790 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800791 // type conversion OK because of check above
792 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700793 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800794 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800795 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
796 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700797 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800798
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700799 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800800 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700801 nReturn = QCBOR_ERR_BAD_INT;
802 } else {
803 pDecodedItem->val.uTagV = uNumber;
804 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
805 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700806 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800807
Laurence Lundbladeee851742020-01-08 08:37:05 -0800808 case CBOR_MAJOR_TYPE_SIMPLE:
809 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800810 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700811 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800812
Laurence Lundbladeee851742020-01-08 08:37:05 -0800813 default:
814 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700815 nReturn = QCBOR_ERR_UNSUPPORTED;
816 break;
817 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800818
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700819Done:
820 return nReturn;
821}
822
823
824
825/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800826 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -0800827 individual chunk items together into one QCBORItem using the string
828 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800829
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530830 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700831 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800832static inline QCBORError
833GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700834{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700835 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundblade30816f22018-11-10 13:40:22 +0700836 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800837 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
838 &(me->StringAllocator) :
839 NULL;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530840 UsefulBufC FullString = NULLUsefulBufC;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800841
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800842 nReturn = GetNext_Item(&(me->InBuf),
843 pDecodedItem,
844 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700845 if(nReturn) {
846 goto Done;
847 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800848
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700849 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530850 // code in this function from here down can be eliminated. Run tests, except
851 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800852
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800853 // Only do indefinite length processing on strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800854 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING &&
855 pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700856 goto Done; // no need to do any work here on non-string types
857 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800858
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800859 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530860 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800861 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700862 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800863
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530864 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800865 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700866 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
867 goto Done;
868 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800869
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700870 // There is an indefinite length string to work on...
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800871 // Track which type of string it is
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700872 const uint8_t uStringType = pDecodedItem->uDataType;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800873
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700874 // Loop getting chunk of indefinite string
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700875 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700876 // Get item for next chunk
877 QCBORItem StringChunkItem;
878 // NULL passed to never string alloc chunk of indefinite length strings
Laurence Lundbladefae26bf2019-02-18 11:15:43 -0800879 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700880 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700881 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700882 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800883
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530884 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700885 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +0800886 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700887 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +0530888 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700889 break;
890 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800891
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700892 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530893 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -0700894 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800895 if(StringChunkItem.uDataType != uStringType ||
896 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700897 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700898 break;
899 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800900
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530901 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800902 // The first time throurgh FullString.ptr is NULL and this is
903 // equivalent to StringAllocator_Allocate()
904 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
905 UNCONST_POINTER(FullString.ptr),
906 FullString.len + StringChunkItem.val.string.len);
907
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700908 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +0530909 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +0700910 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700911 break;
912 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800913
Laurence Lundblade2a6850e2018-10-28 20:13:44 +0700914 // Copy new string chunk at the end of string so far.
915 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700916 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800917
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700918Done:
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800919 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
920 // Getting the item failed, clean up the allocated memory
921 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700922 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800923
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700924 return nReturn;
925}
926
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700927
928/*
Laurence Lundblade59289e52019-12-30 13:44:37 -0800929 Gets all optional tag data items preceding a data item that is not an
930 optional tag and records them as bits in the tag map.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700931 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800932static QCBORError
933GetNext_TaggedItem(QCBORDecodeContext *me,
934 QCBORItem *pDecodedItem,
935 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700936{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700937 // Stack usage: int/ptr: 3 -- 24
Laurence Lundblade30816f22018-11-10 13:40:22 +0700938 QCBORError nReturn;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700939 uint64_t uTagBits = 0;
940 if(pTags) {
941 pTags->uNumUsed = 0;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700942 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700943
Laurence Lundblade59289e52019-12-30 13:44:37 -0800944 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700945 for(;;) {
946 nReturn = GetNext_FullItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700947 if(nReturn) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700948 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700949 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800950
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700951 if(pDecodedItem->uDataType != QCBOR_TYPE_OPTTAG) {
952 // Successful exit from loop; maybe got some tags, maybe not
953 pDecodedItem->uTagBits = uTagBits;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700954 break;
955 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800956
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700957 uint8_t uTagBitIndex;
958 // Tag was mapped, tag was not mapped, error with tag list
959 switch(TagMapper_Lookup(me->pCallerConfiguredTagList, pDecodedItem->val.uTagV, &uTagBitIndex)) {
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800960
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700961 case QCBOR_SUCCESS:
962 // Successfully mapped the tag
963 uTagBits |= 0x01ULL << uTagBitIndex;
964 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800965
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700966 case QCBOR_ERR_BAD_OPT_TAG:
967 // Tag is not recognized. Do nothing
968 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800969
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700970 default:
971 // Error Condition
972 goto Done;
973 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800974
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700975 if(pTags) {
976 // Caller wants all tags recorded in the provided buffer
977 if(pTags->uNumUsed >= pTags->uNumAllocated) {
978 nReturn = QCBOR_ERR_TOO_MANY_TAGS;
979 goto Done;
980 }
981 pTags->puTags[pTags->uNumUsed] = pDecodedItem->val.uTagV;
982 pTags->uNumUsed++;
983 }
984 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800985
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700986Done:
987 return nReturn;
988}
989
990
991/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800992 This layer takes care of map entries. It combines the label and data
993 items into one QCBORItem.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700994 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800995static inline QCBORError
996GetNext_MapEntry(QCBORDecodeContext *me,
997 QCBORItem *pDecodedItem,
998 QCBORTagListOut *pTags)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700999{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001000 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade30816f22018-11-10 13:40:22 +07001001 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001002 if(nReturn)
1003 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001004
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001005 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001006 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001007 goto Done;
1008 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001009
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001010 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1011 // In a map and caller wants maps decoded, not treated as arrays
1012
1013 if(DecodeNesting_TypeIsMap(&(me->nesting))) {
1014 // If in a map and the right decoding mode, get the label
1015
Laurence Lundbladeee851742020-01-08 08:37:05 -08001016 // Save label in pDecodedItem and get the next which will
1017 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001018 QCBORItem LabelItem = *pDecodedItem;
1019 nReturn = GetNext_TaggedItem(me, pDecodedItem, pTags);
1020 if(nReturn)
1021 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001022
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301023 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001024
1025 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1026 // strings are always good labels
1027 pDecodedItem->label.string = LabelItem.val.string;
1028 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1029 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001030 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001031 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1032 goto Done;
1033 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1034 pDecodedItem->label.int64 = LabelItem.val.int64;
1035 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1036 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1037 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1038 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1039 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1040 pDecodedItem->label.string = LabelItem.val.string;
1041 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1042 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1043 } else {
1044 // label is not an int or a string. It is an arrray
1045 // or a float or such and this implementation doesn't handle that.
1046 // Also, tags on labels are ignored.
1047 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1048 goto Done;
1049 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001050 }
1051 } else {
1052 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
1053 // Decoding a map as an array
1054 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
1055 pDecodedItem->val.uCount *= 2;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001056 }
1057 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001058
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001059Done:
1060 return nReturn;
1061}
1062
1063
1064/*
1065 Public function, see header qcbor.h file
1066 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001067QCBORError QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me,
1068 QCBORItem *pDecodedItem,
1069 QCBORTagListOut *pTags)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001070{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001071 // Stack ptr/int: 2, QCBORItem : 64
1072
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301073 // The public entry point for fetching and parsing the next QCBORItem.
1074 // All the CBOR parsing work is here and in subordinate calls.
Laurence Lundblade30816f22018-11-10 13:40:22 +07001075 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001076
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001077 // Check if there are an
1078 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0 && !DecodeNesting_IsNested(&(me->nesting))) {
1079 nReturn = QCBOR_ERR_NO_MORE_ITEMS;
1080 goto Done;
1081 }
1082
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001083 nReturn = GetNext_MapEntry(me, pDecodedItem, pTags);
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001084 if(nReturn) {
1085 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001086 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301087
1088 // Break ending arrays/maps are always processed at the end of this function.
1089 // They should never show up here.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301090 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade6de37062018-10-15 12:22:42 +05301091 nReturn = QCBOR_ERR_BAD_BREAK;
1092 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301093 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001094
Laurence Lundblade6de37062018-10-15 12:22:42 +05301095 // Record the nesting level for this data item before processing any of
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301096 // decrementing and descending.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301097 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001098
Laurence Lundblade6de37062018-10-15 12:22:42 +05301099 // Process the item just received for descent or decrement, and
1100 // ascent if decrements are enough to close out a definite length array/map
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001101 if(IsMapOrArray(pDecodedItem->uDataType)) {
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001102 // If the new item is array or map, the nesting level descends
Laurence Lundblade3a760b02018-10-08 13:46:03 +08001103 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem);
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001104 // Maps and arrays do count in as items in the map/array that encloses
1105 // them so a decrement needs to be done for them too, but that is done
1106 // only when all the items in them have been processed, not when they
Laurence Lundblade9916b1b2019-09-07 22:33:25 -07001107 // are opened with the exception of an empty map or array.
1108 if(pDecodedItem->val.uCount == 0) {
1109 DecodeNesting_DecrementCount(&(me->nesting));
1110 }
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001111 } else {
1112 // Decrement the count of items in the enclosing map/array
1113 // If the count in the enclosing map/array goes to zero, that
Laurence Lundblade6de37062018-10-15 12:22:42 +05301114 // triggers a decrement in the map/array above that and
1115 // an ascend in nesting level.
Laurence Lundblade9e3651c2018-10-10 11:49:55 +08001116 DecodeNesting_DecrementCount(&(me->nesting));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001117 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301118 if(nReturn) {
1119 goto Done;
1120 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001121
Laurence Lundblade6de37062018-10-15 12:22:42 +05301122 // For indefinite length maps/arrays, looking at any and
1123 // all breaks that might terminate them. The equivalent
1124 // for definite length maps/arrays happens in
1125 // DecodeNesting_DecrementCount().
1126 if(DecodeNesting_IsNested(&(me->nesting)) && DecodeNesting_IsIndefiniteLength(&(me->nesting))) {
1127 while(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1128 // Peek forward one item to see if it is a break.
1129 QCBORItem Peek;
1130 size_t uPeek = UsefulInputBuf_Tell(&(me->InBuf));
1131 nReturn = GetNext_Item(&(me->InBuf), &Peek, NULL);
1132 if(nReturn) {
1133 goto Done;
1134 }
1135 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
1136 // It is not a break, rewind so it can be processed normally.
1137 UsefulInputBuf_Seek(&(me->InBuf), uPeek);
1138 break;
1139 }
1140 // It is a break. Ascend one nesting level.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301141 // The break is consumed.
Laurence Lundblade6de37062018-10-15 12:22:42 +05301142 nReturn = DecodeNesting_BreakAscend(&(me->nesting));
1143 if(nReturn) {
1144 // break occured outside of an indefinite length array/map
1145 goto Done;
1146 }
1147 }
1148 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001149
Laurence Lundblade6de37062018-10-15 12:22:42 +05301150 // Tell the caller what level is next. This tells them what maps/arrays
1151 // were closed out and makes it possible for them to reconstruct
1152 // the tree with just the information returned by GetNext
1153 pDecodedItem->uNextNestLevel = DecodeNesting_GetLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001154
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001155Done:
Laurence Lundbladee9482dd2019-10-11 12:58:46 -07001156 if(nReturn != QCBOR_SUCCESS) {
1157 // Make sure uDataType and uLabelType are QCBOR_TYPE_NONE
1158 memset(pDecodedItem, 0, sizeof(QCBORItem));
1159 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001160 return nReturn;
1161}
1162
1163
Laurence Lundblade59289e52019-12-30 13:44:37 -08001164/*
1165 Mostly just assign the right data type for the date string.
1166 */
1167inline static QCBORError DecodeDateString(QCBORItem *pDecodedItem)
1168{
1169 // Stack Use: UsefulBuf 1 16
1170 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1171 return QCBOR_ERR_BAD_OPT_TAG;
1172 }
1173
1174 const UsefulBufC Temp = pDecodedItem->val.string;
1175 pDecodedItem->val.dateString = Temp;
1176 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
1177 return QCBOR_SUCCESS;
1178}
1179
1180
1181/*
1182 Mostly just assign the right data type for the bignum.
1183 */
1184inline static QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
1185{
1186 // Stack Use: UsefulBuf 1 -- 16
1187 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1188 return QCBOR_ERR_BAD_OPT_TAG;
1189 }
1190 const UsefulBufC Temp = pDecodedItem->val.string;
1191 pDecodedItem->val.bigNum = Temp;
Laurence Lundbladeee851742020-01-08 08:37:05 -08001192 const bool bIsPosBigNum = (bool)(pDecodedItem->uTagBits & QCBOR_TAGFLAG_POS_BIGNUM);
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001193 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1194 : QCBOR_TYPE_NEGBIGNUM);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001195 return QCBOR_SUCCESS;
1196}
1197
1198
1199/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001200 The epoch formatted date. Turns lots of different forms of encoding
1201 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001202 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001203static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001204{
1205 // Stack usage: 1
1206 QCBORError nReturn = QCBOR_SUCCESS;
1207
1208 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1209
1210 switch (pDecodedItem->uDataType) {
1211
1212 case QCBOR_TYPE_INT64:
1213 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1214 break;
1215
1216 case QCBOR_TYPE_UINT64:
1217 if(pDecodedItem->val.uint64 > INT64_MAX) {
1218 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1219 goto Done;
1220 }
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001221 pDecodedItem->val.epochDate.nSeconds = (int64_t)pDecodedItem->val.uint64;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001222 break;
1223
1224 case QCBOR_TYPE_DOUBLE:
1225 {
1226 // This comparison needs to be done as a float before
1227 // conversion to an int64_t to be able to detect doubles
1228 // that are too large to fit into an int64_t. A double
1229 // has 52 bits of preceision. An int64_t has 63. Casting
1230 // INT64_MAX to a double actually causes a round up which
1231 // is bad and wrong for the comparison because it will
1232 // allow conversion of doubles that can't fit into a
1233 // uint64_t. To remedy this INT64_MAX - 0x7ff is used as
1234 // the cutoff point as if that rounds up in conversion to
1235 // double it will still be less than INT64_MAX. 0x7ff is
1236 // picked because it has 11 bits set.
1237 //
1238 // INT64_MAX seconds is on the order of 10 billion years,
1239 // and the earth is less than 5 billion years old, so for
1240 // most uses this conversion error won't occur even though
1241 // doubles can go much larger.
1242 //
1243 // Without the 0x7ff there is a ~30 minute range of time
1244 // values 10 billion years in the past and in the future
1245 // where this this code would go wrong.
1246 const double d = pDecodedItem->val.dfnum;
1247 if(d > (double)(INT64_MAX - 0x7ff)) {
1248 nReturn = QCBOR_ERR_DATE_OVERFLOW;
1249 goto Done;
1250 }
1251 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
1252 pDecodedItem->val.epochDate.fSecondsFraction = d - (double)pDecodedItem->val.epochDate.nSeconds;
1253 }
1254 break;
1255
1256 default:
1257 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1258 goto Done;
1259 }
1260 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1261
1262Done:
1263 return nReturn;
1264}
1265
1266
1267#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1268/*
1269 Decode decimal fractions and big floats.
1270
1271 When called pDecodedItem must be the array that is tagged as a big
1272 float or decimal fraction, the array that has the two members, the
1273 exponent and mantissa.
1274
1275 This will fetch and decode the exponent and mantissa and put the
1276 result back into pDecodedItem.
1277 */
1278inline static QCBORError
1279QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1280{
1281 QCBORError nReturn;
1282
1283 // --- Make sure it is an array; track nesting level of members ---
1284 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1285 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1286 goto Done;
1287 }
1288
1289 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001290 // definite length arrays, but not for indefnite. Instead remember
1291 // the nesting level the two integers must be at, which is one
1292 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001293 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1294
1295 // --- Is it a decimal fraction or a bigfloat? ---
1296 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1297 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1298
1299 // --- Get the exponent ---
1300 QCBORItem exponentItem;
1301 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem, NULL);
1302 if(nReturn != QCBOR_SUCCESS) {
1303 goto Done;
1304 }
1305 if(exponentItem.uNestingLevel != nNestLevel) {
1306 // Array is empty or a map/array encountered when expecting an int
1307 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1308 goto Done;
1309 }
1310 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1311 // Data arriving as an unsigned int < INT64_MAX has been converted
1312 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1313 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1314 // will be too large for this to handle and thus an error that will
1315 // get handled in the next else.
1316 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1317 } else {
1318 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1319 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1320 goto Done;
1321 }
1322
1323 // --- Get the mantissa ---
1324 QCBORItem mantissaItem;
1325 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1326 if(nReturn != QCBOR_SUCCESS) {
1327 goto Done;
1328 }
1329 if(mantissaItem.uNestingLevel != nNestLevel) {
1330 // Mantissa missing or map/array encountered when expecting number
1331 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1332 goto Done;
1333 }
1334 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1335 // Data arriving as an unsigned int < INT64_MAX has been converted
1336 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1337 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1338 // will be too large for this to handle and thus an error that
1339 // will get handled in an else below.
1340 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
1341 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM || mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
1342 // Got a good big num mantissa
1343 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1344 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001345 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1346 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1347 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001348 } else {
1349 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1350 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1351 goto Done;
1352 }
1353
1354 // --- Check that array only has the two numbers ---
1355 if(mantissaItem.uNextNestLevel == nNestLevel) {
1356 // Extra items in the decimal fraction / big num
1357 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1358 goto Done;
1359 }
1360
1361Done:
1362
1363 return nReturn;
1364}
1365#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1366
1367
1368/*
1369 Public function, see header qcbor.h file
1370 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001371QCBORError
1372QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
1373 QCBORItem *pDecodedItem,
1374 QCBORTagListOut *pTags)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001375{
1376 QCBORError nReturn;
1377
1378 nReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem, pTags);
1379 if(nReturn != QCBOR_SUCCESS) {
1380 goto Done;
1381 }
1382
1383#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1384#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_SIX
1385#else
1386#define TAG_MAPPER_FIRST_XXX TAG_MAPPER_FIRST_FOUR
1387#endif
1388
1389 // Only pay attention to tags this code knows how to decode.
1390 switch(pDecodedItem->uTagBits & TAG_MAPPER_FIRST_XXX) {
1391 case 0:
1392 // No tags at all or none we know about. Nothing to do.
1393 // This is the pass-through path of this function
1394 // that will mostly be taken when decoding any item.
1395 break;
1396
1397 case QCBOR_TAGFLAG_DATE_STRING:
1398 nReturn = DecodeDateString(pDecodedItem);
1399 break;
1400
1401 case QCBOR_TAGFLAG_DATE_EPOCH:
1402 nReturn = DecodeDateEpoch(pDecodedItem);
1403 break;
1404
1405 case QCBOR_TAGFLAG_POS_BIGNUM:
1406 case QCBOR_TAGFLAG_NEG_BIGNUM:
1407 nReturn = DecodeBigNum(pDecodedItem);
1408 break;
1409
1410#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1411 case QCBOR_TAGFLAG_DECIMAL_FRACTION:
1412 case QCBOR_TAGFLAG_BIGFLOAT:
1413 // For aggregate tagged types, what goes into pTags is only collected
1414 // from the surrounding data item, not the contents, so pTags is not
1415 // passed on here.
1416
1417 nReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
1418 break;
1419#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1420
1421 default:
1422 // Encountering some mixed-up CBOR like something that
1423 // is tagged as both a string and integer date.
1424 nReturn = QCBOR_ERR_BAD_OPT_TAG;
1425 }
1426
1427Done:
1428 if(nReturn != QCBOR_SUCCESS) {
1429 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
1430 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
1431 }
1432 return nReturn;
1433}
1434
1435
1436/*
1437 Public function, see header qcbor.h file
1438 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001439QCBORError QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001440{
1441 return QCBORDecode_GetNextWithTags(me, pDecodedItem, NULL);
1442}
1443
1444
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001445/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05301446 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301447 next one down. If a layer has no work to do for a particular item
1448 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001449
Laurence Lundblade59289e52019-12-30 13:44:37 -08001450 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
1451 tagged data items, turning them into the local C representation.
1452 For the most simple it is just associating a QCBOR_TYPE with the data. For
1453 the complex ones that an aggregate of data items, there is some further
1454 decoding and a little bit of recursion.
1455
1456 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301457 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05301458 out of maps/arrays. It processes all breaks that terminate
1459 maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001460
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301461 - GetNext_MapEntry -- This handles the combining of two
1462 items, the label and the data, that make up a map entry.
1463 It only does work on maps. It combines the label and data
1464 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001465
Laurence Lundblade59289e52019-12-30 13:44:37 -08001466 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
1467 tags into bit flags associated with the data item. No actual decoding
1468 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001469
Laurence Lundblade59289e52019-12-30 13:44:37 -08001470 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301471 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05301472 string allocater to create contiguous space for the item. It
1473 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001474
Laurence Lundblade59289e52019-12-30 13:44:37 -08001475 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
1476 atomic data item has a "major type", an integer "argument" and optionally
1477 some content. For text and byte strings, the content is the bytes
1478 that make up the string. These are the smallest data items that are
1479 considered to be well-formed. The content may also be other data items in
1480 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001481
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001482 Roughly this takes 300 bytes of stack for vars. Need to
1483 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001484
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05301485 */
1486
1487
1488/*
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001489 Public function, see header qcbor.h file
1490 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001491int QCBORDecode_IsTagged(QCBORDecodeContext *me,
1492 const QCBORItem *pItem,
1493 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001494{
1495 const QCBORTagListIn *pCallerConfiguredTagMap = me->pCallerConfiguredTagList;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001496
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001497 uint8_t uTagBitIndex;
1498 // Do not care about errors in pCallerConfiguredTagMap here. They are
1499 // caught during GetNext() before this is called.
1500 if(TagMapper_Lookup(pCallerConfiguredTagMap, uTag, &uTagBitIndex)) {
1501 return 0;
1502 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001503
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001504 const uint64_t uTagBit = 0x01ULL << uTagBitIndex;
1505 return (uTagBit & pItem->uTagBits) != 0;
1506}
1507
1508
1509/*
1510 Public function, see header qcbor.h file
1511 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07001512QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001513{
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001514 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001515
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001516 // Error out if all the maps/arrays are not closed out
1517 if(DecodeNesting_IsNested(&(me->nesting))) {
1518 nReturn = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
1519 goto Done;
1520 }
1521
1522 // Error out if not all the bytes are consumed
1523 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
1524 nReturn = QCBOR_ERR_EXTRA_BYTES;
1525 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001526
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001527Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05301528 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001529 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001530 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001531
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001532 return nReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001533}
1534
1535
1536
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001537/*
1538
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001539Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001540
Laurence Lundbladeee851742020-01-08 08:37:05 -08001541 - Hit end of input before it was expected while decoding type and
1542 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001543
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001544 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001545
Laurence Lundbladeee851742020-01-08 08:37:05 -08001546 - Hit end of input while decoding a text or byte string
1547 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001548
Laurence Lundbladeee851742020-01-08 08:37:05 -08001549 - Encountered conflicting tags -- e.g., an item is tagged both a date
1550 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001551
Laurence Lundbladeee851742020-01-08 08:37:05 -08001552 - Encontered an array or mapp that has too many items
1553 QCBOR_ERR_ARRAY_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001554
Laurence Lundbladeee851742020-01-08 08:37:05 -08001555 - Encountered array/map nesting that is too deep
1556 QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001557
Laurence Lundbladeee851742020-01-08 08:37:05 -08001558 - An epoch date > INT64_MAX or < INT64_MIN was encountered
1559 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001560
Laurence Lundbladeee851742020-01-08 08:37:05 -08001561 - The type of a map label is not a string or int
1562 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001563
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001564 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001565
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001566 */
1567
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001568
1569
Laurence Lundbladef6531662018-12-04 10:42:22 +09001570
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001571/* ===========================================================================
1572 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001573
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001574 This implements a simple sting allocator for indefinite length
1575 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
1576 implements the function type QCBORStringAllocate and allows easy
1577 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09001578
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001579 This particular allocator is built-in for convenience. The caller
1580 can implement their own. All of this following code will get
1581 dead-stripped if QCBORDecode_SetMemPool() is not called.
1582
1583 This is a very primitive memory allocator. It does not track
1584 individual allocations, only a high-water mark. A free or
1585 reallocation must be of the last chunk allocated.
1586
1587 The size of the pool and offset to free memory are packed into the
1588 first 8 bytes of the memory pool so we don't have to keep them in
1589 the decode context. Since the address of the pool may not be
1590 aligned, they have to be packed and unpacked as if they were
1591 serialized data of the wire or such.
1592
1593 The sizes packed in are uint32_t to be the same on all CPU types
1594 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08001595 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001596
1597
Laurence Lundbladeee851742020-01-08 08:37:05 -08001598static inline int
1599MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001600{
1601 // Use of UsefulInputBuf is overkill, but it is convenient.
1602 UsefulInputBuf UIB;
1603
Laurence Lundbladeee851742020-01-08 08:37:05 -08001604 // Just assume the size here. It was checked during SetUp so
1605 // the assumption is safe.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001606 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem, QCBOR_DECODE_MIN_MEM_POOL_SIZE});
1607 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
1608 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
1609 return UsefulInputBuf_GetError(&UIB);
1610}
1611
1612
Laurence Lundbladeee851742020-01-08 08:37:05 -08001613static inline int
1614MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001615{
1616 // Use of UsefulOutBuf is overkill, but convenient. The
1617 // length check performed here is useful.
1618 UsefulOutBuf UOB;
1619
1620 UsefulOutBuf_Init(&UOB, Pool);
1621 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
1622 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
1623 return UsefulOutBuf_GetError(&UOB);
1624}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001625
1626
1627/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001628 Internal function for an allocation, reallocation free and destuct.
1629
1630 Having only one function rather than one each per mode saves space in
1631 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001632
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001633 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1634 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001635static UsefulBuf
1636MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001637{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001638 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001639
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001640 uint32_t uPoolSize;
1641 uint32_t uFreeOffset;
1642
1643 if(uNewSize > UINT32_MAX) {
1644 // This allocator is only good up to 4GB. This check should
1645 // optimize out if sizeof(size_t) == sizeof(uint32_t)
1646 goto Done;
1647 }
1648 const uint32_t uNewSize32 = (uint32_t)uNewSize;
1649
1650 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
1651 goto Done;
1652 }
1653
1654 if(uNewSize) {
1655 if(pMem) {
1656 // REALLOCATION MODE
1657 // Calculate pointer to the end of the memory pool. It is
1658 // assumed that pPool + uPoolSize won't wrap around by
1659 // assuming the caller won't pass a pool buffer in that is
1660 // not in legitimate memory space.
1661 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
1662
1663 // Check that the pointer for reallocation is in the range of the
1664 // pool. This also makes sure that pointer math further down
1665 // doesn't wrap under or over.
1666 if(pMem >= pPool && pMem < pPoolEnd) {
1667 // Offset to start of chunk for reallocation. This won't
1668 // wrap under because of check that pMem >= pPool. Cast
1669 // is safe because the pool is always less than UINT32_MAX
1670 // because of check in QCBORDecode_SetMemPool().
1671 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1672
1673 // Check to see if the allocation will fit. uPoolSize -
1674 // uMemOffset will not wrap under because of check that
1675 // pMem is in the range of the uPoolSize by check above.
1676 if(uNewSize <= uPoolSize - uMemOffset) {
1677 ReturnValue.ptr = pMem;
1678 ReturnValue.len = uNewSize;
1679
1680 // Addition won't wrap around over because uNewSize was
1681 // checked to be sure it is less than the pool size.
1682 uFreeOffset = uMemOffset + uNewSize32;
1683 }
1684 }
1685 } else {
1686 // ALLOCATION MODE
1687 // uPoolSize - uFreeOffset will not underflow because this
1688 // pool implementation makes sure uFreeOffset is always
1689 // smaller than uPoolSize through this check here and
1690 // reallocation case.
1691 if(uNewSize <= uPoolSize - uFreeOffset) {
1692 ReturnValue.len = uNewSize;
1693 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001694 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001695 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001696 }
1697 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001698 if(pMem) {
1699 // FREE MODE
1700 // Cast is safe because of limit on pool size in
1701 // QCBORDecode_SetMemPool()
1702 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
1703 } else {
1704 // DESTRUCT MODE
1705 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001706 }
1707 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001708
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001709 UsefulBuf Pool = {pPool, uPoolSize};
1710 MemPool_Pack(Pool, uFreeOffset);
1711
1712Done:
1713 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001714}
1715
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001716
Laurence Lundbladef6531662018-12-04 10:42:22 +09001717/*
1718 Public function, see header qcbor.h file
1719 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001720QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
1721 UsefulBuf Pool,
1722 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001723{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001724 // The pool size and free mem offset are packed into the beginning
1725 // of the pool memory. This compile time check make sure the
1726 // constant in the header is correct. This check should optimize
1727 // down to nothing.
1728 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001729 return QCBOR_ERR_BUFFER_TOO_SMALL;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001730 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001731
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001732 // The pool size and free offset packed in to the beginning of pool
1733 // memory are only 32-bits. This check will optimize out on 32-bit
1734 // machines.
1735 if(Pool.len > UINT32_MAX) {
1736 return QCBOR_ERR_BUFFER_TOO_LARGE;
1737 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001738
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001739 // This checks that the pool buffer given is big enough.
1740 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
1741 return QCBOR_ERR_BUFFER_TOO_SMALL;
1742 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001743
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001744 pMe->StringAllocator.pfAllocator = MemPool_Function;
1745 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
1746 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001747
Laurence Lundblade30816f22018-11-10 13:40:22 +07001748 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001749}
Laurence Lundbladee6430642020-03-14 21:15:44 -07001750
1751
1752
Laurence Lundbladec4537442020-04-14 18:53:22 -07001753void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07001754{
Laurence Lundbladec4537442020-04-14 18:53:22 -07001755 if(pMe->nLastError != QCBOR_SUCCESS) {
1756 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07001757 return;
1758 }
1759
Laurence Lundbladec4537442020-04-14 18:53:22 -07001760 QCBORError nError;
1761 QCBORItem Item;
1762
1763 nError = QCBORDecode_GetNext(pMe, &Item);
1764 if(nError != QCBOR_SUCCESS) {
1765 pMe->nLastError = nError;
1766 return;
1767 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07001768
1769 switch(Item.uDataType) {
1770 case QCBOR_TYPE_TRUE:
1771 *pValue = true;
1772 break;
1773
1774 case QCBOR_TYPE_FALSE:
1775 *pValue = false;
1776 break;
1777
1778 default:
Laurence Lundbladec4537442020-04-14 18:53:22 -07001779 pMe->nLastError = QCBOR_ERR_NOT_EXPECTED_TYPE;
1780 break;
Laurence Lundbladee6430642020-03-14 21:15:44 -07001781 }
1782}
1783
1784
1785/* Types of text strings
1786 * Plain, b64, b64url, URI, regex, MIME Text
1787 * One function for each with options to expect plain?
1788 * One function for all so you can say what you want?
Laurence Lundbladec4537442020-04-14 18:53:22 -07001789 *
1790 * A label is expected if pLabel is not NULL.
Laurence Lundbladee6430642020-03-14 21:15:44 -07001791 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07001792void QCBORDecode_GetTextFoo(QCBORDecodeContext *pMe, QCBORLabel *pLabel, UsefulBufC *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07001793{
1794 QCBORItem Item;
1795 QCBORError nError;
1796
1797 nError = QCBORDecode_GetNext(pMe, &Item);
1798 if(nError) {
1799 pMe->nLastError = nError;
1800 return;
1801 }
1802
Laurence Lundbladec4537442020-04-14 18:53:22 -07001803 if(pLabel != NULL) {
1804 if(Item.uLabelType == QCBOR_TYPE_NONE) {
1805 pMe->nLastError = 9; // TODO: error code
1806 return;
1807 } else {
1808 // TODO: what about label allocation?
1809 pLabel->uLabelType = Item.uLabelType;
1810 pLabel->label.xx = Item.label.int64; // TOOD: figure out assignment
1811 }
1812 }
Laurence Lundbladee6430642020-03-14 21:15:44 -07001813
1814 switch(Item.uDataType) {
1815 case QCBOR_TYPE_TEXT_STRING:
1816 *pValue = Item.val.string;
1817 break;
1818
1819 default:
Laurence Lundbladec4537442020-04-14 18:53:22 -07001820 pMe->nLastError = QCBOR_ERR_NOT_EXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07001821 }
1822}
1823
1824
Laurence Lundbladec4537442020-04-14 18:53:22 -07001825/*
1826 Options for MIME data, CBOR, positive big num, negative big num ??
1827 */
1828void QCBORDecode_GetStringInternal(QCBORDecodeContext *pMe, UsefulBufC *pValue, uint8_t uType)
1829{
1830 if(pMe->nLastError != QCBOR_SUCCESS) {
1831 // Already in error state, do nothing
1832 return;
1833 }
1834
1835 QCBORError nError;
1836 QCBORItem Item;
1837
1838 nError = QCBORDecode_GetNext(pMe, &Item);
1839 if(nError != QCBOR_SUCCESS) {
1840 pMe->nLastError = nError;
1841 return;
1842 }
1843
1844 if(Item.uDataType == uType) {
1845 *pValue = Item.val.string;
1846 } else {
1847 pMe->nLastError = QCBOR_ERR_NOT_EXPECTED_TYPE;
1848 }
1849}
1850
1851void QCBORDecode_GetBytes(QCBORDecodeContext *pMe, QCBORLabel *pLabel, UsefulBufC *pValue)
1852{
1853 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_BYTE_STRING);
1854}
1855
1856
1857void QCBORDecode_GetText(QCBORDecodeContext *pMe, QCBORLabel *pLabel, UsefulBufC *pValue)
1858{
1859 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_TEXT_STRING);
1860}
1861
1862
1863void QCBORDecode_GetPosBignum(QCBORDecodeContext *pMe, QCBORLabel *pLabel, UsefulBufC *pValue)
1864{
1865 // TODO: do these have to be tagged?
1866 // Probably should allow tagged or untagged, but not wrong-tagged
1867 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_POSBIGNUM);
1868}
1869
1870void QCBORDecode_GetNegBignum(QCBORDecodeContext *pMe, QCBORLabel *pLabel, UsefulBufC *pValue)
1871{
1872 QCBORDecode_GetStringInternal(pMe, pValue, QCBOR_TYPE_NEGBIGNUM);
1873}
1874
1875
1876
Laurence Lundbladee6430642020-03-14 21:15:44 -07001877
1878/* Convert a decimal fraction to an int64_t without using
1879 floating point or math libraries. Most decimal fractions
1880 will not fit in an int64_t and this will error out with
1881 under or overflow
1882 */
1883uint8_t Exponentitate10(int64_t nMantissa, int64_t nExponent, int64_t *pnResult)
1884{
1885 int64_t nResult;
1886
1887 nResult = nMantissa;
1888
1889 /* This loop will run a maximum of 19 times because
1890 * INT64_MAX < 10 ^^ 19. More than that will cause
Laurence Lundbladec4537442020-04-14 18:53:22 -07001891 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07001892 */
1893 while(nExponent > 0) {
1894 if(nResult > INT64_MAX / 10) {
1895 return 99; // Error overflow
1896 }
1897 nResult = nResult * 10;
1898 nExponent--;
1899 }
1900
1901 while(nExponent < 0 ) {
1902 if(nResult == 0) {
1903 return 98; // Underflow error
1904 }
1905 nResult = nResult / 10;
1906 nExponent--;
1907 }
1908
1909 return 0;
1910}
1911
1912
Laurence Lundbladec4537442020-04-14 18:53:22 -07001913
1914
1915uint8_t Exponentitate10U(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
1916{
1917 uint64_t uResult;
1918
1919 uResult = uMantissa;
1920
1921 /* This loop will run a maximum of 19 times because
1922 * UINT64_MAX < 10 ^^ 19. More than that will cause
1923 * exit with the overflow error
1924 */
1925 while(nExponent > 0) {
1926 if(uResult > UINT64_MAX / 10) {
1927 return 99; // Error overflow
1928 }
1929 uResult = uResult * 10;
1930 nExponent--;
1931 }
1932
1933 while(nExponent < 0 ) {
1934 if(uResult == 0) {
1935 return 98; // Underflow error
1936 }
1937 uResult = uResult / 10;
1938 nExponent--;
1939 }
1940
1941 *puResult = uResult;
1942
1943 return 0;
1944}
1945
1946uint8_t Exponentitate10S(int64_t nMantissa, int64_t nExponent, int64_t *pnResult)
1947{
1948 // TODO: is this less code than duplicating the above function?
1949 uint64_t uResult;
1950
1951 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
1952
1953 Exponentitate10U(uMantissa, nExponent, &uResult);
1954
1955 if(uResult > INT64_MAX) {
1956 return 99; // Result is too large
1957 } else if(uResult < (uint64_t)-INT64_MIN) {
1958 return 98; // results is too small (large negative number)
1959 }
1960
1961 // TODO: these casts might not work.
1962 *pnResult = nMantissa > 0 ? (int64_t)uResult : (int64_t) -uResult;
1963
1964 return 0;
1965}
1966
1967
1968uint8_t Exponentitate10SS(int64_t nMantissa, int64_t nExponent, uint64_t *puResult)
1969{
1970 if(nMantissa < 0) {
1971 return 77; // can't return a negative result in an unsigned.
1972 }
1973
1974 return Exponentitate10U((uint64_t)nMantissa, nExponent, puResult);
1975}
1976
1977
1978uint8_t Exponentitate10US(uint64_t uMantissa, int64_t nExponent, int64_t *pnResult)
1979{
1980 // TODO: is this less code than duplicating the above function?
1981 uint64_t uResult;
1982
1983 uint8_t uR;
1984
1985 uR = Exponentitate10U(uMantissa, nExponent, &uResult);
1986 if(uR) {
1987 return uR;
1988 }
1989
1990 if(uResult > INT64_MAX) {
1991 return 88;
1992 }
1993 *pnResult = (int64_t)uResult;
1994
1995 return 0;
1996}
1997
1998#include <math.h>
1999
2000uint8_t Exponentitate10F(uint64_t uMantissa, int64_t nExponent, double *pfResult)
2001{
2002 // TODO: checkout exceptions; what is HUGE_VAL?
2003 *pfResult = pow((double)10, (double)nExponent) * (double)uMantissa;
2004
2005 //if(*pfResult == HUGE_VAL)
2006 return 0;
2007}
2008
2009
Laurence Lundbladee6430642020-03-14 21:15:44 -07002010/* Convert a decimal fraction to an int64_t without using
2011 floating point or math libraries. Most decimal fractions
2012 will not fit in an int64_t and this will error out with
2013 under or overflow
2014 */
2015uint8_t Exponentitate2(int64_t nMantissa, int64_t nExponent, int64_t *pnResult)
2016{
2017 int64_t nResult;
2018
2019 nResult = nMantissa;
2020
2021 /* This loop will run a maximum of 19 times because
2022 * INT64_MAX < 2^31. More than that will cause
2023 * exist with the overflow error
2024 */
2025 while(nExponent > 0) {
2026 if(nResult > INT64_MAX << 1) {
2027 return 99; // Error overflow
2028 }
2029 nResult = nResult >> 1;
2030 nExponent--;
2031 }
2032
2033 while(nExponent < 0 ) {
2034 if(nResult == 0) {
2035 return 98; // Underflow error
2036 }
2037 nResult = nResult << 1;
2038 nExponent--;
2039 }
2040
2041 *pnResult = nResult;
2042
2043 return 0;
2044}
2045
2046/*
2047 A) bignum is positive
2048 A1) output is signed INT64_MAX
2049 A2) output is unsigned UINT64_MAX
2050 B) bignum is negative
2051 B1) output is signed INT64_MAX
2052 B2) output is unsigned error
2053 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07002054QCBORError ConvertBigNum(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002055{
2056 uint64_t nResult;
2057
2058 nResult = 0;
2059 const uint8_t *pByte = BigNum.ptr;
2060 size_t uLen = BigNum.len;
2061 while(uLen--) {
2062 if(nResult > uMax << 8) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002063 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002064 }
2065 nResult = (nResult >> 8) + *pByte;
2066 }
2067
2068 *pResult = nResult;
2069 return 0;
2070}
2071
Laurence Lundbladec4537442020-04-14 18:53:22 -07002072
2073
2074QCBORError ConvertBigNumToDouble(const UsefulBufC BigNum, uint64_t uMax, double *pResult)
2075{
2076 double nResult;
2077
2078 nResult = 0;
2079 const uint8_t *pByte = BigNum.ptr;
2080 size_t uLen = BigNum.len;
2081 /* This will overflow and become the float value INFINITY if the number
2082 is too large to fit. No error will be logged.
2083 TODO: should an error be logged? */
2084 while(uLen--) {
2085 nResult = (nResult * 256) + *pByte;
2086 }
2087
2088 *pResult = nResult;
2089 return 0;
2090}
2091
2092
2093QCBORError ConvertPositiveBigNumToUnSigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002094{
2095 return ConvertBigNum(BigNum, UINT64_MAX, pResult);
2096}
2097
Laurence Lundbladec4537442020-04-14 18:53:22 -07002098QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002099{
2100 uint64_t uResult;
2101 uint8_t n = ConvertBigNum(BigNum, INT64_MAX, &uResult);
2102 if(n) {
2103 return n;
2104 }
2105 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2106 *pResult = (int64_t)uResult;
2107 return 0;
2108}
2109
2110
Laurence Lundbladec4537442020-04-14 18:53:22 -07002111QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002112{
2113 uint64_t uResult;
2114 uint8_t n = ConvertBigNum(BigNum, INT64_MAX-1, &uResult);
2115 if(n) {
2116 return n;
2117 }
2118 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
2119 *pResult = -(int64_t)uResult;
2120 return 0;
2121}
2122
Laurence Lundbladec4537442020-04-14 18:53:22 -07002123// No function to convert a negative bignum to unsigned; it is an error
2124
2125
2126
Laurence Lundbladee6430642020-03-14 21:15:44 -07002127int ConvertXYZ(const UsefulBufC Mantissa, int64_t nExponent, int64_t *pResult)
2128{
2129 int64_t nMantissa;
2130
2131 int xx = ConvertPositiveBigNumToSigned(Mantissa, &nMantissa);
2132 if(xx) {
2133 return xx;
2134 }
2135
2136 return Exponentitate10(nMantissa, nExponent, pResult);
2137}
2138
2139
2140
2141#define QCBOR_DECODE_TYPE_INT64 0x01
2142#define QCBOR_DECODE_TYPE_UINT64 0x02
2143#define QCBOR_DECODE_TYPE_FLOAT 0x03
2144#define QCBOR_DECODE_TYPE_BIGFLOAT 0x04
2145#define QCBOR_DECODE_TYPE_DECIMAL_FRACTION 0x05
2146#define QCBOR_DECODE_TYPE_BIG_NUM 0x06
2147
Laurence Lundbladec4537442020-04-14 18:53:22 -07002148
2149/*
2150 Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
2151 a big float, a decimal fraction or a big num. Conversion will be dones as
2152 expected. Some cases will error out with under or over flow.
2153 */
2154void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue, QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002155{
Laurence Lundbladec4537442020-04-14 18:53:22 -07002156 if(pMe->nLastError != QCBOR_SUCCESS) {
2157 return;
2158 }
2159
Laurence Lundbladee6430642020-03-14 21:15:44 -07002160 QCBORItem Item;
2161 QCBORError nError;
2162
2163 nError = QCBORDecode_GetNext(pMe, &Item);
2164 if(nError) {
2165 pMe->nLastError = nError;
2166 return;
2167 }
2168
Laurence Lundbladee6430642020-03-14 21:15:44 -07002169 switch(Item.uDataType) {
2170 case QCBOR_TYPE_FLOAT:
2171 if(uOptions & QCBOR_DECODE_TYPE_FLOAT) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002172 // TODO: what about under/overflow here?
Laurence Lundbladee6430642020-03-14 21:15:44 -07002173 *pValue = (int64_t)Item.val.dfnum;
2174 } else {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002175 pMe->nLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002176 }
2177 break;
2178
2179 case QCBOR_TYPE_INT64:
2180 if(uOptions & QCBOR_DECODE_TYPE_INT64) {
2181 *pValue = Item.val.int64;
2182 } else {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002183 pMe->nLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002184 }
2185 break;
2186
2187 case QCBOR_TYPE_UINT64:
2188 if(uOptions & QCBOR_DECODE_TYPE_UINT64) {
2189 if(Item.val.uint64 < INT64_MAX) {
2190 *pValue = Item.val.int64;
2191 } else {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002192 pMe->nLastError = QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002193 }
2194 } else {
Laurence Lundbladec4537442020-04-14 18:53:22 -07002195 pMe->nLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
Laurence Lundbladee6430642020-03-14 21:15:44 -07002196 }
2197 break;
2198
Laurence Lundbladec4537442020-04-14 18:53:22 -07002199 default:
2200 pMe->nLastError = 99; // TODO: fix error code after merge
2201 }
2202}
2203
2204/* This works for signed, unsigned and float */
2205void QCBORDecode_GetInt64Convert(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2206{
2207 QCBORItem Item;
2208 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2209}
2210
2211
2212
2213/*
2214 Get the next item as an int64_t. The CBOR type can be unsigned, negative, float
2215 a big float, a decimal fraction or a big num. Conversion will be dones as
2216 expected. Some cases will error out with under or over flow.
2217 */
2218void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uOptions, int64_t *pValue)
2219{
2220 QCBORItem Item;
2221
2222 QCBORDecode_GetInt64ConvertInternal(pMe, uOptions, pValue, &Item);
2223
2224 if(pMe->nLastError != QCBOR_SUCCESS) {
2225 return;
2226 }
2227
2228 switch(Item.uDataType) {
Laurence Lundbladee6430642020-03-14 21:15:44 -07002229 case QCBOR_TYPE_DECIMAL_FRACTION:
2230 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2231 pMe->nLastError = Exponentitate10(Item.val.expAndMantissa.Mantissa.nInt,
2232 Item.val.expAndMantissa.nExponent,
2233 pValue);
2234 } else {
2235 pMe->nLastError = 99; // TODO: error code
2236 }
2237 break;
2238
2239 case QCBOR_TYPE_BIGFLOAT:
2240 if(uOptions & QCBOR_DECODE_TYPE_BIGFLOAT) {
2241 pMe->nLastError = Exponentitate2(Item.val.expAndMantissa.Mantissa.nInt,
2242 Item.val.expAndMantissa.nExponent,
2243 pValue);
2244 } else {
2245 pMe->nLastError = 99; // TODO: error code
2246 }
2247 break;
2248
2249 case QCBOR_TYPE_POSBIGNUM:
2250 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
2251 pMe->nLastError = ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
2252 } else {
2253 pMe->nLastError = 99;
2254 }
2255 break;
2256
2257 case QCBOR_TYPE_NEGBIGNUM:
2258 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
2259 pMe->nLastError = ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
2260 } else {
2261 pMe->nLastError = 99;
2262 }
2263 break;
2264
2265 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
2266 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2267 int64_t nMantissa;
2268 pMe->nLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2269 if(!pMe->nLastError) {
2270 pMe->nLastError = Exponentitate10(nMantissa,
2271 Item.val.expAndMantissa.nExponent,
2272 pValue);
2273 }
2274 } else {
2275 pMe->nLastError = 99; // TODO: error code
2276 }
2277 break;
2278
2279 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
2280 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2281 int64_t nMantissa;
2282 pMe->nLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2283 if(!pMe->nLastError) {
2284 pMe->nLastError = Exponentitate10(nMantissa,
2285 Item.val.expAndMantissa.nExponent,
2286 pValue);
2287 }
2288 } else {
2289 pMe->nLastError = 99; // TODO: error code
2290 }
2291 break;
2292
2293 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
2294 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2295 int64_t nMantissa;
2296 pMe->nLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2297 if(!pMe->nLastError) {
2298 pMe->nLastError = Exponentitate2(nMantissa,
2299 Item.val.expAndMantissa.nExponent,
2300 pValue);
2301 }
2302 } else {
2303 pMe->nLastError = 99; // TODO: error code
2304 }
2305 break;
2306
2307 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
2308 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2309 int64_t nMantissa;
2310 pMe->nLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2311 if(!pMe->nLastError) {
2312 pMe->nLastError = Exponentitate2(nMantissa,
2313 Item.val.expAndMantissa.nExponent,
2314 pValue);
2315 }
2316 } else {
2317 pMe->nLastError = 99; // TODO: error code
2318 }
2319 break;
2320 }
2321}
2322
Laurence Lundbladec4537442020-04-14 18:53:22 -07002323
2324
2325void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe, uint32_t uOptions, uint64_t *pValue, QCBORItem *pItem)
2326{
2327 QCBORItem Item;
2328 QCBORError nError;
2329
2330 nError = QCBORDecode_GetNext(pMe, &Item);
2331 if(nError) {
2332 pMe->nLastError = nError;
2333 return;
2334 }
2335
2336 switch(Item.uDataType) {
2337 case QCBOR_TYPE_FLOAT:
2338 if(uOptions & QCBOR_DECODE_TYPE_FLOAT) {
2339 if(Item.val.dfnum >= 0) {
2340 *pValue = (uint64_t)Item.val.dfnum;
2341 } else {
2342 pMe->nLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
2343 }
2344 } else {
2345 pMe->nLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2346 }
2347 break;
2348
2349 case QCBOR_TYPE_INT64:
2350 if(uOptions & QCBOR_DECODE_TYPE_INT64) {
2351 if(Item.val.int64 >= 0) {
2352 *pValue = (uint64_t)Item.val.int64;
2353 } else {
2354 pMe->nLastError = QCBOR_ERR_NUMBER_SIGN_CONVERSION;
2355 }
2356 } else {
2357 pMe->nLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2358 }
2359 break;
2360
2361 case QCBOR_TYPE_UINT64:
2362 if(uOptions & QCBOR_DECODE_TYPE_UINT64) {
2363 *pValue = Item.val.uint64;
2364 } else {
2365 pMe->nLastError = QCBOR_ERR_CONVERSION_NOT_REQUESTED;
2366 }
2367 break;
2368 }
2369}
2370
2371
Laurence Lundbladee6430642020-03-14 21:15:44 -07002372void QCBORDecode_GetUInt64X(QCBORDecodeContext *pMe, uint32_t uOptions, QCBORLabel *pLabel, uint64_t *pValue)
2373{
2374 QCBORItem Item;
2375 QCBORError nError;
2376
2377 nError = QCBORDecode_GetNext(pMe, &Item);
2378 if(nError) {
2379 pMe->nLastError = nError;
2380 return;
2381 }
2382
2383 if(pLabel != NULL) {
2384 if(Item.uLabelType == QCBOR_TYPE_NONE) {
2385 pMe->nLastError = 9; // TODO: error code
2386 return;
2387 } else {
2388 // TODO: what about label allocation?
2389 pLabel->uLabelType = Item.uLabelType;
2390 pLabel->label.xx = Item.label.int64; // TOOD: figure out assignment
2391 }
2392 }
2393
2394 switch(Item.uDataType) {
2395 case QCBOR_TYPE_FLOAT:
2396 if(uOptions & QCBOR_DECODE_TYPE_FLOAT) {
2397 *pValue = (uint64_t)Item.val.dfnum;
2398 } else {
2399 pMe->nLastError = 99; // TODO: error code
2400 }
2401 break;
2402
2403 case QCBOR_TYPE_INT64:
2404 if(uOptions & QCBOR_DECODE_TYPE_INT64) {
2405 if(Item.val.int64 >= 0) {
2406 *pValue = (uint64_t)Item.val.int64;
2407 } else {
2408 pMe->nLastError = 49; // negative
2409 }
2410 } else {
2411 pMe->nLastError = 99; // TODO: error code
2412 }
2413 break;
2414
2415 case QCBOR_TYPE_UINT64:
2416 if(uOptions & QCBOR_DECODE_TYPE_UINT64) {
2417 *pValue = Item.val.uint64;
2418 } else {
2419 pMe->nLastError = 99; // TODO: error code
2420 }
2421 break;
2422
2423 case QCBOR_TYPE_DECIMAL_FRACTION:
2424 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2425 pMe->nLastError = Exponentitate10(Item.val.expAndMantissa.Mantissa.nInt,
2426 Item.val.expAndMantissa.nExponent,
2427 pValue);
2428 } else {
2429 pMe->nLastError = 99; // TODO: error code
2430 }
2431 break;
2432
2433 case QCBOR_TYPE_BIGFLOAT:
2434 if(uOptions & QCBOR_DECODE_TYPE_BIGFLOAT) {
2435 pMe->nLastError = Exponentitate2(Item.val.expAndMantissa.Mantissa.nInt,
2436 Item.val.expAndMantissa.nExponent,
2437 pValue);
2438 } else {
2439 pMe->nLastError = 99; // TODO: error code
2440 }
2441 break;
2442
2443 case QCBOR_TYPE_POSBIGNUM:
2444 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
2445 pMe->nLastError = ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
2446 } else {
2447 pMe->nLastError = 99;
2448 }
2449 break;
2450
2451 case QCBOR_TYPE_NEGBIGNUM:
2452 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
2453 pMe->nLastError = ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
2454 } else {
2455 pMe->nLastError = 99;
2456 }
2457 break;
2458
2459 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
2460 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2461 int64_t nMantissa;
2462 pMe->nLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2463 if(!pMe->nLastError) {
2464 pMe->nLastError = Exponentitate10(nMantissa,
2465 Item.val.expAndMantissa.nExponent,
2466 pValue);
2467 }
2468 } else {
2469 pMe->nLastError = 99; // TODO: error code
2470 }
2471 break;
2472
2473 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
2474 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2475 int64_t nMantissa;
2476 pMe->nLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2477 if(!pMe->nLastError) {
2478 pMe->nLastError = Exponentitate10(nMantissa,
2479 Item.val.expAndMantissa.nExponent,
2480 pValue);
2481 }
2482 } else {
2483 pMe->nLastError = 99; // TODO: error code
2484 }
2485 break;
2486
2487 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
2488 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2489 int64_t nMantissa;
2490 pMe->nLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2491 if(!pMe->nLastError) {
2492 pMe->nLastError = Exponentitate2(nMantissa,
2493 Item.val.expAndMantissa.nExponent,
2494 pValue);
2495 }
2496 } else {
2497 pMe->nLastError = 99; // TODO: error code
2498 }
2499 break;
2500
2501 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
2502 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2503 int64_t nMantissa;
2504 pMe->nLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2505 if(!pMe->nLastError) {
2506 pMe->nLastError = Exponentitate2(nMantissa,
2507 Item.val.expAndMantissa.nExponent,
2508 pValue);
2509 }
2510 } else {
2511 pMe->nLastError = 99; // TODO: error code
2512 }
2513 break;
2514 }
2515}
2516
Laurence Lundbladec4537442020-04-14 18:53:22 -07002517
2518/*
2519
2520 Convert from bignums,
2521
2522 */
2523void QCBORDecode_GetDouble(QCBORDecodeContext *pMe, uint32_t uOptions, QCBORLabel *pLabel, double *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07002524{
2525 /* the same range of conversions */
2526
Laurence Lundbladec4537442020-04-14 18:53:22 -07002527 /* Conversion from bignums, decimal fractions and such will be interesting */
2528
2529 QCBORItem Item;
2530 QCBORError nError;
2531
2532 nError = QCBORDecode_GetNext(pMe, &Item);
2533 if(nError) {
2534 pMe->nLastError = nError;
2535 return;
2536 }
2537
2538 if(pLabel != NULL) {
2539 if(Item.uLabelType == QCBOR_TYPE_NONE) {
2540 pMe->nLastError = 9; // TODO: error code
2541 return;
2542 } else {
2543 // TODO: what about label allocation?
2544 pLabel->uLabelType = Item.uLabelType;
2545 pLabel->label.xx = Item.label.int64; // TOOD: figure out assignment
2546 }
2547 }
2548
2549 switch(Item.uDataType) {
2550 case QCBOR_TYPE_FLOAT:
2551 if(uOptions & QCBOR_DECODE_TYPE_FLOAT) {
2552 *pValue = Item.val.dfnum;
2553 } else {
2554 pMe->nLastError = 99; // TODO: error code
2555 }
2556 break;
2557
2558 case QCBOR_TYPE_INT64:
2559 if(uOptions & QCBOR_DECODE_TYPE_INT64) {
2560 // TODO: how does this work?
2561 *pValue = (double)Item.val.int64;
2562 } else {
2563 pMe->nLastError = 99; // TODO: error code
2564 }
2565 break;
2566
2567 case QCBOR_TYPE_UINT64:
2568 if(uOptions & QCBOR_DECODE_TYPE_UINT64) {
2569 *pValue = (double)Item.val.uint64;
2570 } else {
2571 pMe->nLastError = 99; // TODO: error code
2572 }
2573 break;
2574
2575 case QCBOR_TYPE_DECIMAL_FRACTION:
2576 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2577 pMe->nLastError = Exponentitate10(Item.val.expAndMantissa.Mantissa.nInt,
2578 Item.val.expAndMantissa.nExponent,
2579 pValue);
2580 } else {
2581 pMe->nLastError = 99; // TODO: error code
2582 }
2583 break;
2584
2585 case QCBOR_TYPE_BIGFLOAT:
2586 if(uOptions & QCBOR_DECODE_TYPE_BIGFLOAT) {
2587 pMe->nLastError = Exponentitate2(Item.val.expAndMantissa.Mantissa.nInt,
2588 Item.val.expAndMantissa.nExponent,
2589 pValue);
2590 } else {
2591 pMe->nLastError = 99; // TODO: error code
2592 }
2593 break;
2594
2595 case QCBOR_TYPE_POSBIGNUM:
2596 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
2597 pMe->nLastError = ConvertPositiveBigNumToSigned(Item.val.bigNum, pValue);
2598 } else {
2599 pMe->nLastError = 99;
2600 }
2601 break;
2602
2603 case QCBOR_TYPE_NEGBIGNUM:
2604 if(uOptions & QCBOR_DECODE_TYPE_BIG_NUM) {
2605 pMe->nLastError = ConvertNegativeBigNumToSigned(Item.val.bigNum, pValue);
2606 } else {
2607 pMe->nLastError = 99;
2608 }
2609 break;
2610
2611 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
2612 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2613 int64_t nMantissa;
2614 pMe->nLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2615 if(!pMe->nLastError) {
2616 pMe->nLastError = Exponentitate10(nMantissa,
2617 Item.val.expAndMantissa.nExponent,
2618 pValue);
2619 }
2620 } else {
2621 pMe->nLastError = 99; // TODO: error code
2622 }
2623 break;
2624
2625 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
2626 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2627 int64_t nMantissa;
2628 pMe->nLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2629 if(!pMe->nLastError) {
2630 pMe->nLastError = Exponentitate10(nMantissa,
2631 Item.val.expAndMantissa.nExponent,
2632 pValue);
2633 }
2634 } else {
2635 pMe->nLastError = 99; // TODO: error code
2636 }
2637 break;
2638
2639 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
2640 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2641 int64_t nMantissa;
2642 pMe->nLastError = ConvertPositiveBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2643 if(!pMe->nLastError) {
2644 pMe->nLastError = Exponentitate2(nMantissa,
2645 Item.val.expAndMantissa.nExponent,
2646 pValue);
2647 }
2648 } else {
2649 pMe->nLastError = 99; // TODO: error code
2650 }
2651 break;
2652
2653 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
2654 if(uOptions & QCBOR_DECODE_TYPE_DECIMAL_FRACTION) {
2655 int64_t nMantissa;
2656 pMe->nLastError = ConvertNegativeBigNumToSigned(Item.val.expAndMantissa.Mantissa.bigNum, &nMantissa);
2657 if(!pMe->nLastError) {
2658 pMe->nLastError = Exponentitate2(nMantissa,
2659 Item.val.expAndMantissa.nExponent,
2660 pValue);
2661 }
2662 } else {
2663 pMe->nLastError = 99; // TODO: error code
2664 }
2665 break;
2666 }
2667
2668
2669
Laurence Lundbladee6430642020-03-14 21:15:44 -07002670}
2671
2672
2673
2674
2675