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