blob: 25c62f77ea2a3135eab8fe8d8a9f2799b8cc7b82 [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) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700342 pDecodedItem->val.string = (UsefulBufC){pBytes, uNumber};
343 pDecodedItem->uDataType = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING) ? QCBOR_TYPE_BYTE_STRING : QCBOR_TYPE_TEXT_STRING;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700344 nReturn = QCBOR_SUCCESS;
345 }
346
347 return nReturn;
348}
349
350
351/*
352 Mostly just assign the right data type for the date string.
353 */
354inline static int DecodeDateString(QCBORItem Item, QCBORItem *pDecodedItem)
355{
356 if(Item.uDataType != QCBOR_TYPE_TEXT_STRING) {
357 return QCBOR_ERR_BAD_OPT_TAG;
358 }
359 pDecodedItem->val.dateString = Item.val.string;
360 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
361 pDecodedItem->uTagBits = Item.uTagBits;
362 pDecodedItem->uTag = Item.uTag;
363 return QCBOR_SUCCESS;
364}
365
366
367/*
368 Mostly just assign the right data type for the bignum.
369 */
370inline static int DecodeBigNum(QCBORItem Item, QCBORItem *pDecodedItem, uint64_t uTagFlags)
371{
372 if(Item.uDataType != QCBOR_TYPE_BYTE_STRING) {
373 return QCBOR_ERR_BAD_OPT_TAG;
374 }
375 pDecodedItem->val.bigNum = Item.val.string;
376 pDecodedItem->uDataType = uTagFlags & QCBOR_TAGFLAG_POS_BIGNUM ? QCBOR_TYPE_POSBIGNUM : QCBOR_TYPE_NEGBIGNUM;
377 pDecodedItem->uTagBits = Item.uTagBits;
378 pDecodedItem->uTag = Item.uTag;
379 return QCBOR_SUCCESS;
380}
381
382
383/*
384 The epoch formatted date. Turns lots of different forms of encoding date into uniform one
385 */
386static int DecodeDateEpoch(QCBORItem Item, QCBORItem *pDecodedItem)
387{
388 int nReturn = QCBOR_SUCCESS;
389
390 pDecodedItem->uTagBits = Item.uTagBits;
391 pDecodedItem->uTag = Item.uTag;
392 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
393 pDecodedItem->val.epochDate.fSecondsFraction = 0;
394
395 switch (Item.uDataType) {
396
397 case QCBOR_TYPE_INT64:
398 pDecodedItem->val.epochDate.nSeconds = Item.val.int64;
399 break;
400
401 case QCBOR_TYPE_UINT64:
402 if(Item.val.uint64 > INT64_MAX) {
403 nReturn = QCBOR_ERR_DATE_OVERFLOW;
404 goto Done;
405 }
406 pDecodedItem->val.epochDate.nSeconds = Item.val.uint64;
407 break;
408
409 default:
410 nReturn = QCBOR_ERR_BAD_OPT_TAG;
411 }
412
413Done:
414 return nReturn;
415}
416
417
418/*
419 Decode the optional tagging that preceeds the real data value. There could be lots of them.
420 */
421static int GetAnItem(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, int bCalledFromDecodeOptional);
422
423/*
424 Returns an error if there was something wrong with the optional item or it couldn't
425 be handled.
426 */
427static int DecodeOptional(UsefulInputBuf *pUInBuf, uint64_t uInputTag, QCBORItem *pDecodedItem)
428{
429 int nReturn = QCBOR_SUCCESS;
430
431 uint64_t uTagFlags = 0; // accumulate the tags in the form of flags
432 uint64_t uTagToProcess = uInputTag; // First process tag passed in
433
434 QCBORItem Item;
435
436 do {
437 if(uTagToProcess < 63) { // 63 is the number of bits in a uint64 - 1
438 uTagFlags |= 0x01LL << uTagToProcess;
439 } else if(uTagToProcess == CBOR_TAG_CBOR_MAGIC) {
440 uTagFlags |= QCBOR_TAGFLAG_CBOR_MAGIC;
441 }
442 /* This code ignores the all but the first tag of value
443 greater than 63. Ignoring tags that are not understoof
444 is allowed by the standard. Multiple tags are
445 presumably rare. */
446
447 nReturn = GetAnItem(pUInBuf, &Item, 1);
448 if(nReturn) {
449 // Bail out of the whole item fetch on any sort of error here
450 goto Done;
451 }
452
453 if(Item.uDataType != QCBOR_TYPE_OPTTAG) {
454 break;
455 }
456
457 uTagToProcess = Item.uTag;
458 } while (1);
459
460
461 /*
462 CBOR allows multiple tags on a data item. It also defines
463 a number of standard tag values, most of which are
464 less than 64. This code can deal with multiple tag
465 values that are less than 64 and the last tag of multiple
466 if the value is more than 64. Or said another way
467 if there is one tag with a value >64 this code works.
468
469 The assumption is that multiple tag values > 64 are rare.
470
471 At this point in this code. uTagFlags has all the flags
472 < 64 and uTagToProcess has the last tag.
473
474 Does this deal with multiple tags on an item we process?
475 */
476
477 Item.uTagBits = uTagFlags;
478 Item.uTag = uTagToProcess;
479
480 switch(uTagFlags & (QCBOR_TAGFLAG_DATE_STRING | QCBOR_TAGFLAG_DATE_EPOCH | QCBOR_TAGFLAG_POS_BIGNUM |QCBOR_TAGFLAG_NEG_BIGNUM)) {
481 case 0:
482 // No tags we know about. Pass them up
483 *pDecodedItem = Item;
484 break;
485
486 case QCBOR_TAGFLAG_DATE_STRING:
487 nReturn = DecodeDateString(Item, pDecodedItem);
488 break;
489
490 case QCBOR_TAGFLAG_DATE_EPOCH:
491 nReturn = DecodeDateEpoch(Item, pDecodedItem);
492 break;
493
494 case QCBOR_TAGFLAG_POS_BIGNUM:
495 case QCBOR_TAGFLAG_NEG_BIGNUM:
496 nReturn = DecodeBigNum(Item, pDecodedItem, uTagFlags);
497 break;
498
499 default:
500 // Encountering some mixed up CBOR like something that
501 // is tagged as both a string and integer date.
502 nReturn = QCBOR_ERR_BAD_OPT_TAG ;
503 }
504
505Done:
506 return nReturn;
507}
508
509
510
511// Make sure the constants align as this is assumed by the GetAnItem() implementation
512#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
513#error QCBOR_TYPE_ARRAY value not lined up with major type
514#endif
515#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
516#error QCBOR_TYPE_MAP value not lined up with major type
517#endif
518
519/*
520 This gets a single data item and decodes it including preceding optional tagging. This does not
521 deal with arrays and maps and nesting except to decode the data item introducing them. Arrays and
522 maps are handled at the next level up in GetNext().
523
524 Errors detected here include: an array that is too long to decode, hit end of buffer unexpectedly,
525 a few forms of invalid encoded CBOR
526 */
527
528static int GetAnItem(UsefulInputBuf *pUInBuf, QCBORItem *pDecodedItem, int bCalledFromDecodeOptional)
529{
530 int nReturn;
531
532 // Get the major type and the number. Number could be length of more bytes or the value depending on the major type
533 // nAdditionalInfo is an encoding of the length of the uNumber and is needed to decode floats and doubles
534 int uMajorType;
535 uint64_t uNumber;
536 uint8_t uAdditionalInfo;
537
538 nReturn = DecodeTypeAndNumber(pUInBuf, &uMajorType, &uNumber, &uAdditionalInfo);
539
540 // Error out here if we got into trouble on the type and number.
541 // The code after this will not work if the type and number is not good.
542 if(nReturn)
543 goto Done;
544
545 pDecodedItem->uTagBits = 0;
546 pDecodedItem->uTag = 0;
547
548 // At this point the major type and the value are valid. We've got the type and the number that
549 // starts every CBOR data item.
550 switch (uMajorType) {
551 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
552 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
553 nReturn = DecodeInteger(uMajorType, uNumber, pDecodedItem);
554 break;
555
556 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
557 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
558 nReturn = DecodeBytes(uMajorType, uNumber, pUInBuf, pDecodedItem);
559 break;
560
561 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
562 case CBOR_MAJOR_TYPE_MAP: // Major type 5
563 // Record the number of items in the array or map
564 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
565 nReturn = QCBOR_ERR_ARRAY_TOO_LONG;
566 goto Done;
567 }
568 pDecodedItem->val.uCount = uNumber; // type conversion OK because of check above
569 pDecodedItem->uDataType = uMajorType; // C preproc #if above makes sure constants align
570 break;
571
572 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
573 pDecodedItem->uTag = uNumber;
574 pDecodedItem->uDataType = QCBOR_TYPE_OPTTAG;
575 if(!bCalledFromDecodeOptional) {
576 // There can be a more than one optional tag in front of an actual data item
577 // they are all handled by looping in DecodeOptional which calls back here
578 // this test avoids infinite recursion.
579 nReturn = DecodeOptional(pUInBuf, uNumber, pDecodedItem);
580 }
581 break;
582
583 case CBOR_MAJOR_TYPE_SIMPLE: // Major type 7, float, double, true, false, null...
584 nReturn = DecodeSimple(uAdditionalInfo, uNumber, pDecodedItem);
585 break;
586
587 default: // Should never happen because DecodeTypeAndNumber() should never return > 7
588 nReturn = QCBOR_ERR_UNSUPPORTED;
589 break;
590 }
591
592Done:
593 return nReturn;
594}
595
596
597/*
598 Public function, see header qcbor.h file
599 */
600int QCBORDecode_GetNext(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
601{
602 int nReturn;
603
604 if(!UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
605 nReturn = QCBOR_ERR_HIT_END;
606 goto Done;
607 }
608
609 nReturn = GetAnItem(&(me->InBuf), pDecodedItem, 0);
610 if(nReturn)
611 goto Done;
612
613 // If in a map and the right decoding mode, get the label
614 if(DecodeNesting_TypeIsMap(&(me->nesting)) && me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
615 // In a map and caller wants maps decoded, not treated as arrays
616
617 // Get the next item which will be the real data; Item will be the label
618 QCBORItem LabelItem = *pDecodedItem;
619 nReturn = GetAnItem(&(me->InBuf), pDecodedItem, 0);
620 if(nReturn)
621 goto Done;
622
623 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
624 // strings are always good labels
625 pDecodedItem->label.string = LabelItem.val.string;
626 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
627 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
628 // It's not a string and we only want strings, probably for easy translation to JSON
629 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
630 goto Done;
631 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
632 pDecodedItem->label.int64 = LabelItem.val.int64;
633 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
634 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
635 pDecodedItem->label.uint64 = LabelItem.val.uint64;
636 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
637 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
638 pDecodedItem->label.string = LabelItem.val.string;
639 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
640 } else {
641 // label is not an int or a string. It is an arrray
642 // or a float or such and this implementation doesn't handle that.
643 nReturn = QCBOR_ERR_MAP_LABEL_TYPE ;
644 goto Done;
645 }
646 }
647
648 // Record the nesting level for this data item
649 pDecodedItem->uNestingLevel = DecodeNesting_GetLevel(&(me->nesting));
650
651 // If the new item is a non-empty array or map, the nesting level descends
652 if(IsMapOrArray(pDecodedItem->uDataType) && pDecodedItem->val.uCount) {
653 nReturn = DecodeNesting_Descend(&(me->nesting), pDecodedItem->uDataType, pDecodedItem->val.uCount);
654 } else {
655 // Track number of items in maps and arrays and ascend nesting if all are consumed
656 // Note that an empty array or map is like a integer or string in effect here
657 DecodeNesting_Decrement(&(me->nesting), pDecodedItem->uDataType);
658 }
659
660Done:
661 return nReturn;
662}
663
664
665/*
666 Public function, see header qcbor.h file
667 */
668int QCBORDecode_Finish(QCBORDecodeContext *me)
669{
670 return UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) ? QCBOR_ERR_EXTRA_BYTES : QCBOR_SUCCESS;
671}
672
673
674
675/*
676
677Decoder errors handled in this file
678
679 - Hit end of input before it was expected while decoding type and number QCBOR_ERR_HIT_END
680
681 - indefinite length, currently not supported QCBOR_ERR_UNSUPPORTED
682
683 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
684
685 - Hit end of input while decoding a text or byte string QCBOR_ERR_HIT_END
686
687 - Encountered conflicting tags -- e.g., an item is tagged both a date string and an epoch date QCBOR_ERR_UNSUPPORTED
688
689 - Encountered a break, not supported because indefinite lengths are not supported QCBOR_ERR_UNSUPPORTED
690
691 - Encontered an array or mapp that has too many items QCBOR_ERR_ARRAY_TOO_LONG
692
693 - Encountered array/map nesting that is too deep QCBOR_ERR_ARRAY_NESTING_TOO_DEEP
694
695 - An epoch date > INT64_MAX or < INT64_MIN was encountered QCBOR_ERR_DATE_OVERFLOW
696
697 - The type of a map label is not a string or int QCBOR_ERR_MAP_LABEL_TYPE
698
699 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
700
701 */
702