blob: b4122059d4eb4039104dcbbc4ed34de2b3bd13c6 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
2Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10 copyright notice, this list of conditions and the following
11 disclaimer in the documentation and/or other materials provided
12 with the distribution.
13 * Neither the name of The Linux Foundation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28==============================================================================*/
29
30/*===================================================================================
31 FILE: qcbor_decode.c
32
33 DESCRIPTION: This file contains the implementation of QCBOR.
34
35 EDIT HISTORY FOR FILE:
36
37 This section contains comments describing changes made to the module.
38 Notice that changes are listed in reverse chronological order.
39
40 when who what, where, why
41 -------- ---- ---------------------------------------------------
42 02/04/17 llundbla Work on CPUs that don's require pointer alignment
43 by making use of changes in UsefulBuf
44 03/01/17 llundbla More data types; decoding improvements and fixes
45 11/13/16 llundbla Integrate most TZ changes back into github version.
46 09/30/16 gkanike Porting to TZ.
47 03/15/16 llundbla Initial Version.
48
49 =====================================================================================*/
50
51#include "qcbor.h"
52
53#include <stdint.h>
54
55#ifdef QSEE
56#include "stringl.h"
57#endif
58
59
60/*
61 Collection of functions to track the map and array nesting for decoding
62 */
63
64inline static int IsMapOrArray(uint8_t uDataType)
65{
66 return uDataType == QCBOR_TYPE_MAP || uDataType == QCBOR_TYPE_ARRAY;
67}
68
69inline static int DecodeNesting_IsNested(const QCBORDecodeNesting *pNesting)
70{
71 return pNesting->pCurrent != &(pNesting->pMapsAndArrays[0]);
72}
73
74inline static int DecodeNesting_TypeIsMap(const QCBORDecodeNesting *pNesting)
75{
76 if(!DecodeNesting_IsNested(pNesting))
77 return 0;
78
79 return CBOR_MAJOR_TYPE_MAP == pNesting->pCurrent->uMajorType;
80}
81
82inline static void DecodeNesting_Decrement(QCBORDecodeNesting *pNesting, uint8_t uDataType)
83{
84 if(!DecodeNesting_IsNested(pNesting)) {
85 return; // at top level where there is no tracking
86 }
87
88 // Decrement
89 pNesting->pCurrent->uCount--;
90
91 // Pop up nesting levels if the counts at the levels is zero
92 while(0 == pNesting->pCurrent->uCount && DecodeNesting_IsNested(pNesting)) {
93 pNesting->pCurrent--;
94 }
95}
96
97inline static int DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uMajorType, int uCount)
98{
99 int nReturn = QCBOR_SUCCESS;
100
101 if(uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
102 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
103 goto Done;
104 }
105
106 if(pNesting->pCurrent >= &(pNesting->pMapsAndArrays[QCBOR_MAX_ARRAY_NESTING])) {
107 nReturn = QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
108 goto Done;
109 }
110
111 pNesting->pCurrent++;
112
113 pNesting->pCurrent->uMajorType = uMajorType;
114 pNesting->pCurrent->uCount = uCount;
115
116Done:
117 return nReturn;;
118}
119
120inline static uint8_t DecodeNesting_GetLevel(QCBORDecodeNesting *pNesting)
121{
122 return pNesting->pCurrent - &(pNesting->pMapsAndArrays[0]);
123}
124
125inline static void DecodeNesting_Init(QCBORDecodeNesting *pNesting)
126{
127 pNesting->pCurrent = &(pNesting->pMapsAndArrays[0]);
128}
129
130
131
132
133/*
134 Public function, see header file
135 */
136void QCBORDecode_Init(QCBORDecodeContext *me, UsefulBufC EncodedCBOR, int8_t nDecodeMode)
137{
138 memset(me, 0, sizeof(QCBORDecodeContext));
139 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
140 // Don't bother with error check on decode mode. If a bad value is passed it will just act as
141 // if the default normal mode of 0 was set.
142 me->uDecodeMode = nDecodeMode;
143 DecodeNesting_Init(&(me->nesting));
144}
145
146
147/*
148 This decodes the fundamental part of a CBOR data item, the type and number
149
150 This is the Counterpart to InsertEncodedTypeAndNumber().
151
152 This does the network->host byte order conversion. The conversion here
153 also results in the conversion for floats in addition to that for
154 lengths, tags and integer values.
155
156 */
157inline static int DecodeTypeAndNumber(UsefulInputBuf *pUInBuf, int *pnMajorType, uint64_t *puNumber, uint8_t *puAdditionalInfo)
158{
159 int nReturn;
160
161 // Get the initial byte that every CBOR data item has
162 const uint8_t InitialByte = UsefulInputBuf_GetByte(pUInBuf);
163
164 // Break down the initial byte
165 const uint8_t uTmpMajorType = InitialByte >> 5;
166 const uint8_t uAdditionalInfo = InitialByte & 0x1f;
167
168 // Get the integer that follows the major type. Do not know if this is a length, value, float or tag at this point
169 // Also convert from network byte order. Call ntohxx on simple variables in case they are macros that
170 // reference their argument multiple times.
171 uint64_t uTmpValue;
172 switch(uAdditionalInfo) {
173
174 case LEN_IS_ONE_BYTE:
175 uTmpValue = UsefulInputBuf_GetByte(pUInBuf);
176 break;
177
178 case LEN_IS_TWO_BYTES:
179 uTmpValue = UsefulInputBuf_GetUint16(pUInBuf);
180 break;
181
182 case LEN_IS_FOUR_BYTES:
183 uTmpValue = UsefulInputBuf_GetUint32(pUInBuf);
184 break;
185
186 case LEN_IS_EIGHT_BYTES:
187 uTmpValue = UsefulInputBuf_GetUint64(pUInBuf);
188 break;
189
190 case ADDINFO_RESERVED1: // reserved by CBOR spec
191 case ADDINFO_RESERVED2: // reserved by CBOR spec
192 case ADDINFO_RESERVED3: // reserved by CBOR spec
193 case LEN_IS_INDEFINITE: // indefinite types not supported (yet)
194 nReturn = QCBOR_ERR_UNSUPPORTED;
195 goto Done;
196
197 default:
198 uTmpValue = uAdditionalInfo;
199 break;
200 }
201
202 // If any of the UsefulInputBuf_Get calls fail we will get here with uTmpValue as 0.
203 // There is no harm in this. This following check takes care of catching all of
204 // these errors.
205
206 if(UsefulInputBuf_GetError(pUInBuf)) {
207 nReturn = QCBOR_ERR_HIT_END;
208 goto Done;
209 }
210
211 // All successful if we got here.
212 nReturn = QCBOR_SUCCESS;
213 *pnMajorType = uTmpMajorType;
214 *puNumber = uTmpValue;
215 *puAdditionalInfo = uAdditionalInfo;
216
217Done:
218 return nReturn;
219}
220
221
222/*
223 CBOR doesn't explicitly specify two's compliment for integers but all CPUs
224 use it these days and the test vectors in the RFC are so. All integers in the CBOR
225 structure are positive and the major type indicates positive or negative.
226 CBOR can express positive integers up to 2^x - 1 where x is the number of bits
227 and negative integers down to 2^x. Note that negative numbers can be one
228 more away from zero than positive.
229 Stdint, as far as I can tell, uses two's compliment to represent
230 negative integers.
231
232 See http://www.unix.org/whitepapers/64bit.html for reasons int isn't
233 used here in any way including in the interface
234 */
235inline static int DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
236{
237 int nReturn = QCBOR_SUCCESS;
238
239 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
240 if (uNumber <= INT64_MAX) {
241 pDecodedItem->val.int64 = (int64_t)uNumber;
242 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
243
244 } else {
245 pDecodedItem->val.uint64 = uNumber;
246 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
247
248 }
249 } else {
250 if(uNumber <= INT64_MAX) {
251 pDecodedItem->val.int64 = -uNumber-1;
252 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
253
254 } else {
255 // C can't represent a negative integer in this range
256 // so it is an error. todo -- test this condition
257 nReturn = QCBOR_ERR_INT_OVERFLOW;
258 }
259 }
260
261 return nReturn;
262}
263
264// Make sure #define value line up as DecodeSimple counts on this.
265#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
266#error QCBOR_TYPE_FALSE macro value wrong
267#endif
268
269#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
270#error QCBOR_TYPE_TRUE macro value wrong
271#endif
272
273#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
274#error QCBOR_TYPE_NULL macro value wrong
275#endif
276
277#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
278#error QCBOR_TYPE_UNDEF macro value wrong
279#endif
280
281#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
282#error QCBOR_TYPE_DOUBLE macro value wrong
283#endif
284
285#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
286#error QCBOR_TYPE_FLOAT macro value wrong
287#endif
288
289/*
290 Decode true, false, floats, break...
291 */
292
293inline static int DecodeSimple(uint8_t uAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
294{
295 int nReturn = QCBOR_SUCCESS;
296
297 // uAdditionalInfo is 5 bits from the initial byte
298 // compile time checks above make sure uAdditionalInfo values line up with uDataType values
299 pDecodedItem->uDataType = uAdditionalInfo;
300
301 switch(uAdditionalInfo) {
302 case ADDINFO_RESERVED1: // 28
303 case ADDINFO_RESERVED2: // 29
304 case ADDINFO_RESERVED3: // 30
305 case CBOR_SIMPLE_BREAK: // 31
306 nReturn = QCBOR_ERR_UNSUPPORTED;
307 break;
308
309 case CBOR_SIMPLEV_FALSE: // 20
310 case CBOR_SIMPLEV_TRUE: // 21
311 case CBOR_SIMPLEV_NULL: // 22
312 case CBOR_SIMPLEV_UNDEF: // 23
313 break; // nothing to do
314
315 case CBOR_SIMPLEV_ONEBYTE: // 24
316 if(uNumber <= CBOR_SIMPLE_BREAK) {
317 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
318 nReturn = QCBOR_ERR_INVALID_CBOR;
319 goto Done;
320 }
321 // fall through intentionally
322
323 default: // 0-19
324 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
325 // DecodeTypeAndNumber will make uNumber equal to uAdditionalInfo when uAdditionalInfo is < 24
326 // This cast is safe because the 2, 4 and 8 byte lengths of uNumber are in the double/float cases above
327 pDecodedItem->val.uSimple = (uint8_t)uNumber;
328 break;
329 }
330
331Done:
332 return nReturn;
333}
334
335
336
337/*
338 Decode text and byte strings
339 */
340inline static int DecodeBytes(int nMajorType, uint64_t uNumber, UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem)
341{
342 const void *pBytes = UsefulInputBuf_GetBytes(pUInBuf, uNumber);
343
344 int nReturn = QCBOR_ERR_HIT_END;
345
346 if(pBytes != NULL) {
347 pDecodedItem->val.string.ptr = pBytes;
348 pDecodedItem->val.string.len = uNumber;
349 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
350 nReturn = QCBOR_SUCCESS;
351 }
352
353 return nReturn;
354}
355
356
357/*
358 Mostly just assign the right data type for the date string.
359 */
360inline static int DecodeDateString(QCBORItem Item, QCBORItem *pDecodedItem)
361{
362 if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) {
363 return QCBOR_ERR_BAD_OPT_TAG;
364 }
365 pDecodedItem->val.dateString = Item.val.string;
366 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
367 pDecodedItem->uTagBits = Item.uTagBits;
368 pDecodedItem->uTag = Item.uTag;
369 return QCBOR_SUCCESS;
370}
371
372
373/*
374 Mostly just assign the right data type for the bignum.
375 */
376inline static int DecodeBigNum(QCBORItem Item, QCBORItem *pDecodedItem, uint64_t uTagFlags)
377{
378 if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
379 return QCBOR_ERR_BAD_OPT_TAG;
380 }
381 pDecodedItem->val.bigNum = Item.val.string;
382 pDecodedItem->uDataType = uTagFlags & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
383 pDecodedItem->uTagBits = Item.uTagBits;
384 pDecodedItem->uTag = Item.uTag;
385 return QCBOR_SUCCESS;
386}
387
388
389/*
390 The epoch formatted date. Turns lots of different forms of encoding date into uniform one
391 */
392static int DecodeDateEpoch(QCBORItem Item, QCBORItem *pDecodedItem)
393{
394 int nReturn = QCBOR_SUCCESS;
395
396 pDecodedItem->uTagBits = Item.uTagBits;
397 pDecodedItem->uTag = Item.uTag;
398 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
399 pDecodedItem->val.epochDate.fSecondsFraction = 0;
400
401 switch (Item.uDataType) {
402
403 case QCBOR_TYPE_INT64:
404 pDecodedItem->val.epochDate.nSeconds = Item.val.int64;
405 break;
406
407 case QCBOR_TYPE_UINT64:
408 if(Item.val.uint64 > INT64_MAX) {
409 nReturn = QCBOR_ERR_DATE_OVERFLOW;
410 goto Done;
411 }
412 pDecodedItem->val.epochDate.nSeconds = Item.val.uint64;
413 break;
414
415 default:
416 nReturn = QCBOR_ERR_BAD_OPT_TAG;
417 }
418
419Done:
420 return nReturn;
421}
422
423
424/*
425 Decode the optional tagging that preceeds the real data value. There could be lots of them.
426 */
427static int GetAnItem(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, int bCalledFromDecodeOptional);
428
429/*
430 Returns an error if there was something wrong with the optional item or it couldn't
431 be handled.
432 */
433static int DecodeOptional(UsefulInputBuf *pUInBuf, uint64_t uInputTag, QCBORItem *pDecodedItem)
434{
435 int nReturn = QCBOR_SUCCESS;
436
437 uint64_t uTagFlags = 0; // accumulate the tags in the form of flags
438 uint64_t uTagToProcess = uInputTag; // First process tag passed in
439
440 QCBORItem Item;
441
442 do {
443 if(uTagToProcess < 63) { // 63 is the number of bits in a uint64 - 1
444 uTagFlags |= 0x01LL << uTagToProcess;
445 } else if(uTagToProcess == CBOR_TAG_CBOR_MAGIC) {
446 uTagFlags |= QCBOR_TAGFLAG_CBOR_MAGIC;
447 }
448 /* This code ignores the all but the first tag of value
449 greater than 63. Ignoring tags that are not understoof
450 is allowed by the standard. Multiple tags are
451 presumably rare. */
452
453 nReturn = GetAnItem(pUInBuf, &Item, 1);
454 if(nReturn) {
455 // Bail out of the whole item fetch on any sort of error here
456 goto Done;
457 }
458
459 if(Item.uDataType != QCBOR_TYPE_OPTTAG) {
460 break;
461 }
462
463 uTagToProcess = Item.uTag;
464 } while (1);
465
466
467 /*
468 CBOR allows multiple tags on a data item. It also defines
469 a number of standard tag values, most of which are
470 less than 64. This code can deal with multiple tag
471 values that are less than 64 and the last tag of multiple
472 if the value is more than 64. Or said another way
473 if there is one tag with a value >64 this code works.
474
475 The assumption is that multiple tag values > 64 are rare.
476
477 At this point in this code. uTagFlags has all the flags
478 < 64 and uTagToProcess has the last tag.
479
480 Does this deal with multiple tags on an item we process?
481 */
482
483 Item.uTagBits = uTagFlags;
484 Item.uTag = uTagToProcess;
485
486 switch(uTagFlags & (QCBOR_TAGFLAG_DATE_STRING | QCBOR_TAGFLAG_DATE_EPOCH | QCBOR_TAGFLAG_POS_BIGNUM |QCBOR_TAGFLAG_NEG_BIGNUM)) {
487 case 0:
488 // No tags we know about. Pass them up
489 *pDecodedItem = Item;
490 break;
491
492 case QCBOR_TAGFLAG_DATE_STRING:
493 nReturn = DecodeDateString(Item, pDecodedItem);
494 break;
495
496 case QCBOR_TAGFLAG_DATE_EPOCH:
497 nReturn = DecodeDateEpoch(Item, pDecodedItem);
498 break;
499
500 case QCBOR_TAGFLAG_POS_BIGNUM:
501 case QCBOR_TAGFLAG_NEG_BIGNUM:
502 nReturn = DecodeBigNum(Item, pDecodedItem, uTagFlags);
503 break;
504
505 default:
506 // Encountering some mixed up CBOR like something that
507 // is tagged as both a string and integer date.
508 nReturn = QCBOR_ERR_BAD_OPT_TAG ;
509 }
510
511Done:
512 return nReturn;
513}
514
515
516
517// Make sure the constants align as this is assumed by the GetAnItem() implementation
518#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
519#error QCBOR_TYPE_ARRAY value not lined up with major type
520#endif
521#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
522#error QCBOR_TYPE_MAP value not lined up with major type
523#endif
524
525/*
526 This gets a single data item and decodes it including preceding optional tagging. This does not
527 deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
528 maps are handled at the next level up in GetNext().
529
530 Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
531 a few forms of invalid encoded CBOR
532 */
533
534static int GetAnItem(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, int bCalledFromDecodeOptional)
535{
536 int nReturn;
537
538 // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
539 // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
540 int uMajorType;
541 uint64_t uNumber;
542 uint8_t uAdditionalInfo;
543
544 nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
545
546 // Error out here if we got into trouble on the type and number.
547 // The code after this will not work if the type and number is not good.
548 if(nReturn)
549 goto Done;
550
551 pDecodedItem->uTagBits = 0;
552 pDecodedItem->uTag = 0;
553
554 // At this point the major type and the value are valid. We've got the type and the number that
555 // starts every CBOR data item.
556 switch (uMajorType) {
557 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
558 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
559 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
560 break;
561
562 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
563 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
564 nReturn = DecodeBytes(uMajorType, uNumber, pUInBuf, pDecodedItem);
565 break;
566
567 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
568 case CBOR_MAJOR_TYPE_MAP: // Major type 5
569 // Record the number of items in the array or map
570 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
571 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
572 goto Done;
573 }
574 pDecodedItem->val.uCount = uNumber; // type conversion OK because of check above
575 pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align
576 break;
577
578 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
579 pDecodedItem->uTag = uNumber;
580 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
581 if(!bCalledFromDecodeOptional) {
582 // There can be a more than one optional tag in front of an actual data item
583 // they are all handled by looping in DecodeOptional which calls back here
584 // this test avoids infinite recursion.
585 nReturn = DecodeOptional(pUInBuf, uNumber, pDecodedItem);
586 }
587 break;
588
589 case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
590 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
591 break;
592
593 default: // Should never happen because DecodeTypeAndNumber() should never return > 7
594 nReturn = QCBOR_ERR_UNSUPPORTED;
595 break;
596 }
597
598Done:
599 return nReturn;
600}
601
602
603/*
604 Public function, see header qcbor.h file
605 */
606int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
607{
608 int nReturn;
609
610 if(!UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
611 nReturn = QCBOR_ERR_HIT_END;
612 goto Done;
613 }
614
615 nReturn = GetAnItem(&(me->InBuf), pDecodedItem, 0);
616 if(nReturn)
617 goto Done;
618
619 // If in a map and the right decoding mode, get the label
620 if(DecodeNesting_TypeIsMap(&(me->nesting)) && me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
621 // In a map and caller wants maps decoded, not treated as arrays
622
623 // Get the next item which will be the real data; Item will be the label
624 QCBORItem LabelItem = *pDecodedItem;
625 nReturn = GetAnItem(&(me->InBuf), pDecodedItem, 0);
626 if(nReturn)
627 goto Done;
628
629 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
630 // strings are always good labels
631 pDecodedItem->label.string = LabelItem.val.string;
632 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
633 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
634 // It's not a string and we only want strings, probably for easy translation to JSON
635 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
636 goto Done;
637 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
638 pDecodedItem->label.int64 = LabelItem.val.int64;
639 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
640 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
641 pDecodedItem->label.uint64 = LabelItem.val.uint64;
642 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
643 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
644 pDecodedItem->label.string = LabelItem.val.string;
645 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
646 } else {
647 // label is not an int or a string. It is an arrray
648 // or a float or such and this implementation doesn't handle that.
649 nReturn = QCBOR_ERR_MAP_LABEL_TYPE ;
650 goto Done;
651 }
652 }
653
654 // Record the nesting level for this data item
655 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
656
657 // If the new item is a non-empty array or map, the nesting level descends
658 if(IsMapOrArray(pDecodedItem->uDataType) && pDecodedItem->val.uCount) {
659 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem->uDataType, pDecodedItem->val.uCount);
660 } else {
661 // Track number of items in maps and arrays and ascend nesting if all are consumed
662 // Note that an empty array or map is like a integer or string in effect here
663 DecodeNesting_Decrement(&(me->nesting), pDecodedItem->uDataType);
664 }
665
666Done:
667 return nReturn;
668}
669
670
671/*
672 Public function, see header qcbor.h file
673 */
674int QCBORDecode_Finish(QCBORDecodeContext *me)
675{
676 return UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) ? QCBOR_ERR_EXTRA_BYTES : QCBOR_SUCCESS;
677}
678
679
680
681/*
682
683Decoder errors handled in this file
684
685 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
686
687 - indefinite length, currently not supported QCBOR_ERR_UNSUPPORTED
688
689 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
690
691 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
692
693 - Encountered conflicting tags -- e.g., an item is tagged both a date string and an epoch date QCBOR_ERR_UNSUPPORTED
694
695 - Encountered a break, not supported because indefinite lengths are not supported QCBOR_ERR_UNSUPPORTED
696
697 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
698
699 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
700
701 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
702
703 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
704
705 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
706
707 */
708