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