blob: a600831085474e38d2ce638548d3a87522eef428 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladeee851742020-01-08 08:37:05 -08003 Copyright (c) 2018-2020, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070035#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundbladec7114722020-08-13 05:11:40 -070036#include "ieee754.h" // Does not use math.h
37
38#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade323f8a92020-09-06 19:43:09 -070039#include <math.h> // For isnan(), llround(), llroudf(), round(), roundf(),
40 // pow(), exp2()
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -070041#include <fenv.h> // feclearexcept(), fetestexcept()
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080042#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070043
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070044
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053045/*
46 This casts away the const-ness of a pointer, usually so it can be
47 freed or realloced.
48 */
49#define UNCONST_POINTER(ptr) ((void *)(ptr))
50
Laurence Lundbladea9489f82020-09-12 13:50:56 -070051#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070052
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070053
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070054static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070055QCBORItem_IsMapOrArray(const QCBORItem *pMe)
56{
57 const uint8_t uDataType = pMe->uDataType;
58 return uDataType == QCBOR_TYPE_MAP ||
59 uDataType == QCBOR_TYPE_ARRAY ||
60 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
61}
62
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070063static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070064QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
65{
66 if(!QCBORItem_IsMapOrArray(pMe)){
67 return false;
68 }
69
70 if(pMe->val.uCount != 0) {
71 return false;
72 }
73 return true;
74}
75
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070076static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070077QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
78{
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080079#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -070080 if(!QCBORItem_IsMapOrArray(pMe)){
81 return false;
82 }
83
84 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
85 return false;
86 }
87 return true;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080088#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
89 (void)pMe;
90 return false;
91#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade02625d42020-06-25 14:41:41 -070092}
93
94
Laurence Lundbladeee851742020-01-08 08:37:05 -080095/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070096 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080097 ===========================================================================*/
98
Laurence Lundblade9c905e82020-04-25 11:31:38 -070099/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700100 See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
Laurence Lundblade93d89472020-10-03 22:30:50 -0700101 the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700102 */
103
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700104
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700105static inline uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700106DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700107{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700108 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700109 /*
110 Limit in DecodeNesting_Descend against more than
111 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
112 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700113 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700114}
115
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700116
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700117static inline uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700118DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700119{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700120 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700121 /*
122 Limit in DecodeNesting_Descend against more than
123 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
124 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700125 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700126}
127
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700128
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700129static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700130DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700131{
132 return pNesting->pCurrentBounded->u.ma.uStartOffset;
133}
134
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700135
Laurence Lundblade085d7952020-07-24 10:26:30 -0700136static inline bool
137DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
138{
139 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
140 return true;
141 } else {
142 return false;
143 }
144}
145
146
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700147static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700148DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700149{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700150 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700151 return true;
152 } else {
153 return false;
154 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700155}
156
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700157
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700158static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700159DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700160{
161 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700162 // Not a map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700163 return false;
164 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800165
166#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700167 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700168 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700169 return false;
170 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800171#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
172
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700173 // All checks passed; is a definte length map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700174 return true;
175}
176
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700177static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700178DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700179{
180 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700181 // is a byte string
Laurence Lundblade642282a2020-06-23 12:00:33 -0700182 return true;
183 }
184 return false;
185}
186
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700187
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700188static inline bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700189{
190 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
191 return true;
192 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700193 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700194 return true;
195 }
196 return false;
197}
198
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700199
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700200static inline void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700201{
202 // Should be only called on maps and arrays
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700203 /*
204 DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
205 larger than DecodeNesting_EnterBoundedMode which keeps it less than
206 uin32_t so the cast is safe.
207 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700208 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700209
210 if(bIsEmpty) {
211 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
212 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700213}
214
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700215
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700216static inline void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700217{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700218 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700219}
220
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700221
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700222static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700223DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700224{
225 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700226 // No bounded map or array set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700227 return false;
228 }
229 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700230 // Not a map or array; end of those is by byte count
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700231 return false;
232 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700233 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
234 // In a traveral at a level deeper than the bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700235 return false;
236 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700237 // Works for both definite and indefinite length maps/arrays
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800238 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
239 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700240 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700241 return false;
242 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700243 // All checks passed, got to the end of an array or map
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700244 return true;
245}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700246
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700247
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700248static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700249DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700250{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700251 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700252 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
253 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700254 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700255 return false;
256 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700257}
258
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700259
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700260static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700261DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700262{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700263 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
264 return true;
265 } else {
266 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700267 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700268}
269
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700270
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700271static inline bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700272DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700273{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700274 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700275 return false;
276 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700277
278 if(pNesting->pCurrentBounded->uLevelType != uType) {
279 return false;
280 }
281
282 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700283}
284
Laurence Lundblade02625d42020-06-25 14:41:41 -0700285
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700286static inline void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700287DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700288{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700289 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700290 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700291}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700292
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700293
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700294static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700295DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
296{
297 // Only call on a defnite length array / map
298 pNesting->pCurrent->u.ma.uCountCursor++;
299}
300
301
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700302static inline void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700303DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
304{
305 pNesting->pCurrent--;
306}
307
Laurence Lundblade02625d42020-06-25 14:41:41 -0700308
309static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700310DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700311{
312 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700313 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700314 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700315 }
316
317 // The actual descend
318 pNesting->pCurrent++;
319
320 pNesting->pCurrent->uLevelType = uType;
321
322 return QCBOR_SUCCESS;
323}
324
325
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700326static inline QCBORError
Laurence Lundblade085d7952020-07-24 10:26:30 -0700327DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700328{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700329 /*
330 Should only be called on map/array.
331
332 Have descended into this before this is called. The job here is
333 just to mark it in bounded mode.
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700334
335 Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
336 uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800337
338 Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700339 */
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800340 if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700341 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700342 }
343
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700344 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700345
346 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700347
348 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700349}
350
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700351
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700352static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700353DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700354 uint8_t uQCBORType,
355 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700356{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700357 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700358
359 if(uCount == 0) {
360 // Nothing to do for empty definite lenth arrays. They are just are
361 // effectively the same as an item that is not a map or array
362 goto Done;
363 // Empty indefinite length maps and arrays are handled elsewhere
364 }
365
366 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700367 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
368 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700369 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700370 goto Done;
371 }
372
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700373 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700374 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700375 goto Done;
376 }
377
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700378 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700379 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
380 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700381
382 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700383
384Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700385 return uError;;
386}
387
388
389static inline void
390DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
391{
392 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
393}
394
395
396static inline void
397DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
398{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700399 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700400 pNesting->pCurrentBounded--;
401 if(DecodeNesting_IsCurrentBounded(pNesting)) {
402 break;
403 }
404 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700405}
406
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700407static inline void
408DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
409{
410 pNesting->pCurrent = pNesting->pCurrentBounded;
411}
412
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700413
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700414static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700415DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700416 uint32_t uEndOffset,
417 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700418{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700419 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700420
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700421 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700422 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700423 goto Done;
424 }
425
Laurence Lundblade02625d42020-06-25 14:41:41 -0700426 // Fill in the new byte string level
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700427 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
428 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700429
Laurence Lundblade02625d42020-06-25 14:41:41 -0700430 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700431 pNesting->pCurrentBounded = pNesting->pCurrent;
432
433Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700434 return uError;;
435}
436
Laurence Lundbladed0304932020-06-27 10:59:38 -0700437
438static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700439DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700440{
441 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700442}
443
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700444
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700445static inline void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800446DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
447{
448 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
449}
450
451
452static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700453DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700454{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700455 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700456 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
457 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700458}
459
460
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700461static inline void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700462DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700463{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700464 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700465 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800466 DecodeNesting_ResetMapOrArrayCount(pNesting);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700467}
468
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700469
Laurence Lundblade02625d42020-06-25 14:41:41 -0700470static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700471DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700472{
473 *pNesting = *pSave;
474}
475
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700476
Laurence Lundblade02625d42020-06-25 14:41:41 -0700477static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700478DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700479{
480 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
481}
482
483
Laurence Lundblade02625d42020-06-25 14:41:41 -0700484static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700485DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700486{
487 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
488}
489
490
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800491#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800492/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800493 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
494
495 The following four functions are pretty wrappers for invocation of
496 the string allocator supplied by the caller.
497
Laurence Lundbladeee851742020-01-08 08:37:05 -0800498 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800499
Laurence Lundbladeee851742020-01-08 08:37:05 -0800500static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800501StringAllocator_Free(const QCBORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800502{
503 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
504}
505
Laurence Lundbladeee851742020-01-08 08:37:05 -0800506// StringAllocator_Reallocate called with pMem NULL is
507// equal to StringAllocator_Allocate()
508static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800509StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800510 void *pMem,
511 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800512{
513 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
514}
515
Laurence Lundbladeee851742020-01-08 08:37:05 -0800516static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800517StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800518{
519 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
520}
521
Laurence Lundbladeee851742020-01-08 08:37:05 -0800522static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800523StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800524{
525 if(pMe->pfAllocator) {
526 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
527 }
528}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800529#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800530
531
Laurence Lundbladeee851742020-01-08 08:37:05 -0800532/*===========================================================================
533 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700534
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800535 See qcbor/qcbor_decode.h for definition of the object
536 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800537 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700538/*
539 Public function, see header file
540 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800541void QCBORDecode_Init(QCBORDecodeContext *me,
542 UsefulBufC EncodedCBOR,
543 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700544{
545 memset(me, 0, sizeof(QCBORDecodeContext));
546 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800547 // Don't bother with error check on decode mode. If a bad value is
548 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700549 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700550 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700551 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700552 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700553 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700554}
555
556
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800557#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
558
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700559/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700560 Public function, see header file
561 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800562void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
563 QCBORStringAllocate pfAllocateFunction,
564 void *pAllocateContext,
565 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700566{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800567 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
568 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
569 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700570}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800571#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700572
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800573
574/*
575 Public function, see header file
576 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700577void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800578 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700579{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700580 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700581 (void)pMe;
582 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700583}
584
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700585
586/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800587 This decodes the fundamental part of a CBOR data item, the type and
588 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800589
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700590 This is the counterpart to QCBOREncode_EncodeHead().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800591
Laurence Lundbladeee851742020-01-08 08:37:05 -0800592 This does the network->host byte order conversion. The conversion
593 here also results in the conversion for floats in addition to that
594 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800595
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700596 This returns:
597 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800598
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800599 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800600 tags and floats and length for strings and arrays
601
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800602 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800603 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800604
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800605 The int type is preferred to uint8_t for some variables as this
606 avoids integer promotions, can reduce code size and makes
607 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700608
609 @retval QCBOR_ERR_UNSUPPORTED
610
611 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700612 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700613static inline QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800614 int *pnMajorType,
615 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800616 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700617{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700618 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800619
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700620 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800621 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800622
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700623 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800624 const int nTmpMajorType = nInitialByte >> 5;
625 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800626
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800627 // Where the number or argument accumulates
628 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800629
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800630 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700631 // Need to get 1,2,4 or 8 additional argument bytes. Map
632 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800633 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800634
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800635 // Loop getting all the bytes in the argument
636 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800637 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800638 // This shift and add gives the endian conversion
639 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
640 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800641 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800642 // The reserved and thus-far unused additional info values
643 nReturn = QCBOR_ERR_UNSUPPORTED;
644 goto Done;
645 } else {
646 // Less than 24, additional info is argument or 31, an indefinite length
647 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800648 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700649 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800650
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700651 if(UsefulInputBuf_GetError(pUInBuf)) {
652 nReturn = QCBOR_ERR_HIT_END;
653 goto Done;
654 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800655
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700656 // All successful if we got here.
657 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800658 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800659 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800660 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800661
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700662Done:
663 return nReturn;
664}
665
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800666
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700667/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800668 CBOR doesn't explicitly specify two's compliment for integers but all
669 CPUs use it these days and the test vectors in the RFC are so. All
670 integers in the CBOR structure are positive and the major type
671 indicates positive or negative. CBOR can express positive integers
672 up to 2^x - 1 where x is the number of bits and negative integers
673 down to 2^x. Note that negative numbers can be one more away from
674 zero than positive. Stdint, as far as I can tell, uses two's
675 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800676
Laurence Lundblade9b334962020-08-27 10:55:53 -0700677 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800678 used carefully here, and in particular why it isn't used in the interface.
679 Also see
680 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
681
682 Int is used for values that need less than 16-bits and would be subject
683 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700684
685 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700686 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700687static inline QCBORError
Laurence Lundbladeee851742020-01-08 08:37:05 -0800688DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700689{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700690 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800691
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700692 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
693 if (uNumber <= INT64_MAX) {
694 pDecodedItem->val.int64 = (int64_t)uNumber;
695 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800696
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700697 } else {
698 pDecodedItem->val.uint64 = uNumber;
699 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800700
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700701 }
702 } else {
703 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800704 // CBOR's representation of negative numbers lines up with the
705 // two-compliment representation. A negative integer has one
706 // more in range than a positive integer. INT64_MIN is
707 // equal to (-INT64_MAX) - 1.
708 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700709 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800710
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700711 } else {
712 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000713 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700714 nReturn = QCBOR_ERR_INT_OVERFLOW;
715 }
716 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800717
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700718 return nReturn;
719}
720
721// Make sure #define value line up as DecodeSimple counts on this.
722#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
723#error QCBOR_TYPE_FALSE macro value wrong
724#endif
725
726#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
727#error QCBOR_TYPE_TRUE macro value wrong
728#endif
729
730#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
731#error QCBOR_TYPE_NULL macro value wrong
732#endif
733
734#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
735#error QCBOR_TYPE_UNDEF macro value wrong
736#endif
737
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700738#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
739#error QCBOR_TYPE_BREAK macro value wrong
740#endif
741
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700742#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
743#error QCBOR_TYPE_DOUBLE macro value wrong
744#endif
745
746#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
747#error QCBOR_TYPE_FLOAT macro value wrong
748#endif
749
750/*
751 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700752
753 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
754
755 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700756 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700757static inline QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800758DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700759{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700760 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800761
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700762 // uAdditionalInfo is 5 bits from the initial byte. Compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800763 // above make sure uAdditionalInfo values line up with uDataType values.
Laurence Lundblade93d89472020-10-03 22:30:50 -0700764 // DecodeTypeAndNumber() never returns an AdditionalInfo > 0x1f so cast
765 // is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800766 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800767
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800768 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800769 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
770 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800771
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700772 case HALF_PREC_FLOAT: // 25
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700773#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700774 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700775 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700776 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700777 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
778 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800779#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700780 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800781#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700782 break;
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700783 case SINGLE_PREC_FLOAT: // 26
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700784 // Single precision is normally returned as a double
785 // since double is widely supported, there is no loss of
786 // precision, it makes it easy for the caller in
787 // most cases and it can be converted back to single
788 // with no loss of precision
789 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700790 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700791 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700792 {
793 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
794#ifndef QCBOR_DISABLE_FLOAT_HW_USE
795 // In the normal case, use HW to convert float to double.
796 pDecodedItem->val.dfnum = (double)f;
797 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800798#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700799 // Use of float HW is disabled, return as a float.
800 pDecodedItem->val.fnum = f;
801 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
802
803 // IEEE754_FloatToDouble() could be used here to return
804 // as a double, but it adds object code and most likely
805 // anyone disabling FLOAT HW use doesn't care about
806 // floats and wants to save object code.
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800807#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700808 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700809 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700810
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700811 case DOUBLE_PREC_FLOAT: // 27
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700812 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700813 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700814 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800815
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700816 case CBOR_SIMPLEV_FALSE: // 20
817 case CBOR_SIMPLEV_TRUE: // 21
818 case CBOR_SIMPLEV_NULL: // 22
819 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700820 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700821 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800822
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700823 case CBOR_SIMPLEV_ONEBYTE: // 24
824 if(uNumber <= CBOR_SIMPLE_BREAK) {
825 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700826 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700827 goto Done;
828 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800829 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700830 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800831
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700832 default: // 0-19
833 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800834 /*
835 DecodeTypeAndNumber will make uNumber equal to
836 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
837 safe because the 2, 4 and 8 byte lengths of uNumber are in
838 the double/float cases above
839 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700840 pDecodedItem->val.uSimple = (uint8_t)uNumber;
841 break;
842 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800843
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700844Done:
845 return nReturn;
846}
847
848
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700849/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530850 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700851
852 @retval QCBOR_ERR_HIT_END
853
854 @retval QCBOR_ERR_STRING_ALLOCATE
855
856 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700857 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800858static inline QCBORError DecodeBytes(const QCBORInternalAllocator *pAllocator,
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800859 uint64_t uStrLen,
860 UsefulInputBuf *pUInBuf,
861 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700862{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700863 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800864
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800865 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
866 // This check makes the casts to size_t below safe.
867
868 // 4 bytes less than the largest sizeof() so this can be tested by
869 // putting a SIZE_MAX length in the CBOR test input (no one will
870 // care the limit on strings is 4 bytes shorter).
871 if(uStrLen > SIZE_MAX-4) {
872 nReturn = QCBOR_ERR_STRING_TOO_LONG;
873 goto Done;
874 }
875
876 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530877 if(UsefulBuf_IsNULLC(Bytes)) {
878 // Failed to get the bytes for this string item
879 nReturn = QCBOR_ERR_HIT_END;
880 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700881 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530882
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800883#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800884 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530885 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800886 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530887 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700888 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530889 goto Done;
890 }
891 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800892 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800893 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530894 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800895#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
896 (void)pAllocator;
897#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
898
899 // Normal case with no string allocator
900 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800901
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530902Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700903 return nReturn;
904}
905
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700906
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800907/* Map the CBOR major types for strings to the QCBOR types for strngs */
908static inline uint8_t MapStringMajorTypes(int nCBORMajorType)
909{
910 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
911 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
912 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800913
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800914 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
915 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
916 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700917
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800918 return (uint8_t)(nCBORMajorType + 4);
919}
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700920
921
Laurence Lundbladeee851742020-01-08 08:37:05 -0800922// Make sure the constants align as this is assumed by
923// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700924#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
925#error QCBOR_TYPE_ARRAY value not lined up with major type
926#endif
927#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
928#error QCBOR_TYPE_MAP value not lined up with major type
929#endif
930
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700931/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800932 This gets a single data item and decodes it including preceding
933 optional tagging. This does not deal with arrays and maps and nesting
934 except to decode the data item introducing them. Arrays and maps are
935 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800936
Laurence Lundbladeee851742020-01-08 08:37:05 -0800937 Errors detected here include: an array that is too long to decode,
938 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700939
940 @retval QCBOR_ERR_UNSUPPORTED
941
942 @retval QCBOR_ERR_HIT_END
943
944 @retval QCBOR_ERR_INT_OVERFLOW
945
946 @retval QCBOR_ERR_STRING_ALLOCATE
947
948 @retval QCBOR_ERR_STRING_TOO_LONG
949
950 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
951
952 @retval QCBOR_ERR_BAD_TYPE_7
953
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700954 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800955static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
956 QCBORItem *pDecodedItem,
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800957 const QCBORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700958{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700959 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800960
Laurence Lundbladeee851742020-01-08 08:37:05 -0800961 /*
962 Get the major type and the number. Number could be length of more
963 bytes or the value depending on the major type nAdditionalInfo is
964 an encoding of the length of the uNumber and is needed to decode
965 floats and doubles
966 */
Rob Gilton47cc9562020-08-10 12:03:38 +0100967 int nMajorType = 0;
968 uint64_t uNumber = 0;
969 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800970
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700971 memset(pDecodedItem, 0, sizeof(QCBORItem));
972
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800973 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800974
Laurence Lundbladeee851742020-01-08 08:37:05 -0800975 // Error out here if we got into trouble on the type and number. The
976 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700977 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700978 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700979 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800980
Laurence Lundbladeee851742020-01-08 08:37:05 -0800981 // At this point the major type and the value are valid. We've got
982 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800983 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700984 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
985 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800986 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700987 nReturn = QCBOR_ERR_BAD_INT;
988 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800989 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700990 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700991 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800992
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700993 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
994 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800995 pDecodedItem->uDataType = MapStringMajorTypes(nMajorType);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800996 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800997 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700998 } else {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800999 nReturn = DecodeBytes(pAllocator, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001000 }
1001 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001002
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001003 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
1004 case CBOR_MAJOR_TYPE_MAP: // Major type 5
1005 // Record the number of items in the array or map
1006 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001007 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001008 goto Done;
1009 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001010 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001011#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -07001012 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001013#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1014 nReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1015 break;
1016#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001017 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001018 // type conversion OK because of check above
1019 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001020 }
Laurence Lundbladeee851742020-01-08 08:37:05 -08001021 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001022 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001023 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001024 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001025
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001026 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001027 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001028 nReturn = QCBOR_ERR_BAD_INT;
1029 } else {
1030 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001031 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001032 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001033 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001034
Laurence Lundbladeee851742020-01-08 08:37:05 -08001035 case CBOR_MAJOR_TYPE_SIMPLE:
1036 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001037 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001038 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001039
Laurence Lundbladeee851742020-01-08 08:37:05 -08001040 default:
1041 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001042 nReturn = QCBOR_ERR_UNSUPPORTED;
1043 break;
1044 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001045
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001046Done:
1047 return nReturn;
1048}
1049
1050
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001051/**
1052 * @brief Process indefinite length strings
1053 *
1054 * @param[in] pMe Decoder context
1055 * @param[in,out] pDecodedItem The decoded item that work is done on.
1056 *
1057 * @retval QCBOR_ERR_UNSUPPORTED
1058 * @retval QCBOR_ERR_HIT_END
1059 * @retval QCBOR_ERR_INT_OVERFLOW
1060 * @retval QCBOR_ERR_STRING_ALLOCATE
1061 * @retval QCBOR_ERR_STRING_TOO_LONG
1062 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1063 * @retval QCBOR_ERR_BAD_TYPE_7
1064 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1065 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1066 *
1067 * If @c pDecodedItem is not an indefinite length string, this does nothing.
1068 *
1069 * If it is, this loops getting the subsequent chunks that make up the
1070 * string. The string allocator is used to make a contiguous buffer for
1071 * the chunks. When this completes @c pDecodedItem contains the
1072 * put-together string.
1073 *
1074 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001075 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001076static inline QCBORError
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001077GetNext_FullItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001078{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001079 /* Aproximate stack usage
1080 * 64-bit 32-bit
1081 * local vars 32 16
1082 * 2 UsefulBufs 32 16
1083 * QCBORItem 56 52
1084 * TOTAL 120 74
1085 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001086
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001087 /* The string allocator is used here for two purposes: 1)
1088 * coalescing the chunks of an indefinite length string, 2)
1089 * allocating storage for every string returned.
1090 *
1091 * The first use is below in this function. Indefinite length
1092 * strings cannot be processed at all without a string allocator.
1093 *
1094 * The second used is in DecodeBytes() which is called by
1095 * GetNext_Item() below. This second use unneccessary for most use
1096 * and only happens when requested in the call to
1097 * QCBORDecode_SetMemPool(). If the second use not requested then
1098 * NULL is passed for the string allocator to GetNext_Item().
1099 *
1100 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1101 * allocator altogether and thus both of these uses. It reduced the
1102 * decoder object code by about 400 bytes.
1103 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001104 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001105
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001106#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001107 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001108
1109 if(pMe->StringAllocator.pfAllocator) {
1110 pAllocator = &(pMe->StringAllocator);
1111 if(pMe->bStringAllocateAll) {
1112 pAllocatorForGetNext = pAllocator;
1113 }
1114 }
1115#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1116
1117 QCBORError uReturn;
1118 uReturn = GetNext_Item(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
1119 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001120 goto Done;
1121 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001122
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001123 /* Only do indefinite length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001124 const uint8_t uStringType = pDecodedItem->uDataType;
1125 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001126 goto Done;
1127 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001128
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001129 /* Is this a string with an indefinite length? */
1130 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1131 goto Done;
1132 }
1133
1134#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1135 /* Can't do indefinite length strings without a string allocator */
1136 if(pAllocator == NULL) {
1137 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1138 goto Done;
1139 }
1140
1141 /* Loop getting chunks of the indefinite length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001142 UsefulBufC FullString = NULLUsefulBufC;
1143
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001144 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001145 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001146 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001147 /* Pass a NULL string allocator to GetNext_Item() because the
1148 * individual string chunks in an indefinite length should not
1149 * be allocated. They are always copied in the the contiguous
1150 * buffer allocated here.
1151 */
1152 uReturn = GetNext_Item(&(pMe->InBuf), &StringChunkItem, NULL);
1153 if(uReturn) {
1154 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001155 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001156
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001157 /* Is item is the marker for end of the indefinite length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001158 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001159 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001160 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301161 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001162 break;
1163 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001164
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001165 /* All chunks must be of the same type, the type of the item
1166 * that introduces the indefinite length string. This also
1167 * catches errors where the chunk is not a string at all and an
1168 * indefinite length string inside an indefinite length string.
1169 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001170 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001171 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1172 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001173 break;
1174 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001175
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001176 /* The first time throurgh FullString.ptr is NULL and this is
1177 * equivalent to StringAllocator_Allocate(). Subsequently it is
1178 * not NULL and a reallocation happens.
1179 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001180 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1181 UNCONST_POINTER(FullString.ptr),
1182 FullString.len + StringChunkItem.val.string.len);
1183
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001184 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001185 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001186 break;
1187 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001188
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001189 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001190 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001191 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001192
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001193 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1194 /* Getting the item failed, clean up the allocated memory */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001195 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001196 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001197#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1198 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1199#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001200
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001201Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001202 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001203}
1204
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001205
Laurence Lundblade9b334962020-08-27 10:55:53 -07001206static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001207 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001208 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001209 } else if(uTagVal == CBOR_TAG_INVALID16) {
1210 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001211 } else {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001212 // This won't be negative because of code below in GetNext_TaggedItem()
1213 const unsigned uIndex = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
1214 return me->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001215 }
1216}
1217
Laurence Lundblade9b334962020-08-27 10:55:53 -07001218
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001219/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001220 Gets all optional tag data items preceding a data item that is not an
1221 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001222
1223 @retval QCBOR_ERR_UNSUPPORTED
1224
1225 @retval QCBOR_ERR_HIT_END
1226
1227 @retval QCBOR_ERR_INT_OVERFLOW
1228
1229 @retval QCBOR_ERR_STRING_ALLOCATE
1230
1231 @retval QCBOR_ERR_STRING_TOO_LONG
1232
1233 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1234
1235 @retval QCBOR_ERR_BAD_TYPE_7
1236
1237 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1238
1239 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1240
1241 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001242 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001243static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001244GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001245{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001246 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1247 CBOR_TAG_INVALID16,
1248 CBOR_TAG_INVALID16,
1249 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001250
Laurence Lundblade9b334962020-08-27 10:55:53 -07001251 QCBORError uReturn = QCBOR_SUCCESS;
1252
Laurence Lundblade59289e52019-12-30 13:44:37 -08001253 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001254 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001255 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1256 if(uErr != QCBOR_SUCCESS) {
1257 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001258 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001259 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001260
Laurence Lundblade9b334962020-08-27 10:55:53 -07001261 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001262 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001263 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001264 break;
1265 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001266
Laurence Lundblade9b334962020-08-27 10:55:53 -07001267 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1268 // No room in the tag list
1269 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1270 // Continue on to get all tags on this item even though
1271 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001272 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001273 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001274 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001275 // Slide tags over one in the array to make room at index 0
1276 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1277 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001278 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001279
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001280 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001281 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001282 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001283 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001284 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001285 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001286 break;
1287 }
1288 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1289 break;
1290 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001291 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001292 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1293 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001294 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1295 // Continue on to get all tags on this item even though
1296 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001297 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001298 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001299 }
1300
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001301 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001302 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001303 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001304
1305 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001306 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001307 }
1308 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001309
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001310Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001311 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001312}
1313
1314
1315/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001316 This layer takes care of map entries. It combines the label and data
1317 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001318
1319 @retval QCBOR_ERR_UNSUPPORTED
1320
1321 @retval QCBOR_ERR_HIT_END
1322
1323 @retval QCBOR_ERR_INT_OVERFLOW
1324
1325 @retval QCBOR_ERR_STRING_ALLOCATE
1326
1327 @retval QCBOR_ERR_STRING_TOO_LONG
1328
1329 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1330
1331 @retval QCBOR_ERR_BAD_TYPE_7
1332
1333 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1334
1335 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1336
1337 @retval QCBOR_ERR_TOO_MANY_TAGS
1338
1339 @retval QCBOR_ERR_MAP_LABEL_TYPE
1340
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001341 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001342 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001343static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001344GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001345{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001346 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001347 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001348 if(nReturn)
1349 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001350
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001351 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001352 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001353 goto Done;
1354 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001355
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001356 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1357 // In a map and caller wants maps decoded, not treated as arrays
1358
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001359 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001360 // If in a map and the right decoding mode, get the label
1361
Laurence Lundbladeee851742020-01-08 08:37:05 -08001362 // Save label in pDecodedItem and get the next which will
1363 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001364 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001365 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001366 if(QCBORDecode_IsUnrecoverableError(nReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001367 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001368 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001369
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301370 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001371
1372 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1373 // strings are always good labels
1374 pDecodedItem->label.string = LabelItem.val.string;
1375 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1376 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001377 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001378 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1379 goto Done;
1380 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1381 pDecodedItem->label.int64 = LabelItem.val.int64;
1382 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1383 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1384 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1385 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1386 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1387 pDecodedItem->label.string = LabelItem.val.string;
1388 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1389 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1390 } else {
1391 // label is not an int or a string. It is an arrray
1392 // or a float or such and this implementation doesn't handle that.
1393 // Also, tags on labels are ignored.
1394 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1395 goto Done;
1396 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001397 }
1398 } else {
1399 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001400 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001401 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001402 goto Done;
1403 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001404 // Decoding a map as an array
1405 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001406 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1407 // Cast is needed because of integer promotion
1408 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001409 }
1410 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001411
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001412Done:
1413 return nReturn;
1414}
1415
1416
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001417#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -07001418/*
1419 See if next item is a CBOR break. If it is, it is consumed,
1420 if not it is not consumed.
1421*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001422static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001423NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1424{
1425 *pbNextIsBreak = false;
1426 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001427 QCBORItem Peek;
1428 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1429 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1430 if(uReturn != QCBOR_SUCCESS) {
1431 return uReturn;
1432 }
1433 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001434 // It is not a break, rewind so it can be processed normally.
1435 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001436 } else {
1437 *pbNextIsBreak = true;
1438 }
1439 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001440
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001441 return QCBOR_SUCCESS;
1442}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001443#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001444
1445
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001446/*
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001447 * An item was just consumed, now figure out if it was the
1448 * end of an array/map map that can be closed out. That
1449 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001450*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001451static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001452{
1453 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001454
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001455 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001456 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1457
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001458 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1459 /* Nesting level is bstr-wrapped CBOR */
1460
1461 /* Ascent for bstr-wrapped CBOR is always by explicit call
1462 * so no further ascending can happen.
1463 */
1464 break;
1465
1466 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1467 /* Level is a definite-length array/map */
1468
1469 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001470 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1471 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001472 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001473 break;
1474 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001475 /* All items in a definite length array were consumed so it
1476 * is time to ascend one level. This happens below.
1477 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001478
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001479#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001480 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001481 /* Level is an indefinite-length array/map. */
1482
1483 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001484 bool bIsBreak = false;
1485 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1486 if(uReturn != QCBOR_SUCCESS) {
1487 goto Done;
1488 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001489
1490 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001491 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001492 break;
1493 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001494
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001495 /* It was a break in an indefinite length map / array so
1496 * it is time to ascend one level.
1497 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001498
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001499#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001500 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001501
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001502
1503 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001504
Laurence Lundblade93d89472020-10-03 22:30:50 -07001505 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001506 * QCBORDecode_ExitBoundedMode().
1507 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001508 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001509 /* Set the count to zero for definite length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001510 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001511 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001512 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001513 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001514
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001515 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001516 break;
1517 }
1518
1519 /* Finally, actually ascend one level. */
1520 DecodeNesting_Ascend(&(pMe->nesting));
1521 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001522
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001523 uReturn = QCBOR_SUCCESS;
1524
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001525#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001526Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001527#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1528
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001529 return uReturn;
1530}
1531
1532
1533/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001534 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001535 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1536 indefinte length maps and arrays by looking at the item count or
1537 finding CBOR breaks. It detects the ends of the top-level sequence
1538 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001539
1540 @retval QCBOR_ERR_UNSUPPORTED X
1541
1542 @retval QCBOR_ERR_HIT_END
1543
1544 @retval QCBOR_ERR_INT_OVERFLOW X
1545
1546 @retval QCBOR_ERR_STRING_ALLOCATE
1547
1548 @retval QCBOR_ERR_STRING_TOO_LONG
1549
1550 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1551
1552 @retval QCBOR_ERR_BAD_TYPE_7 X
1553
1554 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1555
1556 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1557
1558 @retval QCBOR_ERR_TOO_MANY_TAGS
1559
1560 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1561
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001562 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001563
1564 @retval QCBOR_ERR_NO_MORE_ITEMS
1565
1566 @retval QCBOR_ERR_BAD_BREAK
1567
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001568 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001569static QCBORError
1570QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001571{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001572 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001573 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001574
Laurence Lundblade642282a2020-06-23 12:00:33 -07001575 /*
1576 If out of bytes to consume, it is either the end of the top-level
1577 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001578
Laurence Lundblade642282a2020-06-23 12:00:33 -07001579 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1580 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1581 CBOR is exited, the length is set back to the top-level's length
1582 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001583 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001584 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001585 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001586 goto Done;
1587 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001588
Laurence Lundblade642282a2020-06-23 12:00:33 -07001589 /*
1590 Check to see if at the end of a bounded definite length map or
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001591 array. The check for a break ending indefinite length array is
1592 later in NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001593 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001594 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001595 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001596 goto Done;
1597 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001598
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001599 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001600 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001601 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1602 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001603 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001604 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301605
Laurence Lundblade642282a2020-06-23 12:00:33 -07001606 /*
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001607 Breaks ending arrays/maps are processed later in the call to
1608 NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001609 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301610 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001611 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301612 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301613 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001614
Laurence Lundblade642282a2020-06-23 12:00:33 -07001615 /*
1616 Record the nesting level for this data item before processing any
1617 of decrementing and descending.
1618 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001619 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001620
Laurence Lundblade642282a2020-06-23 12:00:33 -07001621
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001622 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001623 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001624 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001625 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001626
Laurence Lundblade93d89472020-10-03 22:30:50 -07001627 Empty indefinite length maps and arrays are descended into, but
1628 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001629
1630 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001631 encloses them so a decrement needs to be done for them too, but
1632 that is done only when all the items in them have been
1633 processed, not when they are opened with the exception of an
1634 empty map or array.
1635 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001636 QCBORError uDescendErr;
1637 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001638 pDecodedItem->uDataType,
1639 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001640 if(uDescendErr != QCBOR_SUCCESS) {
1641 /* This error is probably a traversal error and it
1642 overrides the non-traversal error. */
1643 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001644 goto Done;
1645 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001646 }
1647
Laurence Lundblade02625d42020-06-25 14:41:41 -07001648 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1649 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1650 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001651 /*
1652 The following cases are handled here:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001653 - A non-aggregate item like an integer or string
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001654 - An empty definite length map or array
1655 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001656
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001657 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001658 definite length map/array and break detection for an indefinite
1659 length map/array. If the end of the map/array was reached, then
1660 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001661 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001662 QCBORError uAscendErr;
1663 uAscendErr = NestLevelAscender(me, true);
1664 if(uAscendErr != QCBOR_SUCCESS) {
1665 /* This error is probably a traversal error and it
1666 overrides the non-traversal error. */
1667 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001668 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001669 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301670 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001671
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001672 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001673 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001674 Tell the caller what level is next. This tells them what
1675 maps/arrays were closed out and makes it possible for them to
1676 reconstruct the tree with just the information returned in
1677 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001678 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001679 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001680 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001681 pDecodedItem->uNextNestLevel = 0;
1682 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001683 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001684 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001685
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001686Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001687 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001688}
1689
Laurence Lundblade9b334962020-08-27 10:55:53 -07001690static void ShiftTags(QCBORItem *pDecodedItem)
1691{
1692 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1693 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1694 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1695 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1696}
1697
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001698
Laurence Lundblade9b334962020-08-27 10:55:53 -07001699
Laurence Lundblade59289e52019-12-30 13:44:37 -08001700/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001701 The epoch formatted date. Turns lots of different forms of encoding
1702 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001703 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001704static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001705{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001706 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001707
1708 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1709
1710 switch (pDecodedItem->uDataType) {
1711
1712 case QCBOR_TYPE_INT64:
1713 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1714 break;
1715
1716 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001717 // This only happens for CBOR type 0 > INT64_MAX so it is
1718 // always an overflow.
1719 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1720 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001721 break;
1722
1723 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001724 case QCBOR_TYPE_FLOAT:
1725#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001726 {
1727 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001728 // conversion to an int64_t to be able to detect doubles that
1729 // are too large to fit into an int64_t. A double has 52
1730 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1731 // to a double actually causes a round up which is bad and
1732 // wrong for the comparison because it will allow conversion
1733 // of doubles that can't fit into a uint64_t. To remedy this
1734 // INT64_MAX - 0x7ff is used as the cutoff point because if
1735 // that value rounds up in conversion to double it will still
1736 // be less than INT64_MAX. 0x7ff is picked because it has 11
1737 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001738 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001739 // INT64_MAX seconds is on the order of 10 billion years, and
1740 // the earth is less than 5 billion years old, so for most
1741 // uses this conversion error won't occur even though doubles
1742 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001743 //
1744 // Without the 0x7ff there is a ~30 minute range of time
1745 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001746 // where this code would go wrong. Some compilers
1747 // will generate warnings or errors without the 0x7ff
1748 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001749 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1750 pDecodedItem->val.dfnum :
1751 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001752 if(isnan(d) ||
1753 d > (double)(INT64_MAX - 0x7ff) ||
1754 d < (double)(INT64_MIN + 0x7ff)) {
1755 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001756 goto Done;
1757 }
1758 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001759 pDecodedItem->val.epochDate.fSecondsFraction =
1760 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001761 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001762#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001763
Laurence Lundbladec7114722020-08-13 05:11:40 -07001764 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001765 goto Done;
1766
Laurence Lundblade9682a532020-06-06 18:33:04 -07001767#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001768 break;
1769
1770 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001771 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001772 goto Done;
1773 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001774
Laurence Lundblade59289e52019-12-30 13:44:37 -08001775 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1776
1777Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001778 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001779}
1780
1781
1782#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1783/*
1784 Decode decimal fractions and big floats.
1785
1786 When called pDecodedItem must be the array that is tagged as a big
1787 float or decimal fraction, the array that has the two members, the
1788 exponent and mantissa.
1789
1790 This will fetch and decode the exponent and mantissa and put the
1791 result back into pDecodedItem.
1792 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001793static inline QCBORError
Laurence Lundblade59289e52019-12-30 13:44:37 -08001794QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1795{
1796 QCBORError nReturn;
1797
1798 // --- Make sure it is an array; track nesting level of members ---
1799 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1800 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1801 goto Done;
1802 }
1803
1804 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001805 // definite length arrays, but not for indefnite. Instead remember
1806 // the nesting level the two integers must be at, which is one
1807 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001808 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1809
1810 // --- Is it a decimal fraction or a bigfloat? ---
1811 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1812 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1813
1814 // --- Get the exponent ---
1815 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001816 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001817 if(nReturn != QCBOR_SUCCESS) {
1818 goto Done;
1819 }
1820 if(exponentItem.uNestingLevel != nNestLevel) {
1821 // Array is empty or a map/array encountered when expecting an int
1822 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1823 goto Done;
1824 }
1825 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1826 // Data arriving as an unsigned int < INT64_MAX has been converted
1827 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1828 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1829 // will be too large for this to handle and thus an error that will
1830 // get handled in the next else.
1831 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1832 } else {
1833 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1834 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1835 goto Done;
1836 }
1837
1838 // --- Get the mantissa ---
1839 QCBORItem mantissaItem;
1840 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1841 if(nReturn != QCBOR_SUCCESS) {
1842 goto Done;
1843 }
1844 if(mantissaItem.uNestingLevel != nNestLevel) {
1845 // Mantissa missing or map/array encountered when expecting number
1846 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1847 goto Done;
1848 }
1849 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1850 // Data arriving as an unsigned int < INT64_MAX has been converted
1851 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1852 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1853 // will be too large for this to handle and thus an error that
1854 // will get handled in an else below.
1855 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001856 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
1857 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001858 // Got a good big num mantissa
1859 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1860 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001861 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1862 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1863 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001864 } else {
1865 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1866 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1867 goto Done;
1868 }
1869
1870 // --- Check that array only has the two numbers ---
1871 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001872 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001873 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1874 goto Done;
1875 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001876 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001877
1878Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001879 return nReturn;
1880}
1881#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1882
1883
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001884static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001885{
1886 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1887 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001888 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001889 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1890 } else {
1891 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001892
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001893 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001894
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001895 return QCBOR_SUCCESS;
1896}
1897
1898
Laurence Lundblade99615302020-11-29 11:19:47 -08001899/*
1900 * Table of CBOR tags whose content is either a text string or a byte
1901 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
1902 * of uQCBORtype indicates the content should be a byte string rather
1903 * than a text string
1904 */
1905struct StringTagMapEntry {
1906 uint16_t uTagNumber;
1907 uint8_t uQCBORtype;
1908};
1909
1910#define IS_BYTE_STRING_BIT 0x80
1911#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
1912
1913static const struct StringTagMapEntry StringTagMap[] = {
1914 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
1915 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
1916 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
1917 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
1918 {CBOR_TAG_URI, QCBOR_TYPE_URI},
1919 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
1920 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
1921 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
1922 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
1923 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
1924 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
1925};
1926
1927
1928/*
1929 * Process the CBOR tags that whose content is a byte string or a text
1930 * string and for which the string is just passed on to the caller.
1931 *
1932 * This maps the CBOR tag to the QCBOR type and checks the content
1933 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08001934 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08001935 * possible.
1936 *
1937 * This returns QCBOR_SUCCESS if the tag was procssed,
1938 * QCBOR_ERR_UNSUPPORTED if the tag was not processed and
1939 * QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
1940 */
1941static inline
1942QCBORError ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001943{
Laurence Lundblade99615302020-11-29 11:19:47 -08001944 /* This only works on tags that were not mapped; no need for other yet */
1945 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
1946 return QCBOR_ERR_UNSUPPORTED;
1947 }
1948
1949 unsigned uIndex;
1950 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
1951 if(StringTagMap[uIndex].uTagNumber == uTag) {
1952 break;
1953 }
1954 }
1955
1956 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
1957 if(uQCBORType == QCBOR_TYPE_NONE) {
1958 /* repurpose this error to mean, not handled here */
1959 return QCBOR_ERR_UNSUPPORTED;
1960 }
1961
1962 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
1963 if(uQCBORType & IS_BYTE_STRING_BIT) {
1964 uExpectedType = QCBOR_TYPE_BYTE_STRING;
1965 }
1966
1967 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001968 return QCBOR_ERR_BAD_OPT_TAG;
1969 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001970
Laurence Lundblade99615302020-11-29 11:19:47 -08001971 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001972 return QCBOR_SUCCESS;
1973}
1974
1975
Laurence Lundblade59289e52019-12-30 13:44:37 -08001976/*
Laurence Lundblade99615302020-11-29 11:19:47 -08001977 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
1978 * but the whole tag was not decoded. Here, the whole tags (tag number
1979 * and tag content) that are supported by QCBOR are decoded. This is a
1980 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001981 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001982static QCBORError
1983QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001984{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001985 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001986
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001987 uReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
1988 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001989 goto Done;
1990 }
1991
Laurence Lundblade99615302020-11-29 11:19:47 -08001992 /* When there are no tag numbers for the item, this exits first
1993 * thing and effectively does nothing.
1994 *
1995 * This loops over all the tag numbers accumulated for this item
1996 * trying to decode and interpret them. This stops at the end of
1997 * the list or at the first tag number that can't be interpreted by
1998 * this code. This is effectively a recursive processing of the
1999 * tags number list that handles nested tags.
2000 */
2001 while(1) {
2002 /* Don't bother to unmap tags via QCBORITem.uTags since this
2003 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2004 */
2005 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002006
Laurence Lundblade99615302020-11-29 11:19:47 -08002007 if(uTagToProcess == CBOR_TAG_INVALID16) {
2008 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002009 break;
2010
Laurence Lundblade99615302020-11-29 11:19:47 -08002011 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002012 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002013
Laurence Lundblade93d89472020-10-03 22:30:50 -07002014#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002015 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2016 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002017 uReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
Laurence Lundblade93d89472020-10-03 22:30:50 -07002018#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002019
Laurence Lundblade99615302020-11-29 11:19:47 -08002020 } else if(uTagToProcess == CBOR_TAG_MIME ||
2021 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002022 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002023
Laurence Lundblade99615302020-11-29 11:19:47 -08002024 } else {
2025 /* See if it is a pass-through byte/text string tag; process if so */
2026 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002027
Laurence Lundblade99615302020-11-29 11:19:47 -08002028 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2029 /* It wasn't a pass-through byte/text string tag so it is
2030 * an unknown tag. This is the exit from the loop on the
2031 * first unknown tag. It is a successful exit.
2032 */
2033 uReturn = QCBOR_SUCCESS;
2034 break;
2035 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002036 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002037
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002038 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002039 /* Error exit from the loop */
2040 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002041 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002042
2043 /* A tag was successfully processed, shift it out of the list of
2044 * tags returned. This is the loop increment.
2045 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002046 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002047 }
2048
2049Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002050 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002051}
2052
2053
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002054/*
2055 Public function, see header qcbor/qcbor_decode.h file
2056 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002057QCBORError
2058QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2059{
2060 QCBORError uErr;
2061 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2062 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002063 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2064 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2065 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002066 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002067}
2068
2069
2070/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002071 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002072 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002073QCBORError
2074QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2075{
2076 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2077 const UsefulInputBuf Save = pMe->InBuf;
2078
2079 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2080
2081 pMe->nesting = SaveNesting;
2082 pMe->InBuf = Save;
2083
2084 return uErr;
2085}
2086
2087
2088/*
2089 Public function, see header qcbor/qcbor_decode.h file
2090 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002091void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2092{
2093 if(pMe->uLastError != QCBOR_SUCCESS) {
2094 return;
2095 }
2096
2097 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2098}
2099
2100
2101/*
2102 Public function, see header qcbor/qcbor_decode.h file
2103 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002104QCBORError
2105QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2106 QCBORItem *pDecodedItem,
2107 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002108{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002109 QCBORError nReturn;
2110
2111 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2112 if(nReturn != QCBOR_SUCCESS) {
2113 return nReturn;
2114 }
2115
2116 if(pTags != NULL) {
2117 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002118 // Reverse the order because pTags is reverse of
2119 // QCBORItem.uTags.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002120 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2121 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002122 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002123 }
2124 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2125 return QCBOR_ERR_TOO_MANY_TAGS;
2126 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002127 pTags->puTags[pTags->uNumUsed] = ConvertTag(me,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002128 pTags->uNumUsed++;
2129 }
2130 }
2131
2132 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002133}
2134
2135
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002136/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302137 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302138 next one down. If a layer has no work to do for a particular item
2139 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002140
Laurence Lundblade59289e52019-12-30 13:44:37 -08002141 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2142 tagged data items, turning them into the local C representation.
2143 For the most simple it is just associating a QCBOR_TYPE with the data. For
2144 the complex ones that an aggregate of data items, there is some further
2145 decoding and a little bit of recursion.
2146
2147 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302148 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302149 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002150 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002151
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302152 - GetNext_MapEntry -- This handles the combining of two
2153 items, the label and the data, that make up a map entry.
2154 It only does work on maps. It combines the label and data
2155 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002156
Laurence Lundblade59289e52019-12-30 13:44:37 -08002157 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2158 tags into bit flags associated with the data item. No actual decoding
2159 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002160
Laurence Lundblade59289e52019-12-30 13:44:37 -08002161 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302162 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302163 string allocater to create contiguous space for the item. It
2164 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002165
Laurence Lundblade59289e52019-12-30 13:44:37 -08002166 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2167 atomic data item has a "major type", an integer "argument" and optionally
2168 some content. For text and byte strings, the content is the bytes
2169 that make up the string. These are the smallest data items that are
2170 considered to be well-formed. The content may also be other data items in
2171 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002172
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002173 Roughly this takes 300 bytes of stack for vars. Need to
2174 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002175
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302176 */
2177
2178
2179/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002180 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002181 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002182bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002183 const QCBORItem *pItem,
2184 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002185{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002186 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2187 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002188 break;
2189 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002190 if(ConvertTag(me, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002191 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002192 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002193 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002194
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002195 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002196}
2197
2198
2199/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002200 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002201 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002202QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002203{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002204 QCBORError uReturn = me->uLastError;
2205
2206 if(uReturn != QCBOR_SUCCESS) {
2207 goto Done;
2208 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002209
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002210 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002211 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002212 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002213 goto Done;
2214 }
2215
2216 // Error out if not all the bytes are consumed
2217 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002218 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002219 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002220
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002221Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002222#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade6de37062018-10-15 12:22:42 +05302223 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002224 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002225 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002226#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002227
Laurence Lundblade085d7952020-07-24 10:26:30 -07002228 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002229}
2230
2231
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002232/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002233 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002234*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002235// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002236uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2237 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002238 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002239{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002240 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2241 return CBOR_TAG_INVALID64;
2242 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002243 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2244 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002245 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002246 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002247 }
2248}
2249
Laurence Lundblade9b334962020-08-27 10:55:53 -07002250/*
2251 Public function, see header qcbor/qcbor_decode.h file
2252*/
2253uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2254 uint32_t uIndex)
2255{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002256 if(pMe->uLastError != QCBOR_SUCCESS) {
2257 return CBOR_TAG_INVALID64;
2258 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002259 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2260 return CBOR_TAG_INVALID64;
2261 } else {
2262 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2263 }
2264}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002265
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002266/*
2267
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002268Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002269
Laurence Lundbladeee851742020-01-08 08:37:05 -08002270 - Hit end of input before it was expected while decoding type and
2271 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002272
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002273 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002274
Laurence Lundbladeee851742020-01-08 08:37:05 -08002275 - Hit end of input while decoding a text or byte string
2276 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002277
Laurence Lundbladeee851742020-01-08 08:37:05 -08002278 - Encountered conflicting tags -- e.g., an item is tagged both a date
2279 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002280
Laurence Lundbladeee851742020-01-08 08:37:05 -08002281 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002282 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002283
Laurence Lundbladeee851742020-01-08 08:37:05 -08002284 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002285 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002286
Laurence Lundbladeee851742020-01-08 08:37:05 -08002287 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2288 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002289
Laurence Lundbladeee851742020-01-08 08:37:05 -08002290 - The type of a map label is not a string or int
2291 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002292
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002293 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002294
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002295 */
2296
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002297
2298
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002299#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002300
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002301/* ===========================================================================
2302 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002303
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002304 This implements a simple sting allocator for indefinite length
2305 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2306 implements the function type QCBORStringAllocate and allows easy
2307 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002308
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002309 This particular allocator is built-in for convenience. The caller
2310 can implement their own. All of this following code will get
2311 dead-stripped if QCBORDecode_SetMemPool() is not called.
2312
2313 This is a very primitive memory allocator. It does not track
2314 individual allocations, only a high-water mark. A free or
2315 reallocation must be of the last chunk allocated.
2316
2317 The size of the pool and offset to free memory are packed into the
2318 first 8 bytes of the memory pool so we don't have to keep them in
2319 the decode context. Since the address of the pool may not be
2320 aligned, they have to be packed and unpacked as if they were
2321 serialized data of the wire or such.
2322
2323 The sizes packed in are uint32_t to be the same on all CPU types
2324 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002325 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002326
2327
Laurence Lundbladeee851742020-01-08 08:37:05 -08002328static inline int
2329MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002330{
2331 // Use of UsefulInputBuf is overkill, but it is convenient.
2332 UsefulInputBuf UIB;
2333
Laurence Lundbladeee851742020-01-08 08:37:05 -08002334 // Just assume the size here. It was checked during SetUp so
2335 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002336 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002337 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2338 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2339 return UsefulInputBuf_GetError(&UIB);
2340}
2341
2342
Laurence Lundbladeee851742020-01-08 08:37:05 -08002343static inline int
2344MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002345{
2346 // Use of UsefulOutBuf is overkill, but convenient. The
2347 // length check performed here is useful.
2348 UsefulOutBuf UOB;
2349
2350 UsefulOutBuf_Init(&UOB, Pool);
2351 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2352 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2353 return UsefulOutBuf_GetError(&UOB);
2354}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002355
2356
2357/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002358 Internal function for an allocation, reallocation free and destuct.
2359
2360 Having only one function rather than one each per mode saves space in
2361 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002362
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002363 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2364 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002365static UsefulBuf
2366MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002367{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002368 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002369
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002370 uint32_t uPoolSize;
2371 uint32_t uFreeOffset;
2372
2373 if(uNewSize > UINT32_MAX) {
2374 // This allocator is only good up to 4GB. This check should
2375 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2376 goto Done;
2377 }
2378 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2379
2380 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2381 goto Done;
2382 }
2383
2384 if(uNewSize) {
2385 if(pMem) {
2386 // REALLOCATION MODE
2387 // Calculate pointer to the end of the memory pool. It is
2388 // assumed that pPool + uPoolSize won't wrap around by
2389 // assuming the caller won't pass a pool buffer in that is
2390 // not in legitimate memory space.
2391 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2392
2393 // Check that the pointer for reallocation is in the range of the
2394 // pool. This also makes sure that pointer math further down
2395 // doesn't wrap under or over.
2396 if(pMem >= pPool && pMem < pPoolEnd) {
2397 // Offset to start of chunk for reallocation. This won't
2398 // wrap under because of check that pMem >= pPool. Cast
2399 // is safe because the pool is always less than UINT32_MAX
2400 // because of check in QCBORDecode_SetMemPool().
2401 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2402
2403 // Check to see if the allocation will fit. uPoolSize -
2404 // uMemOffset will not wrap under because of check that
2405 // pMem is in the range of the uPoolSize by check above.
2406 if(uNewSize <= uPoolSize - uMemOffset) {
2407 ReturnValue.ptr = pMem;
2408 ReturnValue.len = uNewSize;
2409
2410 // Addition won't wrap around over because uNewSize was
2411 // checked to be sure it is less than the pool size.
2412 uFreeOffset = uMemOffset + uNewSize32;
2413 }
2414 }
2415 } else {
2416 // ALLOCATION MODE
2417 // uPoolSize - uFreeOffset will not underflow because this
2418 // pool implementation makes sure uFreeOffset is always
2419 // smaller than uPoolSize through this check here and
2420 // reallocation case.
2421 if(uNewSize <= uPoolSize - uFreeOffset) {
2422 ReturnValue.len = uNewSize;
2423 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002424 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002425 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002426 }
2427 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002428 if(pMem) {
2429 // FREE MODE
2430 // Cast is safe because of limit on pool size in
2431 // QCBORDecode_SetMemPool()
2432 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2433 } else {
2434 // DESTRUCT MODE
2435 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002436 }
2437 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002438
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002439 UsefulBuf Pool = {pPool, uPoolSize};
2440 MemPool_Pack(Pool, uFreeOffset);
2441
2442Done:
2443 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002444}
2445
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002446
Laurence Lundbladef6531662018-12-04 10:42:22 +09002447/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002448 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002449 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002450QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2451 UsefulBuf Pool,
2452 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002453{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002454 // The pool size and free mem offset are packed into the beginning
2455 // of the pool memory. This compile time check make sure the
2456 // constant in the header is correct. This check should optimize
2457 // down to nothing.
2458 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002459 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002460 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002461
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002462 // The pool size and free offset packed in to the beginning of pool
2463 // memory are only 32-bits. This check will optimize out on 32-bit
2464 // machines.
2465 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002466 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002467 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002468
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002469 // This checks that the pool buffer given is big enough.
2470 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002471 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002472 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002473
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002474 pMe->StringAllocator.pfAllocator = MemPool_Function;
2475 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2476 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002477
Laurence Lundblade30816f22018-11-10 13:40:22 +07002478 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002479}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002480#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002481
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002482
2483
Laurence Lundblade9b334962020-08-27 10:55:53 -07002484static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2485{
2486 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2487}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002488
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002489
2490/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002491 Consume an entire map or array (and do next to
2492 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002493 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002494static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002495ConsumeItem(QCBORDecodeContext *pMe,
2496 const QCBORItem *pItemToConsume,
2497 uint_fast8_t *puNextNestLevel)
2498{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002499 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002500 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002501
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002502 // If it is a map or array, this will tell if it is empty.
2503 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2504
2505 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2506 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002507
Laurence Lundblade1341c592020-04-11 14:19:05 -07002508 /* This works for definite and indefinite length
2509 * maps and arrays by using the nesting level
2510 */
2511 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002512 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002513 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002514 goto Done;
2515 }
2516 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002517
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002518 *puNextNestLevel = Item.uNextNestLevel;
2519
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002520 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002521
Laurence Lundblade1341c592020-04-11 14:19:05 -07002522 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002523 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002524 /* Just pass the nesting level through */
2525 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2526
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002527 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002528 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002529
2530Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002531 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002532}
2533
2534
Laurence Lundblade1341c592020-04-11 14:19:05 -07002535/* Return true if the labels in Item1 and Item2 are the same.
2536 Works only for integer and string labels. Returns false
2537 for any other type. */
2538static inline bool
2539MatchLabel(QCBORItem Item1, QCBORItem Item2)
2540{
2541 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2542 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2543 return true;
2544 }
2545 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002546 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002547 return true;
2548 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002549 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002550 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2551 return true;
2552 }
2553 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2554 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2555 return true;
2556 }
2557 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002558
Laurence Lundblade1341c592020-04-11 14:19:05 -07002559 /* Other label types are never matched */
2560 return false;
2561}
2562
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002563
2564/*
2565 Returns true if Item1 and Item2 are the same type
2566 or if either are of QCBOR_TYPE_ANY.
2567 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002568static inline bool
2569MatchType(QCBORItem Item1, QCBORItem Item2)
2570{
2571 if(Item1.uDataType == Item2.uDataType) {
2572 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002573 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002574 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002575 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002576 return true;
2577 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002578 return false;
2579}
2580
2581
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002582/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002583 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002584
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002585 @param[in] pMe The decode context to search.
2586 @param[in,out] pItemArray The items to search for and the items found.
2587 @param[out] puOffset Byte offset of last item matched.
2588 @param[in] pCBContext Context for the not-found item call back.
2589 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002590
2591 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2592
Laurence Lundblade93d89472020-10-03 22:30:50 -07002593 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2594 were found for one of the labels being
2595 search for. This duplicate detection is
2596 only performed for items in pItemArray,
2597 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002598
Laurence Lundblade93d89472020-10-03 22:30:50 -07002599 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2600 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002601
2602 @retval Also errors returned by QCBORDecode_GetNext().
2603
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002604 On input pItemArray contains a list of labels and data types
2605 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002606
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002607 On output the fully retrieved items are filled in with
2608 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002609
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002610 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002611
2612 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002613 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002614static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002615MapSearch(QCBORDecodeContext *pMe,
2616 QCBORItem *pItemArray,
2617 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002618 void *pCBContext,
2619 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002620{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002621 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002622 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002623
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002624 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002625 uReturn = pMe->uLastError;
2626 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002627 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002628
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002629 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002630 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2631 /* QCBOR_TYPE_NONE as first item indicates just looking
2632 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002633 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2634 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002635 }
2636
Laurence Lundblade085d7952020-07-24 10:26:30 -07002637 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2638 // It is an empty bounded array or map
2639 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2640 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002641 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002642 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002643 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002644 // Nothing is ever found in an empty array or map. All items
2645 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002646 uReturn = QCBOR_SUCCESS;
2647 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002648 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002649 }
2650
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002651 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002652 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2653
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002654 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002655 UsefulInputBuf_Seek(&(pMe->InBuf),
2656 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002657
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002658 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002659 Loop over all the items in the map or array. Each item
2660 could be a map or array, but label matching is only at
2661 the main level. This handles definite and indefinite
2662 length maps and arrays. The only reason this is ever
2663 called on arrays is to find their end position.
2664
2665 This will always run over all items in order to do
2666 duplicate detection.
2667
2668 This will exit with failure if it encounters an
2669 unrecoverable error, but continue on for recoverable
2670 errors.
2671
2672 If a recoverable error occurs on a matched item, then
2673 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002674 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002675 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002676 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002677 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002678 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002679 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002680
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002681 /* Get the item */
2682 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002683 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2684 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002685 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002686 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002687 goto Done;
2688 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002689 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002690 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002691 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002692 goto Done;
2693 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002694
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002695 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002696 bool bMatched = false;
2697 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2698 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002699 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002700 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2701 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002702 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002703 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002704 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002705 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002706 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002707 goto Done;
2708 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002709
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002710 if(uResult != QCBOR_SUCCESS) {
2711 uReturn = uResult;
2712 goto Done;
2713 }
2714
Laurence Lundblade1341c592020-04-11 14:19:05 -07002715 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002716 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002717 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002718 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002719 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002720 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002721 bMatched = true;
2722 }
2723 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002724
2725
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002726 if(!bMatched && pfCallback != NULL) {
2727 /*
2728 Call the callback on unmatched labels.
2729 (It is tempting to do duplicate detection here, but that would
2730 require dynamic memory allocation because the number of labels
2731 that might be encountered is unbounded.)
2732 */
2733 uReturn = (*pfCallback)(pCBContext, &Item);
2734 if(uReturn != QCBOR_SUCCESS) {
2735 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002736 }
2737 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002738
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002739 /*
2740 Consume the item whether matched or not. This
2741 does the work of traversing maps and array and
2742 everything in them. In this loop only the
2743 items at the current nesting level are examined
2744 to match the labels.
2745 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002746 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002747 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002748 goto Done;
2749 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002750
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002751 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002752
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002753 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002754
2755 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002756
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002757 // Check here makes sure that this won't accidentally be
2758 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002759 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08002760 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
2761 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002762 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2763 goto Done;
2764 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002765 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2766 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002767
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002768 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002769 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2770
2771 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002772 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002773 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002774 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002775 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2776 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002777 }
2778 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002779
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002780 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002781}
2782
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002783
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002784/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002785 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002786*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002787void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2788 int64_t nLabel,
2789 uint8_t uQcborType,
2790 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002791{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002792 if(pMe->uLastError != QCBOR_SUCCESS) {
2793 return;
2794 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002795
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002796 QCBORItem OneItemSeach[2];
2797 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2798 OneItemSeach[0].label.int64 = nLabel;
2799 OneItemSeach[0].uDataType = uQcborType;
2800 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002801
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002802 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002803
2804 *pItem = OneItemSeach[0];
2805
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002806 if(uReturn != QCBOR_SUCCESS) {
2807 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002808 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002809 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002810 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002811 }
2812
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002813 Done:
2814 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002815}
2816
2817
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002818/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002819 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002820*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002821void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2822 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002823 uint8_t uQcborType,
2824 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002825{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002826 if(pMe->uLastError != QCBOR_SUCCESS) {
2827 return;
2828 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002829
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002830 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002831 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2832 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2833 OneItemSeach[0].uDataType = uQcborType;
2834 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002835
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002836 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2837 if(uReturn != QCBOR_SUCCESS) {
2838 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002839 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002840 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002841 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002842 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002843 }
2844
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002845 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002846
2847Done:
2848 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002849}
2850
2851
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002852
Laurence Lundblade93d89472020-10-03 22:30:50 -07002853static QCBORError
2854CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002855{
2856 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2857 if(uDataType == puTypeList[i]) {
2858 return QCBOR_SUCCESS;
2859 }
2860 }
2861 return QCBOR_ERR_UNEXPECTED_TYPE;
2862}
2863
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002864
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002865/**
2866 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002867 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002868
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002869 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2870 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002871
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002872 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
2873 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002874 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002875static QCBORError
2876CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002877{
2878 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2879 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2880 /* There are tags that QCBOR couldn't process on this item and
2881 the caller has told us there should not be. */
2882 return QCBOR_ERR_UNEXPECTED_TYPE;
2883 }
2884
2885 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2886 const int nItemType = pItem->uDataType;
2887
2888 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2889 // Must match the tag and only the tag
2890 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2891 }
2892
2893 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2894 if(uReturn == QCBOR_SUCCESS) {
2895 return QCBOR_SUCCESS;
2896 }
2897
2898 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2899 /* Must match the content type and only the content type.
2900 There was no match just above so it is a fail. */
2901 return QCBOR_ERR_UNEXPECTED_TYPE;
2902 }
2903
2904 /* If here it can match either the tag or the content
2905 and it hasn't matched the content, so the end
2906 result is whether it matches the tag. This is
2907 also the case that the CBOR standard discourages. */
2908
2909 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2910}
2911
Laurence Lundblade9b334962020-08-27 10:55:53 -07002912
Laurence Lundblade9b334962020-08-27 10:55:53 -07002913
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002914// This could be semi-private if need be
2915static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002916void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2917 int64_t nLabel,
2918 TagSpecification TagSpec,
2919 QCBORItem *pItem)
2920{
2921 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2922 if(pMe->uLastError != QCBOR_SUCCESS) {
2923 return;
2924 }
2925
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002926 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002927}
2928
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002929
2930// This could be semi-private if need be
2931static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002932void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2933 const char *szLabel,
2934 TagSpecification TagSpec,
2935 QCBORItem *pItem)
2936{
2937 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2938 if(pMe->uLastError != QCBOR_SUCCESS) {
2939 return;
2940 }
2941
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002942 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002943}
2944
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002945// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002946void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2947 int64_t nLabel,
2948 TagSpecification TagSpec,
2949 UsefulBufC *pString)
2950{
2951 QCBORItem Item;
2952 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2953 if(pMe->uLastError == QCBOR_SUCCESS) {
2954 *pString = Item.val.string;
2955 }
2956}
2957
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002958// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002959void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2960 const char * szLabel,
2961 TagSpecification TagSpec,
2962 UsefulBufC *pString)
2963{
2964 QCBORItem Item;
2965 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2966 if(pMe->uLastError == QCBOR_SUCCESS) {
2967 *pString = Item.val.string;
2968 }
2969}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002970
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002971/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002972 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002973*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002974void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002975{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002976 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
2977 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002978}
2979
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002980/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002981 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002982*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002983void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
2984 QCBORItem *pItemList,
2985 void *pCallbackCtx,
2986 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002987{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002988 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
2989 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002990}
2991
2992
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08002993/**
2994 * @brief Search for a map/array by label and enter it
2995 *
2996 * @param[in] pMe The decode context.
2997 * @param[in] pSearch The map/array to search for.
2998 *
2999 * @c pSearch is expected to contain one item of type map or array
3000 * with the label specified. The current bounded map will be searched for
3001 * this and if found will be entered.
3002 *
3003 * If the label is not found, or the item found is not a map or array,
3004 * the error state is set.
3005 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003006static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003007{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003008 // The first item in pSearch is the one that is to be
3009 // entered. It should be the only one filled in. Any other
3010 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003011 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003012 return;
3013 }
3014
3015 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003016 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003017 if(pMe->uLastError != QCBOR_SUCCESS) {
3018 return;
3019 }
3020
Laurence Lundblade9b334962020-08-27 10:55:53 -07003021 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003022 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003023 return;
3024 }
3025
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003026 /*
3027 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3028 * next item for the pre-order traversal cursor to be the map/array
3029 * found by MapSearch(). The next few lines of code force the
3030 * cursor to that.
3031 *
3032 * There is no need to retain the old cursor because
3033 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3034 * beginning of the map/array being entered.
3035 *
3036 * The cursor is forced by: 1) setting the input buffer position to
3037 * the item offset found by MapSearch(), 2) setting the map/array
3038 * counter to the total in the map/array, 3) setting the nesting
3039 * level. Setting the map/array counter to the total is not
3040 * strictly correct, but this is OK because this cursor only needs
3041 * to be used to get one item and MapSearch() has already found it
3042 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003043 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003044 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003045
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003046 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3047
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003048 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003049
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003050 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003051}
3052
3053
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003054/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003055 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003056*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003057void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003058{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003059 QCBORItem OneItemSeach[2];
3060 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3061 OneItemSeach[0].label.int64 = nLabel;
3062 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3063 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003064
Laurence Lundblade9b334962020-08-27 10:55:53 -07003065 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003066 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003067}
3068
3069
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003070/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003071 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003072*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003073void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003074{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003075 QCBORItem OneItemSeach[2];
3076 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3077 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3078 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3079 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003080
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003081 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003082}
3083
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003084/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003085 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003086*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003087void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003088{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003089 QCBORItem OneItemSeach[2];
3090 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3091 OneItemSeach[0].label.int64 = nLabel;
3092 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3093 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003094
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003095 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003096}
3097
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003098/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003099 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003100*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003101void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3102{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003103 QCBORItem OneItemSeach[2];
3104 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3105 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3106 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3107 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003108
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003109 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003110}
3111
3112
Laurence Lundblade02625d42020-06-25 14:41:41 -07003113// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003114void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003115{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003116 QCBORError uErr;
3117
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003118 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003119 if(pMe->uLastError != QCBOR_SUCCESS) {
3120 // Already in error state; do nothing.
3121 return;
3122 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003123
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003124 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003125 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003126 uErr = QCBORDecode_GetNext(pMe, &Item);
3127 if(uErr != QCBOR_SUCCESS) {
3128 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003129 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003130 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003131 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3132 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003133 }
3134
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003135 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003136
3137
Laurence Lundbladef0499502020-08-01 11:55:57 -07003138 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003139 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003140 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3141 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003142 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003143 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3144 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003145 // Special case to increment nesting level for zero-length maps
3146 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003147 DecodeNesting_Descend(&(pMe->nesting), uType);
3148 }
3149
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003150 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003151
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003152 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3153 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003154
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003155 if(pItem != NULL) {
3156 *pItem = Item;
3157 }
3158
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003159Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003160 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003161}
3162
Laurence Lundblade02625d42020-06-25 14:41:41 -07003163
3164/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003165 This is the common work for exiting a level that is a bounded map,
3166 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003167
3168 One chunk of work is to set up the pre-order traversal so it is at
3169 the item just after the bounded map, array or bstr that is being
3170 exited. This is somewhat complex.
3171
3172 The other work is to level-up the bounded mode to next higest bounded
3173 mode or the top level if there isn't one.
3174 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003175static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003176ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003177{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003178 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003179
Laurence Lundblade02625d42020-06-25 14:41:41 -07003180 /*
3181 First the pre-order-traversal byte offset is positioned to the
3182 item just after the bounded mode item that was just consumed.
3183 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003184 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3185
Laurence Lundblade02625d42020-06-25 14:41:41 -07003186 /*
3187 Next, set the current nesting level to one above the bounded level
3188 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003189
Laurence Lundblade02625d42020-06-25 14:41:41 -07003190 DecodeNesting_CheckBoundedType() is always called before this and
3191 makes sure pCurrentBounded is valid.
3192 */
3193 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3194
3195 /*
3196 This does the complex work of leveling up the pre-order traversal
3197 when the end of a map or array or another bounded level is
3198 reached. It may do nothing, or ascend all the way to the top
3199 level.
3200 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003201 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003202 if(uErr != QCBOR_SUCCESS) {
3203 goto Done;
3204 }
3205
Laurence Lundblade02625d42020-06-25 14:41:41 -07003206 /*
3207 This makes the next highest bounded level the current bounded
3208 level. If there is no next highest level, then no bounded mode is
3209 in effect.
3210 */
3211 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003212
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003213 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003214
3215Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003216 return uErr;
3217}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003218
Laurence Lundblade02625d42020-06-25 14:41:41 -07003219
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003220// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003221void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003222{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003223 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003224 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003225 return;
3226 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003227
Laurence Lundblade02625d42020-06-25 14:41:41 -07003228 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003229
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003230 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003231 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003232 goto Done;
3233 }
3234
Laurence Lundblade02625d42020-06-25 14:41:41 -07003235 /*
3236 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003237 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003238 from previous map search, then do a dummy search.
3239 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003240 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003241 QCBORItem Dummy;
3242 Dummy.uLabelType = QCBOR_TYPE_NONE;
3243 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3244 if(uErr != QCBOR_SUCCESS) {
3245 goto Done;
3246 }
3247 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003248
Laurence Lundblade02625d42020-06-25 14:41:41 -07003249 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003250
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003251Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003252 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003253}
3254
3255
Laurence Lundblade1341c592020-04-11 14:19:05 -07003256
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003257static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003258 const QCBORItem *pItem,
3259 uint8_t uTagRequirement,
3260 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003261{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003262 if(pBstr) {
3263 *pBstr = NULLUsefulBufC;
3264 }
3265
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003266 if(pMe->uLastError != QCBOR_SUCCESS) {
3267 // Already in error state; do nothing.
3268 return pMe->uLastError;
3269 }
3270
3271 QCBORError uError = QCBOR_SUCCESS;
3272
3273 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3274 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3275 goto Done;;
3276 }
3277
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003278 const TagSpecification TagSpec =
3279 {
3280 uTagRequirement,
3281 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3282 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3283 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003284
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003285 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003286 if(uError != QCBOR_SUCCESS) {
3287 goto Done;
3288 }
3289
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003290 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003291 // Reverse the decrement done by GetNext() for the bstr so the
3292 // increment in NestLevelAscender() called by ExitBoundedLevel()
3293 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003294 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003295 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003296
3297 if(pBstr) {
3298 *pBstr = pItem->val.string;
3299 }
3300
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003301 // This saves the current length of the UsefulInputBuf and then
3302 // narrows the UsefulInputBuf to start and length of the wrapped
3303 // CBOR that is being entered.
3304 //
3305 // This makes sure the length is less than
3306 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3307 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3308 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3309 // the casts safe. uEndOfBstr will always be less than
3310 // uPreviousLength because of the way UsefulInputBuf works so there
3311 // is no need to check it. There is also a range check in the
3312 // seek.
3313 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003314 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003315 // amount to much code.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003316 // Cast of uPreviousLength to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003317 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003318 if((uint32_t)uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003319 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003320 goto Done;
3321 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003322 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003323 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003324 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003325
Laurence Lundblade02625d42020-06-25 14:41:41 -07003326 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003327 (uint32_t)uPreviousLength,
3328 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003329Done:
3330 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003331}
3332
3333
Laurence Lundblade02625d42020-06-25 14:41:41 -07003334/*
3335 Public function, see header qcbor/qcbor_decode.h file
3336 */
3337void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003338 uint8_t uTagRequirement,
3339 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003340{
3341 if(pMe->uLastError != QCBOR_SUCCESS) {
3342 // Already in error state; do nothing.
3343 return;
3344 }
3345
3346 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003347 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003348 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3349 if(pMe->uLastError != QCBOR_SUCCESS) {
3350 return;
3351 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003352
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003353 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003354 &Item,
3355 uTagRequirement,
3356 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003357}
3358
3359
Laurence Lundblade02625d42020-06-25 14:41:41 -07003360/*
3361 Public function, see header qcbor/qcbor_decode.h file
3362 */
3363void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003364 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003365 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003366 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003367{
3368 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003369 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003370
Laurence Lundblade93d89472020-10-03 22:30:50 -07003371 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3372 &Item,
3373 uTagRequirement,
3374 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003375}
3376
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003377
Laurence Lundblade02625d42020-06-25 14:41:41 -07003378/*
3379 Public function, see header qcbor/qcbor_decode.h file
3380 */
3381void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003382 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003383 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003384 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003385{
3386 QCBORItem Item;
3387 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3388
Laurence Lundblade93d89472020-10-03 22:30:50 -07003389 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3390 &Item,
3391 uTagRequirement,
3392 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003393}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003394
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003395
Laurence Lundblade02625d42020-06-25 14:41:41 -07003396/*
3397 Public function, see header qcbor/qcbor_decode.h file
3398 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003399void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003400{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003401 if(pMe->uLastError != QCBOR_SUCCESS) {
3402 // Already in error state; do nothing.
3403 return;
3404 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003405
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003406 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003407 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003408 return;
3409 }
3410
3411 /*
3412 Reset the length of the UsefulInputBuf to what it was before
3413 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003414 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003415 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003416 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003417
3418
Laurence Lundblade02625d42020-06-25 14:41:41 -07003419 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003420 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003421}
3422
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003423
Laurence Lundbladee6430642020-03-14 21:15:44 -07003424
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003425
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003426
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003427
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003428
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003429
Laurence Lundblade93d89472020-10-03 22:30:50 -07003430static QCBORError
3431InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003432{
3433 switch(pItem->uDataType) {
3434 case QCBOR_TYPE_TRUE:
3435 *pBool = true;
3436 return QCBOR_SUCCESS;
3437 break;
3438
3439 case QCBOR_TYPE_FALSE:
3440 *pBool = false;
3441 return QCBOR_SUCCESS;
3442 break;
3443
3444 default:
3445 return QCBOR_ERR_UNEXPECTED_TYPE;
3446 break;
3447 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003448 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003449}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003450
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003451
Laurence Lundblade9b334962020-08-27 10:55:53 -07003452
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003453/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003454 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003455*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003456void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003457{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003458 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003459 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003460 return;
3461 }
3462
Laurence Lundbladec4537442020-04-14 18:53:22 -07003463 QCBORError nError;
3464 QCBORItem Item;
3465
3466 nError = QCBORDecode_GetNext(pMe, &Item);
3467 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003468 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003469 return;
3470 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003471 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003472}
3473
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003474
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003475/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003476 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003477*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003478void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003479{
3480 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003481 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003482
Laurence Lundblade9b334962020-08-27 10:55:53 -07003483 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003484}
3485
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003486
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003487/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003488 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003489*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003490void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3491{
3492 QCBORItem Item;
3493 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3494
Laurence Lundblade9b334962020-08-27 10:55:53 -07003495 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003496}
3497
3498
3499
Laurence Lundbladec7114722020-08-13 05:11:40 -07003500
3501static void ProcessEpochDate(QCBORDecodeContext *pMe,
3502 QCBORItem *pItem,
3503 uint8_t uTagRequirement,
3504 int64_t *pnTime)
3505{
3506 if(pMe->uLastError != QCBOR_SUCCESS) {
3507 // Already in error state, do nothing
3508 return;
3509 }
3510
3511 QCBORError uErr;
3512
3513 const TagSpecification TagSpec =
3514 {
3515 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003516 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3517 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003518 };
3519
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003520 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003521 if(uErr != QCBOR_SUCCESS) {
3522 goto Done;
3523 }
3524
3525 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3526 uErr = DecodeDateEpoch(pItem);
3527 if(uErr != QCBOR_SUCCESS) {
3528 goto Done;
3529 }
3530 }
3531
Laurence Lundblade9b334962020-08-27 10:55:53 -07003532 // Save the tags in the last item's tags in the decode context
3533 // for QCBORDecode_GetNthTagOfLast()
3534 CopyTags(pMe, pItem);
3535
Laurence Lundbladec7114722020-08-13 05:11:40 -07003536 *pnTime = pItem->val.epochDate.nSeconds;
3537
3538Done:
3539 pMe->uLastError = (uint8_t)uErr;
3540}
3541
3542
3543void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003544 uint8_t uTagRequirement,
3545 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003546{
3547 if(pMe->uLastError != QCBOR_SUCCESS) {
3548 // Already in error state, do nothing
3549 return;
3550 }
3551
3552 QCBORItem Item;
3553 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3554
3555 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3556}
3557
3558
3559void
3560QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3561 int64_t nLabel,
3562 uint8_t uTagRequirement,
3563 int64_t *pnTime)
3564{
3565 QCBORItem Item;
3566 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3567 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3568}
3569
3570
3571void
3572QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3573 const char *szLabel,
3574 uint8_t uTagRequirement,
3575 int64_t *pnTime)
3576{
3577 QCBORItem Item;
3578 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3579 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3580}
3581
3582
3583
3584
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003585void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3586 TagSpecification TagSpec,
3587 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003588{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003589 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003590 // Already in error state, do nothing
3591 return;
3592 }
3593
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003594 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003595 QCBORItem Item;
3596
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003597 uError = QCBORDecode_GetNext(pMe, &Item);
3598 if(uError != QCBOR_SUCCESS) {
3599 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003600 return;
3601 }
3602
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003603 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003604
3605 if(pMe->uLastError == QCBOR_SUCCESS) {
3606 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003607 } else {
3608 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003609 }
3610}
3611
Laurence Lundbladec4537442020-04-14 18:53:22 -07003612
3613
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003614
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003615static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003616 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003617 UsefulBufC *pValue,
3618 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003619{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003620 const TagSpecification TagSpec =
3621 {
3622 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003623 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3624 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003625 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003626
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003627 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003628 if(uErr != QCBOR_SUCCESS) {
3629 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003630 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003631
3632 *pValue = pItem->val.string;
3633
3634 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3635 *pbIsNegative = false;
3636 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3637 *pbIsNegative = true;
3638 }
3639
3640 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003641}
3642
3643
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003644/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003645 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003646 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003647void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3648 uint8_t uTagRequirement,
3649 UsefulBufC *pValue,
3650 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003651{
3652 if(pMe->uLastError != QCBOR_SUCCESS) {
3653 // Already in error state, do nothing
3654 return;
3655 }
3656
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003657 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003658 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3659 if(uError != QCBOR_SUCCESS) {
3660 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003661 return;
3662 }
3663
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003664 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003665}
3666
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003667
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003668/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003669 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003670*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003671void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3672 int64_t nLabel,
3673 uint8_t uTagRequirement,
3674 UsefulBufC *pValue,
3675 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003676{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003677 QCBORItem Item;
3678 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003679 if(pMe->uLastError != QCBOR_SUCCESS) {
3680 return;
3681 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003682
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003683 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003684}
3685
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003686
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003687/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003688 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003689*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003690void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3691 const char *szLabel,
3692 uint8_t uTagRequirement,
3693 UsefulBufC *pValue,
3694 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003695{
3696 QCBORItem Item;
3697 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003698 if(pMe->uLastError != QCBOR_SUCCESS) {
3699 return;
3700 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003701
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003702 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003703}
3704
3705
3706
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003707
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003708// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003709QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3710 const QCBORItem *pItem,
3711 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003712 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003713{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003714 const TagSpecification TagSpecText =
3715 {
3716 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003717 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3718 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003719 };
3720 const TagSpecification TagSpecBinary =
3721 {
3722 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003723 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3724 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003725 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003726
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003727 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003728
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003729 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003730 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003731 if(pbIsTag257 != NULL) {
3732 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003733 }
3734 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003735 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003736 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003737 if(pbIsTag257 != NULL) {
3738 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003739 }
3740 uReturn = QCBOR_SUCCESS;
3741
3742 } else {
3743 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3744 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003745
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003746 return uReturn;
3747}
3748
Laurence Lundblade93d89472020-10-03 22:30:50 -07003749// Improvement: add methods for wrapped CBOR, a simple alternate
3750// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003751
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003752
3753
3754
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003755#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003756
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003757typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003758
3759
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003760// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003761static QCBORError
3762Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003763{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003764 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003765
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003766 if(uResult != 0) {
3767 /* This loop will run a maximum of 19 times because
3768 * UINT64_MAX < 10 ^^ 19. More than that will cause
3769 * exit with the overflow error
3770 */
3771 for(; nExponent > 0; nExponent--) {
3772 if(uResult > UINT64_MAX / 10) {
3773 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3774 }
3775 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003776 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003777
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003778 for(; nExponent < 0; nExponent++) {
3779 uResult = uResult / 10;
3780 if(uResult == 0) {
3781 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3782 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003783 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003784 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003785 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003786
3787 *puResult = uResult;
3788
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003789 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003790}
3791
3792
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003793// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003794static QCBORError
3795Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003796{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003797 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003798
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003799 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003800
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003801 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003802 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003803 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003804 */
3805 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003806 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003807 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003808 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003809 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003810 nExponent--;
3811 }
3812
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003813 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003814 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003815 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3816 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003817 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003818 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003819 }
3820
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003821 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003822
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003823 return QCBOR_SUCCESS;
3824}
3825
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003826
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003827/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003828 Compute value with signed mantissa and signed result. Works with
3829 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003830 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003831static inline QCBORError ExponentiateNN(int64_t nMantissa,
3832 int64_t nExponent,
3833 int64_t *pnResult,
3834 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003835{
3836 uint64_t uResult;
3837
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003838 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003839 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003840 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3841
3842 // Do the exponentiation of the positive mantissa
3843 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3844 if(uReturn) {
3845 return uReturn;
3846 }
3847
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003848
Laurence Lundblade983500d2020-05-14 11:49:34 -07003849 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3850 of INT64_MIN. This assumes two's compliment representation where
3851 INT64_MIN is one increment farther from 0 than INT64_MAX.
3852 Trying to write -INT64_MIN doesn't work to get this because the
3853 compiler tries to work with an int64_t which can't represent
3854 -INT64_MIN.
3855 */
3856 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3857
3858 // Error out if too large
3859 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003860 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3861 }
3862
3863 // Casts are safe because of checks above
3864 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3865
3866 return QCBOR_SUCCESS;
3867}
3868
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003869
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003870/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003871 Compute value with signed mantissa and unsigned result. Works with
3872 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003873 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003874static inline QCBORError ExponentitateNU(int64_t nMantissa,
3875 int64_t nExponent,
3876 uint64_t *puResult,
3877 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003878{
3879 if(nMantissa < 0) {
3880 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3881 }
3882
3883 // Cast to unsigned is OK because of check for negative
3884 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3885 // Exponentiation is straight forward
3886 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3887}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003888
3889
3890/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003891 Compute value with signed mantissa and unsigned result. Works with
3892 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003893 */
3894static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3895 int64_t nExponent,
3896 uint64_t *puResult,
3897 fExponentiator pfExp)
3898{
3899 return (*pfExp)(uMantissa, nExponent, puResult);
3900}
3901
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003902#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3903
3904
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003905
3906
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003907
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003908static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003909{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003910 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003911
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003912 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003913 const uint8_t *pByte = BigNum.ptr;
3914 size_t uLen = BigNum.len;
3915 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003916 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003917 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003918 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003919 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003920 }
3921
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003922 *pResult = uResult;
3923 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003924}
3925
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003926
Laurence Lundblade887add82020-05-17 05:50:34 -07003927static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003928{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003929 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003930}
3931
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003932
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003933static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003934{
3935 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003936 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3937 if(uError) {
3938 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003939 }
3940 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3941 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003942 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003943}
3944
3945
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003946static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003947{
3948 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003949 /* The negative integer furthest from zero for a C int64_t is
3950 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3951 negative number in CBOR is computed as -n - 1 where n is the
3952 encoded integer, where n is what is in the variable BigNum. When
3953 converting BigNum to a uint64_t, the maximum value is thus
3954 INT64_MAX, so that when it -n - 1 is applied to it the result will
3955 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003956
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003957 -n - 1 <= INT64_MIN.
3958 -n - 1 <= -INT64_MAX - 1
3959 n <= INT64_MAX.
3960 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003961 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003962 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003963 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003964 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003965
3966 /// Now apply -n - 1. The cast is safe because
3967 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3968 // is the largest positive integer that an int64_t can
3969 // represent. */
3970 *pnResult = -(int64_t)uResult - 1;
3971
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003972 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003973}
3974
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003975
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003976
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003977
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003978
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003979/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003980Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003981
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003982\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003983
Laurence Lundblade93d89472020-10-03 22:30:50 -07003984\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
3985 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003986
3987\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3988
Laurence Lundblade93d89472020-10-03 22:30:50 -07003989\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
3990 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003991*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07003992static QCBORError
3993ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003994{
3995 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003996 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003997 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003998#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003999 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004000 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4001 http://www.cplusplus.com/reference/cmath/llround/
4002 */
4003 // Not interested in FE_INEXACT
4004 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004005 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4006 *pnValue = llround(pItem->val.dfnum);
4007 } else {
4008 *pnValue = lroundf(pItem->val.fnum);
4009 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004010 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4011 // llround() shouldn't result in divide by zero, but catch
4012 // it here in case it unexpectedly does. Don't try to
4013 // distinguish between the various exceptions because it seems
4014 // they vary by CPU, compiler and OS.
4015 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004016 }
4017 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004018 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004019 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004020#else
4021 return QCBOR_ERR_HW_FLOAT_DISABLED;
4022#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004023 break;
4024
4025 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004026 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004027 *pnValue = pItem->val.int64;
4028 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004029 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004030 }
4031 break;
4032
4033 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004034 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004035 if(pItem->val.uint64 < INT64_MAX) {
4036 *pnValue = pItem->val.int64;
4037 } else {
4038 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4039 }
4040 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004041 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004042 }
4043 break;
4044
4045 default:
4046 return QCBOR_ERR_UNEXPECTED_TYPE;
4047 }
4048 return QCBOR_SUCCESS;
4049}
4050
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004051
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004052void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004053 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004054 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004055 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004056{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004057 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004058 return;
4059 }
4060
Laurence Lundbladee6430642020-03-14 21:15:44 -07004061 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004062 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4063 if(uError) {
4064 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004065 return;
4066 }
4067
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004068 if(pItem) {
4069 *pItem = Item;
4070 }
4071
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004072 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004073}
4074
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004075
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004076void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4077 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004078 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004079 int64_t *pnValue,
4080 QCBORItem *pItem)
4081{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004082 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004083 if(pMe->uLastError != QCBOR_SUCCESS) {
4084 return;
4085 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004086
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004087 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004088}
4089
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004090
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004091void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4092 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004093 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004094 int64_t *pnValue,
4095 QCBORItem *pItem)
4096{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004097 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004098 if(pMe->uLastError != QCBOR_SUCCESS) {
4099 return;
4100 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004101
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004102 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004103}
4104
4105
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004106/*
4107 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004108
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004109 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004110
Laurence Lundblade93d89472020-10-03 22:30:50 -07004111 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4112 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004113
4114 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4115
Laurence Lundblade93d89472020-10-03 22:30:50 -07004116 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4117 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004118 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004119static QCBORError
4120Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004121{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004122 switch(pItem->uDataType) {
4123
4124 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004125 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004126 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004127 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004128 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004129 }
4130 break;
4131
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004132 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004133 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004134 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004135 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004136 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004137 }
4138 break;
4139
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004140#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4141 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004142 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004143 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004144 pItem->val.expAndMantissa.nExponent,
4145 pnValue,
4146 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004147 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004148 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004149 }
4150 break;
4151
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004152 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004153 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004154 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004155 pItem->val.expAndMantissa.nExponent,
4156 pnValue,
4157 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004158 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004159 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004160 }
4161 break;
4162
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004163 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004164 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004165 int64_t nMantissa;
4166 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004167 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4168 if(uErr) {
4169 return uErr;
4170 }
4171 return ExponentiateNN(nMantissa,
4172 pItem->val.expAndMantissa.nExponent,
4173 pnValue,
4174 Exponentitate10);
4175 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004176 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004177 }
4178 break;
4179
4180 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004181 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004182 int64_t nMantissa;
4183 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004184 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4185 if(uErr) {
4186 return uErr;
4187 }
4188 return ExponentiateNN(nMantissa,
4189 pItem->val.expAndMantissa.nExponent,
4190 pnValue,
4191 Exponentitate10);
4192 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004193 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004194 }
4195 break;
4196
4197 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004198 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004199 int64_t nMantissa;
4200 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004201 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4202 if(uErr) {
4203 return uErr;
4204 }
4205 return ExponentiateNN(nMantissa,
4206 pItem->val.expAndMantissa.nExponent,
4207 pnValue,
4208 Exponentitate2);
4209 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004210 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004211 }
4212 break;
4213
4214 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004215 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004216 int64_t nMantissa;
4217 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004218 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4219 if(uErr) {
4220 return uErr;
4221 }
4222 return ExponentiateNN(nMantissa,
4223 pItem->val.expAndMantissa.nExponent,
4224 pnValue,
4225 Exponentitate2);
4226 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004227 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004228 }
4229 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004230#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4231
Laurence Lundbladee6430642020-03-14 21:15:44 -07004232
Laurence Lundbladec4537442020-04-14 18:53:22 -07004233 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004234 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004235}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004236
4237
Laurence Lundbladec4537442020-04-14 18:53:22 -07004238/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004239 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004240 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004241void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004242{
4243 QCBORItem Item;
4244
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004245 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004246
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004247 if(pMe->uLastError == QCBOR_SUCCESS) {
4248 // The above conversion succeeded
4249 return;
4250 }
4251
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004252 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004253 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004254 return;
4255 }
4256
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004257 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004258}
4259
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004260
4261/*
4262Public function, see header qcbor/qcbor_decode.h file
4263*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004264void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4265 int64_t nLabel,
4266 uint32_t uConvertTypes,
4267 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004268{
4269 QCBORItem Item;
4270
Laurence Lundblade93d89472020-10-03 22:30:50 -07004271 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4272 nLabel,
4273 uConvertTypes,
4274 pnValue,
4275 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004276
4277 if(pMe->uLastError == QCBOR_SUCCESS) {
4278 // The above conversion succeeded
4279 return;
4280 }
4281
4282 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4283 // The above conversion failed in a way that code below can't correct
4284 return;
4285 }
4286
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004287 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004288}
4289
4290
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004291/*
4292Public function, see header qcbor/qcbor_decode.h file
4293*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004294void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4295 const char *szLabel,
4296 uint32_t uConvertTypes,
4297 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004298{
4299 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004300 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4301 szLabel,
4302 uConvertTypes,
4303 pnValue,
4304 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004305
4306 if(pMe->uLastError == QCBOR_SUCCESS) {
4307 // The above conversion succeeded
4308 return;
4309 }
4310
4311 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4312 // The above conversion failed in a way that code below can't correct
4313 return;
4314 }
4315
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004316 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004317}
4318
4319
Laurence Lundblade93d89472020-10-03 22:30:50 -07004320static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004321{
4322 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004323 case QCBOR_TYPE_DOUBLE:
4324 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004325#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004326 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004327 // Can't use llround here because it will not convert values
4328 // greater than INT64_MAX and less than UINT64_MAX that
4329 // need to be converted so it is more complicated.
4330 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4331 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4332 if(isnan(pItem->val.dfnum)) {
4333 return QCBOR_ERR_FLOAT_EXCEPTION;
4334 } else if(pItem->val.dfnum < 0) {
4335 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4336 } else {
4337 double dRounded = round(pItem->val.dfnum);
4338 // See discussion in DecodeDateEpoch() for
4339 // explanation of - 0x7ff
4340 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4341 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4342 }
4343 *puValue = (uint64_t)dRounded;
4344 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004345 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004346 if(isnan(pItem->val.fnum)) {
4347 return QCBOR_ERR_FLOAT_EXCEPTION;
4348 } else if(pItem->val.fnum < 0) {
4349 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4350 } else {
4351 float fRounded = roundf(pItem->val.fnum);
4352 // See discussion in DecodeDateEpoch() for
4353 // explanation of - 0x7ff
4354 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4355 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4356 }
4357 *puValue = (uint64_t)fRounded;
4358 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004359 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004360 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4361 // round() and roundf() shouldn't result in exceptions here, but
4362 // catch them to be robust and thorough. Don't try to
4363 // distinguish between the various exceptions because it seems
4364 // they vary by CPU, compiler and OS.
4365 return QCBOR_ERR_FLOAT_EXCEPTION;
4366 }
4367
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004368 } else {
4369 return QCBOR_ERR_UNEXPECTED_TYPE;
4370 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004371#else
4372 return QCBOR_ERR_HW_FLOAT_DISABLED;
4373#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004374 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004375
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004376 case QCBOR_TYPE_INT64:
4377 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4378 if(pItem->val.int64 >= 0) {
4379 *puValue = (uint64_t)pItem->val.int64;
4380 } else {
4381 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4382 }
4383 } else {
4384 return QCBOR_ERR_UNEXPECTED_TYPE;
4385 }
4386 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004387
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004388 case QCBOR_TYPE_UINT64:
4389 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4390 *puValue = pItem->val.uint64;
4391 } else {
4392 return QCBOR_ERR_UNEXPECTED_TYPE;
4393 }
4394 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004395
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004396 default:
4397 return QCBOR_ERR_UNEXPECTED_TYPE;
4398 }
4399
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004400 return QCBOR_SUCCESS;
4401}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004402
4403
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004404void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004405 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004406 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004407 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004408{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004409 if(pMe->uLastError != QCBOR_SUCCESS) {
4410 return;
4411 }
4412
Laurence Lundbladec4537442020-04-14 18:53:22 -07004413 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004414
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004415 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4416 if(uError) {
4417 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004418 return;
4419 }
4420
Laurence Lundbladea826c502020-05-10 21:07:00 -07004421 if(pItem) {
4422 *pItem = Item;
4423 }
4424
Laurence Lundblade93d89472020-10-03 22:30:50 -07004425 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004426}
4427
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004428
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004429void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004430 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004431 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004432 uint64_t *puValue,
4433 QCBORItem *pItem)
4434{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004435 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004436 if(pMe->uLastError != QCBOR_SUCCESS) {
4437 return;
4438 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004439
Laurence Lundblade93d89472020-10-03 22:30:50 -07004440 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004441}
4442
4443
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004444void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004445 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004446 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004447 uint64_t *puValue,
4448 QCBORItem *pItem)
4449{
4450 if(pMe->uLastError != QCBOR_SUCCESS) {
4451 return;
4452 }
4453
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004454 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004455 if(pMe->uLastError != QCBOR_SUCCESS) {
4456 return;
4457 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004458
Laurence Lundblade93d89472020-10-03 22:30:50 -07004459 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004460}
4461
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004462
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004463
Laurence Lundblade93d89472020-10-03 22:30:50 -07004464static QCBORError
4465UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004466{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004467 switch(pItem->uDataType) {
4468
4469 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004470 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004471 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4472 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004473 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004474 }
4475 break;
4476
4477 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004478 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004479 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4480 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004481 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004482 }
4483 break;
4484
4485#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4486
4487 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004488 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004489 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004490 pItem->val.expAndMantissa.nExponent,
4491 puValue,
4492 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004493 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004494 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004495 }
4496 break;
4497
4498 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004499 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004500 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4501 pItem->val.expAndMantissa.nExponent,
4502 puValue,
4503 Exponentitate2);
4504 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004505 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004506 }
4507 break;
4508
4509 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004510 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004511 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004512 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004513 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004514 if(uErr != QCBOR_SUCCESS) {
4515 return uErr;
4516 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004517 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004518 pItem->val.expAndMantissa.nExponent,
4519 puValue,
4520 Exponentitate10);
4521 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004522 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004523 }
4524 break;
4525
4526 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004527 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004528 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4529 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004530 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004531 }
4532 break;
4533
4534 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004535 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004536 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004537 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004538 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004539 if(uErr != QCBOR_SUCCESS) {
4540 return uErr;
4541 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004542 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004543 pItem->val.expAndMantissa.nExponent,
4544 puValue,
4545 Exponentitate2);
4546 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004547 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004548 }
4549 break;
4550
4551 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004552 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004553 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4554 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004555 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004556 }
4557 break;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004558#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004559 default:
4560 return QCBOR_ERR_UNEXPECTED_TYPE;
4561 }
4562}
4563
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004564
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004565/*
4566 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004567 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004568void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004569{
4570 QCBORItem Item;
4571
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004572 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004573
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004574 if(pMe->uLastError == QCBOR_SUCCESS) {
4575 // The above conversion succeeded
4576 return;
4577 }
4578
4579 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4580 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004581 return;
4582 }
4583
Laurence Lundblade93d89472020-10-03 22:30:50 -07004584 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004585}
4586
Laurence Lundbladec4537442020-04-14 18:53:22 -07004587
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004588/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004589 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004590*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004591void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004592 int64_t nLabel,
4593 uint32_t uConvertTypes,
4594 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004595{
4596 QCBORItem Item;
4597
Laurence Lundblade93d89472020-10-03 22:30:50 -07004598 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4599 nLabel,
4600 uConvertTypes,
4601 puValue,
4602 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004603
4604 if(pMe->uLastError == QCBOR_SUCCESS) {
4605 // The above conversion succeeded
4606 return;
4607 }
4608
4609 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4610 // The above conversion failed in a way that code below can't correct
4611 return;
4612 }
4613
Laurence Lundblade93d89472020-10-03 22:30:50 -07004614 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004615}
4616
4617
4618/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004619 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004620*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004621void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004622 const char *szLabel,
4623 uint32_t uConvertTypes,
4624 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004625{
4626 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004627 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4628 szLabel,
4629 uConvertTypes,
4630 puValue,
4631 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004632
4633 if(pMe->uLastError == QCBOR_SUCCESS) {
4634 // The above conversion succeeded
4635 return;
4636 }
4637
4638 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4639 // The above conversion failed in a way that code below can't correct
4640 return;
4641 }
4642
Laurence Lundblade93d89472020-10-03 22:30:50 -07004643 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004644}
4645
4646
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004647
4648
Laurence Lundblade9b334962020-08-27 10:55:53 -07004649static QCBORError ConvertDouble(const QCBORItem *pItem,
4650 uint32_t uConvertTypes,
4651 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004652{
4653 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004654 case QCBOR_TYPE_FLOAT:
4655#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4656 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4657 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004658 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004659 *pdValue = (double)pItem->val.fnum;
4660 } else {
4661 return QCBOR_ERR_UNEXPECTED_TYPE;
4662 }
4663 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004664#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004665 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08004666#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004667 break;
4668
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004669 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004670 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4671 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004672 *pdValue = pItem->val.dfnum;
4673 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004674 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004675 }
4676 }
4677 break;
4678
4679 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004680#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004681 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004682 // A simple cast seems to do the job with no worry of exceptions.
4683 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004684 *pdValue = (double)pItem->val.int64;
4685
4686 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004687 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004688 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004689#else
4690 return QCBOR_ERR_HW_FLOAT_DISABLED;
4691#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004692 break;
4693
4694 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004695#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004696 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004697 // A simple cast seems to do the job with no worry of exceptions.
4698 // There will be precision loss for some values.
4699 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004700 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004701 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004702 }
4703 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004704#else
4705 return QCBOR_ERR_HW_FLOAT_DISABLED;
4706#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004707
4708 default:
4709 return QCBOR_ERR_UNEXPECTED_TYPE;
4710 }
4711
4712 return QCBOR_SUCCESS;
4713}
4714
4715
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004716void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004717 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004718 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004719 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004720{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004721 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004722 return;
4723 }
4724
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004725 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004726
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004727 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004728 if(uError) {
4729 pMe->uLastError = (uint8_t)uError;
4730 return;
4731 }
4732
4733 if(pItem) {
4734 *pItem = Item;
4735 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004736
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004737 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004738}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004739
Laurence Lundbladec4537442020-04-14 18:53:22 -07004740
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004741void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4742 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004743 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004744 double *pdValue,
4745 QCBORItem *pItem)
4746{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004747 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004748 if(pMe->uLastError != QCBOR_SUCCESS) {
4749 return;
4750 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004751
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004752 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004753}
4754
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004755
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004756void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4757 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004758 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004759 double *pdValue,
4760 QCBORItem *pItem)
4761{
4762 if(pMe->uLastError != QCBOR_SUCCESS) {
4763 return;
4764 }
4765
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004766 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004767 if(pMe->uLastError != QCBOR_SUCCESS) {
4768 return;
4769 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004770
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004771 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004772}
4773
4774
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004775#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004776static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4777{
4778 double dResult;
4779
4780 dResult = 0.0;
4781 const uint8_t *pByte = BigNum.ptr;
4782 size_t uLen = BigNum.len;
4783 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004784 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004785 while(uLen--) {
4786 dResult = (dResult * 256.0) + (double)*pByte++;
4787 }
4788
4789 return dResult;
4790}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004791#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4792
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004793
Laurence Lundblade93d89472020-10-03 22:30:50 -07004794static QCBORError
4795DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004796{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004797#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004798 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004799 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4800
4801 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004802 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004803
4804#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004805 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004806 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004807 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004808 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4809 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4810 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004811 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004812 }
4813 break;
4814
4815 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004816 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004817 // Underflow gives 0, overflow gives infinity
4818 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4819 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004820 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004821 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004822 }
4823 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004824#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004825
4826 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004827 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004828 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4829 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004830 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004831 }
4832 break;
4833
4834 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004835 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004836 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004837 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004838 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004839 }
4840 break;
4841
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004842#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004843 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004844 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004845 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4846 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4847 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004848 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004849 }
4850 break;
4851
4852 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004853 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004854 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4855 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4856 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004857 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004858 }
4859 break;
4860
4861 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004862 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004863 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4864 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4865 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004866 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004867 }
4868 break;
4869
4870 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004871 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004872 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004873 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4874 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004875 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004876 }
4877 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004878#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4879
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004880 default:
4881 return QCBOR_ERR_UNEXPECTED_TYPE;
4882 }
4883
4884 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004885
4886#else
4887 (void)pItem;
4888 (void)uConvertTypes;
4889 (void)pdValue;
4890 return QCBOR_ERR_HW_FLOAT_DISABLED;
4891#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4892
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004893}
4894
4895
4896/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004897 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004898*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004899void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4900 uint32_t uConvertTypes,
4901 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004902{
4903
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004904 QCBORItem Item;
4905
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004906 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004907
4908 if(pMe->uLastError == QCBOR_SUCCESS) {
4909 // The above conversion succeeded
4910 return;
4911 }
4912
4913 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4914 // The above conversion failed in a way that code below can't correct
4915 return;
4916 }
4917
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004918 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004919}
4920
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004921
4922/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004923 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004924*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004925void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4926 int64_t nLabel,
4927 uint32_t uConvertTypes,
4928 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004929{
4930 QCBORItem Item;
4931
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004932 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004933
4934 if(pMe->uLastError == QCBOR_SUCCESS) {
4935 // The above conversion succeeded
4936 return;
4937 }
4938
4939 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4940 // The above conversion failed in a way that code below can't correct
4941 return;
4942 }
4943
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004944 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004945}
4946
4947
4948/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004949 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004950*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004951void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4952 const char *szLabel,
4953 uint32_t uConvertTypes,
4954 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004955{
4956 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004957 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004958
4959 if(pMe->uLastError == QCBOR_SUCCESS) {
4960 // The above conversion succeeded
4961 return;
4962 }
4963
4964 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4965 // The above conversion failed in a way that code below can't correct
4966 return;
4967 }
4968
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004969 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004970}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004971
4972
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004973
4974
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004975#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004976static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4977{
4978 while((uInt & 0xff00000000000000UL) == 0) {
4979 uInt = uInt << 8;
4980 };
4981
4982 UsefulOutBuf UOB;
4983
4984 UsefulOutBuf_Init(&UOB, Buffer);
4985
4986 while(uInt) {
4987 const uint64_t xx = uInt & 0xff00000000000000UL;
4988 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4989 uInt = uInt << 8;
4990 (void)xx;
4991 }
4992
4993 return UsefulOutBuf_OutUBuf(&UOB);
4994}
4995
4996
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004997static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4998 TagSpecification TagSpec,
4999 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005000{
5001 QCBORError uErr;
5002 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005003 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005004 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005005 if(uErr != QCBOR_SUCCESS) {
5006 goto Done;
5007 }
5008
5009 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5010 break; // Successful exit. Moving on to finish decoding.
5011 }
5012
5013 // The item is an array, which means an undecoded
5014 // mantissa and exponent, so decode it. It will then
5015 // have a different type and exit the loop if.
5016 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5017 if(uErr != QCBOR_SUCCESS) {
5018 goto Done;
5019 }
5020
5021 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005022 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005023 }
5024Done:
5025 return uErr;
5026}
5027
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005028
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005029static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005030 TagSpecification TagSpec,
5031 QCBORItem *pItem,
5032 int64_t *pnMantissa,
5033 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005034{
5035 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005036
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005037 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005038 if(uErr != QCBOR_SUCCESS) {
5039 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005040 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005041
Laurence Lundblade9b334962020-08-27 10:55:53 -07005042 switch (pItem->uDataType) {
5043
5044 case QCBOR_TYPE_DECIMAL_FRACTION:
5045 case QCBOR_TYPE_BIGFLOAT:
5046 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5047 *pnExponent = pItem->val.expAndMantissa.nExponent;
5048 break;
5049
5050 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5051 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5052 *pnExponent = pItem->val.expAndMantissa.nExponent;
5053 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5054 break;
5055
5056 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5057 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5058 *pnExponent = pItem->val.expAndMantissa.nExponent;
5059 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5060 break;
5061
5062 default:
5063 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5064 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005065
5066 Done:
5067 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005068}
5069
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005070
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005071static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005072 TagSpecification TagSpec,
5073 QCBORItem *pItem,
5074 UsefulBuf BufferForMantissa,
5075 UsefulBufC *pMantissa,
5076 bool *pbIsNegative,
5077 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005078{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005079 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005080
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005081 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005082 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005083 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005084 }
5085
5086 uint64_t uMantissa;
5087
5088 switch (pItem->uDataType) {
5089
5090 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005091 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005092 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5093 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5094 *pbIsNegative = false;
5095 } else {
5096 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5097 *pbIsNegative = true;
5098 }
5099 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5100 *pnExponent = pItem->val.expAndMantissa.nExponent;
5101 break;
5102
5103 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005104 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005105 *pnExponent = pItem->val.expAndMantissa.nExponent;
5106 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5107 *pbIsNegative = false;
5108 break;
5109
5110 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005111 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005112 *pnExponent = pItem->val.expAndMantissa.nExponent;
5113 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5114 *pbIsNegative = true;
5115 break;
5116
5117 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005118 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005119 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005120
5121Done:
5122 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005123}
5124
5125
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005126/*
5127 Public function, see header qcbor/qcbor_decode.h file
5128*/
5129void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5130 uint8_t uTagRequirement,
5131 int64_t *pnMantissa,
5132 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005133{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005134 if(pMe->uLastError != QCBOR_SUCCESS) {
5135 return;
5136 }
5137
5138 QCBORItem Item;
5139 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5140 if(uError) {
5141 pMe->uLastError = (uint8_t)uError;
5142 return;
5143 }
5144
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005145 const TagSpecification TagSpec =
5146 {
5147 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005148 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5149 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5150 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005151 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005152
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005153 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005154}
5155
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005156
5157/*
5158 Public function, see header qcbor/qcbor_decode.h file
5159*/
5160void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005161 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005162 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005163 int64_t *pnMantissa,
5164 int64_t *pnExponent)
5165{
5166 if(pMe->uLastError != QCBOR_SUCCESS) {
5167 return;
5168 }
5169
5170 QCBORItem Item;
5171 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5172
5173 const TagSpecification TagSpec =
5174 {
5175 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005176 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5177 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5178 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005179 };
5180
5181 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5182}
5183
5184
5185/*
5186 Public function, see header qcbor/qcbor_decode.h file
5187*/
5188void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005189 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005190 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005191 int64_t *pnMantissa,
5192 int64_t *pnExponent)
5193{
5194 if(pMe->uLastError != QCBOR_SUCCESS) {
5195 return;
5196 }
5197
5198 QCBORItem Item;
5199 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5200
5201 const TagSpecification TagSpec =
5202 {
5203 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005204 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5205 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5206 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005207 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005208
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005209 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5210}
5211
5212
5213/*
5214 Public function, see header qcbor/qcbor_decode.h file
5215*/
5216void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5217 uint8_t uTagRequirement,
5218 UsefulBuf MantissaBuffer,
5219 UsefulBufC *pMantissa,
5220 bool *pbMantissaIsNegative,
5221 int64_t *pnExponent)
5222{
5223 if(pMe->uLastError != QCBOR_SUCCESS) {
5224 return;
5225 }
5226
5227 QCBORItem Item;
5228 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5229 if(uError) {
5230 pMe->uLastError = (uint8_t)uError;
5231 return;
5232 }
5233
5234 const TagSpecification TagSpec =
5235 {
5236 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005237 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5238 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5239 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005240 };
5241
Laurence Lundblade93d89472020-10-03 22:30:50 -07005242 ProcessMantissaAndExponentBig(pMe,
5243 TagSpec,
5244 &Item,
5245 MantissaBuffer,
5246 pMantissa,
5247 pbMantissaIsNegative,
5248 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005249}
5250
5251
5252/*
5253 Public function, see header qcbor/qcbor_decode.h file
5254*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005255void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005256 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005257 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005258 UsefulBuf BufferForMantissa,
5259 UsefulBufC *pMantissa,
5260 bool *pbIsNegative,
5261 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005262{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005263 if(pMe->uLastError != QCBOR_SUCCESS) {
5264 return;
5265 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005266
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005267 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005268 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005269 if(pMe->uLastError != QCBOR_SUCCESS) {
5270 return;
5271 }
5272
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005273 const TagSpecification TagSpec =
5274 {
5275 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005276 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5277 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5278 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005279 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005280
Laurence Lundblade93d89472020-10-03 22:30:50 -07005281 ProcessMantissaAndExponentBig(pMe,
5282 TagSpec,
5283 &Item,
5284 BufferForMantissa,
5285 pMantissa,
5286 pbIsNegative,
5287 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005288}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005289
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005290
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005291/*
5292 Public function, see header qcbor/qcbor_decode.h file
5293*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005294void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005295 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005296 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005297 UsefulBuf BufferForMantissa,
5298 UsefulBufC *pMantissa,
5299 bool *pbIsNegative,
5300 int64_t *pnExponent)
5301{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005302 if(pMe->uLastError != QCBOR_SUCCESS) {
5303 return;
5304 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005305
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005306 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005307 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5308 if(pMe->uLastError != QCBOR_SUCCESS) {
5309 return;
5310 }
5311
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005312 const TagSpecification TagSpec =
5313 {
5314 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005315 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5316 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5317 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005318 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005319
5320 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5321}
5322
5323
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005324/*
5325 Public function, see header qcbor/qcbor_decode.h file
5326*/
5327void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5328 uint8_t uTagRequirement,
5329 int64_t *pnMantissa,
5330 int64_t *pnExponent)
5331{
5332 if(pMe->uLastError != QCBOR_SUCCESS) {
5333 return;
5334 }
5335
5336 QCBORItem Item;
5337 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5338 if(uError) {
5339 pMe->uLastError = (uint8_t)uError;
5340 return;
5341 }
5342 const TagSpecification TagSpec =
5343 {
5344 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005345 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5346 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5347 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005348 };
5349
5350 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5351}
5352
5353
5354/*
5355 Public function, see header qcbor/qcbor_decode.h file
5356*/
5357void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005358 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005359 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005360 int64_t *pnMantissa,
5361 int64_t *pnExponent)
5362{
5363 if(pMe->uLastError != QCBOR_SUCCESS) {
5364 return;
5365 }
5366
5367 QCBORItem Item;
5368 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5369 if(pMe->uLastError != QCBOR_SUCCESS) {
5370 return;
5371 }
5372
5373 const TagSpecification TagSpec =
5374 {
5375 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005376 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5377 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5378 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005379 };
5380
5381 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5382}
5383
5384
5385/*
5386 Public function, see header qcbor/qcbor_decode.h file
5387*/
5388void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005389 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005390 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005391 int64_t *pnMantissa,
5392 int64_t *pnExponent)
5393{
5394 if(pMe->uLastError != QCBOR_SUCCESS) {
5395 return;
5396 }
5397
5398 QCBORItem Item;
5399 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5400 if(pMe->uLastError != QCBOR_SUCCESS) {
5401 return;
5402 }
5403
5404 const TagSpecification TagSpec =
5405 {
5406 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005407 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5408 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5409 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005410 };
5411
5412 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5413}
5414
5415
5416/*
5417 Public function, see header qcbor/qcbor_decode.h file
5418*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005419void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5420 uint8_t uTagRequirement,
5421 UsefulBuf MantissaBuffer,
5422 UsefulBufC *pMantissa,
5423 bool *pbMantissaIsNegative,
5424 int64_t *pnExponent)
5425{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005426 if(pMe->uLastError != QCBOR_SUCCESS) {
5427 return;
5428 }
5429
5430 QCBORItem Item;
5431 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5432 if(uError) {
5433 pMe->uLastError = (uint8_t)uError;
5434 return;
5435 }
5436
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005437 const TagSpecification TagSpec =
5438 {
5439 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005440 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5441 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5442 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005443 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005444
5445 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005446}
5447
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005448
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005449/*
5450 Public function, see header qcbor/qcbor_decode.h file
5451*/
5452void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005453 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005454 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005455 UsefulBuf BufferForMantissa,
5456 UsefulBufC *pMantissa,
5457 bool *pbIsNegative,
5458 int64_t *pnExponent)
5459{
5460 if(pMe->uLastError != QCBOR_SUCCESS) {
5461 return;
5462 }
5463
5464 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005465 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5466 if(pMe->uLastError != QCBOR_SUCCESS) {
5467 return;
5468 }
5469
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005470 const TagSpecification TagSpec =
5471 {
5472 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005473 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5474 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5475 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005476 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005477
Laurence Lundblade93d89472020-10-03 22:30:50 -07005478 ProcessMantissaAndExponentBig(pMe,
5479 TagSpec,
5480 &Item,
5481 BufferForMantissa,
5482 pMantissa,
5483 pbIsNegative,
5484 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005485}
5486
5487
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005488/*
5489 Public function, see header qcbor/qcbor_decode.h file
5490*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005491void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005492 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005493 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005494 UsefulBuf BufferForMantissa,
5495 UsefulBufC *pMantissa,
5496 bool *pbIsNegative,
5497 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005498{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005499 if(pMe->uLastError != QCBOR_SUCCESS) {
5500 return;
5501 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005502
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005503 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005504 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5505 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005506 return;
5507 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005508
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005509 const TagSpecification TagSpec =
5510 {
5511 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005512 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5513 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5514 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005515 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005516
Laurence Lundblade93d89472020-10-03 22:30:50 -07005517 ProcessMantissaAndExponentBig(pMe,
5518 TagSpec,
5519 &Item,
5520 BufferForMantissa,
5521 pMantissa,
5522 pbIsNegative,
5523 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005524}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005525
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005526#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */