blob: 9650e6add100a2b9e93d1891ec21d6eb7076f1ae [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 Lundbladec7114722020-08-13 05:11:40 -070042#endif
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{
79 if(!QCBORItem_IsMapOrArray(pMe)){
80 return false;
81 }
82
83 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
84 return false;
85 }
86 return true;
87}
88
89
Laurence Lundbladeee851742020-01-08 08:37:05 -080090/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070091 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080092 ===========================================================================*/
93
Laurence Lundblade9c905e82020-04-25 11:31:38 -070094/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070095 See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
Laurence Lundblade93d89472020-10-03 22:30:50 -070096 the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -070097 */
98
Laurence Lundblade24d509a2020-06-06 18:43:15 -070099
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700100static inline uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700101DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700102{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700103 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700104 /*
105 Limit in DecodeNesting_Descend against more than
106 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
107 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700108 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700109}
110
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700111
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700112static inline uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700113DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700114{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700115 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700116 /*
117 Limit in DecodeNesting_Descend against more than
118 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
119 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700120 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700121}
122
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700123
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700124static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700125DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700126{
127 return pNesting->pCurrentBounded->u.ma.uStartOffset;
128}
129
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700130
Laurence Lundblade085d7952020-07-24 10:26:30 -0700131static inline bool
132DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
133{
134 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
135 return true;
136 } else {
137 return false;
138 }
139}
140
141
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700142static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700143DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700144{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700145 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700146 return true;
147 } else {
148 return false;
149 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700150}
151
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700152
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700153static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700154DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700155{
156 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700157 // Not a map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700158 return false;
159 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700160 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700161 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700162 return false;
163 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700164 // All checks passed; is a definte length map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700165 return true;
166}
167
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700168
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700169static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700170DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700171{
172 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700173 // is a byte string
Laurence Lundblade642282a2020-06-23 12:00:33 -0700174 return true;
175 }
176 return false;
177}
178
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700179
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700180static inline bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700181{
182 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
183 return true;
184 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700185 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700186 return true;
187 }
188 return false;
189}
190
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700191
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700192static inline void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700193{
194 // Should be only called on maps and arrays
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700195 /*
196 DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
197 larger than DecodeNesting_EnterBoundedMode which keeps it less than
198 uin32_t so the cast is safe.
199 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700200 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700201
202 if(bIsEmpty) {
203 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
204 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700205}
206
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700207
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700208static inline void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700209{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700210 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700211}
212
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700213
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700214static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700215DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700216{
217 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700218 // No bounded map or array set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700219 return false;
220 }
221 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700222 // Not a map or array; end of those is by byte count
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700223 return false;
224 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700225 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
226 // In a traveral at a level deeper than the bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700227 return false;
228 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700229 // Works for both definite and indefinite length maps/arrays
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800230 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
231 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700232 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700233 return false;
234 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700235 // All checks passed, got to the end of an array or map
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700236 return true;
237}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700238
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700239
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700240static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700241DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700242{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700243 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700244 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
245 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700246 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700247 return false;
248 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700249}
250
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700251
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700252static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700253DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700254{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700255 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
256 return true;
257 } else {
258 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700259 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700260}
261
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700262
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700263static inline bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700264DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700265{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700266 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700267 return false;
268 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700269
270 if(pNesting->pCurrentBounded->uLevelType != uType) {
271 return false;
272 }
273
274 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700275}
276
Laurence Lundblade02625d42020-06-25 14:41:41 -0700277
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700278static inline void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700279DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700280{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700281 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700282 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700283}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700284
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700285
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700286static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700287DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
288{
289 // Only call on a defnite length array / map
290 pNesting->pCurrent->u.ma.uCountCursor++;
291}
292
293
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700294static inline void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700295DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
296{
297 pNesting->pCurrent--;
298}
299
Laurence Lundblade02625d42020-06-25 14:41:41 -0700300
301static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700302DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700303{
304 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700305 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700306 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700307 }
308
309 // The actual descend
310 pNesting->pCurrent++;
311
312 pNesting->pCurrent->uLevelType = uType;
313
314 return QCBOR_SUCCESS;
315}
316
317
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700318static inline QCBORError
Laurence Lundblade085d7952020-07-24 10:26:30 -0700319DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700320{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700321 /*
322 Should only be called on map/array.
323
324 Have descended into this before this is called. The job here is
325 just to mark it in bounded mode.
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700326
327 Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
328 uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800329
330 Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700331 */
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800332 if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700333 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700334 }
335
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700336 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700337
338 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700339
340 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700341}
342
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700343
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700344static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700345DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700346 uint8_t uQCBORType,
347 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700348{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700349 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700350
351 if(uCount == 0) {
352 // Nothing to do for empty definite lenth arrays. They are just are
353 // effectively the same as an item that is not a map or array
354 goto Done;
355 // Empty indefinite length maps and arrays are handled elsewhere
356 }
357
358 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700359 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
360 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700361 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700362 goto Done;
363 }
364
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700365 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700366 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700367 goto Done;
368 }
369
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700370 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700371 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
372 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700373
374 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700375
376Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700377 return uError;;
378}
379
380
381static inline void
382DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
383{
384 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
385}
386
387
388static inline void
389DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
390{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700391 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700392 pNesting->pCurrentBounded--;
393 if(DecodeNesting_IsCurrentBounded(pNesting)) {
394 break;
395 }
396 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700397}
398
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700399static inline void
400DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
401{
402 pNesting->pCurrent = pNesting->pCurrentBounded;
403}
404
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700405
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700406static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700407DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700408 uint32_t uEndOffset,
409 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700410{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700411 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700412
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700413 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700414 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700415 goto Done;
416 }
417
Laurence Lundblade02625d42020-06-25 14:41:41 -0700418 // Fill in the new byte string level
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700419 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
420 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700421
Laurence Lundblade02625d42020-06-25 14:41:41 -0700422 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700423 pNesting->pCurrentBounded = pNesting->pCurrent;
424
425Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700426 return uError;;
427}
428
Laurence Lundbladed0304932020-06-27 10:59:38 -0700429
430static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700431DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700432{
433 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700434}
435
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700436
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700437static inline void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800438DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
439{
440 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
441}
442
443
444static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700445DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700446{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700447 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700448 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
449 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700450}
451
452
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700453static inline void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700454DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700455{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700456 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700457 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800458 DecodeNesting_ResetMapOrArrayCount(pNesting);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700459}
460
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700461
Laurence Lundblade02625d42020-06-25 14:41:41 -0700462static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700463DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700464{
465 *pNesting = *pSave;
466}
467
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700468
Laurence Lundblade02625d42020-06-25 14:41:41 -0700469static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700470DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700471{
472 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
473}
474
475
Laurence Lundblade02625d42020-06-25 14:41:41 -0700476static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700477DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700478{
479 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
480}
481
482
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800483#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800484/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800485 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
486
487 The following four functions are pretty wrappers for invocation of
488 the string allocator supplied by the caller.
489
Laurence Lundbladeee851742020-01-08 08:37:05 -0800490 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800491
Laurence Lundbladeee851742020-01-08 08:37:05 -0800492static inline void
493StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800494{
495 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
496}
497
Laurence Lundbladeee851742020-01-08 08:37:05 -0800498// StringAllocator_Reallocate called with pMem NULL is
499// equal to StringAllocator_Allocate()
500static inline UsefulBuf
501StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
502 void *pMem,
503 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800504{
505 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
506}
507
Laurence Lundbladeee851742020-01-08 08:37:05 -0800508static inline UsefulBuf
509StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800510{
511 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
512}
513
Laurence Lundbladeee851742020-01-08 08:37:05 -0800514static inline void
515StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800516{
517 if(pMe->pfAllocator) {
518 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
519 }
520}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800521#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800522
523
Laurence Lundbladeee851742020-01-08 08:37:05 -0800524/*===========================================================================
525 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700526
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800527 See qcbor/qcbor_decode.h for definition of the object
528 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800529 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700530/*
531 Public function, see header file
532 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800533void QCBORDecode_Init(QCBORDecodeContext *me,
534 UsefulBufC EncodedCBOR,
535 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700536{
537 memset(me, 0, sizeof(QCBORDecodeContext));
538 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800539 // Don't bother with error check on decode mode. If a bad value is
540 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700541 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700542 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700543 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700544 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700545 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700546}
547
548
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800549#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
550
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700551/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700552 Public function, see header file
553 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800554void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
555 QCBORStringAllocate pfAllocateFunction,
556 void *pAllocateContext,
557 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700558{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800559 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
560 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
561 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700562}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800563#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700564
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800565
566/*
567 Public function, see header file
568 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700569void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800570 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700571{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700572 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700573 (void)pMe;
574 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700575}
576
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700577
578/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800579 This decodes the fundamental part of a CBOR data item, the type and
580 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800581
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700582 This is the counterpart to QCBOREncode_EncodeHead().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800583
Laurence Lundbladeee851742020-01-08 08:37:05 -0800584 This does the network->host byte order conversion. The conversion
585 here also results in the conversion for floats in addition to that
586 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800587
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700588 This returns:
589 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800590
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800591 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800592 tags and floats and length for strings and arrays
593
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800594 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800595 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800596
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800597 The int type is preferred to uint8_t for some variables as this
598 avoids integer promotions, can reduce code size and makes
599 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700600
601 @retval QCBOR_ERR_UNSUPPORTED
602
603 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700604 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700605static inline QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800606 int *pnMajorType,
607 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800608 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700609{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700610 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800611
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700612 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800613 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800614
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700615 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800616 const int nTmpMajorType = nInitialByte >> 5;
617 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800618
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800619 // Where the number or argument accumulates
620 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800621
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800622 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700623 // Need to get 1,2,4 or 8 additional argument bytes. Map
624 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800625 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800626
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800627 // Loop getting all the bytes in the argument
628 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800629 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800630 // This shift and add gives the endian conversion
631 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
632 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800633 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800634 // The reserved and thus-far unused additional info values
635 nReturn = QCBOR_ERR_UNSUPPORTED;
636 goto Done;
637 } else {
638 // Less than 24, additional info is argument or 31, an indefinite length
639 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800640 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700641 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800642
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700643 if(UsefulInputBuf_GetError(pUInBuf)) {
644 nReturn = QCBOR_ERR_HIT_END;
645 goto Done;
646 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800647
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700648 // All successful if we got here.
649 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800650 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800651 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800652 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800653
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700654Done:
655 return nReturn;
656}
657
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800658
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700659/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800660 CBOR doesn't explicitly specify two's compliment for integers but all
661 CPUs use it these days and the test vectors in the RFC are so. All
662 integers in the CBOR structure are positive and the major type
663 indicates positive or negative. CBOR can express positive integers
664 up to 2^x - 1 where x is the number of bits and negative integers
665 down to 2^x. Note that negative numbers can be one more away from
666 zero than positive. Stdint, as far as I can tell, uses two's
667 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800668
Laurence Lundblade9b334962020-08-27 10:55:53 -0700669 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800670 used carefully here, and in particular why it isn't used in the interface.
671 Also see
672 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
673
674 Int is used for values that need less than 16-bits and would be subject
675 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700676
677 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700678 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700679static inline QCBORError
Laurence Lundbladeee851742020-01-08 08:37:05 -0800680DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700681{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700682 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800683
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700684 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
685 if (uNumber <= INT64_MAX) {
686 pDecodedItem->val.int64 = (int64_t)uNumber;
687 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800688
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700689 } else {
690 pDecodedItem->val.uint64 = uNumber;
691 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800692
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700693 }
694 } else {
695 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800696 // CBOR's representation of negative numbers lines up with the
697 // two-compliment representation. A negative integer has one
698 // more in range than a positive integer. INT64_MIN is
699 // equal to (-INT64_MAX) - 1.
700 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700701 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800702
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700703 } else {
704 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000705 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700706 nReturn = QCBOR_ERR_INT_OVERFLOW;
707 }
708 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800709
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700710 return nReturn;
711}
712
713// Make sure #define value line up as DecodeSimple counts on this.
714#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
715#error QCBOR_TYPE_FALSE macro value wrong
716#endif
717
718#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
719#error QCBOR_TYPE_TRUE macro value wrong
720#endif
721
722#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
723#error QCBOR_TYPE_NULL macro value wrong
724#endif
725
726#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
727#error QCBOR_TYPE_UNDEF macro value wrong
728#endif
729
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700730#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
731#error QCBOR_TYPE_BREAK macro value wrong
732#endif
733
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700734#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
735#error QCBOR_TYPE_DOUBLE macro value wrong
736#endif
737
738#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
739#error QCBOR_TYPE_FLOAT macro value wrong
740#endif
741
742/*
743 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700744
745 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
746
747 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700748 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700749static inline QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800750DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700751{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700752 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800753
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700754 // uAdditionalInfo is 5 bits from the initial byte. Compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800755 // above make sure uAdditionalInfo values line up with uDataType values.
Laurence Lundblade93d89472020-10-03 22:30:50 -0700756 // DecodeTypeAndNumber() never returns an AdditionalInfo > 0x1f so cast
757 // is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800758 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800759
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800760 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800761 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
762 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800763
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700764 case HALF_PREC_FLOAT: // 25
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700765#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700766 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700767 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700768 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700769 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
770 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700771#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700772 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700773#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700774 break;
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700775 case SINGLE_PREC_FLOAT: // 26
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700776 // Single precision is normally returned as a double
777 // since double is widely supported, there is no loss of
778 // precision, it makes it easy for the caller in
779 // most cases and it can be converted back to single
780 // with no loss of precision
781 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700782 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700783 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700784 {
785 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
786#ifndef QCBOR_DISABLE_FLOAT_HW_USE
787 // In the normal case, use HW to convert float to double.
788 pDecodedItem->val.dfnum = (double)f;
789 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700790#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700791 // Use of float HW is disabled, return as a float.
792 pDecodedItem->val.fnum = f;
793 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
794
795 // IEEE754_FloatToDouble() could be used here to return
796 // as a double, but it adds object code and most likely
797 // anyone disabling FLOAT HW use doesn't care about
798 // floats and wants to save object code.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700799#endif
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700800 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700801 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700802
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700803 case DOUBLE_PREC_FLOAT: // 27
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700804 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700805 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700806 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800807
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700808 case CBOR_SIMPLEV_FALSE: // 20
809 case CBOR_SIMPLEV_TRUE: // 21
810 case CBOR_SIMPLEV_NULL: // 22
811 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700812 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700813 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800814
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700815 case CBOR_SIMPLEV_ONEBYTE: // 24
816 if(uNumber <= CBOR_SIMPLE_BREAK) {
817 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700818 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700819 goto Done;
820 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800821 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700822 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800823
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700824 default: // 0-19
825 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800826 /*
827 DecodeTypeAndNumber will make uNumber equal to
828 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
829 safe because the 2, 4 and 8 byte lengths of uNumber are in
830 the double/float cases above
831 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700832 pDecodedItem->val.uSimple = (uint8_t)uNumber;
833 break;
834 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800835
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700836Done:
837 return nReturn;
838}
839
840
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700841/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530842 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700843
844 @retval QCBOR_ERR_HIT_END
845
846 @retval QCBOR_ERR_STRING_ALLOCATE
847
848 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700849 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700850static inline QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800851 uint64_t uStrLen,
852 UsefulInputBuf *pUInBuf,
853 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700854{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700855 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800856
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800857 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
858 // This check makes the casts to size_t below safe.
859
860 // 4 bytes less than the largest sizeof() so this can be tested by
861 // putting a SIZE_MAX length in the CBOR test input (no one will
862 // care the limit on strings is 4 bytes shorter).
863 if(uStrLen > SIZE_MAX-4) {
864 nReturn = QCBOR_ERR_STRING_TOO_LONG;
865 goto Done;
866 }
867
868 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530869 if(UsefulBuf_IsNULLC(Bytes)) {
870 // Failed to get the bytes for this string item
871 nReturn = QCBOR_ERR_HIT_END;
872 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700873 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530874
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800875#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800876 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530877 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800878 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530879 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700880 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530881 goto Done;
882 }
883 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800884 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800885 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530886 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800887#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
888 (void)pAllocator;
889#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
890
891 // Normal case with no string allocator
892 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800893
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530894Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700895 return nReturn;
896}
897
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700898
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800899/* Map the CBOR major types for strings to the QCBOR types for strngs */
900static inline uint8_t MapStringMajorTypes(int nCBORMajorType)
901{
902 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
903 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
904 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800905
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800906 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
907 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
908 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700909
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800910 return (uint8_t)(nCBORMajorType + 4);
911}
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700912
913
Laurence Lundbladeee851742020-01-08 08:37:05 -0800914// Make sure the constants align as this is assumed by
915// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700916#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
917#error QCBOR_TYPE_ARRAY value not lined up with major type
918#endif
919#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
920#error QCBOR_TYPE_MAP value not lined up with major type
921#endif
922
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700923/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800924 This gets a single data item and decodes it including preceding
925 optional tagging. This does not deal with arrays and maps and nesting
926 except to decode the data item introducing them. Arrays and maps are
927 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800928
Laurence Lundbladeee851742020-01-08 08:37:05 -0800929 Errors detected here include: an array that is too long to decode,
930 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700931
932 @retval QCBOR_ERR_UNSUPPORTED
933
934 @retval QCBOR_ERR_HIT_END
935
936 @retval QCBOR_ERR_INT_OVERFLOW
937
938 @retval QCBOR_ERR_STRING_ALLOCATE
939
940 @retval QCBOR_ERR_STRING_TOO_LONG
941
942 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
943
944 @retval QCBOR_ERR_BAD_TYPE_7
945
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700946 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800947static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
948 QCBORItem *pDecodedItem,
949 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700950{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700951 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800952
Laurence Lundbladeee851742020-01-08 08:37:05 -0800953 /*
954 Get the major type and the number. Number could be length of more
955 bytes or the value depending on the major type nAdditionalInfo is
956 an encoding of the length of the uNumber and is needed to decode
957 floats and doubles
958 */
Rob Gilton47cc9562020-08-10 12:03:38 +0100959 int nMajorType = 0;
960 uint64_t uNumber = 0;
961 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800962
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700963 memset(pDecodedItem, 0, sizeof(QCBORItem));
964
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800965 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800966
Laurence Lundbladeee851742020-01-08 08:37:05 -0800967 // Error out here if we got into trouble on the type and number. The
968 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700969 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700970 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700971 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800972
Laurence Lundbladeee851742020-01-08 08:37:05 -0800973 // At this point the major type and the value are valid. We've got
974 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800975 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700976 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
977 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800978 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700979 nReturn = QCBOR_ERR_BAD_INT;
980 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800981 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700982 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700983 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800984
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700985 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
986 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800987 pDecodedItem->uDataType = MapStringMajorTypes(nMajorType);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800988 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800989 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700990 } else {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800991 nReturn = DecodeBytes(pAllocator, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700992 }
993 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800994
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700995 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
996 case CBOR_MAJOR_TYPE_MAP: // Major type 5
997 // Record the number of items in the array or map
998 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700999 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001000 goto Done;
1001 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001002 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001003 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001004 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001005 // type conversion OK because of check above
1006 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001007 }
Laurence Lundbladeee851742020-01-08 08:37:05 -08001008 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001009 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001010 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001011 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001012
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001013 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001014 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001015 nReturn = QCBOR_ERR_BAD_INT;
1016 } else {
1017 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001018 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001019 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001020 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001021
Laurence Lundbladeee851742020-01-08 08:37:05 -08001022 case CBOR_MAJOR_TYPE_SIMPLE:
1023 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001024 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001025 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001026
Laurence Lundbladeee851742020-01-08 08:37:05 -08001027 default:
1028 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001029 nReturn = QCBOR_ERR_UNSUPPORTED;
1030 break;
1031 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001032
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001033Done:
1034 return nReturn;
1035}
1036
1037
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001038/**
1039 * @brief Process indefinite length strings
1040 *
1041 * @param[in] pMe Decoder context
1042 * @param[in,out] pDecodedItem The decoded item that work is done on.
1043 *
1044 * @retval QCBOR_ERR_UNSUPPORTED
1045 * @retval QCBOR_ERR_HIT_END
1046 * @retval QCBOR_ERR_INT_OVERFLOW
1047 * @retval QCBOR_ERR_STRING_ALLOCATE
1048 * @retval QCBOR_ERR_STRING_TOO_LONG
1049 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1050 * @retval QCBOR_ERR_BAD_TYPE_7
1051 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1052 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1053 *
1054 * If @c pDecodedItem is not an indefinite length string, this does nothing.
1055 *
1056 * If it is, this loops getting the subsequent chunks that make up the
1057 * string. The string allocator is used to make a contiguous buffer for
1058 * the chunks. When this completes @c pDecodedItem contains the
1059 * put-together string.
1060 *
1061 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001062 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001063static inline QCBORError
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001064GetNext_FullItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001065{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001066 /* Aproximate stack usage
1067 * 64-bit 32-bit
1068 * local vars 32 16
1069 * 2 UsefulBufs 32 16
1070 * QCBORItem 56 52
1071 * TOTAL 120 74
1072 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001073
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001074 /* The string allocator is used here for two purposes: 1)
1075 * coalescing the chunks of an indefinite length string, 2)
1076 * allocating storage for every string returned.
1077 *
1078 * The first use is below in this function. Indefinite length
1079 * strings cannot be processed at all without a string allocator.
1080 *
1081 * The second used is in DecodeBytes() which is called by
1082 * GetNext_Item() below. This second use unneccessary for most use
1083 * and only happens when requested in the call to
1084 * QCBORDecode_SetMemPool(). If the second use not requested then
1085 * NULL is passed for the string allocator to GetNext_Item().
1086 *
1087 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1088 * allocator altogether and thus both of these uses. It reduced the
1089 * decoder object code by about 400 bytes.
1090 */
1091 const QCORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001092
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001093#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1094 const QCORInternalAllocator *pAllocator = NULL;
1095
1096 if(pMe->StringAllocator.pfAllocator) {
1097 pAllocator = &(pMe->StringAllocator);
1098 if(pMe->bStringAllocateAll) {
1099 pAllocatorForGetNext = pAllocator;
1100 }
1101 }
1102#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1103
1104 QCBORError uReturn;
1105 uReturn = GetNext_Item(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
1106 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001107 goto Done;
1108 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001109
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001110 /* Only do indefinite length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001111 const uint8_t uStringType = pDecodedItem->uDataType;
1112 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001113 goto Done;
1114 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001115
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001116 /* Is this a string with an indefinite length? */
1117 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1118 goto Done;
1119 }
1120
1121#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1122 /* Can't do indefinite length strings without a string allocator */
1123 if(pAllocator == NULL) {
1124 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1125 goto Done;
1126 }
1127
1128 /* Loop getting chunks of the indefinite length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001129 UsefulBufC FullString = NULLUsefulBufC;
1130
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001131 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001132 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001133 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001134 /* Pass a NULL string allocator to GetNext_Item() because the
1135 * individual string chunks in an indefinite length should not
1136 * be allocated. They are always copied in the the contiguous
1137 * buffer allocated here.
1138 */
1139 uReturn = GetNext_Item(&(pMe->InBuf), &StringChunkItem, NULL);
1140 if(uReturn) {
1141 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001142 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001143
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001144 /* Is item is the marker for end of the indefinite length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001145 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001146 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001147 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301148 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001149 break;
1150 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001151
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001152 /* All chunks must be of the same type, the type of the item
1153 * that introduces the indefinite length string. This also
1154 * catches errors where the chunk is not a string at all and an
1155 * indefinite length string inside an indefinite length string.
1156 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001157 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001158 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1159 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001160 break;
1161 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001162
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001163 /* The first time throurgh FullString.ptr is NULL and this is
1164 * equivalent to StringAllocator_Allocate(). Subsequently it is
1165 * not NULL and a reallocation happens.
1166 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001167 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1168 UNCONST_POINTER(FullString.ptr),
1169 FullString.len + StringChunkItem.val.string.len);
1170
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001171 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001172 uReturn = QCBOR_ERR_STRING_ALLOCATE;
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 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001177 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001178 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001179
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001180 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1181 /* Getting the item failed, clean up the allocated memory */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001182 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001183 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001184#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1185 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1186#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001187
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001188Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001189 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001190}
1191
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001192
Laurence Lundblade9b334962020-08-27 10:55:53 -07001193static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001194 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001195 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001196 } else if(uTagVal == CBOR_TAG_INVALID16) {
1197 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001198 } else {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001199 // This won't be negative because of code below in GetNext_TaggedItem()
1200 const unsigned uIndex = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
1201 return me->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001202 }
1203}
1204
Laurence Lundblade9b334962020-08-27 10:55:53 -07001205
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001206/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001207 Gets all optional tag data items preceding a data item that is not an
1208 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001209
1210 @retval QCBOR_ERR_UNSUPPORTED
1211
1212 @retval QCBOR_ERR_HIT_END
1213
1214 @retval QCBOR_ERR_INT_OVERFLOW
1215
1216 @retval QCBOR_ERR_STRING_ALLOCATE
1217
1218 @retval QCBOR_ERR_STRING_TOO_LONG
1219
1220 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1221
1222 @retval QCBOR_ERR_BAD_TYPE_7
1223
1224 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1225
1226 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1227
1228 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001229 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001230static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001231GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001232{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001233 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1234 CBOR_TAG_INVALID16,
1235 CBOR_TAG_INVALID16,
1236 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001237
Laurence Lundblade9b334962020-08-27 10:55:53 -07001238 QCBORError uReturn = QCBOR_SUCCESS;
1239
Laurence Lundblade59289e52019-12-30 13:44:37 -08001240 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001241 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001242 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1243 if(uErr != QCBOR_SUCCESS) {
1244 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001245 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001246 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001247
Laurence Lundblade9b334962020-08-27 10:55:53 -07001248 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001249 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001250 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001251 break;
1252 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001253
Laurence Lundblade9b334962020-08-27 10:55:53 -07001254 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1255 // No room in the tag list
1256 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1257 // Continue on to get all tags on this item even though
1258 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001259 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001260 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001261 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001262 // Slide tags over one in the array to make room at index 0
1263 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1264 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001265 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001266
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001267 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001268 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001269 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001270 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001271 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001272 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001273 break;
1274 }
1275 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1276 break;
1277 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001278 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001279 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1280 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001281 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1282 // Continue on to get all tags on this item even though
1283 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001284 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001285 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001286 }
1287
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001288 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001289 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001290 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001291
1292 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001293 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001294 }
1295 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001296
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001297Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001298 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001299}
1300
1301
1302/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001303 This layer takes care of map entries. It combines the label and data
1304 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001305
1306 @retval QCBOR_ERR_UNSUPPORTED
1307
1308 @retval QCBOR_ERR_HIT_END
1309
1310 @retval QCBOR_ERR_INT_OVERFLOW
1311
1312 @retval QCBOR_ERR_STRING_ALLOCATE
1313
1314 @retval QCBOR_ERR_STRING_TOO_LONG
1315
1316 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1317
1318 @retval QCBOR_ERR_BAD_TYPE_7
1319
1320 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1321
1322 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1323
1324 @retval QCBOR_ERR_TOO_MANY_TAGS
1325
1326 @retval QCBOR_ERR_MAP_LABEL_TYPE
1327
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001328 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001329 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001330static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001331GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001332{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001333 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001334 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001335 if(nReturn)
1336 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001337
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001338 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001339 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001340 goto Done;
1341 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001342
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001343 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1344 // In a map and caller wants maps decoded, not treated as arrays
1345
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001346 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001347 // If in a map and the right decoding mode, get the label
1348
Laurence Lundbladeee851742020-01-08 08:37:05 -08001349 // Save label in pDecodedItem and get the next which will
1350 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001351 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001352 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001353 if(QCBORDecode_IsUnrecoverableError(nReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001354 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001355 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001356
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301357 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001358
1359 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1360 // strings are always good labels
1361 pDecodedItem->label.string = LabelItem.val.string;
1362 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1363 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001364 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001365 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1366 goto Done;
1367 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1368 pDecodedItem->label.int64 = LabelItem.val.int64;
1369 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1370 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1371 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1372 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1373 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1374 pDecodedItem->label.string = LabelItem.val.string;
1375 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1376 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1377 } else {
1378 // label is not an int or a string. It is an arrray
1379 // or a float or such and this implementation doesn't handle that.
1380 // Also, tags on labels are ignored.
1381 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1382 goto Done;
1383 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001384 }
1385 } else {
1386 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001387 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001388 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001389 goto Done;
1390 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001391 // Decoding a map as an array
1392 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001393 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1394 // Cast is needed because of integer promotion
1395 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001396 }
1397 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001398
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001399Done:
1400 return nReturn;
1401}
1402
1403
Laurence Lundblade02625d42020-06-25 14:41:41 -07001404/*
1405 See if next item is a CBOR break. If it is, it is consumed,
1406 if not it is not consumed.
1407*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001408static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001409NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1410{
1411 *pbNextIsBreak = false;
1412 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001413 QCBORItem Peek;
1414 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1415 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1416 if(uReturn != QCBOR_SUCCESS) {
1417 return uReturn;
1418 }
1419 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001420 // It is not a break, rewind so it can be processed normally.
1421 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001422 } else {
1423 *pbNextIsBreak = true;
1424 }
1425 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001426
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001427 return QCBOR_SUCCESS;
1428}
1429
1430
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001431/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001432 An item was just consumed, now figure out if it was the
1433 end of an array or map that can be closed out. That
1434 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001435*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001436static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001437{
1438 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001439
Laurence Lundblade642282a2020-06-23 12:00:33 -07001440 /* This loops ascending nesting levels as long as there is ascending to do */
1441 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1442
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001443 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001444 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001445 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1446 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001447 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001448 break;
1449 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07001450 /* All of a definite length array was consumed; fall through to
1451 ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001452
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001453 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001454 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001455 bool bIsBreak = false;
1456 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1457 if(uReturn != QCBOR_SUCCESS) {
1458 goto Done;
1459 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001460
1461 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001462 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001463 break;
1464 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001465
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001466 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001467 /*
1468 Break occurred inside a bstr-wrapped CBOR or
1469 in the top level sequence. This is always an
1470 error because neither are an indefinte length
1471 map/array.
1472 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001473 uReturn = QCBOR_ERR_BAD_BREAK;
1474 goto Done;
1475 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001476
Laurence Lundblade02625d42020-06-25 14:41:41 -07001477 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001478 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001479
Laurence Lundblade02625d42020-06-25 14:41:41 -07001480 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001481
Laurence Lundblade93d89472020-10-03 22:30:50 -07001482 /* But ascent in bounded mode is only by explicit call to
1483 QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001484 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001485 /* Set the count to zero for definite length arrays to indicate
1486 cursor is at end of bounded map / array */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001487 if(bMarkEnd) {
1488 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001489 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001490
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001491 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001492 break;
1493 }
1494
1495 /* Finally, actually ascend one level. */
1496 DecodeNesting_Ascend(&(pMe->nesting));
1497 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001498
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001499 uReturn = QCBOR_SUCCESS;
1500
1501Done:
1502 return uReturn;
1503}
1504
1505
1506/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001507 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001508 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1509 indefinte length maps and arrays by looking at the item count or
1510 finding CBOR breaks. It detects the ends of the top-level sequence
1511 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001512
1513 @retval QCBOR_ERR_UNSUPPORTED X
1514
1515 @retval QCBOR_ERR_HIT_END
1516
1517 @retval QCBOR_ERR_INT_OVERFLOW X
1518
1519 @retval QCBOR_ERR_STRING_ALLOCATE
1520
1521 @retval QCBOR_ERR_STRING_TOO_LONG
1522
1523 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1524
1525 @retval QCBOR_ERR_BAD_TYPE_7 X
1526
1527 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1528
1529 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1530
1531 @retval QCBOR_ERR_TOO_MANY_TAGS
1532
1533 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1534
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001535 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001536
1537 @retval QCBOR_ERR_NO_MORE_ITEMS
1538
1539 @retval QCBOR_ERR_BAD_BREAK
1540
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001541 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001542static QCBORError
1543QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001544{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001545 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001546 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001547
Laurence Lundblade642282a2020-06-23 12:00:33 -07001548 /*
1549 If out of bytes to consume, it is either the end of the top-level
1550 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001551
Laurence Lundblade642282a2020-06-23 12:00:33 -07001552 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1553 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1554 CBOR is exited, the length is set back to the top-level's length
1555 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001556 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001557 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001558 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001559 goto Done;
1560 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001561
Laurence Lundblade642282a2020-06-23 12:00:33 -07001562 /*
1563 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001564 array. The check for the end of an indefinite length array is
1565 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001566 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001567 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001568 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001569 goto Done;
1570 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001571
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001572 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001573 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001574 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1575 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001576 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001577 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301578
Laurence Lundblade642282a2020-06-23 12:00:33 -07001579 /*
1580 Breaks ending arrays/maps are always processed at the end of this
1581 function. They should never show up here.
1582 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301583 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001584 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301585 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301586 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001587
Laurence Lundblade642282a2020-06-23 12:00:33 -07001588 /*
1589 Record the nesting level for this data item before processing any
1590 of decrementing and descending.
1591 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001592 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001593
Laurence Lundblade642282a2020-06-23 12:00:33 -07001594
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001595 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001596 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001597 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001598 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001599
Laurence Lundblade93d89472020-10-03 22:30:50 -07001600 Empty indefinite length maps and arrays are descended into, but
1601 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001602
1603 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001604 encloses them so a decrement needs to be done for them too, but
1605 that is done only when all the items in them have been
1606 processed, not when they are opened with the exception of an
1607 empty map or array.
1608 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001609 QCBORError uDescendErr;
1610 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001611 pDecodedItem->uDataType,
1612 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001613 if(uDescendErr != QCBOR_SUCCESS) {
1614 /* This error is probably a traversal error and it
1615 overrides the non-traversal error. */
1616 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001617 goto Done;
1618 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001619 }
1620
Laurence Lundblade02625d42020-06-25 14:41:41 -07001621 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1622 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1623 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001624 /*
1625 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001626 - A non-aggregate like an integer or string
1627 - An empty definite length map or array
1628 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001629
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001630 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001631 definite length map/array and break detection for an indefinite
1632 length map/array. If the end of the map/array was reached, then
1633 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001634 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001635 QCBORError uAscendErr;
1636 uAscendErr = NestLevelAscender(me, true);
1637 if(uAscendErr != QCBOR_SUCCESS) {
1638 /* This error is probably a traversal error and it
1639 overrides the non-traversal error. */
1640 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001641 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001642 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301643 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001644
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001645 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001646 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001647 Tell the caller what level is next. This tells them what
1648 maps/arrays were closed out and makes it possible for them to
1649 reconstruct the tree with just the information returned in
1650 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001651 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001652 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001653 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001654 pDecodedItem->uNextNestLevel = 0;
1655 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001656 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001657 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001658
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001659Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001660 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001661}
1662
Laurence Lundblade9b334962020-08-27 10:55:53 -07001663static void ShiftTags(QCBORItem *pDecodedItem)
1664{
1665 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1666 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1667 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1668 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1669}
1670
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001671
Laurence Lundblade9b334962020-08-27 10:55:53 -07001672
Laurence Lundblade59289e52019-12-30 13:44:37 -08001673/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001674 The epoch formatted date. Turns lots of different forms of encoding
1675 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001676 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001677static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001678{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001679 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001680
1681 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1682
1683 switch (pDecodedItem->uDataType) {
1684
1685 case QCBOR_TYPE_INT64:
1686 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1687 break;
1688
1689 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001690 // This only happens for CBOR type 0 > INT64_MAX so it is
1691 // always an overflow.
1692 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1693 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001694 break;
1695
1696 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001697 case QCBOR_TYPE_FLOAT:
1698#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001699 {
1700 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001701 // conversion to an int64_t to be able to detect doubles that
1702 // are too large to fit into an int64_t. A double has 52
1703 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1704 // to a double actually causes a round up which is bad and
1705 // wrong for the comparison because it will allow conversion
1706 // of doubles that can't fit into a uint64_t. To remedy this
1707 // INT64_MAX - 0x7ff is used as the cutoff point because if
1708 // that value rounds up in conversion to double it will still
1709 // be less than INT64_MAX. 0x7ff is picked because it has 11
1710 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001711 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001712 // INT64_MAX seconds is on the order of 10 billion years, and
1713 // the earth is less than 5 billion years old, so for most
1714 // uses this conversion error won't occur even though doubles
1715 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001716 //
1717 // Without the 0x7ff there is a ~30 minute range of time
1718 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001719 // where this code would go wrong. Some compilers
1720 // will generate warnings or errors without the 0x7ff
1721 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001722 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1723 pDecodedItem->val.dfnum :
1724 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001725 if(isnan(d) ||
1726 d > (double)(INT64_MAX - 0x7ff) ||
1727 d < (double)(INT64_MIN + 0x7ff)) {
1728 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001729 goto Done;
1730 }
1731 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001732 pDecodedItem->val.epochDate.fSecondsFraction =
1733 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001734 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001735#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001736
Laurence Lundbladec7114722020-08-13 05:11:40 -07001737 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001738 goto Done;
1739
Laurence Lundblade9682a532020-06-06 18:33:04 -07001740#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001741 break;
1742
1743 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001744 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001745 goto Done;
1746 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001747
Laurence Lundblade59289e52019-12-30 13:44:37 -08001748 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1749
1750Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001751 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001752}
1753
1754
1755#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1756/*
1757 Decode decimal fractions and big floats.
1758
1759 When called pDecodedItem must be the array that is tagged as a big
1760 float or decimal fraction, the array that has the two members, the
1761 exponent and mantissa.
1762
1763 This will fetch and decode the exponent and mantissa and put the
1764 result back into pDecodedItem.
1765 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001766static inline QCBORError
Laurence Lundblade59289e52019-12-30 13:44:37 -08001767QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1768{
1769 QCBORError nReturn;
1770
1771 // --- Make sure it is an array; track nesting level of members ---
1772 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1773 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1774 goto Done;
1775 }
1776
1777 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001778 // definite length arrays, but not for indefnite. Instead remember
1779 // the nesting level the two integers must be at, which is one
1780 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001781 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1782
1783 // --- Is it a decimal fraction or a bigfloat? ---
1784 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1785 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1786
1787 // --- Get the exponent ---
1788 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001789 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001790 if(nReturn != QCBOR_SUCCESS) {
1791 goto Done;
1792 }
1793 if(exponentItem.uNestingLevel != nNestLevel) {
1794 // Array is empty or a map/array encountered when expecting an int
1795 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1796 goto Done;
1797 }
1798 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1799 // Data arriving as an unsigned int < INT64_MAX has been converted
1800 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1801 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1802 // will be too large for this to handle and thus an error that will
1803 // get handled in the next else.
1804 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1805 } else {
1806 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1807 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1808 goto Done;
1809 }
1810
1811 // --- Get the mantissa ---
1812 QCBORItem mantissaItem;
1813 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1814 if(nReturn != QCBOR_SUCCESS) {
1815 goto Done;
1816 }
1817 if(mantissaItem.uNestingLevel != nNestLevel) {
1818 // Mantissa missing or map/array encountered when expecting number
1819 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1820 goto Done;
1821 }
1822 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1823 // Data arriving as an unsigned int < INT64_MAX has been converted
1824 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1825 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1826 // will be too large for this to handle and thus an error that
1827 // will get handled in an else below.
1828 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001829 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
1830 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001831 // Got a good big num mantissa
1832 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1833 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001834 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1835 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1836 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001837 } else {
1838 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1839 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1840 goto Done;
1841 }
1842
1843 // --- Check that array only has the two numbers ---
1844 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001845 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001846 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1847 goto Done;
1848 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001849 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001850
1851Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001852 return nReturn;
1853}
1854#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1855
1856
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001857static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001858{
1859 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1860 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001861 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001862 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1863 } else {
1864 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001865
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001866 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001867
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001868 return QCBOR_SUCCESS;
1869}
1870
1871
Laurence Lundblade99615302020-11-29 11:19:47 -08001872/*
1873 * Table of CBOR tags whose content is either a text string or a byte
1874 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
1875 * of uQCBORtype indicates the content should be a byte string rather
1876 * than a text string
1877 */
1878struct StringTagMapEntry {
1879 uint16_t uTagNumber;
1880 uint8_t uQCBORtype;
1881};
1882
1883#define IS_BYTE_STRING_BIT 0x80
1884#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
1885
1886static const struct StringTagMapEntry StringTagMap[] = {
1887 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
1888 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
1889 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
1890 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
1891 {CBOR_TAG_URI, QCBOR_TYPE_URI},
1892 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
1893 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
1894 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
1895 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
1896 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
1897 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
1898};
1899
1900
1901/*
1902 * Process the CBOR tags that whose content is a byte string or a text
1903 * string and for which the string is just passed on to the caller.
1904 *
1905 * This maps the CBOR tag to the QCBOR type and checks the content
1906 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08001907 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08001908 * possible.
1909 *
1910 * This returns QCBOR_SUCCESS if the tag was procssed,
1911 * QCBOR_ERR_UNSUPPORTED if the tag was not processed and
1912 * QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
1913 */
1914static inline
1915QCBORError ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001916{
Laurence Lundblade99615302020-11-29 11:19:47 -08001917 /* This only works on tags that were not mapped; no need for other yet */
1918 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
1919 return QCBOR_ERR_UNSUPPORTED;
1920 }
1921
1922 unsigned uIndex;
1923 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
1924 if(StringTagMap[uIndex].uTagNumber == uTag) {
1925 break;
1926 }
1927 }
1928
1929 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
1930 if(uQCBORType == QCBOR_TYPE_NONE) {
1931 /* repurpose this error to mean, not handled here */
1932 return QCBOR_ERR_UNSUPPORTED;
1933 }
1934
1935 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
1936 if(uQCBORType & IS_BYTE_STRING_BIT) {
1937 uExpectedType = QCBOR_TYPE_BYTE_STRING;
1938 }
1939
1940 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001941 return QCBOR_ERR_BAD_OPT_TAG;
1942 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001943
Laurence Lundblade99615302020-11-29 11:19:47 -08001944 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001945 return QCBOR_SUCCESS;
1946}
1947
1948
Laurence Lundblade59289e52019-12-30 13:44:37 -08001949/*
Laurence Lundblade99615302020-11-29 11:19:47 -08001950 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
1951 * but the whole tag was not decoded. Here, the whole tags (tag number
1952 * and tag content) that are supported by QCBOR are decoded. This is a
1953 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001954 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001955static QCBORError
1956QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001957{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001958 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001959
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001960 uReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
1961 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001962 goto Done;
1963 }
1964
Laurence Lundblade99615302020-11-29 11:19:47 -08001965 /* When there are no tag numbers for the item, this exits first
1966 * thing and effectively does nothing.
1967 *
1968 * This loops over all the tag numbers accumulated for this item
1969 * trying to decode and interpret them. This stops at the end of
1970 * the list or at the first tag number that can't be interpreted by
1971 * this code. This is effectively a recursive processing of the
1972 * tags number list that handles nested tags.
1973 */
1974 while(1) {
1975 /* Don't bother to unmap tags via QCBORITem.uTags since this
1976 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
1977 */
1978 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08001979
Laurence Lundblade99615302020-11-29 11:19:47 -08001980 if(uTagToProcess == CBOR_TAG_INVALID16) {
1981 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001982 break;
1983
Laurence Lundblade99615302020-11-29 11:19:47 -08001984 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001985 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001986
Laurence Lundblade93d89472020-10-03 22:30:50 -07001987#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08001988 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
1989 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001990 uReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
Laurence Lundblade93d89472020-10-03 22:30:50 -07001991#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001992
Laurence Lundblade99615302020-11-29 11:19:47 -08001993 } else if(uTagToProcess == CBOR_TAG_MIME ||
1994 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001995 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001996
Laurence Lundblade99615302020-11-29 11:19:47 -08001997 } else {
1998 /* See if it is a pass-through byte/text string tag; process if so */
1999 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002000
Laurence Lundblade99615302020-11-29 11:19:47 -08002001 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2002 /* It wasn't a pass-through byte/text string tag so it is
2003 * an unknown tag. This is the exit from the loop on the
2004 * first unknown tag. It is a successful exit.
2005 */
2006 uReturn = QCBOR_SUCCESS;
2007 break;
2008 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002009 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002010
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002011 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002012 /* Error exit from the loop */
2013 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002014 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002015
2016 /* A tag was successfully processed, shift it out of the list of
2017 * tags returned. This is the loop increment.
2018 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002019 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002020 }
2021
2022Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002023 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002024}
2025
2026
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002027/*
2028 Public function, see header qcbor/qcbor_decode.h file
2029 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002030QCBORError
2031QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2032{
2033 QCBORError uErr;
2034 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2035 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002036 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2037 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2038 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002039 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002040}
2041
2042
2043/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002044 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002045 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002046QCBORError
2047QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2048{
2049 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2050 const UsefulInputBuf Save = pMe->InBuf;
2051
2052 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2053
2054 pMe->nesting = SaveNesting;
2055 pMe->InBuf = Save;
2056
2057 return uErr;
2058}
2059
2060
2061/*
2062 Public function, see header qcbor/qcbor_decode.h file
2063 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002064void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2065{
2066 if(pMe->uLastError != QCBOR_SUCCESS) {
2067 return;
2068 }
2069
2070 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2071}
2072
2073
2074/*
2075 Public function, see header qcbor/qcbor_decode.h file
2076 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002077QCBORError
2078QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2079 QCBORItem *pDecodedItem,
2080 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002081{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002082 QCBORError nReturn;
2083
2084 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2085 if(nReturn != QCBOR_SUCCESS) {
2086 return nReturn;
2087 }
2088
2089 if(pTags != NULL) {
2090 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002091 // Reverse the order because pTags is reverse of
2092 // QCBORItem.uTags.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002093 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2094 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002095 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002096 }
2097 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2098 return QCBOR_ERR_TOO_MANY_TAGS;
2099 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002100 pTags->puTags[pTags->uNumUsed] = ConvertTag(me,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002101 pTags->uNumUsed++;
2102 }
2103 }
2104
2105 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002106}
2107
2108
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002109/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302110 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302111 next one down. If a layer has no work to do for a particular item
2112 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002113
Laurence Lundblade59289e52019-12-30 13:44:37 -08002114 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2115 tagged data items, turning them into the local C representation.
2116 For the most simple it is just associating a QCBOR_TYPE with the data. For
2117 the complex ones that an aggregate of data items, there is some further
2118 decoding and a little bit of recursion.
2119
2120 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302121 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302122 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002123 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002124
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302125 - GetNext_MapEntry -- This handles the combining of two
2126 items, the label and the data, that make up a map entry.
2127 It only does work on maps. It combines the label and data
2128 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002129
Laurence Lundblade59289e52019-12-30 13:44:37 -08002130 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2131 tags into bit flags associated with the data item. No actual decoding
2132 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002133
Laurence Lundblade59289e52019-12-30 13:44:37 -08002134 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302135 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302136 string allocater to create contiguous space for the item. It
2137 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002138
Laurence Lundblade59289e52019-12-30 13:44:37 -08002139 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2140 atomic data item has a "major type", an integer "argument" and optionally
2141 some content. For text and byte strings, the content is the bytes
2142 that make up the string. These are the smallest data items that are
2143 considered to be well-formed. The content may also be other data items in
2144 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002145
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002146 Roughly this takes 300 bytes of stack for vars. Need to
2147 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002148
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302149 */
2150
2151
2152/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002153 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002154 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002155bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002156 const QCBORItem *pItem,
2157 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002158{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002159 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2160 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002161 break;
2162 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002163 if(ConvertTag(me, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002164 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002165 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002166 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002167
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002168 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002169}
2170
2171
2172/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002173 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002174 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002175QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002176{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002177 QCBORError uReturn = me->uLastError;
2178
2179 if(uReturn != QCBOR_SUCCESS) {
2180 goto Done;
2181 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002182
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002183 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002184 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002185 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002186 goto Done;
2187 }
2188
2189 // Error out if not all the bytes are consumed
2190 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002191 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002192 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002193
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002194Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002195#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade6de37062018-10-15 12:22:42 +05302196 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002197 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002198 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002199#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002200
Laurence Lundblade085d7952020-07-24 10:26:30 -07002201 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002202}
2203
2204
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002205/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002206 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002207*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002208// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002209uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2210 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002211 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002212{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002213 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2214 return CBOR_TAG_INVALID64;
2215 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002216 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2217 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002218 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002219 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002220 }
2221}
2222
Laurence Lundblade9b334962020-08-27 10:55:53 -07002223/*
2224 Public function, see header qcbor/qcbor_decode.h file
2225*/
2226uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2227 uint32_t uIndex)
2228{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002229 if(pMe->uLastError != QCBOR_SUCCESS) {
2230 return CBOR_TAG_INVALID64;
2231 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002232 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2233 return CBOR_TAG_INVALID64;
2234 } else {
2235 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2236 }
2237}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002238
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002239/*
2240
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002241Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002242
Laurence Lundbladeee851742020-01-08 08:37:05 -08002243 - Hit end of input before it was expected while decoding type and
2244 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002245
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002246 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002247
Laurence Lundbladeee851742020-01-08 08:37:05 -08002248 - Hit end of input while decoding a text or byte string
2249 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002250
Laurence Lundbladeee851742020-01-08 08:37:05 -08002251 - Encountered conflicting tags -- e.g., an item is tagged both a date
2252 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002253
Laurence Lundbladeee851742020-01-08 08:37:05 -08002254 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002255 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002256
Laurence Lundbladeee851742020-01-08 08:37:05 -08002257 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002258 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002259
Laurence Lundbladeee851742020-01-08 08:37:05 -08002260 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2261 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002262
Laurence Lundbladeee851742020-01-08 08:37:05 -08002263 - The type of a map label is not a string or int
2264 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002265
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002266 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002267
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002268 */
2269
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002270
2271
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002272#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002273
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002274/* ===========================================================================
2275 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002276
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002277 This implements a simple sting allocator for indefinite length
2278 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2279 implements the function type QCBORStringAllocate and allows easy
2280 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002281
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002282 This particular allocator is built-in for convenience. The caller
2283 can implement their own. All of this following code will get
2284 dead-stripped if QCBORDecode_SetMemPool() is not called.
2285
2286 This is a very primitive memory allocator. It does not track
2287 individual allocations, only a high-water mark. A free or
2288 reallocation must be of the last chunk allocated.
2289
2290 The size of the pool and offset to free memory are packed into the
2291 first 8 bytes of the memory pool so we don't have to keep them in
2292 the decode context. Since the address of the pool may not be
2293 aligned, they have to be packed and unpacked as if they were
2294 serialized data of the wire or such.
2295
2296 The sizes packed in are uint32_t to be the same on all CPU types
2297 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002298 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002299
2300
Laurence Lundbladeee851742020-01-08 08:37:05 -08002301static inline int
2302MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002303{
2304 // Use of UsefulInputBuf is overkill, but it is convenient.
2305 UsefulInputBuf UIB;
2306
Laurence Lundbladeee851742020-01-08 08:37:05 -08002307 // Just assume the size here. It was checked during SetUp so
2308 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002309 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002310 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2311 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2312 return UsefulInputBuf_GetError(&UIB);
2313}
2314
2315
Laurence Lundbladeee851742020-01-08 08:37:05 -08002316static inline int
2317MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002318{
2319 // Use of UsefulOutBuf is overkill, but convenient. The
2320 // length check performed here is useful.
2321 UsefulOutBuf UOB;
2322
2323 UsefulOutBuf_Init(&UOB, Pool);
2324 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2325 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2326 return UsefulOutBuf_GetError(&UOB);
2327}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002328
2329
2330/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002331 Internal function for an allocation, reallocation free and destuct.
2332
2333 Having only one function rather than one each per mode saves space in
2334 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002335
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002336 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2337 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002338static UsefulBuf
2339MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002340{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002341 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002342
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002343 uint32_t uPoolSize;
2344 uint32_t uFreeOffset;
2345
2346 if(uNewSize > UINT32_MAX) {
2347 // This allocator is only good up to 4GB. This check should
2348 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2349 goto Done;
2350 }
2351 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2352
2353 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2354 goto Done;
2355 }
2356
2357 if(uNewSize) {
2358 if(pMem) {
2359 // REALLOCATION MODE
2360 // Calculate pointer to the end of the memory pool. It is
2361 // assumed that pPool + uPoolSize won't wrap around by
2362 // assuming the caller won't pass a pool buffer in that is
2363 // not in legitimate memory space.
2364 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2365
2366 // Check that the pointer for reallocation is in the range of the
2367 // pool. This also makes sure that pointer math further down
2368 // doesn't wrap under or over.
2369 if(pMem >= pPool && pMem < pPoolEnd) {
2370 // Offset to start of chunk for reallocation. This won't
2371 // wrap under because of check that pMem >= pPool. Cast
2372 // is safe because the pool is always less than UINT32_MAX
2373 // because of check in QCBORDecode_SetMemPool().
2374 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2375
2376 // Check to see if the allocation will fit. uPoolSize -
2377 // uMemOffset will not wrap under because of check that
2378 // pMem is in the range of the uPoolSize by check above.
2379 if(uNewSize <= uPoolSize - uMemOffset) {
2380 ReturnValue.ptr = pMem;
2381 ReturnValue.len = uNewSize;
2382
2383 // Addition won't wrap around over because uNewSize was
2384 // checked to be sure it is less than the pool size.
2385 uFreeOffset = uMemOffset + uNewSize32;
2386 }
2387 }
2388 } else {
2389 // ALLOCATION MODE
2390 // uPoolSize - uFreeOffset will not underflow because this
2391 // pool implementation makes sure uFreeOffset is always
2392 // smaller than uPoolSize through this check here and
2393 // reallocation case.
2394 if(uNewSize <= uPoolSize - uFreeOffset) {
2395 ReturnValue.len = uNewSize;
2396 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002397 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002398 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002399 }
2400 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002401 if(pMem) {
2402 // FREE MODE
2403 // Cast is safe because of limit on pool size in
2404 // QCBORDecode_SetMemPool()
2405 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2406 } else {
2407 // DESTRUCT MODE
2408 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002409 }
2410 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002411
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002412 UsefulBuf Pool = {pPool, uPoolSize};
2413 MemPool_Pack(Pool, uFreeOffset);
2414
2415Done:
2416 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002417}
2418
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002419
Laurence Lundbladef6531662018-12-04 10:42:22 +09002420/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002421 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002422 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002423QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2424 UsefulBuf Pool,
2425 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002426{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002427 // The pool size and free mem offset are packed into the beginning
2428 // of the pool memory. This compile time check make sure the
2429 // constant in the header is correct. This check should optimize
2430 // down to nothing.
2431 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002432 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002433 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002434
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002435 // The pool size and free offset packed in to the beginning of pool
2436 // memory are only 32-bits. This check will optimize out on 32-bit
2437 // machines.
2438 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002439 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002440 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002441
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002442 // This checks that the pool buffer given is big enough.
2443 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002444 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002445 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002446
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002447 pMe->StringAllocator.pfAllocator = MemPool_Function;
2448 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2449 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002450
Laurence Lundblade30816f22018-11-10 13:40:22 +07002451 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002452}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002453#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002454
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002455
2456
Laurence Lundblade9b334962020-08-27 10:55:53 -07002457static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2458{
2459 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2460}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002461
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002462
2463/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002464 Consume an entire map or array (and do next to
2465 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002466 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002467static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002468ConsumeItem(QCBORDecodeContext *pMe,
2469 const QCBORItem *pItemToConsume,
2470 uint_fast8_t *puNextNestLevel)
2471{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002472 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002473 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002474
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002475 // If it is a map or array, this will tell if it is empty.
2476 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2477
2478 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2479 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002480
Laurence Lundblade1341c592020-04-11 14:19:05 -07002481 /* This works for definite and indefinite length
2482 * maps and arrays by using the nesting level
2483 */
2484 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002485 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002486 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002487 goto Done;
2488 }
2489 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002490
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002491 *puNextNestLevel = Item.uNextNestLevel;
2492
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002493 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002494
Laurence Lundblade1341c592020-04-11 14:19:05 -07002495 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002496 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002497 /* Just pass the nesting level through */
2498 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2499
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002500 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002501 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002502
2503Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002504 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002505}
2506
2507
Laurence Lundblade1341c592020-04-11 14:19:05 -07002508/* Return true if the labels in Item1 and Item2 are the same.
2509 Works only for integer and string labels. Returns false
2510 for any other type. */
2511static inline bool
2512MatchLabel(QCBORItem Item1, QCBORItem Item2)
2513{
2514 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2515 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2516 return true;
2517 }
2518 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002519 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002520 return true;
2521 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002522 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002523 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2524 return true;
2525 }
2526 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2527 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2528 return true;
2529 }
2530 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002531
Laurence Lundblade1341c592020-04-11 14:19:05 -07002532 /* Other label types are never matched */
2533 return false;
2534}
2535
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002536
2537/*
2538 Returns true if Item1 and Item2 are the same type
2539 or if either are of QCBOR_TYPE_ANY.
2540 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002541static inline bool
2542MatchType(QCBORItem Item1, QCBORItem Item2)
2543{
2544 if(Item1.uDataType == Item2.uDataType) {
2545 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002546 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002547 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002548 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002549 return true;
2550 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002551 return false;
2552}
2553
2554
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002555/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002556 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002557
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002558 @param[in] pMe The decode context to search.
2559 @param[in,out] pItemArray The items to search for and the items found.
2560 @param[out] puOffset Byte offset of last item matched.
2561 @param[in] pCBContext Context for the not-found item call back.
2562 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002563
2564 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2565
Laurence Lundblade93d89472020-10-03 22:30:50 -07002566 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2567 were found for one of the labels being
2568 search for. This duplicate detection is
2569 only performed for items in pItemArray,
2570 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002571
Laurence Lundblade93d89472020-10-03 22:30:50 -07002572 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2573 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002574
2575 @retval Also errors returned by QCBORDecode_GetNext().
2576
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002577 On input pItemArray contains a list of labels and data types
2578 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002579
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002580 On output the fully retrieved items are filled in with
2581 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002582
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002583 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002584
2585 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002586 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002587static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002588MapSearch(QCBORDecodeContext *pMe,
2589 QCBORItem *pItemArray,
2590 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002591 void *pCBContext,
2592 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002593{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002594 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002595 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002596
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002597 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002598 uReturn = pMe->uLastError;
2599 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002600 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002601
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002602 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002603 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2604 /* QCBOR_TYPE_NONE as first item indicates just looking
2605 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002606 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2607 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002608 }
2609
Laurence Lundblade085d7952020-07-24 10:26:30 -07002610 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2611 // It is an empty bounded array or map
2612 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2613 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002614 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002615 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002616 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002617 // Nothing is ever found in an empty array or map. All items
2618 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002619 uReturn = QCBOR_SUCCESS;
2620 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002621 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002622 }
2623
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002624 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002625 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2626
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002627 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002628 UsefulInputBuf_Seek(&(pMe->InBuf),
2629 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002630
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002631 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002632 Loop over all the items in the map or array. Each item
2633 could be a map or array, but label matching is only at
2634 the main level. This handles definite and indefinite
2635 length maps and arrays. The only reason this is ever
2636 called on arrays is to find their end position.
2637
2638 This will always run over all items in order to do
2639 duplicate detection.
2640
2641 This will exit with failure if it encounters an
2642 unrecoverable error, but continue on for recoverable
2643 errors.
2644
2645 If a recoverable error occurs on a matched item, then
2646 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002647 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002648 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002649 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002650 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002651 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002652 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002653
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002654 /* Get the item */
2655 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002656 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2657 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002658 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002659 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002660 goto Done;
2661 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002662 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002663 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002664 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002665 goto Done;
2666 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002667
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002668 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002669 bool bMatched = false;
2670 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2671 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002672 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002673 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2674 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002675 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002676 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002677 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002678 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002679 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002680 goto Done;
2681 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002682
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002683 if(uResult != QCBOR_SUCCESS) {
2684 uReturn = uResult;
2685 goto Done;
2686 }
2687
Laurence Lundblade1341c592020-04-11 14:19:05 -07002688 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002689 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002690 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002691 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002692 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002693 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002694 bMatched = true;
2695 }
2696 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002697
2698
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002699 if(!bMatched && pfCallback != NULL) {
2700 /*
2701 Call the callback on unmatched labels.
2702 (It is tempting to do duplicate detection here, but that would
2703 require dynamic memory allocation because the number of labels
2704 that might be encountered is unbounded.)
2705 */
2706 uReturn = (*pfCallback)(pCBContext, &Item);
2707 if(uReturn != QCBOR_SUCCESS) {
2708 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002709 }
2710 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002711
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002712 /*
2713 Consume the item whether matched or not. This
2714 does the work of traversing maps and array and
2715 everything in them. In this loop only the
2716 items at the current nesting level are examined
2717 to match the labels.
2718 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002719 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002720 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002721 goto Done;
2722 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002723
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002724 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002725
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002726 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002727
2728 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002729
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002730 // Check here makes sure that this won't accidentally be
2731 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002732 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08002733 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
2734 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002735 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2736 goto Done;
2737 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002738 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2739 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002740
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002741 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002742 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2743
2744 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002745 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002746 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002747 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002748 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2749 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002750 }
2751 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002752
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002753 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002754}
2755
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002756
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002757/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002758 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002759*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002760void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2761 int64_t nLabel,
2762 uint8_t uQcborType,
2763 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002764{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002765 if(pMe->uLastError != QCBOR_SUCCESS) {
2766 return;
2767 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002768
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002769 QCBORItem OneItemSeach[2];
2770 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2771 OneItemSeach[0].label.int64 = nLabel;
2772 OneItemSeach[0].uDataType = uQcborType;
2773 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002774
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002775 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002776
2777 *pItem = OneItemSeach[0];
2778
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002779 if(uReturn != QCBOR_SUCCESS) {
2780 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002781 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002782 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002783 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002784 }
2785
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002786 Done:
2787 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002788}
2789
2790
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002791/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002792 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002793*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002794void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2795 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002796 uint8_t uQcborType,
2797 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002798{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002799 if(pMe->uLastError != QCBOR_SUCCESS) {
2800 return;
2801 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002802
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002803 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002804 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2805 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2806 OneItemSeach[0].uDataType = uQcborType;
2807 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002808
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002809 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2810 if(uReturn != QCBOR_SUCCESS) {
2811 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002812 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002813 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002814 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002815 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002816 }
2817
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002818 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002819
2820Done:
2821 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002822}
2823
2824
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002825
Laurence Lundblade93d89472020-10-03 22:30:50 -07002826static QCBORError
2827CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002828{
2829 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2830 if(uDataType == puTypeList[i]) {
2831 return QCBOR_SUCCESS;
2832 }
2833 }
2834 return QCBOR_ERR_UNEXPECTED_TYPE;
2835}
2836
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002837
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002838/**
2839 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002840 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002841
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002842 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2843 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002844
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002845 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
2846 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002847 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002848static QCBORError
2849CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002850{
2851 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2852 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2853 /* There are tags that QCBOR couldn't process on this item and
2854 the caller has told us there should not be. */
2855 return QCBOR_ERR_UNEXPECTED_TYPE;
2856 }
2857
2858 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2859 const int nItemType = pItem->uDataType;
2860
2861 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2862 // Must match the tag and only the tag
2863 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2864 }
2865
2866 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2867 if(uReturn == QCBOR_SUCCESS) {
2868 return QCBOR_SUCCESS;
2869 }
2870
2871 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2872 /* Must match the content type and only the content type.
2873 There was no match just above so it is a fail. */
2874 return QCBOR_ERR_UNEXPECTED_TYPE;
2875 }
2876
2877 /* If here it can match either the tag or the content
2878 and it hasn't matched the content, so the end
2879 result is whether it matches the tag. This is
2880 also the case that the CBOR standard discourages. */
2881
2882 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2883}
2884
Laurence Lundblade9b334962020-08-27 10:55:53 -07002885
Laurence Lundblade9b334962020-08-27 10:55:53 -07002886
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002887// This could be semi-private if need be
2888static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002889void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2890 int64_t nLabel,
2891 TagSpecification TagSpec,
2892 QCBORItem *pItem)
2893{
2894 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2895 if(pMe->uLastError != QCBOR_SUCCESS) {
2896 return;
2897 }
2898
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002899 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002900}
2901
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002902
2903// This could be semi-private if need be
2904static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002905void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2906 const char *szLabel,
2907 TagSpecification TagSpec,
2908 QCBORItem *pItem)
2909{
2910 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2911 if(pMe->uLastError != QCBOR_SUCCESS) {
2912 return;
2913 }
2914
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002915 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002916}
2917
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002918// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002919void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2920 int64_t nLabel,
2921 TagSpecification TagSpec,
2922 UsefulBufC *pString)
2923{
2924 QCBORItem Item;
2925 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2926 if(pMe->uLastError == QCBOR_SUCCESS) {
2927 *pString = Item.val.string;
2928 }
2929}
2930
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002931// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002932void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2933 const char * szLabel,
2934 TagSpecification TagSpec,
2935 UsefulBufC *pString)
2936{
2937 QCBORItem Item;
2938 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2939 if(pMe->uLastError == QCBOR_SUCCESS) {
2940 *pString = Item.val.string;
2941 }
2942}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002943
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002944/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002945 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002946*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002947void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002948{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002949 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
2950 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002951}
2952
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002953/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002954 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002955*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002956void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
2957 QCBORItem *pItemList,
2958 void *pCallbackCtx,
2959 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002960{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002961 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
2962 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002963}
2964
2965
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08002966/**
2967 * @brief Search for a map/array by label and enter it
2968 *
2969 * @param[in] pMe The decode context.
2970 * @param[in] pSearch The map/array to search for.
2971 *
2972 * @c pSearch is expected to contain one item of type map or array
2973 * with the label specified. The current bounded map will be searched for
2974 * this and if found will be entered.
2975 *
2976 * If the label is not found, or the item found is not a map or array,
2977 * the error state is set.
2978 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002979static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002980{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002981 // The first item in pSearch is the one that is to be
2982 // entered. It should be the only one filled in. Any other
2983 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07002984 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002985 return;
2986 }
2987
2988 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002989 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002990 if(pMe->uLastError != QCBOR_SUCCESS) {
2991 return;
2992 }
2993
Laurence Lundblade9b334962020-08-27 10:55:53 -07002994 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002995 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002996 return;
2997 }
2998
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08002999 /*
3000 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3001 * next item for the pre-order traversal cursor to be the map/array
3002 * found by MapSearch(). The next few lines of code force the
3003 * cursor to that.
3004 *
3005 * There is no need to retain the old cursor because
3006 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3007 * beginning of the map/array being entered.
3008 *
3009 * The cursor is forced by: 1) setting the input buffer position to
3010 * the item offset found by MapSearch(), 2) setting the map/array
3011 * counter to the total in the map/array, 3) setting the nesting
3012 * level. Setting the map/array counter to the total is not
3013 * strictly correct, but this is OK because this cursor only needs
3014 * to be used to get one item and MapSearch() has already found it
3015 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003016 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003017 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003018
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003019 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3020
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003021 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003022
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003023 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003024}
3025
3026
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003027/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003028 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003029*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003030void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003031{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003032 QCBORItem OneItemSeach[2];
3033 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3034 OneItemSeach[0].label.int64 = nLabel;
3035 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3036 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003037
Laurence Lundblade9b334962020-08-27 10:55:53 -07003038 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003039 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003040}
3041
3042
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003043/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003044 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003045*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003046void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003047{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003048 QCBORItem OneItemSeach[2];
3049 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3050 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3051 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3052 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003053
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003054 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003055}
3056
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003057/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003058 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003059*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003060void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003061{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003062 QCBORItem OneItemSeach[2];
3063 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3064 OneItemSeach[0].label.int64 = nLabel;
3065 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3066 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003067
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003068 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003069}
3070
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003071/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003072 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003073*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003074void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3075{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003076 QCBORItem OneItemSeach[2];
3077 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3078 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3079 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3080 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003081
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003082 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003083}
3084
3085
Laurence Lundblade02625d42020-06-25 14:41:41 -07003086// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003087void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003088{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003089 QCBORError uErr;
3090
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003091 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003092 if(pMe->uLastError != QCBOR_SUCCESS) {
3093 // Already in error state; do nothing.
3094 return;
3095 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003096
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003097 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003098 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003099 uErr = QCBORDecode_GetNext(pMe, &Item);
3100 if(uErr != QCBOR_SUCCESS) {
3101 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003102 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003103 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003104 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3105 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003106 }
3107
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003108 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003109
3110
Laurence Lundbladef0499502020-08-01 11:55:57 -07003111 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003112 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003113 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3114 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003115 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003116 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3117 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003118 // Special case to increment nesting level for zero-length maps
3119 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003120 DecodeNesting_Descend(&(pMe->nesting), uType);
3121 }
3122
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003123 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003124
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003125 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3126 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003127
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003128 if(pItem != NULL) {
3129 *pItem = Item;
3130 }
3131
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003132Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003133 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003134}
3135
Laurence Lundblade02625d42020-06-25 14:41:41 -07003136
3137/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003138 This is the common work for exiting a level that is a bounded map,
3139 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003140
3141 One chunk of work is to set up the pre-order traversal so it is at
3142 the item just after the bounded map, array or bstr that is being
3143 exited. This is somewhat complex.
3144
3145 The other work is to level-up the bounded mode to next higest bounded
3146 mode or the top level if there isn't one.
3147 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003148static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003149ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003150{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003151 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003152
Laurence Lundblade02625d42020-06-25 14:41:41 -07003153 /*
3154 First the pre-order-traversal byte offset is positioned to the
3155 item just after the bounded mode item that was just consumed.
3156 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003157 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3158
Laurence Lundblade02625d42020-06-25 14:41:41 -07003159 /*
3160 Next, set the current nesting level to one above the bounded level
3161 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003162
Laurence Lundblade02625d42020-06-25 14:41:41 -07003163 DecodeNesting_CheckBoundedType() is always called before this and
3164 makes sure pCurrentBounded is valid.
3165 */
3166 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3167
3168 /*
3169 This does the complex work of leveling up the pre-order traversal
3170 when the end of a map or array or another bounded level is
3171 reached. It may do nothing, or ascend all the way to the top
3172 level.
3173 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003174 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003175 if(uErr != QCBOR_SUCCESS) {
3176 goto Done;
3177 }
3178
Laurence Lundblade02625d42020-06-25 14:41:41 -07003179 /*
3180 This makes the next highest bounded level the current bounded
3181 level. If there is no next highest level, then no bounded mode is
3182 in effect.
3183 */
3184 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003185
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003186 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003187
3188Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003189 return uErr;
3190}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003191
Laurence Lundblade02625d42020-06-25 14:41:41 -07003192
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003193// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003194void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003195{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003196 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003197 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003198 return;
3199 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003200
Laurence Lundblade02625d42020-06-25 14:41:41 -07003201 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003202
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003203 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003204 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003205 goto Done;
3206 }
3207
Laurence Lundblade02625d42020-06-25 14:41:41 -07003208 /*
3209 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003210 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003211 from previous map search, then do a dummy search.
3212 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003213 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003214 QCBORItem Dummy;
3215 Dummy.uLabelType = QCBOR_TYPE_NONE;
3216 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3217 if(uErr != QCBOR_SUCCESS) {
3218 goto Done;
3219 }
3220 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003221
Laurence Lundblade02625d42020-06-25 14:41:41 -07003222 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003223
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003224Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003225 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003226}
3227
3228
Laurence Lundblade1341c592020-04-11 14:19:05 -07003229
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003230static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003231 const QCBORItem *pItem,
3232 uint8_t uTagRequirement,
3233 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003234{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003235 if(pBstr) {
3236 *pBstr = NULLUsefulBufC;
3237 }
3238
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003239 if(pMe->uLastError != QCBOR_SUCCESS) {
3240 // Already in error state; do nothing.
3241 return pMe->uLastError;
3242 }
3243
3244 QCBORError uError = QCBOR_SUCCESS;
3245
3246 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3247 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3248 goto Done;;
3249 }
3250
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003251 const TagSpecification TagSpec =
3252 {
3253 uTagRequirement,
3254 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3255 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3256 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003257
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003258 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003259 if(uError != QCBOR_SUCCESS) {
3260 goto Done;
3261 }
3262
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003263 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003264 // Reverse the decrement done by GetNext() for the bstr so the
3265 // increment in NestLevelAscender() called by ExitBoundedLevel()
3266 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003267 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003268 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003269
3270 if(pBstr) {
3271 *pBstr = pItem->val.string;
3272 }
3273
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003274 // This saves the current length of the UsefulInputBuf and then
3275 // narrows the UsefulInputBuf to start and length of the wrapped
3276 // CBOR that is being entered.
3277 //
3278 // This makes sure the length is less than
3279 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3280 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3281 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3282 // the casts safe. uEndOfBstr will always be less than
3283 // uPreviousLength because of the way UsefulInputBuf works so there
3284 // is no need to check it. There is also a range check in the
3285 // seek.
3286 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003287 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003288 // amount to much code.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003289 // Cast of uPreviousLength to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003290 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003291 if((uint32_t)uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003292 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003293 goto Done;
3294 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003295 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003296 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003297 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003298
Laurence Lundblade02625d42020-06-25 14:41:41 -07003299 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003300 (uint32_t)uPreviousLength,
3301 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003302Done:
3303 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003304}
3305
3306
Laurence Lundblade02625d42020-06-25 14:41:41 -07003307/*
3308 Public function, see header qcbor/qcbor_decode.h file
3309 */
3310void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003311 uint8_t uTagRequirement,
3312 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003313{
3314 if(pMe->uLastError != QCBOR_SUCCESS) {
3315 // Already in error state; do nothing.
3316 return;
3317 }
3318
3319 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003320 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003321 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3322 if(pMe->uLastError != QCBOR_SUCCESS) {
3323 return;
3324 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003325
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003326 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003327 &Item,
3328 uTagRequirement,
3329 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003330}
3331
3332
Laurence Lundblade02625d42020-06-25 14:41:41 -07003333/*
3334 Public function, see header qcbor/qcbor_decode.h file
3335 */
3336void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003337 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003338 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003339 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003340{
3341 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003342 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003343
Laurence Lundblade93d89472020-10-03 22:30:50 -07003344 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3345 &Item,
3346 uTagRequirement,
3347 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003348}
3349
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003350
Laurence Lundblade02625d42020-06-25 14:41:41 -07003351/*
3352 Public function, see header qcbor/qcbor_decode.h file
3353 */
3354void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003355 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003356 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003357 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003358{
3359 QCBORItem Item;
3360 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3361
Laurence Lundblade93d89472020-10-03 22:30:50 -07003362 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3363 &Item,
3364 uTagRequirement,
3365 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003366}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003367
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003368
Laurence Lundblade02625d42020-06-25 14:41:41 -07003369/*
3370 Public function, see header qcbor/qcbor_decode.h file
3371 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003372void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003373{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003374 if(pMe->uLastError != QCBOR_SUCCESS) {
3375 // Already in error state; do nothing.
3376 return;
3377 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003378
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003379 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003380 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003381 return;
3382 }
3383
3384 /*
3385 Reset the length of the UsefulInputBuf to what it was before
3386 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003387 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003388 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003389 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003390
3391
Laurence Lundblade02625d42020-06-25 14:41:41 -07003392 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003393 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003394}
3395
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003396
Laurence Lundbladee6430642020-03-14 21:15:44 -07003397
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003398
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003399
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003400
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003401
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003402
Laurence Lundblade93d89472020-10-03 22:30:50 -07003403static QCBORError
3404InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003405{
3406 switch(pItem->uDataType) {
3407 case QCBOR_TYPE_TRUE:
3408 *pBool = true;
3409 return QCBOR_SUCCESS;
3410 break;
3411
3412 case QCBOR_TYPE_FALSE:
3413 *pBool = false;
3414 return QCBOR_SUCCESS;
3415 break;
3416
3417 default:
3418 return QCBOR_ERR_UNEXPECTED_TYPE;
3419 break;
3420 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003421 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003422}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003423
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003424
Laurence Lundblade9b334962020-08-27 10:55:53 -07003425
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003426/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003427 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003428*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003429void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003430{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003431 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003432 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003433 return;
3434 }
3435
Laurence Lundbladec4537442020-04-14 18:53:22 -07003436 QCBORError nError;
3437 QCBORItem Item;
3438
3439 nError = QCBORDecode_GetNext(pMe, &Item);
3440 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003441 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003442 return;
3443 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003444 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003445}
3446
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003447
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003448/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003449 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003450*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003451void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003452{
3453 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003454 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003455
Laurence Lundblade9b334962020-08-27 10:55:53 -07003456 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003457}
3458
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003459
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003460/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003461 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003462*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003463void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3464{
3465 QCBORItem Item;
3466 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3467
Laurence Lundblade9b334962020-08-27 10:55:53 -07003468 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003469}
3470
3471
3472
Laurence Lundbladec7114722020-08-13 05:11:40 -07003473
3474static void ProcessEpochDate(QCBORDecodeContext *pMe,
3475 QCBORItem *pItem,
3476 uint8_t uTagRequirement,
3477 int64_t *pnTime)
3478{
3479 if(pMe->uLastError != QCBOR_SUCCESS) {
3480 // Already in error state, do nothing
3481 return;
3482 }
3483
3484 QCBORError uErr;
3485
3486 const TagSpecification TagSpec =
3487 {
3488 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003489 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3490 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003491 };
3492
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003493 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003494 if(uErr != QCBOR_SUCCESS) {
3495 goto Done;
3496 }
3497
3498 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3499 uErr = DecodeDateEpoch(pItem);
3500 if(uErr != QCBOR_SUCCESS) {
3501 goto Done;
3502 }
3503 }
3504
Laurence Lundblade9b334962020-08-27 10:55:53 -07003505 // Save the tags in the last item's tags in the decode context
3506 // for QCBORDecode_GetNthTagOfLast()
3507 CopyTags(pMe, pItem);
3508
Laurence Lundbladec7114722020-08-13 05:11:40 -07003509 *pnTime = pItem->val.epochDate.nSeconds;
3510
3511Done:
3512 pMe->uLastError = (uint8_t)uErr;
3513}
3514
3515
3516void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003517 uint8_t uTagRequirement,
3518 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003519{
3520 if(pMe->uLastError != QCBOR_SUCCESS) {
3521 // Already in error state, do nothing
3522 return;
3523 }
3524
3525 QCBORItem Item;
3526 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3527
3528 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3529}
3530
3531
3532void
3533QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3534 int64_t nLabel,
3535 uint8_t uTagRequirement,
3536 int64_t *pnTime)
3537{
3538 QCBORItem Item;
3539 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3540 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3541}
3542
3543
3544void
3545QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3546 const char *szLabel,
3547 uint8_t uTagRequirement,
3548 int64_t *pnTime)
3549{
3550 QCBORItem Item;
3551 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3552 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3553}
3554
3555
3556
3557
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003558void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3559 TagSpecification TagSpec,
3560 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003561{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003562 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003563 // Already in error state, do nothing
3564 return;
3565 }
3566
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003567 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003568 QCBORItem Item;
3569
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003570 uError = QCBORDecode_GetNext(pMe, &Item);
3571 if(uError != QCBOR_SUCCESS) {
3572 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003573 return;
3574 }
3575
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003576 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003577
3578 if(pMe->uLastError == QCBOR_SUCCESS) {
3579 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003580 } else {
3581 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003582 }
3583}
3584
Laurence Lundbladec4537442020-04-14 18:53:22 -07003585
3586
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003587
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003588static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003589 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003590 UsefulBufC *pValue,
3591 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003592{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003593 const TagSpecification TagSpec =
3594 {
3595 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003596 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3597 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003598 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003599
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003600 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003601 if(uErr != QCBOR_SUCCESS) {
3602 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003603 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003604
3605 *pValue = pItem->val.string;
3606
3607 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3608 *pbIsNegative = false;
3609 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3610 *pbIsNegative = true;
3611 }
3612
3613 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003614}
3615
3616
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003617/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003618 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003619 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003620void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3621 uint8_t uTagRequirement,
3622 UsefulBufC *pValue,
3623 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003624{
3625 if(pMe->uLastError != QCBOR_SUCCESS) {
3626 // Already in error state, do nothing
3627 return;
3628 }
3629
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003630 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003631 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3632 if(uError != QCBOR_SUCCESS) {
3633 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003634 return;
3635 }
3636
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003637 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003638}
3639
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003640
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003641/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003642 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003643*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003644void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3645 int64_t nLabel,
3646 uint8_t uTagRequirement,
3647 UsefulBufC *pValue,
3648 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003649{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003650 QCBORItem Item;
3651 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003652 if(pMe->uLastError != QCBOR_SUCCESS) {
3653 return;
3654 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003655
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003656 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003657}
3658
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003659
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003660/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003661 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003662*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003663void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3664 const char *szLabel,
3665 uint8_t uTagRequirement,
3666 UsefulBufC *pValue,
3667 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003668{
3669 QCBORItem Item;
3670 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003671 if(pMe->uLastError != QCBOR_SUCCESS) {
3672 return;
3673 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003674
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003675 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003676}
3677
3678
3679
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003680
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003681// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003682QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3683 const QCBORItem *pItem,
3684 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003685 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003686{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003687 const TagSpecification TagSpecText =
3688 {
3689 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003690 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3691 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003692 };
3693 const TagSpecification TagSpecBinary =
3694 {
3695 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003696 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3697 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003698 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003699
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003700 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003701
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003702 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003703 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003704 if(pbIsTag257 != NULL) {
3705 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003706 }
3707 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003708 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003709 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003710 if(pbIsTag257 != NULL) {
3711 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003712 }
3713 uReturn = QCBOR_SUCCESS;
3714
3715 } else {
3716 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3717 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003718
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003719 return uReturn;
3720}
3721
Laurence Lundblade93d89472020-10-03 22:30:50 -07003722// Improvement: add methods for wrapped CBOR, a simple alternate
3723// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003724
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003725
3726
3727
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003728#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003729
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003730typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003731
3732
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003733// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003734static QCBORError
3735Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003736{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003737 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003738
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003739 if(uResult != 0) {
3740 /* This loop will run a maximum of 19 times because
3741 * UINT64_MAX < 10 ^^ 19. More than that will cause
3742 * exit with the overflow error
3743 */
3744 for(; nExponent > 0; nExponent--) {
3745 if(uResult > UINT64_MAX / 10) {
3746 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3747 }
3748 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003749 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003750
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003751 for(; nExponent < 0; nExponent++) {
3752 uResult = uResult / 10;
3753 if(uResult == 0) {
3754 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3755 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003756 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003757 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003758 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003759
3760 *puResult = uResult;
3761
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003762 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003763}
3764
3765
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003766// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003767static QCBORError
3768Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003769{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003770 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003771
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003772 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003773
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003774 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003775 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003776 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003777 */
3778 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003779 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003780 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003781 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003782 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003783 nExponent--;
3784 }
3785
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003786 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003787 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003788 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3789 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003790 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003791 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003792 }
3793
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003794 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003795
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003796 return QCBOR_SUCCESS;
3797}
3798
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003799
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003800/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003801 Compute value with signed mantissa and signed result. Works with
3802 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003803 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003804static inline QCBORError ExponentiateNN(int64_t nMantissa,
3805 int64_t nExponent,
3806 int64_t *pnResult,
3807 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003808{
3809 uint64_t uResult;
3810
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003811 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003812 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003813 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3814
3815 // Do the exponentiation of the positive mantissa
3816 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3817 if(uReturn) {
3818 return uReturn;
3819 }
3820
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003821
Laurence Lundblade983500d2020-05-14 11:49:34 -07003822 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3823 of INT64_MIN. This assumes two's compliment representation where
3824 INT64_MIN is one increment farther from 0 than INT64_MAX.
3825 Trying to write -INT64_MIN doesn't work to get this because the
3826 compiler tries to work with an int64_t which can't represent
3827 -INT64_MIN.
3828 */
3829 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3830
3831 // Error out if too large
3832 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003833 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3834 }
3835
3836 // Casts are safe because of checks above
3837 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3838
3839 return QCBOR_SUCCESS;
3840}
3841
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003842
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003843/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003844 Compute value with signed mantissa and unsigned result. Works with
3845 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003846 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003847static inline QCBORError ExponentitateNU(int64_t nMantissa,
3848 int64_t nExponent,
3849 uint64_t *puResult,
3850 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003851{
3852 if(nMantissa < 0) {
3853 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3854 }
3855
3856 // Cast to unsigned is OK because of check for negative
3857 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3858 // Exponentiation is straight forward
3859 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3860}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003861
3862
3863/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003864 Compute value with signed mantissa and unsigned result. Works with
3865 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003866 */
3867static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3868 int64_t nExponent,
3869 uint64_t *puResult,
3870 fExponentiator pfExp)
3871{
3872 return (*pfExp)(uMantissa, nExponent, puResult);
3873}
3874
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003875#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3876
3877
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003878
3879
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003880
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003881static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003882{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003883 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003884
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003885 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003886 const uint8_t *pByte = BigNum.ptr;
3887 size_t uLen = BigNum.len;
3888 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003889 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003890 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003891 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003892 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003893 }
3894
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003895 *pResult = uResult;
3896 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003897}
3898
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003899
Laurence Lundblade887add82020-05-17 05:50:34 -07003900static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003901{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003902 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003903}
3904
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003905
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003906static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003907{
3908 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003909 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3910 if(uError) {
3911 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003912 }
3913 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3914 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003915 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003916}
3917
3918
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003919static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003920{
3921 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003922 /* The negative integer furthest from zero for a C int64_t is
3923 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3924 negative number in CBOR is computed as -n - 1 where n is the
3925 encoded integer, where n is what is in the variable BigNum. When
3926 converting BigNum to a uint64_t, the maximum value is thus
3927 INT64_MAX, so that when it -n - 1 is applied to it the result will
3928 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003929
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003930 -n - 1 <= INT64_MIN.
3931 -n - 1 <= -INT64_MAX - 1
3932 n <= INT64_MAX.
3933 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003934 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003935 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003936 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003937 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003938
3939 /// Now apply -n - 1. The cast is safe because
3940 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3941 // is the largest positive integer that an int64_t can
3942 // represent. */
3943 *pnResult = -(int64_t)uResult - 1;
3944
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003945 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003946}
3947
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003948
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003949
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003950
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003951
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003952/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003953Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003954
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003955\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003956
Laurence Lundblade93d89472020-10-03 22:30:50 -07003957\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
3958 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003959
3960\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3961
Laurence Lundblade93d89472020-10-03 22:30:50 -07003962\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
3963 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003964*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07003965static QCBORError
3966ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003967{
3968 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003969 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003970 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003971#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003972 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003973 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
3974 http://www.cplusplus.com/reference/cmath/llround/
3975 */
3976 // Not interested in FE_INEXACT
3977 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003978 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
3979 *pnValue = llround(pItem->val.dfnum);
3980 } else {
3981 *pnValue = lroundf(pItem->val.fnum);
3982 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003983 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
3984 // llround() shouldn't result in divide by zero, but catch
3985 // it here in case it unexpectedly does. Don't try to
3986 // distinguish between the various exceptions because it seems
3987 // they vary by CPU, compiler and OS.
3988 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003989 }
3990 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003991 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003992 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003993#else
3994 return QCBOR_ERR_HW_FLOAT_DISABLED;
3995#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003996 break;
3997
3998 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003999 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004000 *pnValue = pItem->val.int64;
4001 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004002 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004003 }
4004 break;
4005
4006 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004007 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004008 if(pItem->val.uint64 < INT64_MAX) {
4009 *pnValue = pItem->val.int64;
4010 } else {
4011 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4012 }
4013 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004014 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004015 }
4016 break;
4017
4018 default:
4019 return QCBOR_ERR_UNEXPECTED_TYPE;
4020 }
4021 return QCBOR_SUCCESS;
4022}
4023
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004024
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004025void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004026 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004027 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004028 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004029{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004030 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004031 return;
4032 }
4033
Laurence Lundbladee6430642020-03-14 21:15:44 -07004034 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004035 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4036 if(uError) {
4037 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004038 return;
4039 }
4040
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004041 if(pItem) {
4042 *pItem = Item;
4043 }
4044
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004045 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004046}
4047
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004048
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004049void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4050 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004051 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004052 int64_t *pnValue,
4053 QCBORItem *pItem)
4054{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004055 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004056 if(pMe->uLastError != QCBOR_SUCCESS) {
4057 return;
4058 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004059
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004060 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004061}
4062
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004063
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004064void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4065 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004066 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004067 int64_t *pnValue,
4068 QCBORItem *pItem)
4069{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004070 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004071 if(pMe->uLastError != QCBOR_SUCCESS) {
4072 return;
4073 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004074
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004075 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004076}
4077
4078
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004079/*
4080 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004081
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004082 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004083
Laurence Lundblade93d89472020-10-03 22:30:50 -07004084 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4085 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004086
4087 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4088
Laurence Lundblade93d89472020-10-03 22:30:50 -07004089 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4090 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004091 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004092static QCBORError
4093Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004094{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004095 switch(pItem->uDataType) {
4096
4097 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004098 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004099 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004100 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004101 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004102 }
4103 break;
4104
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004105 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004106 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004107 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004108 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004109 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004110 }
4111 break;
4112
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004113#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4114 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004115 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004116 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004117 pItem->val.expAndMantissa.nExponent,
4118 pnValue,
4119 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004120 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004121 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004122 }
4123 break;
4124
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004125 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004126 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004127 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004128 pItem->val.expAndMantissa.nExponent,
4129 pnValue,
4130 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004131 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004132 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004133 }
4134 break;
4135
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004136 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004137 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004138 int64_t nMantissa;
4139 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004140 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4141 if(uErr) {
4142 return uErr;
4143 }
4144 return ExponentiateNN(nMantissa,
4145 pItem->val.expAndMantissa.nExponent,
4146 pnValue,
4147 Exponentitate10);
4148 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004149 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004150 }
4151 break;
4152
4153 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004154 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004155 int64_t nMantissa;
4156 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004157 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4158 if(uErr) {
4159 return uErr;
4160 }
4161 return ExponentiateNN(nMantissa,
4162 pItem->val.expAndMantissa.nExponent,
4163 pnValue,
4164 Exponentitate10);
4165 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004166 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004167 }
4168 break;
4169
4170 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004171 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004172 int64_t nMantissa;
4173 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004174 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4175 if(uErr) {
4176 return uErr;
4177 }
4178 return ExponentiateNN(nMantissa,
4179 pItem->val.expAndMantissa.nExponent,
4180 pnValue,
4181 Exponentitate2);
4182 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004183 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004184 }
4185 break;
4186
4187 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004188 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004189 int64_t nMantissa;
4190 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004191 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4192 if(uErr) {
4193 return uErr;
4194 }
4195 return ExponentiateNN(nMantissa,
4196 pItem->val.expAndMantissa.nExponent,
4197 pnValue,
4198 Exponentitate2);
4199 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004200 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004201 }
4202 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004203#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4204
Laurence Lundbladee6430642020-03-14 21:15:44 -07004205
Laurence Lundbladec4537442020-04-14 18:53:22 -07004206 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004207 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004208}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004209
4210
Laurence Lundbladec4537442020-04-14 18:53:22 -07004211/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004212 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004213 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004214void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004215{
4216 QCBORItem Item;
4217
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004218 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004219
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004220 if(pMe->uLastError == QCBOR_SUCCESS) {
4221 // The above conversion succeeded
4222 return;
4223 }
4224
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004225 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004226 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004227 return;
4228 }
4229
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004230 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004231}
4232
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004233
4234/*
4235Public function, see header qcbor/qcbor_decode.h file
4236*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004237void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4238 int64_t nLabel,
4239 uint32_t uConvertTypes,
4240 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004241{
4242 QCBORItem Item;
4243
Laurence Lundblade93d89472020-10-03 22:30:50 -07004244 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4245 nLabel,
4246 uConvertTypes,
4247 pnValue,
4248 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004249
4250 if(pMe->uLastError == QCBOR_SUCCESS) {
4251 // The above conversion succeeded
4252 return;
4253 }
4254
4255 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4256 // The above conversion failed in a way that code below can't correct
4257 return;
4258 }
4259
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004260 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004261}
4262
4263
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004264/*
4265Public function, see header qcbor/qcbor_decode.h file
4266*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004267void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4268 const char *szLabel,
4269 uint32_t uConvertTypes,
4270 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004271{
4272 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004273 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4274 szLabel,
4275 uConvertTypes,
4276 pnValue,
4277 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004278
4279 if(pMe->uLastError == QCBOR_SUCCESS) {
4280 // The above conversion succeeded
4281 return;
4282 }
4283
4284 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4285 // The above conversion failed in a way that code below can't correct
4286 return;
4287 }
4288
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004289 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004290}
4291
4292
Laurence Lundblade93d89472020-10-03 22:30:50 -07004293static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004294{
4295 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004296 case QCBOR_TYPE_DOUBLE:
4297 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004298#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004299 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004300 // Can't use llround here because it will not convert values
4301 // greater than INT64_MAX and less than UINT64_MAX that
4302 // need to be converted so it is more complicated.
4303 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4304 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4305 if(isnan(pItem->val.dfnum)) {
4306 return QCBOR_ERR_FLOAT_EXCEPTION;
4307 } else if(pItem->val.dfnum < 0) {
4308 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4309 } else {
4310 double dRounded = round(pItem->val.dfnum);
4311 // See discussion in DecodeDateEpoch() for
4312 // explanation of - 0x7ff
4313 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4314 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4315 }
4316 *puValue = (uint64_t)dRounded;
4317 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004318 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004319 if(isnan(pItem->val.fnum)) {
4320 return QCBOR_ERR_FLOAT_EXCEPTION;
4321 } else if(pItem->val.fnum < 0) {
4322 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4323 } else {
4324 float fRounded = roundf(pItem->val.fnum);
4325 // See discussion in DecodeDateEpoch() for
4326 // explanation of - 0x7ff
4327 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4328 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4329 }
4330 *puValue = (uint64_t)fRounded;
4331 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004332 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004333 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4334 // round() and roundf() shouldn't result in exceptions here, but
4335 // catch them to be robust and thorough. Don't try to
4336 // distinguish between the various exceptions because it seems
4337 // they vary by CPU, compiler and OS.
4338 return QCBOR_ERR_FLOAT_EXCEPTION;
4339 }
4340
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004341 } else {
4342 return QCBOR_ERR_UNEXPECTED_TYPE;
4343 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004344#else
4345 return QCBOR_ERR_HW_FLOAT_DISABLED;
4346#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004347 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004348
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004349 case QCBOR_TYPE_INT64:
4350 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4351 if(pItem->val.int64 >= 0) {
4352 *puValue = (uint64_t)pItem->val.int64;
4353 } else {
4354 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4355 }
4356 } else {
4357 return QCBOR_ERR_UNEXPECTED_TYPE;
4358 }
4359 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004360
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004361 case QCBOR_TYPE_UINT64:
4362 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4363 *puValue = pItem->val.uint64;
4364 } else {
4365 return QCBOR_ERR_UNEXPECTED_TYPE;
4366 }
4367 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004368
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004369 default:
4370 return QCBOR_ERR_UNEXPECTED_TYPE;
4371 }
4372
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004373 return QCBOR_SUCCESS;
4374}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004375
4376
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004377void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004378 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004379 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004380 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004381{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004382 if(pMe->uLastError != QCBOR_SUCCESS) {
4383 return;
4384 }
4385
Laurence Lundbladec4537442020-04-14 18:53:22 -07004386 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004387
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004388 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4389 if(uError) {
4390 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004391 return;
4392 }
4393
Laurence Lundbladea826c502020-05-10 21:07:00 -07004394 if(pItem) {
4395 *pItem = Item;
4396 }
4397
Laurence Lundblade93d89472020-10-03 22:30:50 -07004398 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004399}
4400
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004401
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004402void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004403 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004404 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004405 uint64_t *puValue,
4406 QCBORItem *pItem)
4407{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004408 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004409 if(pMe->uLastError != QCBOR_SUCCESS) {
4410 return;
4411 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004412
Laurence Lundblade93d89472020-10-03 22:30:50 -07004413 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004414}
4415
4416
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004417void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004418 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004419 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004420 uint64_t *puValue,
4421 QCBORItem *pItem)
4422{
4423 if(pMe->uLastError != QCBOR_SUCCESS) {
4424 return;
4425 }
4426
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004427 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004428 if(pMe->uLastError != QCBOR_SUCCESS) {
4429 return;
4430 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004431
Laurence Lundblade93d89472020-10-03 22:30:50 -07004432 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004433}
4434
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004435
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004436
Laurence Lundblade93d89472020-10-03 22:30:50 -07004437static QCBORError
4438UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004439{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004440 switch(pItem->uDataType) {
4441
4442 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004443 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004444 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4445 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004446 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004447 }
4448 break;
4449
4450 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004451 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004452 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4453 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004454 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004455 }
4456 break;
4457
4458#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4459
4460 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004461 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004462 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004463 pItem->val.expAndMantissa.nExponent,
4464 puValue,
4465 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004466 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004467 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004468 }
4469 break;
4470
4471 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004472 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004473 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4474 pItem->val.expAndMantissa.nExponent,
4475 puValue,
4476 Exponentitate2);
4477 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004478 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004479 }
4480 break;
4481
4482 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004483 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004484 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004485 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004486 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004487 if(uErr != QCBOR_SUCCESS) {
4488 return uErr;
4489 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004490 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004491 pItem->val.expAndMantissa.nExponent,
4492 puValue,
4493 Exponentitate10);
4494 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004495 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004496 }
4497 break;
4498
4499 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004500 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004501 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4502 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004503 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004504 }
4505 break;
4506
4507 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004508 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004509 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004510 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004511 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004512 if(uErr != QCBOR_SUCCESS) {
4513 return uErr;
4514 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004515 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004516 pItem->val.expAndMantissa.nExponent,
4517 puValue,
4518 Exponentitate2);
4519 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004520 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004521 }
4522 break;
4523
4524 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004525 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004526 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4527 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004528 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004529 }
4530 break;
4531#endif
4532 default:
4533 return QCBOR_ERR_UNEXPECTED_TYPE;
4534 }
4535}
4536
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004537
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004538/*
4539 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004540 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004541void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004542{
4543 QCBORItem Item;
4544
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004545 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004546
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004547 if(pMe->uLastError == QCBOR_SUCCESS) {
4548 // The above conversion succeeded
4549 return;
4550 }
4551
4552 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4553 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004554 return;
4555 }
4556
Laurence Lundblade93d89472020-10-03 22:30:50 -07004557 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004558}
4559
Laurence Lundbladec4537442020-04-14 18:53:22 -07004560
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004561/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004562 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004563*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004564void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004565 int64_t nLabel,
4566 uint32_t uConvertTypes,
4567 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004568{
4569 QCBORItem Item;
4570
Laurence Lundblade93d89472020-10-03 22:30:50 -07004571 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4572 nLabel,
4573 uConvertTypes,
4574 puValue,
4575 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004576
4577 if(pMe->uLastError == QCBOR_SUCCESS) {
4578 // The above conversion succeeded
4579 return;
4580 }
4581
4582 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4583 // The above conversion failed in a way that code below can't correct
4584 return;
4585 }
4586
Laurence Lundblade93d89472020-10-03 22:30:50 -07004587 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004588}
4589
4590
4591/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004592 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004593*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004594void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004595 const char *szLabel,
4596 uint32_t uConvertTypes,
4597 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004598{
4599 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004600 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4601 szLabel,
4602 uConvertTypes,
4603 puValue,
4604 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004605
4606 if(pMe->uLastError == QCBOR_SUCCESS) {
4607 // The above conversion succeeded
4608 return;
4609 }
4610
4611 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4612 // The above conversion failed in a way that code below can't correct
4613 return;
4614 }
4615
Laurence Lundblade93d89472020-10-03 22:30:50 -07004616 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004617}
4618
4619
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004620
4621
Laurence Lundblade9b334962020-08-27 10:55:53 -07004622static QCBORError ConvertDouble(const QCBORItem *pItem,
4623 uint32_t uConvertTypes,
4624 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004625{
4626 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004627 case QCBOR_TYPE_FLOAT:
4628#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4629 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4630 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004631 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004632 *pdValue = (double)pItem->val.fnum;
4633 } else {
4634 return QCBOR_ERR_UNEXPECTED_TYPE;
4635 }
4636 }
4637#else
4638 return QCBOR_ERR_HW_FLOAT_DISABLED;
4639#endif
4640 break;
4641
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004642 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004643 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4644 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004645 *pdValue = pItem->val.dfnum;
4646 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004647 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004648 }
4649 }
4650 break;
4651
4652 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004653#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004654 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004655 // A simple cast seems to do the job with no worry of exceptions.
4656 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004657 *pdValue = (double)pItem->val.int64;
4658
4659 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004660 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004661 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004662#else
4663 return QCBOR_ERR_HW_FLOAT_DISABLED;
4664#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004665 break;
4666
4667 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004668#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004669 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004670 // A simple cast seems to do the job with no worry of exceptions.
4671 // There will be precision loss for some values.
4672 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004673 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004674 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004675 }
4676 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004677#else
4678 return QCBOR_ERR_HW_FLOAT_DISABLED;
4679#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004680
4681 default:
4682 return QCBOR_ERR_UNEXPECTED_TYPE;
4683 }
4684
4685 return QCBOR_SUCCESS;
4686}
4687
4688
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004689void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004690 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004691 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004692 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004693{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004694 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004695 return;
4696 }
4697
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004698 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004699
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004700 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004701 if(uError) {
4702 pMe->uLastError = (uint8_t)uError;
4703 return;
4704 }
4705
4706 if(pItem) {
4707 *pItem = Item;
4708 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004709
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004710 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004711}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004712
Laurence Lundbladec4537442020-04-14 18:53:22 -07004713
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004714void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4715 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004716 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004717 double *pdValue,
4718 QCBORItem *pItem)
4719{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004720 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004721 if(pMe->uLastError != QCBOR_SUCCESS) {
4722 return;
4723 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004724
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004725 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004726}
4727
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004728
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004729void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4730 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004731 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004732 double *pdValue,
4733 QCBORItem *pItem)
4734{
4735 if(pMe->uLastError != QCBOR_SUCCESS) {
4736 return;
4737 }
4738
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004739 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004740 if(pMe->uLastError != QCBOR_SUCCESS) {
4741 return;
4742 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004743
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004744 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004745}
4746
4747
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004748#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004749static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4750{
4751 double dResult;
4752
4753 dResult = 0.0;
4754 const uint8_t *pByte = BigNum.ptr;
4755 size_t uLen = BigNum.len;
4756 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004757 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004758 while(uLen--) {
4759 dResult = (dResult * 256.0) + (double)*pByte++;
4760 }
4761
4762 return dResult;
4763}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004764#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4765
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004766
Laurence Lundblade93d89472020-10-03 22:30:50 -07004767static QCBORError
4768DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004769{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004770#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004771 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004772 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4773
4774 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004775 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004776
4777#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004778 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004779 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004780 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004781 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4782 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4783 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004784 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004785 }
4786 break;
4787
4788 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004789 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004790 // Underflow gives 0, overflow gives infinity
4791 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4792 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004793 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004794 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004795 }
4796 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004797#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004798
4799 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004800 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004801 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4802 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004803 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004804 }
4805 break;
4806
4807 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004808 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004809 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004810 } 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
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004815#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004816 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004817 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004818 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4819 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4820 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004821 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004822 }
4823 break;
4824
4825 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004826 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004827 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4828 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
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_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004835 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004836 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4837 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4838 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004839 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004840 }
4841 break;
4842
4843 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004844 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004845 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004846 *pdValue = dMantissa * exp2((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;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004851#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4852
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004853 default:
4854 return QCBOR_ERR_UNEXPECTED_TYPE;
4855 }
4856
4857 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004858
4859#else
4860 (void)pItem;
4861 (void)uConvertTypes;
4862 (void)pdValue;
4863 return QCBOR_ERR_HW_FLOAT_DISABLED;
4864#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4865
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004866}
4867
4868
4869/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004870 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004871*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004872void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4873 uint32_t uConvertTypes,
4874 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004875{
4876
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004877 QCBORItem Item;
4878
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004879 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004880
4881 if(pMe->uLastError == QCBOR_SUCCESS) {
4882 // The above conversion succeeded
4883 return;
4884 }
4885
4886 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4887 // The above conversion failed in a way that code below can't correct
4888 return;
4889 }
4890
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004891 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004892}
4893
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004894
4895/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004896 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004897*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004898void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4899 int64_t nLabel,
4900 uint32_t uConvertTypes,
4901 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004902{
4903 QCBORItem Item;
4904
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004905 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004906
4907 if(pMe->uLastError == QCBOR_SUCCESS) {
4908 // The above conversion succeeded
4909 return;
4910 }
4911
4912 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4913 // The above conversion failed in a way that code below can't correct
4914 return;
4915 }
4916
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004917 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004918}
4919
4920
4921/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004922 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004923*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004924void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4925 const char *szLabel,
4926 uint32_t uConvertTypes,
4927 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004928{
4929 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004930 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004931
4932 if(pMe->uLastError == QCBOR_SUCCESS) {
4933 // The above conversion succeeded
4934 return;
4935 }
4936
4937 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4938 // The above conversion failed in a way that code below can't correct
4939 return;
4940 }
4941
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004942 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004943}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004944
4945
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004946
4947
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004948#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004949static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4950{
4951 while((uInt & 0xff00000000000000UL) == 0) {
4952 uInt = uInt << 8;
4953 };
4954
4955 UsefulOutBuf UOB;
4956
4957 UsefulOutBuf_Init(&UOB, Buffer);
4958
4959 while(uInt) {
4960 const uint64_t xx = uInt & 0xff00000000000000UL;
4961 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4962 uInt = uInt << 8;
4963 (void)xx;
4964 }
4965
4966 return UsefulOutBuf_OutUBuf(&UOB);
4967}
4968
4969
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004970static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4971 TagSpecification TagSpec,
4972 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004973{
4974 QCBORError uErr;
4975 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004976 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004977 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004978 if(uErr != QCBOR_SUCCESS) {
4979 goto Done;
4980 }
4981
4982 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4983 break; // Successful exit. Moving on to finish decoding.
4984 }
4985
4986 // The item is an array, which means an undecoded
4987 // mantissa and exponent, so decode it. It will then
4988 // have a different type and exit the loop if.
4989 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4990 if(uErr != QCBOR_SUCCESS) {
4991 goto Done;
4992 }
4993
4994 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07004995 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004996 }
4997Done:
4998 return uErr;
4999}
5000
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005001
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005002static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005003 TagSpecification TagSpec,
5004 QCBORItem *pItem,
5005 int64_t *pnMantissa,
5006 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005007{
5008 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005009
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005010 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005011 if(uErr != QCBOR_SUCCESS) {
5012 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005013 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005014
Laurence Lundblade9b334962020-08-27 10:55:53 -07005015 switch (pItem->uDataType) {
5016
5017 case QCBOR_TYPE_DECIMAL_FRACTION:
5018 case QCBOR_TYPE_BIGFLOAT:
5019 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5020 *pnExponent = pItem->val.expAndMantissa.nExponent;
5021 break;
5022
5023 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5024 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5025 *pnExponent = pItem->val.expAndMantissa.nExponent;
5026 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5027 break;
5028
5029 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5030 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5031 *pnExponent = pItem->val.expAndMantissa.nExponent;
5032 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5033 break;
5034
5035 default:
5036 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5037 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005038
5039 Done:
5040 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005041}
5042
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005043
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005044static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005045 TagSpecification TagSpec,
5046 QCBORItem *pItem,
5047 UsefulBuf BufferForMantissa,
5048 UsefulBufC *pMantissa,
5049 bool *pbIsNegative,
5050 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005051{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005052 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005053
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005054 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005055 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005056 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005057 }
5058
5059 uint64_t uMantissa;
5060
5061 switch (pItem->uDataType) {
5062
5063 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005064 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005065 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5066 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5067 *pbIsNegative = false;
5068 } else {
5069 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5070 *pbIsNegative = true;
5071 }
5072 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5073 *pnExponent = pItem->val.expAndMantissa.nExponent;
5074 break;
5075
5076 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005077 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005078 *pnExponent = pItem->val.expAndMantissa.nExponent;
5079 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5080 *pbIsNegative = false;
5081 break;
5082
5083 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005084 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005085 *pnExponent = pItem->val.expAndMantissa.nExponent;
5086 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5087 *pbIsNegative = true;
5088 break;
5089
5090 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005091 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005092 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005093
5094Done:
5095 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005096}
5097
5098
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005099/*
5100 Public function, see header qcbor/qcbor_decode.h file
5101*/
5102void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5103 uint8_t uTagRequirement,
5104 int64_t *pnMantissa,
5105 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005106{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005107 if(pMe->uLastError != QCBOR_SUCCESS) {
5108 return;
5109 }
5110
5111 QCBORItem Item;
5112 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5113 if(uError) {
5114 pMe->uLastError = (uint8_t)uError;
5115 return;
5116 }
5117
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005118 const TagSpecification TagSpec =
5119 {
5120 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005121 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5122 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5123 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005124 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005125
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005126 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005127}
5128
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005129
5130/*
5131 Public function, see header qcbor/qcbor_decode.h file
5132*/
5133void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005134 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005135 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005136 int64_t *pnMantissa,
5137 int64_t *pnExponent)
5138{
5139 if(pMe->uLastError != QCBOR_SUCCESS) {
5140 return;
5141 }
5142
5143 QCBORItem Item;
5144 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5145
5146 const TagSpecification TagSpec =
5147 {
5148 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005149 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5150 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5151 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005152 };
5153
5154 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5155}
5156
5157
5158/*
5159 Public function, see header qcbor/qcbor_decode.h file
5160*/
5161void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005162 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005163 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005164 int64_t *pnMantissa,
5165 int64_t *pnExponent)
5166{
5167 if(pMe->uLastError != QCBOR_SUCCESS) {
5168 return;
5169 }
5170
5171 QCBORItem Item;
5172 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5173
5174 const TagSpecification TagSpec =
5175 {
5176 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005177 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5178 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5179 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005180 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005181
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005182 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5183}
5184
5185
5186/*
5187 Public function, see header qcbor/qcbor_decode.h file
5188*/
5189void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5190 uint8_t uTagRequirement,
5191 UsefulBuf MantissaBuffer,
5192 UsefulBufC *pMantissa,
5193 bool *pbMantissaIsNegative,
5194 int64_t *pnExponent)
5195{
5196 if(pMe->uLastError != QCBOR_SUCCESS) {
5197 return;
5198 }
5199
5200 QCBORItem Item;
5201 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5202 if(uError) {
5203 pMe->uLastError = (uint8_t)uError;
5204 return;
5205 }
5206
5207 const TagSpecification TagSpec =
5208 {
5209 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005210 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5211 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5212 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005213 };
5214
Laurence Lundblade93d89472020-10-03 22:30:50 -07005215 ProcessMantissaAndExponentBig(pMe,
5216 TagSpec,
5217 &Item,
5218 MantissaBuffer,
5219 pMantissa,
5220 pbMantissaIsNegative,
5221 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005222}
5223
5224
5225/*
5226 Public function, see header qcbor/qcbor_decode.h file
5227*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005228void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005229 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005230 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005231 UsefulBuf BufferForMantissa,
5232 UsefulBufC *pMantissa,
5233 bool *pbIsNegative,
5234 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005235{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005236 if(pMe->uLastError != QCBOR_SUCCESS) {
5237 return;
5238 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005239
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005240 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005241 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005242 if(pMe->uLastError != QCBOR_SUCCESS) {
5243 return;
5244 }
5245
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005246 const TagSpecification TagSpec =
5247 {
5248 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005249 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5250 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5251 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005252 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005253
Laurence Lundblade93d89472020-10-03 22:30:50 -07005254 ProcessMantissaAndExponentBig(pMe,
5255 TagSpec,
5256 &Item,
5257 BufferForMantissa,
5258 pMantissa,
5259 pbIsNegative,
5260 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005261}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005262
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005263
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005264/*
5265 Public function, see header qcbor/qcbor_decode.h file
5266*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005267void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005268 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005269 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005270 UsefulBuf BufferForMantissa,
5271 UsefulBufC *pMantissa,
5272 bool *pbIsNegative,
5273 int64_t *pnExponent)
5274{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005275 if(pMe->uLastError != QCBOR_SUCCESS) {
5276 return;
5277 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005278
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005279 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005280 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5281 if(pMe->uLastError != QCBOR_SUCCESS) {
5282 return;
5283 }
5284
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005285 const TagSpecification TagSpec =
5286 {
5287 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005288 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5289 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5290 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005291 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005292
5293 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5294}
5295
5296
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005297/*
5298 Public function, see header qcbor/qcbor_decode.h file
5299*/
5300void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5301 uint8_t uTagRequirement,
5302 int64_t *pnMantissa,
5303 int64_t *pnExponent)
5304{
5305 if(pMe->uLastError != QCBOR_SUCCESS) {
5306 return;
5307 }
5308
5309 QCBORItem Item;
5310 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5311 if(uError) {
5312 pMe->uLastError = (uint8_t)uError;
5313 return;
5314 }
5315 const TagSpecification TagSpec =
5316 {
5317 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005318 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5319 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5320 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005321 };
5322
5323 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5324}
5325
5326
5327/*
5328 Public function, see header qcbor/qcbor_decode.h file
5329*/
5330void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005331 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005332 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005333 int64_t *pnMantissa,
5334 int64_t *pnExponent)
5335{
5336 if(pMe->uLastError != QCBOR_SUCCESS) {
5337 return;
5338 }
5339
5340 QCBORItem Item;
5341 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5342 if(pMe->uLastError != QCBOR_SUCCESS) {
5343 return;
5344 }
5345
5346 const TagSpecification TagSpec =
5347 {
5348 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005349 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5350 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5351 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005352 };
5353
5354 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5355}
5356
5357
5358/*
5359 Public function, see header qcbor/qcbor_decode.h file
5360*/
5361void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005362 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005363 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005364 int64_t *pnMantissa,
5365 int64_t *pnExponent)
5366{
5367 if(pMe->uLastError != QCBOR_SUCCESS) {
5368 return;
5369 }
5370
5371 QCBORItem Item;
5372 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5373 if(pMe->uLastError != QCBOR_SUCCESS) {
5374 return;
5375 }
5376
5377 const TagSpecification TagSpec =
5378 {
5379 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005380 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5381 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5382 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005383 };
5384
5385 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5386}
5387
5388
5389/*
5390 Public function, see header qcbor/qcbor_decode.h file
5391*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005392void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5393 uint8_t uTagRequirement,
5394 UsefulBuf MantissaBuffer,
5395 UsefulBufC *pMantissa,
5396 bool *pbMantissaIsNegative,
5397 int64_t *pnExponent)
5398{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005399 if(pMe->uLastError != QCBOR_SUCCESS) {
5400 return;
5401 }
5402
5403 QCBORItem Item;
5404 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5405 if(uError) {
5406 pMe->uLastError = (uint8_t)uError;
5407 return;
5408 }
5409
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005410 const TagSpecification TagSpec =
5411 {
5412 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005413 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5414 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5415 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005416 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005417
5418 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005419}
5420
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005421
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005422/*
5423 Public function, see header qcbor/qcbor_decode.h file
5424*/
5425void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005426 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005427 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005428 UsefulBuf BufferForMantissa,
5429 UsefulBufC *pMantissa,
5430 bool *pbIsNegative,
5431 int64_t *pnExponent)
5432{
5433 if(pMe->uLastError != QCBOR_SUCCESS) {
5434 return;
5435 }
5436
5437 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005438 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5439 if(pMe->uLastError != QCBOR_SUCCESS) {
5440 return;
5441 }
5442
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005443 const TagSpecification TagSpec =
5444 {
5445 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005446 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5447 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5448 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005449 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005450
Laurence Lundblade93d89472020-10-03 22:30:50 -07005451 ProcessMantissaAndExponentBig(pMe,
5452 TagSpec,
5453 &Item,
5454 BufferForMantissa,
5455 pMantissa,
5456 pbIsNegative,
5457 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005458}
5459
5460
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005461/*
5462 Public function, see header qcbor/qcbor_decode.h file
5463*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005464void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005465 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005466 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005467 UsefulBuf BufferForMantissa,
5468 UsefulBufC *pMantissa,
5469 bool *pbIsNegative,
5470 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005471{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005472 if(pMe->uLastError != QCBOR_SUCCESS) {
5473 return;
5474 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005475
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005476 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005477 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5478 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005479 return;
5480 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005481
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005482 const TagSpecification TagSpec =
5483 {
5484 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005485 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5486 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5487 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005488 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005489
Laurence Lundblade93d89472020-10-03 22:30:50 -07005490 ProcessMantissaAndExponentBig(pMe,
5491 TagSpec,
5492 &Item,
5493 BufferForMantissa,
5494 pMantissa,
5495 pbIsNegative,
5496 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005497}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005498
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005499#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */