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