blob: efe6ebc70937201905908056b7bec947bd59b9cc [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 Lundbladea8edadb2020-06-27 22:35:37 -0700329 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700330 if(uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700331 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700332 }
333
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700334 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700335
336 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700337
338 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700339}
340
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700341
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700342static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700343DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700344 uint8_t uQCBORType,
345 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700346{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700347 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700348
349 if(uCount == 0) {
350 // Nothing to do for empty definite lenth arrays. They are just are
351 // effectively the same as an item that is not a map or array
352 goto Done;
353 // Empty indefinite length maps and arrays are handled elsewhere
354 }
355
356 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700357 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
358 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700359 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700360 goto Done;
361 }
362
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700363 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700364 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700365 goto Done;
366 }
367
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700368 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700369 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
370 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700371
372 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700373
374Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700375 return uError;;
376}
377
378
379static inline void
380DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
381{
382 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
383}
384
385
386static inline void
387DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
388{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700389 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700390 pNesting->pCurrentBounded--;
391 if(DecodeNesting_IsCurrentBounded(pNesting)) {
392 break;
393 }
394 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700395}
396
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700397static inline void
398DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
399{
400 pNesting->pCurrent = pNesting->pCurrentBounded;
401}
402
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700403
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700404static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700405DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700406 uint32_t uEndOffset,
407 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700408{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700409 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700410
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700411 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700412 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700413 goto Done;
414 }
415
Laurence Lundblade02625d42020-06-25 14:41:41 -0700416 // Fill in the new byte string level
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700417 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
418 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700419
Laurence Lundblade02625d42020-06-25 14:41:41 -0700420 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700421 pNesting->pCurrentBounded = pNesting->pCurrent;
422
423Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700424 return uError;;
425}
426
Laurence Lundbladed0304932020-06-27 10:59:38 -0700427
428static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700429DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700430{
431 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700432}
433
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700434
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700435static inline void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800436DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
437{
438 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
439}
440
441
442static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700443DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700444{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700445 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700446 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
447 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700448}
449
450
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700451static inline void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700452DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700453{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700454 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700455 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800456 DecodeNesting_ResetMapOrArrayCount(pNesting);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700457}
458
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700459
Laurence Lundblade02625d42020-06-25 14:41:41 -0700460static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700461DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700462{
463 *pNesting = *pSave;
464}
465
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700466
Laurence Lundblade02625d42020-06-25 14:41:41 -0700467static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700468DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700469{
470 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
471}
472
473
Laurence Lundblade02625d42020-06-25 14:41:41 -0700474static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700475DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700476{
477 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
478}
479
480
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800481#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800482/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800483 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
484
485 The following four functions are pretty wrappers for invocation of
486 the string allocator supplied by the caller.
487
Laurence Lundbladeee851742020-01-08 08:37:05 -0800488 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800489
Laurence Lundbladeee851742020-01-08 08:37:05 -0800490static inline void
491StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800492{
493 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
494}
495
Laurence Lundbladeee851742020-01-08 08:37:05 -0800496// StringAllocator_Reallocate called with pMem NULL is
497// equal to StringAllocator_Allocate()
498static inline UsefulBuf
499StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
500 void *pMem,
501 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800502{
503 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
504}
505
Laurence Lundbladeee851742020-01-08 08:37:05 -0800506static inline UsefulBuf
507StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800508{
509 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
510}
511
Laurence Lundbladeee851742020-01-08 08:37:05 -0800512static inline void
513StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800514{
515 if(pMe->pfAllocator) {
516 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
517 }
518}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800519#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800520
521
Laurence Lundbladeee851742020-01-08 08:37:05 -0800522/*===========================================================================
523 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700524
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800525 See qcbor/qcbor_decode.h for definition of the object
526 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800527 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700528/*
529 Public function, see header file
530 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800531void QCBORDecode_Init(QCBORDecodeContext *me,
532 UsefulBufC EncodedCBOR,
533 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700534{
535 memset(me, 0, sizeof(QCBORDecodeContext));
536 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800537 // Don't bother with error check on decode mode. If a bad value is
538 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700539 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700540 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700541 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700542 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700543 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700544}
545
546
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800547#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
548
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700549/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700550 Public function, see header file
551 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800552void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
553 QCBORStringAllocate pfAllocateFunction,
554 void *pAllocateContext,
555 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700556{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800557 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
558 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
559 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700560}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800561#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700562
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800563
564/*
565 Public function, see header file
566 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700567void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800568 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700569{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700570 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700571 (void)pMe;
572 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700573}
574
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700575
576/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800577 This decodes the fundamental part of a CBOR data item, the type and
578 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800579
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700580 This is the counterpart to QCBOREncode_EncodeHead().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800581
Laurence Lundbladeee851742020-01-08 08:37:05 -0800582 This does the network->host byte order conversion. The conversion
583 here also results in the conversion for floats in addition to that
584 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800585
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700586 This returns:
587 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800588
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800589 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800590 tags and floats and length for strings and arrays
591
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800592 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800593 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800594
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800595 The int type is preferred to uint8_t for some variables as this
596 avoids integer promotions, can reduce code size and makes
597 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700598
599 @retval QCBOR_ERR_UNSUPPORTED
600
601 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700602 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700603static inline QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800604 int *pnMajorType,
605 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800606 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700607{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700608 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800609
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700610 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800611 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800612
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700613 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800614 const int nTmpMajorType = nInitialByte >> 5;
615 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800616
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800617 // Where the number or argument accumulates
618 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800619
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800620 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700621 // Need to get 1,2,4 or 8 additional argument bytes. Map
622 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800623 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800624
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800625 // Loop getting all the bytes in the argument
626 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800627 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800628 // This shift and add gives the endian conversion
629 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
630 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800631 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800632 // The reserved and thus-far unused additional info values
633 nReturn = QCBOR_ERR_UNSUPPORTED;
634 goto Done;
635 } else {
636 // Less than 24, additional info is argument or 31, an indefinite length
637 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800638 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700639 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800640
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700641 if(UsefulInputBuf_GetError(pUInBuf)) {
642 nReturn = QCBOR_ERR_HIT_END;
643 goto Done;
644 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800645
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700646 // All successful if we got here.
647 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800648 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800649 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800650 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800651
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700652Done:
653 return nReturn;
654}
655
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800656
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700657/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800658 CBOR doesn't explicitly specify two's compliment for integers but all
659 CPUs use it these days and the test vectors in the RFC are so. All
660 integers in the CBOR structure are positive and the major type
661 indicates positive or negative. CBOR can express positive integers
662 up to 2^x - 1 where x is the number of bits and negative integers
663 down to 2^x. Note that negative numbers can be one more away from
664 zero than positive. Stdint, as far as I can tell, uses two's
665 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800666
Laurence Lundblade9b334962020-08-27 10:55:53 -0700667 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800668 used carefully here, and in particular why it isn't used in the interface.
669 Also see
670 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
671
672 Int is used for values that need less than 16-bits and would be subject
673 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700674
675 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700676 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700677static inline QCBORError
Laurence Lundbladeee851742020-01-08 08:37:05 -0800678DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700679{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700680 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800681
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700682 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
683 if (uNumber <= INT64_MAX) {
684 pDecodedItem->val.int64 = (int64_t)uNumber;
685 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800686
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700687 } else {
688 pDecodedItem->val.uint64 = uNumber;
689 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800690
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700691 }
692 } else {
693 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800694 // CBOR's representation of negative numbers lines up with the
695 // two-compliment representation. A negative integer has one
696 // more in range than a positive integer. INT64_MIN is
697 // equal to (-INT64_MAX) - 1.
698 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700699 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800700
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700701 } else {
702 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000703 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700704 nReturn = QCBOR_ERR_INT_OVERFLOW;
705 }
706 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800707
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700708 return nReturn;
709}
710
711// Make sure #define value line up as DecodeSimple counts on this.
712#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
713#error QCBOR_TYPE_FALSE macro value wrong
714#endif
715
716#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
717#error QCBOR_TYPE_TRUE macro value wrong
718#endif
719
720#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
721#error QCBOR_TYPE_NULL macro value wrong
722#endif
723
724#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
725#error QCBOR_TYPE_UNDEF macro value wrong
726#endif
727
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700728#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
729#error QCBOR_TYPE_BREAK macro value wrong
730#endif
731
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700732#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
733#error QCBOR_TYPE_DOUBLE macro value wrong
734#endif
735
736#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
737#error QCBOR_TYPE_FLOAT macro value wrong
738#endif
739
740/*
741 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700742
743 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
744
745 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700746 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700747static inline QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800748DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700749{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700750 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800751
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700752 // uAdditionalInfo is 5 bits from the initial byte. Compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800753 // above make sure uAdditionalInfo values line up with uDataType values.
Laurence Lundblade93d89472020-10-03 22:30:50 -0700754 // DecodeTypeAndNumber() never returns an AdditionalInfo > 0x1f so cast
755 // is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800756 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800757
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800758 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800759 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
760 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800761
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700762 case HALF_PREC_FLOAT: // 25
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700763#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700764 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700765 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700766 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700767 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
768 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700769#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700770 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700771#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700772 break;
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700773 case SINGLE_PREC_FLOAT: // 26
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700774 // Single precision is normally returned as a double
775 // since double is widely supported, there is no loss of
776 // precision, it makes it easy for the caller in
777 // most cases and it can be converted back to single
778 // with no loss of precision
779 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700780 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700781 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700782 {
783 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
784#ifndef QCBOR_DISABLE_FLOAT_HW_USE
785 // In the normal case, use HW to convert float to double.
786 pDecodedItem->val.dfnum = (double)f;
787 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700788#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700789 // Use of float HW is disabled, return as a float.
790 pDecodedItem->val.fnum = f;
791 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
792
793 // IEEE754_FloatToDouble() could be used here to return
794 // as a double, but it adds object code and most likely
795 // anyone disabling FLOAT HW use doesn't care about
796 // floats and wants to save object code.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700797#endif
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700798 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700799 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700800
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700801 case DOUBLE_PREC_FLOAT: // 27
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700802 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700803 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700804 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800805
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700806 case CBOR_SIMPLEV_FALSE: // 20
807 case CBOR_SIMPLEV_TRUE: // 21
808 case CBOR_SIMPLEV_NULL: // 22
809 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700810 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700811 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800812
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700813 case CBOR_SIMPLEV_ONEBYTE: // 24
814 if(uNumber <= CBOR_SIMPLE_BREAK) {
815 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700816 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700817 goto Done;
818 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800819 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700820 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800821
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700822 default: // 0-19
823 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800824 /*
825 DecodeTypeAndNumber will make uNumber equal to
826 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
827 safe because the 2, 4 and 8 byte lengths of uNumber are in
828 the double/float cases above
829 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700830 pDecodedItem->val.uSimple = (uint8_t)uNumber;
831 break;
832 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800833
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700834Done:
835 return nReturn;
836}
837
838
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700839/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530840 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700841
842 @retval QCBOR_ERR_HIT_END
843
844 @retval QCBOR_ERR_STRING_ALLOCATE
845
846 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700847 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700848static inline QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800849 uint64_t uStrLen,
850 UsefulInputBuf *pUInBuf,
851 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700852{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700853 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800854
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800855 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
856 // This check makes the casts to size_t below safe.
857
858 // 4 bytes less than the largest sizeof() so this can be tested by
859 // putting a SIZE_MAX length in the CBOR test input (no one will
860 // care the limit on strings is 4 bytes shorter).
861 if(uStrLen > SIZE_MAX-4) {
862 nReturn = QCBOR_ERR_STRING_TOO_LONG;
863 goto Done;
864 }
865
866 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530867 if(UsefulBuf_IsNULLC(Bytes)) {
868 // Failed to get the bytes for this string item
869 nReturn = QCBOR_ERR_HIT_END;
870 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700871 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530872
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800873#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800874 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530875 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800876 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530877 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700878 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530879 goto Done;
880 }
881 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800882 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800883 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530884 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800885#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
886 (void)pAllocator;
887#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
888
889 // Normal case with no string allocator
890 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800891
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530892Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700893 return nReturn;
894}
895
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700896
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800897/* Map the CBOR major types for strings to the QCBOR types for strngs */
898static inline uint8_t MapStringMajorTypes(int nCBORMajorType)
899{
900 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
901 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
902 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800903
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800904 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
905 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
906 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700907
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800908 return (uint8_t)(nCBORMajorType + 4);
909}
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700910
911
Laurence Lundbladeee851742020-01-08 08:37:05 -0800912// Make sure the constants align as this is assumed by
913// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700914#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
915#error QCBOR_TYPE_ARRAY value not lined up with major type
916#endif
917#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
918#error QCBOR_TYPE_MAP value not lined up with major type
919#endif
920
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700921/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800922 This gets a single data item and decodes it including preceding
923 optional tagging. This does not deal with arrays and maps and nesting
924 except to decode the data item introducing them. Arrays and maps are
925 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800926
Laurence Lundbladeee851742020-01-08 08:37:05 -0800927 Errors detected here include: an array that is too long to decode,
928 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700929
930 @retval QCBOR_ERR_UNSUPPORTED
931
932 @retval QCBOR_ERR_HIT_END
933
934 @retval QCBOR_ERR_INT_OVERFLOW
935
936 @retval QCBOR_ERR_STRING_ALLOCATE
937
938 @retval QCBOR_ERR_STRING_TOO_LONG
939
940 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
941
942 @retval QCBOR_ERR_BAD_TYPE_7
943
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700944 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800945static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
946 QCBORItem *pDecodedItem,
947 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700948{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700949 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800950
Laurence Lundbladeee851742020-01-08 08:37:05 -0800951 /*
952 Get the major type and the number. Number could be length of more
953 bytes or the value depending on the major type nAdditionalInfo is
954 an encoding of the length of the uNumber and is needed to decode
955 floats and doubles
956 */
Rob Gilton47cc9562020-08-10 12:03:38 +0100957 int nMajorType = 0;
958 uint64_t uNumber = 0;
959 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800960
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700961 memset(pDecodedItem, 0, sizeof(QCBORItem));
962
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800963 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800964
Laurence Lundbladeee851742020-01-08 08:37:05 -0800965 // Error out here if we got into trouble on the type and number. The
966 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700967 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700968 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700969 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800970
Laurence Lundbladeee851742020-01-08 08:37:05 -0800971 // At this point the major type and the value are valid. We've got
972 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800973 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700974 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
975 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800976 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700977 nReturn = QCBOR_ERR_BAD_INT;
978 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800979 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700980 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700981 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800982
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700983 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
984 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800985 pDecodedItem->uDataType = MapStringMajorTypes(nMajorType);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800986 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800987 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700988 } else {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800989 nReturn = DecodeBytes(pAllocator, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700990 }
991 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800992
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700993 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
994 case CBOR_MAJOR_TYPE_MAP: // Major type 5
995 // Record the number of items in the array or map
996 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700997 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700998 goto Done;
999 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001000 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001001 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001002 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001003 // type conversion OK because of check above
1004 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001005 }
Laurence Lundbladeee851742020-01-08 08:37:05 -08001006 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001007 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001008 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001009 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001010
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001011 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001012 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001013 nReturn = QCBOR_ERR_BAD_INT;
1014 } else {
1015 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001016 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001017 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001018 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001019
Laurence Lundbladeee851742020-01-08 08:37:05 -08001020 case CBOR_MAJOR_TYPE_SIMPLE:
1021 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001022 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001023 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001024
Laurence Lundbladeee851742020-01-08 08:37:05 -08001025 default:
1026 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001027 nReturn = QCBOR_ERR_UNSUPPORTED;
1028 break;
1029 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001030
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001031Done:
1032 return nReturn;
1033}
1034
1035
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001036/**
1037 * @brief Process indefinite length strings
1038 *
1039 * @param[in] pMe Decoder context
1040 * @param[in,out] pDecodedItem The decoded item that work is done on.
1041 *
1042 * @retval QCBOR_ERR_UNSUPPORTED
1043 * @retval QCBOR_ERR_HIT_END
1044 * @retval QCBOR_ERR_INT_OVERFLOW
1045 * @retval QCBOR_ERR_STRING_ALLOCATE
1046 * @retval QCBOR_ERR_STRING_TOO_LONG
1047 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1048 * @retval QCBOR_ERR_BAD_TYPE_7
1049 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1050 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1051 *
1052 * If @c pDecodedItem is not an indefinite length string, this does nothing.
1053 *
1054 * If it is, this loops getting the subsequent chunks that make up the
1055 * string. The string allocator is used to make a contiguous buffer for
1056 * the chunks. When this completes @c pDecodedItem contains the
1057 * put-together string.
1058 *
1059 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001060 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001061static inline QCBORError
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001062GetNext_FullItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001063{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001064 /* Aproximate stack usage
1065 * 64-bit 32-bit
1066 * local vars 32 16
1067 * 2 UsefulBufs 32 16
1068 * QCBORItem 56 52
1069 * TOTAL 120 74
1070 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001071
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001072 /* The string allocator is used here for two purposes: 1)
1073 * coalescing the chunks of an indefinite length string, 2)
1074 * allocating storage for every string returned.
1075 *
1076 * The first use is below in this function. Indefinite length
1077 * strings cannot be processed at all without a string allocator.
1078 *
1079 * The second used is in DecodeBytes() which is called by
1080 * GetNext_Item() below. This second use unneccessary for most use
1081 * and only happens when requested in the call to
1082 * QCBORDecode_SetMemPool(). If the second use not requested then
1083 * NULL is passed for the string allocator to GetNext_Item().
1084 *
1085 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1086 * allocator altogether and thus both of these uses. It reduced the
1087 * decoder object code by about 400 bytes.
1088 */
1089 const QCORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001090
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001091#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1092 const QCORInternalAllocator *pAllocator = NULL;
1093
1094 if(pMe->StringAllocator.pfAllocator) {
1095 pAllocator = &(pMe->StringAllocator);
1096 if(pMe->bStringAllocateAll) {
1097 pAllocatorForGetNext = pAllocator;
1098 }
1099 }
1100#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1101
1102 QCBORError uReturn;
1103 uReturn = GetNext_Item(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
1104 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001105 goto Done;
1106 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001107
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001108 /* Only do indefinite length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001109 const uint8_t uStringType = pDecodedItem->uDataType;
1110 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001111 goto Done;
1112 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001113
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001114 /* Is this a string with an indefinite length? */
1115 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1116 goto Done;
1117 }
1118
1119#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1120 /* Can't do indefinite length strings without a string allocator */
1121 if(pAllocator == NULL) {
1122 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1123 goto Done;
1124 }
1125
1126 /* Loop getting chunks of the indefinite length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001127 UsefulBufC FullString = NULLUsefulBufC;
1128
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001129 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001130 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001131 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001132 /* Pass a NULL string allocator to GetNext_Item() because the
1133 * individual string chunks in an indefinite length should not
1134 * be allocated. They are always copied in the the contiguous
1135 * buffer allocated here.
1136 */
1137 uReturn = GetNext_Item(&(pMe->InBuf), &StringChunkItem, NULL);
1138 if(uReturn) {
1139 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001140 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001141
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001142 /* Is item is the marker for end of the indefinite length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001143 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001144 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001145 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301146 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001147 break;
1148 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001149
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001150 /* All chunks must be of the same type, the type of the item
1151 * that introduces the indefinite length string. This also
1152 * catches errors where the chunk is not a string at all and an
1153 * indefinite length string inside an indefinite length string.
1154 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001155 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001156 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1157 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001158 break;
1159 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001160
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001161 /* The first time throurgh FullString.ptr is NULL and this is
1162 * equivalent to StringAllocator_Allocate(). Subsequently it is
1163 * not NULL and a reallocation happens.
1164 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001165 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1166 UNCONST_POINTER(FullString.ptr),
1167 FullString.len + StringChunkItem.val.string.len);
1168
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001169 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001170 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001171 break;
1172 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001173
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001174 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001175 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001176 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001177
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001178 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1179 /* Getting the item failed, clean up the allocated memory */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001180 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001181 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001182#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1183 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1184#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001185
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001186Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001187 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001188}
1189
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001190
Laurence Lundblade9b334962020-08-27 10:55:53 -07001191static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001192 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001193 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001194 } else if(uTagVal == CBOR_TAG_INVALID16) {
1195 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001196 } else {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001197 // This won't be negative because of code below in GetNext_TaggedItem()
1198 const unsigned uIndex = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
1199 return me->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001200 }
1201}
1202
Laurence Lundblade9b334962020-08-27 10:55:53 -07001203
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001204/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001205 Gets all optional tag data items preceding a data item that is not an
1206 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001207
1208 @retval QCBOR_ERR_UNSUPPORTED
1209
1210 @retval QCBOR_ERR_HIT_END
1211
1212 @retval QCBOR_ERR_INT_OVERFLOW
1213
1214 @retval QCBOR_ERR_STRING_ALLOCATE
1215
1216 @retval QCBOR_ERR_STRING_TOO_LONG
1217
1218 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1219
1220 @retval QCBOR_ERR_BAD_TYPE_7
1221
1222 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1223
1224 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1225
1226 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001227 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001228static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001229GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001230{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001231 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1232 CBOR_TAG_INVALID16,
1233 CBOR_TAG_INVALID16,
1234 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001235
Laurence Lundblade9b334962020-08-27 10:55:53 -07001236 QCBORError uReturn = QCBOR_SUCCESS;
1237
Laurence Lundblade59289e52019-12-30 13:44:37 -08001238 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001239 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001240 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1241 if(uErr != QCBOR_SUCCESS) {
1242 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001243 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001244 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001245
Laurence Lundblade9b334962020-08-27 10:55:53 -07001246 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001247 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001248 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001249 break;
1250 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001251
Laurence Lundblade9b334962020-08-27 10:55:53 -07001252 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1253 // No room in the tag list
1254 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1255 // Continue on to get all tags on this item even though
1256 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001257 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001258 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001259 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001260 // Slide tags over one in the array to make room at index 0
1261 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1262 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001263 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001264
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001265 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001266 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001267 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001268 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001269 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001270 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001271 break;
1272 }
1273 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1274 break;
1275 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001276 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001277 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1278 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001279 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1280 // Continue on to get all tags on this item even though
1281 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001282 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001283 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001284 }
1285
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001286 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001287 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001288 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001289
1290 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001291 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001292 }
1293 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001294
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001295Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001296 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001297}
1298
1299
1300/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001301 This layer takes care of map entries. It combines the label and data
1302 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001303
1304 @retval QCBOR_ERR_UNSUPPORTED
1305
1306 @retval QCBOR_ERR_HIT_END
1307
1308 @retval QCBOR_ERR_INT_OVERFLOW
1309
1310 @retval QCBOR_ERR_STRING_ALLOCATE
1311
1312 @retval QCBOR_ERR_STRING_TOO_LONG
1313
1314 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1315
1316 @retval QCBOR_ERR_BAD_TYPE_7
1317
1318 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1319
1320 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1321
1322 @retval QCBOR_ERR_TOO_MANY_TAGS
1323
1324 @retval QCBOR_ERR_MAP_LABEL_TYPE
1325
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001326 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001327 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001328static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001329GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001330{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001331 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001332 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001333 if(nReturn)
1334 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001335
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001336 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001337 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001338 goto Done;
1339 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001340
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001341 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1342 // In a map and caller wants maps decoded, not treated as arrays
1343
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001344 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001345 // If in a map and the right decoding mode, get the label
1346
Laurence Lundbladeee851742020-01-08 08:37:05 -08001347 // Save label in pDecodedItem and get the next which will
1348 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001349 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001350 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001351 if(QCBORDecode_IsUnrecoverableError(nReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001352 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001353 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001354
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301355 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001356
1357 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1358 // strings are always good labels
1359 pDecodedItem->label.string = LabelItem.val.string;
1360 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1361 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001362 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001363 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1364 goto Done;
1365 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1366 pDecodedItem->label.int64 = LabelItem.val.int64;
1367 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1368 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1369 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1370 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1371 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1372 pDecodedItem->label.string = LabelItem.val.string;
1373 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1374 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1375 } else {
1376 // label is not an int or a string. It is an arrray
1377 // or a float or such and this implementation doesn't handle that.
1378 // Also, tags on labels are ignored.
1379 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1380 goto Done;
1381 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001382 }
1383 } else {
1384 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001385 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001386 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001387 goto Done;
1388 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001389 // Decoding a map as an array
1390 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001391 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1392 // Cast is needed because of integer promotion
1393 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001394 }
1395 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001396
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001397Done:
1398 return nReturn;
1399}
1400
1401
Laurence Lundblade02625d42020-06-25 14:41:41 -07001402/*
1403 See if next item is a CBOR break. If it is, it is consumed,
1404 if not it is not consumed.
1405*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001406static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001407NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1408{
1409 *pbNextIsBreak = false;
1410 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001411 QCBORItem Peek;
1412 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1413 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1414 if(uReturn != QCBOR_SUCCESS) {
1415 return uReturn;
1416 }
1417 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001418 // It is not a break, rewind so it can be processed normally.
1419 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001420 } else {
1421 *pbNextIsBreak = true;
1422 }
1423 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001424
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001425 return QCBOR_SUCCESS;
1426}
1427
1428
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001429/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001430 An item was just consumed, now figure out if it was the
1431 end of an array or map that can be closed out. That
1432 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001433*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001434static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001435{
1436 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001437
Laurence Lundblade642282a2020-06-23 12:00:33 -07001438 /* This loops ascending nesting levels as long as there is ascending to do */
1439 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1440
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001441 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001442 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001443 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1444 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001445 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001446 break;
1447 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07001448 /* All of a definite length array was consumed; fall through to
1449 ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001450
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001451 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001452 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001453 bool bIsBreak = false;
1454 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1455 if(uReturn != QCBOR_SUCCESS) {
1456 goto Done;
1457 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001458
1459 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001460 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001461 break;
1462 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001463
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001464 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001465 /*
1466 Break occurred inside a bstr-wrapped CBOR or
1467 in the top level sequence. This is always an
1468 error because neither are an indefinte length
1469 map/array.
1470 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001471 uReturn = QCBOR_ERR_BAD_BREAK;
1472 goto Done;
1473 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001474
Laurence Lundblade02625d42020-06-25 14:41:41 -07001475 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001476 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001477
Laurence Lundblade02625d42020-06-25 14:41:41 -07001478 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001479
Laurence Lundblade93d89472020-10-03 22:30:50 -07001480 /* But ascent in bounded mode is only by explicit call to
1481 QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001482 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001483 /* Set the count to zero for definite length arrays to indicate
1484 cursor is at end of bounded map / array */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001485 if(bMarkEnd) {
1486 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001487 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001488
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001489 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001490 break;
1491 }
1492
1493 /* Finally, actually ascend one level. */
1494 DecodeNesting_Ascend(&(pMe->nesting));
1495 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001496
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001497 uReturn = QCBOR_SUCCESS;
1498
1499Done:
1500 return uReturn;
1501}
1502
1503
1504/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001505 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001506 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1507 indefinte length maps and arrays by looking at the item count or
1508 finding CBOR breaks. It detects the ends of the top-level sequence
1509 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001510
1511 @retval QCBOR_ERR_UNSUPPORTED X
1512
1513 @retval QCBOR_ERR_HIT_END
1514
1515 @retval QCBOR_ERR_INT_OVERFLOW X
1516
1517 @retval QCBOR_ERR_STRING_ALLOCATE
1518
1519 @retval QCBOR_ERR_STRING_TOO_LONG
1520
1521 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1522
1523 @retval QCBOR_ERR_BAD_TYPE_7 X
1524
1525 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1526
1527 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1528
1529 @retval QCBOR_ERR_TOO_MANY_TAGS
1530
1531 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1532
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001533 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001534
1535 @retval QCBOR_ERR_NO_MORE_ITEMS
1536
1537 @retval QCBOR_ERR_BAD_BREAK
1538
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001539 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001540static QCBORError
1541QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001542{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001543 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001544 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001545
Laurence Lundblade642282a2020-06-23 12:00:33 -07001546 /*
1547 If out of bytes to consume, it is either the end of the top-level
1548 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001549
Laurence Lundblade642282a2020-06-23 12:00:33 -07001550 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1551 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1552 CBOR is exited, the length is set back to the top-level's length
1553 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001554 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001555 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001556 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001557 goto Done;
1558 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001559
Laurence Lundblade642282a2020-06-23 12:00:33 -07001560 /*
1561 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001562 array. The check for the end of an indefinite length array is
1563 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001564 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001565 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001566 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001567 goto Done;
1568 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001569
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001570 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001571 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001572 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1573 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001574 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001575 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301576
Laurence Lundblade642282a2020-06-23 12:00:33 -07001577 /*
1578 Breaks ending arrays/maps are always processed at the end of this
1579 function. They should never show up here.
1580 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301581 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001582 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301583 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301584 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001585
Laurence Lundblade642282a2020-06-23 12:00:33 -07001586 /*
1587 Record the nesting level for this data item before processing any
1588 of decrementing and descending.
1589 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001590 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001591
Laurence Lundblade642282a2020-06-23 12:00:33 -07001592
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001593 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001594 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001595 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001596 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001597
Laurence Lundblade93d89472020-10-03 22:30:50 -07001598 Empty indefinite length maps and arrays are descended into, but
1599 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001600
1601 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001602 encloses them so a decrement needs to be done for them too, but
1603 that is done only when all the items in them have been
1604 processed, not when they are opened with the exception of an
1605 empty map or array.
1606 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001607 QCBORError uDescendErr;
1608 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001609 pDecodedItem->uDataType,
1610 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001611 if(uDescendErr != QCBOR_SUCCESS) {
1612 /* This error is probably a traversal error and it
1613 overrides the non-traversal error. */
1614 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001615 goto Done;
1616 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001617 }
1618
Laurence Lundblade02625d42020-06-25 14:41:41 -07001619 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1620 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1621 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001622 /*
1623 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001624 - A non-aggregate like an integer or string
1625 - An empty definite length map or array
1626 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001627
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001628 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001629 definite length map/array and break detection for an indefinite
1630 length map/array. If the end of the map/array was reached, then
1631 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001632 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001633 QCBORError uAscendErr;
1634 uAscendErr = NestLevelAscender(me, true);
1635 if(uAscendErr != QCBOR_SUCCESS) {
1636 /* This error is probably a traversal error and it
1637 overrides the non-traversal error. */
1638 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001639 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001640 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301641 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001642
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001643 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001644 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001645 Tell the caller what level is next. This tells them what
1646 maps/arrays were closed out and makes it possible for them to
1647 reconstruct the tree with just the information returned in
1648 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001649 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001650 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001651 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001652 pDecodedItem->uNextNestLevel = 0;
1653 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001654 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001655 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001656
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001657Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001658 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001659}
1660
Laurence Lundblade9b334962020-08-27 10:55:53 -07001661static void ShiftTags(QCBORItem *pDecodedItem)
1662{
1663 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1664 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1665 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1666 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1667}
1668
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001669
Laurence Lundblade59289e52019-12-30 13:44:37 -08001670/*
1671 Mostly just assign the right data type for the date string.
1672 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001673static inline QCBORError DecodeDateString(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001674{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001675 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1676 return QCBOR_ERR_BAD_OPT_TAG;
1677 }
1678
1679 const UsefulBufC Temp = pDecodedItem->val.string;
1680 pDecodedItem->val.dateString = Temp;
1681 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001682 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001683 return QCBOR_SUCCESS;
1684}
1685
1686
Laurence Lundblade9b334962020-08-27 10:55:53 -07001687
Laurence Lundblade59289e52019-12-30 13:44:37 -08001688/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001689 The epoch formatted date. Turns lots of different forms of encoding
1690 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001691 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001692static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001693{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001694 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001695
1696 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1697
1698 switch (pDecodedItem->uDataType) {
1699
1700 case QCBOR_TYPE_INT64:
1701 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1702 break;
1703
1704 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001705 // This only happens for CBOR type 0 > INT64_MAX so it is
1706 // always an overflow.
1707 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1708 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001709 break;
1710
1711 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001712 case QCBOR_TYPE_FLOAT:
1713#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001714 {
1715 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001716 // conversion to an int64_t to be able to detect doubles that
1717 // are too large to fit into an int64_t. A double has 52
1718 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1719 // to a double actually causes a round up which is bad and
1720 // wrong for the comparison because it will allow conversion
1721 // of doubles that can't fit into a uint64_t. To remedy this
1722 // INT64_MAX - 0x7ff is used as the cutoff point because if
1723 // that value rounds up in conversion to double it will still
1724 // be less than INT64_MAX. 0x7ff is picked because it has 11
1725 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001726 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001727 // INT64_MAX seconds is on the order of 10 billion years, and
1728 // the earth is less than 5 billion years old, so for most
1729 // uses this conversion error won't occur even though doubles
1730 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001731 //
1732 // Without the 0x7ff there is a ~30 minute range of time
1733 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001734 // where this code would go wrong. Some compilers
1735 // will generate warnings or errors without the 0x7ff
1736 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001737 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1738 pDecodedItem->val.dfnum :
1739 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001740 if(isnan(d) ||
1741 d > (double)(INT64_MAX - 0x7ff) ||
1742 d < (double)(INT64_MIN + 0x7ff)) {
1743 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001744 goto Done;
1745 }
1746 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001747 pDecodedItem->val.epochDate.fSecondsFraction =
1748 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001749 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001750#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001751
Laurence Lundbladec7114722020-08-13 05:11:40 -07001752 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001753 goto Done;
1754
Laurence Lundblade9682a532020-06-06 18:33:04 -07001755#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001756 break;
1757
1758 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001759 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001760 goto Done;
1761 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001762
Laurence Lundblade59289e52019-12-30 13:44:37 -08001763 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1764
1765Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001766 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001767}
1768
1769
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001770/*
1771 Mostly just assign the right data type for the bignum.
1772 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001773static inline QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001774{
1775 // Stack Use: UsefulBuf 1 -- 16
1776 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1777 return QCBOR_ERR_BAD_OPT_TAG;
1778 }
1779 const UsefulBufC Temp = pDecodedItem->val.string;
1780 pDecodedItem->val.bigNum = Temp;
1781 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1782 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1783 : QCBOR_TYPE_NEGBIGNUM);
1784 return QCBOR_SUCCESS;
1785}
1786
1787
Laurence Lundblade59289e52019-12-30 13:44:37 -08001788#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1789/*
1790 Decode decimal fractions and big floats.
1791
1792 When called pDecodedItem must be the array that is tagged as a big
1793 float or decimal fraction, the array that has the two members, the
1794 exponent and mantissa.
1795
1796 This will fetch and decode the exponent and mantissa and put the
1797 result back into pDecodedItem.
1798 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001799static inline QCBORError
Laurence Lundblade59289e52019-12-30 13:44:37 -08001800QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1801{
1802 QCBORError nReturn;
1803
1804 // --- Make sure it is an array; track nesting level of members ---
1805 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1806 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1807 goto Done;
1808 }
1809
1810 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001811 // definite length arrays, but not for indefnite. Instead remember
1812 // the nesting level the two integers must be at, which is one
1813 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001814 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1815
1816 // --- Is it a decimal fraction or a bigfloat? ---
1817 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1818 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1819
1820 // --- Get the exponent ---
1821 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001822 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001823 if(nReturn != QCBOR_SUCCESS) {
1824 goto Done;
1825 }
1826 if(exponentItem.uNestingLevel != nNestLevel) {
1827 // Array is empty or a map/array encountered when expecting an int
1828 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1829 goto Done;
1830 }
1831 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1832 // Data arriving as an unsigned int < INT64_MAX has been converted
1833 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1834 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1835 // will be too large for this to handle and thus an error that will
1836 // get handled in the next else.
1837 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1838 } else {
1839 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1840 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1841 goto Done;
1842 }
1843
1844 // --- Get the mantissa ---
1845 QCBORItem mantissaItem;
1846 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1847 if(nReturn != QCBOR_SUCCESS) {
1848 goto Done;
1849 }
1850 if(mantissaItem.uNestingLevel != nNestLevel) {
1851 // Mantissa missing or map/array encountered when expecting number
1852 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1853 goto Done;
1854 }
1855 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1856 // Data arriving as an unsigned int < INT64_MAX has been converted
1857 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1858 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1859 // will be too large for this to handle and thus an error that
1860 // will get handled in an else below.
1861 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001862 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
1863 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001864 // Got a good big num mantissa
1865 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1866 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001867 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1868 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1869 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001870 } else {
1871 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1872 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1873 goto Done;
1874 }
1875
1876 // --- Check that array only has the two numbers ---
1877 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001878 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001879 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1880 goto Done;
1881 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001882 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001883
1884Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001885 return nReturn;
1886}
1887#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1888
1889
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001890static inline QCBORError DecodeURI(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001891{
1892 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1893 return QCBOR_ERR_BAD_OPT_TAG;
1894 }
1895 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1896 return QCBOR_SUCCESS;
1897}
1898
1899
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001900static inline QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001901{
1902 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1903 return QCBOR_ERR_BAD_OPT_TAG;
1904 }
1905 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001906
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001907 return QCBOR_SUCCESS;
1908}
1909
1910
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001911static inline QCBORError DecodeB64(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001912{
1913 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1914 return QCBOR_ERR_BAD_OPT_TAG;
1915 }
1916 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001917
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001918 return QCBOR_SUCCESS;
1919}
1920
1921
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001922static inline QCBORError DecodeRegex(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001923{
1924 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1925 return QCBOR_ERR_BAD_OPT_TAG;
1926 }
1927 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001928
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001929 return QCBOR_SUCCESS;
1930}
1931
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001932
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001933static inline QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001934{
1935 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1936 return QCBOR_ERR_BAD_OPT_TAG;
1937 }
1938 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001939
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001940 return QCBOR_SUCCESS;
1941}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001942
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001943
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001944static inline QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001945{
1946 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1947 return QCBOR_ERR_BAD_OPT_TAG;
1948 }
1949 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001950
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001951 return QCBOR_SUCCESS;
1952}
1953
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001954
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001955static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001956{
1957 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1958 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001959 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001960 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1961 } else {
1962 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001963
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001964 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001965
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001966 return QCBOR_SUCCESS;
1967}
1968
1969
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001970static inline QCBORError DecodeUUID(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001971{
1972 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1973 return QCBOR_ERR_BAD_OPT_TAG;
1974 }
1975 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001976
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001977 return QCBOR_SUCCESS;
1978}
1979
1980
Laurence Lundblade59289e52019-12-30 13:44:37 -08001981/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001982 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001983 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001984static QCBORError
1985QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001986{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001987 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001988
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001989 uReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
1990 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001991 goto Done;
1992 }
1993
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001994 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
1995 switch(pDecodedItem->uTags[uTagIndex]) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001996
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001997 // Many of the functions here only just map a CBOR tag to
1998 // a QCBOR_TYPE for a string and could probably be
1999 // implemented with less object code. This implementation
2000 // of string types takes about 120 bytes of object code
2001 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002002 case CBOR_TAG_DATE_STRING:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002003 uReturn = DecodeDateString(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002004 break;
2005
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002006 case CBOR_TAG_DATE_EPOCH:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002007 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002008 break;
2009
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002010 case CBOR_TAG_POS_BIGNUM:
2011 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002012 uReturn = DecodeBigNum(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002013 break;
2014
Laurence Lundblade93d89472020-10-03 22:30:50 -07002015#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002016 case CBOR_TAG_DECIMAL_FRACTION:
2017 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08002018 // For aggregate tagged types, what goes into pTags is only collected
2019 // from the surrounding data item, not the contents, so pTags is not
2020 // passed on here.
2021
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002022 uReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002023 break;
Laurence Lundblade93d89472020-10-03 22:30:50 -07002024#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002025
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002026 case CBOR_TAG_CBOR:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002027 uReturn = DecodeWrappedCBOR(pDecodedItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002028 break;
2029
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002030 case CBOR_TAG_CBOR_SEQUENCE:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002031 uReturn = DecodeWrappedCBORSequence(pDecodedItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002032 break;
2033
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002034 case CBOR_TAG_URI:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002035 uReturn = DecodeURI(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002036 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002037
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002038 case CBOR_TAG_B64URL:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002039 uReturn = DecodeB64URL(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002040 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002041
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002042 case CBOR_TAG_B64:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002043 uReturn = DecodeB64(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002044 break;
2045
2046 case CBOR_TAG_MIME:
2047 case CBOR_TAG_BINARY_MIME:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002048 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002049 break;
2050
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002051 case CBOR_TAG_REGEX:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002052 uReturn = DecodeRegex(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002053 break;
2054
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002055 case CBOR_TAG_BIN_UUID:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002056 uReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002057 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002058
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002059 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002060 // The end of the tag list or no tags
2061 // Successful exit from the loop.
2062 goto Done;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002063
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002064 default:
2065 // A tag that is not understood
2066 // A successful exit from the loop
2067 goto Done;
2068
2069 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002070 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002071 goto Done;
2072 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002073 // A tag was successfully processed, shift it
2074 // out of the list of tags returned.
2075 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002076 }
2077
2078Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002079 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002080}
2081
2082
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002083/*
2084 Public function, see header qcbor/qcbor_decode.h file
2085 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002086QCBORError
2087QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2088{
2089 QCBORError uErr;
2090 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2091 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002092 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2093 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2094 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002095 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002096}
2097
2098
2099/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002100 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002101 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002102QCBORError
2103QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2104{
2105 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2106 const UsefulInputBuf Save = pMe->InBuf;
2107
2108 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2109
2110 pMe->nesting = SaveNesting;
2111 pMe->InBuf = Save;
2112
2113 return uErr;
2114}
2115
2116
2117/*
2118 Public function, see header qcbor/qcbor_decode.h file
2119 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002120void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2121{
2122 if(pMe->uLastError != QCBOR_SUCCESS) {
2123 return;
2124 }
2125
2126 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2127}
2128
2129
2130/*
2131 Public function, see header qcbor/qcbor_decode.h file
2132 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002133QCBORError
2134QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2135 QCBORItem *pDecodedItem,
2136 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002137{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002138 QCBORError nReturn;
2139
2140 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2141 if(nReturn != QCBOR_SUCCESS) {
2142 return nReturn;
2143 }
2144
2145 if(pTags != NULL) {
2146 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002147 // Reverse the order because pTags is reverse of
2148 // QCBORItem.uTags.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002149 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2150 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002151 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002152 }
2153 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2154 return QCBOR_ERR_TOO_MANY_TAGS;
2155 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002156 pTags->puTags[pTags->uNumUsed] = ConvertTag(me,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002157 pTags->uNumUsed++;
2158 }
2159 }
2160
2161 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002162}
2163
2164
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002165/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302166 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302167 next one down. If a layer has no work to do for a particular item
2168 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002169
Laurence Lundblade59289e52019-12-30 13:44:37 -08002170 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2171 tagged data items, turning them into the local C representation.
2172 For the most simple it is just associating a QCBOR_TYPE with the data. For
2173 the complex ones that an aggregate of data items, there is some further
2174 decoding and a little bit of recursion.
2175
2176 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302177 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302178 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002179 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002180
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302181 - GetNext_MapEntry -- This handles the combining of two
2182 items, the label and the data, that make up a map entry.
2183 It only does work on maps. It combines the label and data
2184 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002185
Laurence Lundblade59289e52019-12-30 13:44:37 -08002186 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2187 tags into bit flags associated with the data item. No actual decoding
2188 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002189
Laurence Lundblade59289e52019-12-30 13:44:37 -08002190 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302191 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302192 string allocater to create contiguous space for the item. It
2193 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002194
Laurence Lundblade59289e52019-12-30 13:44:37 -08002195 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2196 atomic data item has a "major type", an integer "argument" and optionally
2197 some content. For text and byte strings, the content is the bytes
2198 that make up the string. These are the smallest data items that are
2199 considered to be well-formed. The content may also be other data items in
2200 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002201
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002202 Roughly this takes 300 bytes of stack for vars. Need to
2203 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002204
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302205 */
2206
2207
2208/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002209 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002210 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002211bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002212 const QCBORItem *pItem,
2213 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002214{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002215 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2216 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002217 break;
2218 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002219 if(ConvertTag(me, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002220 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002221 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002222 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002223
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002224 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002225}
2226
2227
2228/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002229 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002230 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002231QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002232{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002233 QCBORError uReturn = me->uLastError;
2234
2235 if(uReturn != QCBOR_SUCCESS) {
2236 goto Done;
2237 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002238
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002239 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002240 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002241 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002242 goto Done;
2243 }
2244
2245 // Error out if not all the bytes are consumed
2246 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002247 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002248 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002249
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002250Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002251#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade6de37062018-10-15 12:22:42 +05302252 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002253 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002254 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002255#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002256
Laurence Lundblade085d7952020-07-24 10:26:30 -07002257 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002258}
2259
2260
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002261/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002262 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002263*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002264// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002265uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2266 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002267 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002268{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002269 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2270 return CBOR_TAG_INVALID64;
2271 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002272 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2273 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002274 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002275 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002276 }
2277}
2278
Laurence Lundblade9b334962020-08-27 10:55:53 -07002279/*
2280 Public function, see header qcbor/qcbor_decode.h file
2281*/
2282uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2283 uint32_t uIndex)
2284{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002285 if(pMe->uLastError != QCBOR_SUCCESS) {
2286 return CBOR_TAG_INVALID64;
2287 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002288 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2289 return CBOR_TAG_INVALID64;
2290 } else {
2291 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2292 }
2293}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002294
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002295/*
2296
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002297Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002298
Laurence Lundbladeee851742020-01-08 08:37:05 -08002299 - Hit end of input before it was expected while decoding type and
2300 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002301
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002302 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002303
Laurence Lundbladeee851742020-01-08 08:37:05 -08002304 - Hit end of input while decoding a text or byte string
2305 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002306
Laurence Lundbladeee851742020-01-08 08:37:05 -08002307 - Encountered conflicting tags -- e.g., an item is tagged both a date
2308 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002309
Laurence Lundbladeee851742020-01-08 08:37:05 -08002310 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002311 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002312
Laurence Lundbladeee851742020-01-08 08:37:05 -08002313 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002314 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002315
Laurence Lundbladeee851742020-01-08 08:37:05 -08002316 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2317 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002318
Laurence Lundbladeee851742020-01-08 08:37:05 -08002319 - The type of a map label is not a string or int
2320 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002321
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002322 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002323
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002324 */
2325
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002326
2327
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002328#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002329
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002330/* ===========================================================================
2331 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002332
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002333 This implements a simple sting allocator for indefinite length
2334 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2335 implements the function type QCBORStringAllocate and allows easy
2336 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002337
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002338 This particular allocator is built-in for convenience. The caller
2339 can implement their own. All of this following code will get
2340 dead-stripped if QCBORDecode_SetMemPool() is not called.
2341
2342 This is a very primitive memory allocator. It does not track
2343 individual allocations, only a high-water mark. A free or
2344 reallocation must be of the last chunk allocated.
2345
2346 The size of the pool and offset to free memory are packed into the
2347 first 8 bytes of the memory pool so we don't have to keep them in
2348 the decode context. Since the address of the pool may not be
2349 aligned, they have to be packed and unpacked as if they were
2350 serialized data of the wire or such.
2351
2352 The sizes packed in are uint32_t to be the same on all CPU types
2353 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002354 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002355
2356
Laurence Lundbladeee851742020-01-08 08:37:05 -08002357static inline int
2358MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002359{
2360 // Use of UsefulInputBuf is overkill, but it is convenient.
2361 UsefulInputBuf UIB;
2362
Laurence Lundbladeee851742020-01-08 08:37:05 -08002363 // Just assume the size here. It was checked during SetUp so
2364 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002365 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002366 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2367 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2368 return UsefulInputBuf_GetError(&UIB);
2369}
2370
2371
Laurence Lundbladeee851742020-01-08 08:37:05 -08002372static inline int
2373MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002374{
2375 // Use of UsefulOutBuf is overkill, but convenient. The
2376 // length check performed here is useful.
2377 UsefulOutBuf UOB;
2378
2379 UsefulOutBuf_Init(&UOB, Pool);
2380 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2381 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2382 return UsefulOutBuf_GetError(&UOB);
2383}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002384
2385
2386/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002387 Internal function for an allocation, reallocation free and destuct.
2388
2389 Having only one function rather than one each per mode saves space in
2390 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002391
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002392 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2393 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002394static UsefulBuf
2395MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002396{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002397 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002398
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002399 uint32_t uPoolSize;
2400 uint32_t uFreeOffset;
2401
2402 if(uNewSize > UINT32_MAX) {
2403 // This allocator is only good up to 4GB. This check should
2404 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2405 goto Done;
2406 }
2407 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2408
2409 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2410 goto Done;
2411 }
2412
2413 if(uNewSize) {
2414 if(pMem) {
2415 // REALLOCATION MODE
2416 // Calculate pointer to the end of the memory pool. It is
2417 // assumed that pPool + uPoolSize won't wrap around by
2418 // assuming the caller won't pass a pool buffer in that is
2419 // not in legitimate memory space.
2420 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2421
2422 // Check that the pointer for reallocation is in the range of the
2423 // pool. This also makes sure that pointer math further down
2424 // doesn't wrap under or over.
2425 if(pMem >= pPool && pMem < pPoolEnd) {
2426 // Offset to start of chunk for reallocation. This won't
2427 // wrap under because of check that pMem >= pPool. Cast
2428 // is safe because the pool is always less than UINT32_MAX
2429 // because of check in QCBORDecode_SetMemPool().
2430 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2431
2432 // Check to see if the allocation will fit. uPoolSize -
2433 // uMemOffset will not wrap under because of check that
2434 // pMem is in the range of the uPoolSize by check above.
2435 if(uNewSize <= uPoolSize - uMemOffset) {
2436 ReturnValue.ptr = pMem;
2437 ReturnValue.len = uNewSize;
2438
2439 // Addition won't wrap around over because uNewSize was
2440 // checked to be sure it is less than the pool size.
2441 uFreeOffset = uMemOffset + uNewSize32;
2442 }
2443 }
2444 } else {
2445 // ALLOCATION MODE
2446 // uPoolSize - uFreeOffset will not underflow because this
2447 // pool implementation makes sure uFreeOffset is always
2448 // smaller than uPoolSize through this check here and
2449 // reallocation case.
2450 if(uNewSize <= uPoolSize - uFreeOffset) {
2451 ReturnValue.len = uNewSize;
2452 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002453 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002454 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002455 }
2456 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002457 if(pMem) {
2458 // FREE MODE
2459 // Cast is safe because of limit on pool size in
2460 // QCBORDecode_SetMemPool()
2461 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2462 } else {
2463 // DESTRUCT MODE
2464 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002465 }
2466 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002467
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002468 UsefulBuf Pool = {pPool, uPoolSize};
2469 MemPool_Pack(Pool, uFreeOffset);
2470
2471Done:
2472 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002473}
2474
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002475
Laurence Lundbladef6531662018-12-04 10:42:22 +09002476/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002477 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002478 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002479QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2480 UsefulBuf Pool,
2481 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002482{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002483 // The pool size and free mem offset are packed into the beginning
2484 // of the pool memory. This compile time check make sure the
2485 // constant in the header is correct. This check should optimize
2486 // down to nothing.
2487 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002488 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002489 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002490
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002491 // The pool size and free offset packed in to the beginning of pool
2492 // memory are only 32-bits. This check will optimize out on 32-bit
2493 // machines.
2494 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002495 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002496 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002497
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002498 // This checks that the pool buffer given is big enough.
2499 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002500 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002501 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002502
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002503 pMe->StringAllocator.pfAllocator = MemPool_Function;
2504 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2505 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002506
Laurence Lundblade30816f22018-11-10 13:40:22 +07002507 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002508}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002509#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002510
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002511
2512
Laurence Lundblade9b334962020-08-27 10:55:53 -07002513static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2514{
2515 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2516}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002517
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002518
2519/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002520 Consume an entire map or array (and do next to
2521 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002522 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002523static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002524ConsumeItem(QCBORDecodeContext *pMe,
2525 const QCBORItem *pItemToConsume,
2526 uint_fast8_t *puNextNestLevel)
2527{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002528 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002529 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002530
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002531 // If it is a map or array, this will tell if it is empty.
2532 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2533
2534 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2535 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002536
Laurence Lundblade1341c592020-04-11 14:19:05 -07002537 /* This works for definite and indefinite length
2538 * maps and arrays by using the nesting level
2539 */
2540 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002541 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002542 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002543 goto Done;
2544 }
2545 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002546
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002547 *puNextNestLevel = Item.uNextNestLevel;
2548
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002549 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002550
Laurence Lundblade1341c592020-04-11 14:19:05 -07002551 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002552 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002553 /* Just pass the nesting level through */
2554 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2555
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002556 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002557 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002558
2559Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002560 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002561}
2562
2563
Laurence Lundblade1341c592020-04-11 14:19:05 -07002564/* Return true if the labels in Item1 and Item2 are the same.
2565 Works only for integer and string labels. Returns false
2566 for any other type. */
2567static inline bool
2568MatchLabel(QCBORItem Item1, QCBORItem Item2)
2569{
2570 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2571 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2572 return true;
2573 }
2574 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002575 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002576 return true;
2577 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002578 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002579 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2580 return true;
2581 }
2582 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2583 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2584 return true;
2585 }
2586 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002587
Laurence Lundblade1341c592020-04-11 14:19:05 -07002588 /* Other label types are never matched */
2589 return false;
2590}
2591
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002592
2593/*
2594 Returns true if Item1 and Item2 are the same type
2595 or if either are of QCBOR_TYPE_ANY.
2596 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002597static inline bool
2598MatchType(QCBORItem Item1, QCBORItem Item2)
2599{
2600 if(Item1.uDataType == Item2.uDataType) {
2601 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002602 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002603 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002604 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002605 return true;
2606 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002607 return false;
2608}
2609
2610
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002611/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002612 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002613
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002614 @param[in] pMe The decode context to search.
2615 @param[in,out] pItemArray The items to search for and the items found.
2616 @param[out] puOffset Byte offset of last item matched.
2617 @param[in] pCBContext Context for the not-found item call back.
2618 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002619
2620 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2621
Laurence Lundblade93d89472020-10-03 22:30:50 -07002622 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2623 were found for one of the labels being
2624 search for. This duplicate detection is
2625 only performed for items in pItemArray,
2626 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002627
Laurence Lundblade93d89472020-10-03 22:30:50 -07002628 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2629 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002630
2631 @retval Also errors returned by QCBORDecode_GetNext().
2632
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002633 On input pItemArray contains a list of labels and data types
2634 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002635
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002636 On output the fully retrieved items are filled in with
2637 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002638
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002639 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002640
2641 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002642 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002643static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002644MapSearch(QCBORDecodeContext *pMe,
2645 QCBORItem *pItemArray,
2646 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002647 void *pCBContext,
2648 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002649{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002650 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002651 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002652
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002653 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002654 uReturn = pMe->uLastError;
2655 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002656 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002657
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002658 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002659 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2660 /* QCBOR_TYPE_NONE as first item indicates just looking
2661 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002662 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2663 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002664 }
2665
Laurence Lundblade085d7952020-07-24 10:26:30 -07002666 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2667 // It is an empty bounded array or map
2668 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2669 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002670 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002671 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002672 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002673 // Nothing is ever found in an empty array or map. All items
2674 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002675 uReturn = QCBOR_SUCCESS;
2676 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002677 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002678 }
2679
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002680 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002681 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2682
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002683 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002684 UsefulInputBuf_Seek(&(pMe->InBuf),
2685 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002686
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002687 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002688 Loop over all the items in the map or array. Each item
2689 could be a map or array, but label matching is only at
2690 the main level. This handles definite and indefinite
2691 length maps and arrays. The only reason this is ever
2692 called on arrays is to find their end position.
2693
2694 This will always run over all items in order to do
2695 duplicate detection.
2696
2697 This will exit with failure if it encounters an
2698 unrecoverable error, but continue on for recoverable
2699 errors.
2700
2701 If a recoverable error occurs on a matched item, then
2702 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002703 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002704 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002705 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002706 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002707 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002708 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002709
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002710 /* Get the item */
2711 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002712 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2713 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002714 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002715 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002716 goto Done;
2717 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002718 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002719 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002720 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002721 goto Done;
2722 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002723
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002724 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002725 bool bMatched = false;
2726 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2727 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002728 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002729 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2730 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002731 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002732 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002733 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002734 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002735 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002736 goto Done;
2737 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002738
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002739 if(uResult != QCBOR_SUCCESS) {
2740 uReturn = uResult;
2741 goto Done;
2742 }
2743
Laurence Lundblade1341c592020-04-11 14:19:05 -07002744 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002745 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002746 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002747 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002748 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002749 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002750 bMatched = true;
2751 }
2752 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002753
2754
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002755 if(!bMatched && pfCallback != NULL) {
2756 /*
2757 Call the callback on unmatched labels.
2758 (It is tempting to do duplicate detection here, but that would
2759 require dynamic memory allocation because the number of labels
2760 that might be encountered is unbounded.)
2761 */
2762 uReturn = (*pfCallback)(pCBContext, &Item);
2763 if(uReturn != QCBOR_SUCCESS) {
2764 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002765 }
2766 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002767
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002768 /*
2769 Consume the item whether matched or not. This
2770 does the work of traversing maps and array and
2771 everything in them. In this loop only the
2772 items at the current nesting level are examined
2773 to match the labels.
2774 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002775 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002776 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002777 goto Done;
2778 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002779
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002780 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002781
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002782 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002783
2784 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002785
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002786 // Check here makes sure that this won't accidentally be
2787 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002788 // QCBOR_MAX_DECODE_INPUT_SIZE.
2789 if(uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
2790 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2791 goto Done;
2792 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002793 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2794 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002795
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002796 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002797 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2798
2799 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002800 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002801 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002802 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002803 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2804 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002805 }
2806 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002807
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002808 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002809}
2810
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002811
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002812/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002813 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002814*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002815void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2816 int64_t nLabel,
2817 uint8_t uQcborType,
2818 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002819{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002820 if(pMe->uLastError != QCBOR_SUCCESS) {
2821 return;
2822 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002823
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002824 QCBORItem OneItemSeach[2];
2825 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2826 OneItemSeach[0].label.int64 = nLabel;
2827 OneItemSeach[0].uDataType = uQcborType;
2828 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002829
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002830 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002831
2832 *pItem = OneItemSeach[0];
2833
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002834 if(uReturn != QCBOR_SUCCESS) {
2835 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002836 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002837 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002838 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002839 }
2840
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002841 Done:
2842 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002843}
2844
2845
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002846/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002847 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002848*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002849void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2850 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002851 uint8_t uQcborType,
2852 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002853{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002854 if(pMe->uLastError != QCBOR_SUCCESS) {
2855 return;
2856 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002857
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002858 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002859 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2860 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2861 OneItemSeach[0].uDataType = uQcborType;
2862 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002863
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002864 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2865 if(uReturn != QCBOR_SUCCESS) {
2866 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002867 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002868 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002869 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002870 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002871 }
2872
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002873 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002874
2875Done:
2876 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002877}
2878
2879
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002880
Laurence Lundblade93d89472020-10-03 22:30:50 -07002881static QCBORError
2882CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002883{
2884 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2885 if(uDataType == puTypeList[i]) {
2886 return QCBOR_SUCCESS;
2887 }
2888 }
2889 return QCBOR_ERR_UNEXPECTED_TYPE;
2890}
2891
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002892
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002893/**
2894 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002895 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002896
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002897 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2898 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002899
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002900 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
2901 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002902 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002903static QCBORError
2904CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002905{
2906 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2907 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2908 /* There are tags that QCBOR couldn't process on this item and
2909 the caller has told us there should not be. */
2910 return QCBOR_ERR_UNEXPECTED_TYPE;
2911 }
2912
2913 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2914 const int nItemType = pItem->uDataType;
2915
2916 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2917 // Must match the tag and only the tag
2918 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2919 }
2920
2921 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2922 if(uReturn == QCBOR_SUCCESS) {
2923 return QCBOR_SUCCESS;
2924 }
2925
2926 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2927 /* Must match the content type and only the content type.
2928 There was no match just above so it is a fail. */
2929 return QCBOR_ERR_UNEXPECTED_TYPE;
2930 }
2931
2932 /* If here it can match either the tag or the content
2933 and it hasn't matched the content, so the end
2934 result is whether it matches the tag. This is
2935 also the case that the CBOR standard discourages. */
2936
2937 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2938}
2939
Laurence Lundblade9b334962020-08-27 10:55:53 -07002940
Laurence Lundblade9b334962020-08-27 10:55:53 -07002941
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002942// This could be semi-private if need be
2943static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002944void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2945 int64_t nLabel,
2946 TagSpecification TagSpec,
2947 QCBORItem *pItem)
2948{
2949 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2950 if(pMe->uLastError != QCBOR_SUCCESS) {
2951 return;
2952 }
2953
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002954 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002955}
2956
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002957
2958// This could be semi-private if need be
2959static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002960void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2961 const char *szLabel,
2962 TagSpecification TagSpec,
2963 QCBORItem *pItem)
2964{
2965 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2966 if(pMe->uLastError != QCBOR_SUCCESS) {
2967 return;
2968 }
2969
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002970 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002971}
2972
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002973// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002974void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2975 int64_t nLabel,
2976 TagSpecification TagSpec,
2977 UsefulBufC *pString)
2978{
2979 QCBORItem Item;
2980 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2981 if(pMe->uLastError == QCBOR_SUCCESS) {
2982 *pString = Item.val.string;
2983 }
2984}
2985
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002986// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002987void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2988 const char * szLabel,
2989 TagSpecification TagSpec,
2990 UsefulBufC *pString)
2991{
2992 QCBORItem Item;
2993 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2994 if(pMe->uLastError == QCBOR_SUCCESS) {
2995 *pString = Item.val.string;
2996 }
2997}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002998
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002999/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003000 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003001*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003002void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003003{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003004 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3005 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003006}
3007
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003008/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003009 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003010*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003011void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3012 QCBORItem *pItemList,
3013 void *pCallbackCtx,
3014 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003015{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003016 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3017 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003018}
3019
3020
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003021/**
3022 * @brief Search for a map/array by label and enter it
3023 *
3024 * @param[in] pMe The decode context.
3025 * @param[in] pSearch The map/array to search for.
3026 *
3027 * @c pSearch is expected to contain one item of type map or array
3028 * with the label specified. The current bounded map will be searched for
3029 * this and if found will be entered.
3030 *
3031 * If the label is not found, or the item found is not a map or array,
3032 * the error state is set.
3033 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003034static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003035{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003036 // The first item in pSearch is the one that is to be
3037 // entered. It should be the only one filled in. Any other
3038 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003039 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003040 return;
3041 }
3042
3043 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003044 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003045 if(pMe->uLastError != QCBOR_SUCCESS) {
3046 return;
3047 }
3048
Laurence Lundblade9b334962020-08-27 10:55:53 -07003049 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003050 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003051 return;
3052 }
3053
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003054 /*
3055 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3056 * next item for the pre-order traversal cursor to be the map/array
3057 * found by MapSearch(). The next few lines of code force the
3058 * cursor to that.
3059 *
3060 * There is no need to retain the old cursor because
3061 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3062 * beginning of the map/array being entered.
3063 *
3064 * The cursor is forced by: 1) setting the input buffer position to
3065 * the item offset found by MapSearch(), 2) setting the map/array
3066 * counter to the total in the map/array, 3) setting the nesting
3067 * level. Setting the map/array counter to the total is not
3068 * strictly correct, but this is OK because this cursor only needs
3069 * to be used to get one item and MapSearch() has already found it
3070 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003071 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003072 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003073
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003074 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3075
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003076 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003077
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003078 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003079}
3080
3081
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003082/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003083 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003084*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003085void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003086{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003087 QCBORItem OneItemSeach[2];
3088 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3089 OneItemSeach[0].label.int64 = nLabel;
3090 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3091 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003092
Laurence Lundblade9b334962020-08-27 10:55:53 -07003093 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003094 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003095}
3096
3097
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003098/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003099 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003100*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003101void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003102{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003103 QCBORItem OneItemSeach[2];
3104 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3105 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3106 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3107 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003108
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003109 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003110}
3111
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003112/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003113 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003114*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003115void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003116{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003117 QCBORItem OneItemSeach[2];
3118 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3119 OneItemSeach[0].label.int64 = nLabel;
3120 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3121 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003122
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003123 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003124}
3125
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003126/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003127 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003128*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003129void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3130{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003131 QCBORItem OneItemSeach[2];
3132 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3133 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3134 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3135 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003136
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003137 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003138}
3139
3140
Laurence Lundblade02625d42020-06-25 14:41:41 -07003141// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003142void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003143{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003144 QCBORError uErr;
3145
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003146 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003147 if(pMe->uLastError != QCBOR_SUCCESS) {
3148 // Already in error state; do nothing.
3149 return;
3150 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003151
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003152 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003153 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003154 uErr = QCBORDecode_GetNext(pMe, &Item);
3155 if(uErr != QCBOR_SUCCESS) {
3156 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003157 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003158 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003159 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3160 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003161 }
3162
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003163 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003164
3165
Laurence Lundbladef0499502020-08-01 11:55:57 -07003166 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003167 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003168 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3169 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003170 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003171 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3172 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003173 // Special case to increment nesting level for zero-length maps
3174 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003175 DecodeNesting_Descend(&(pMe->nesting), uType);
3176 }
3177
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003178 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003179
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003180 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3181 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003182
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003183 if(pItem != NULL) {
3184 *pItem = Item;
3185 }
3186
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003187Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003188 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003189}
3190
Laurence Lundblade02625d42020-06-25 14:41:41 -07003191
3192/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003193 This is the common work for exiting a level that is a bounded map,
3194 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003195
3196 One chunk of work is to set up the pre-order traversal so it is at
3197 the item just after the bounded map, array or bstr that is being
3198 exited. This is somewhat complex.
3199
3200 The other work is to level-up the bounded mode to next higest bounded
3201 mode or the top level if there isn't one.
3202 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003203static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003204ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003205{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003206 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003207
Laurence Lundblade02625d42020-06-25 14:41:41 -07003208 /*
3209 First the pre-order-traversal byte offset is positioned to the
3210 item just after the bounded mode item that was just consumed.
3211 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003212 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3213
Laurence Lundblade02625d42020-06-25 14:41:41 -07003214 /*
3215 Next, set the current nesting level to one above the bounded level
3216 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003217
Laurence Lundblade02625d42020-06-25 14:41:41 -07003218 DecodeNesting_CheckBoundedType() is always called before this and
3219 makes sure pCurrentBounded is valid.
3220 */
3221 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3222
3223 /*
3224 This does the complex work of leveling up the pre-order traversal
3225 when the end of a map or array or another bounded level is
3226 reached. It may do nothing, or ascend all the way to the top
3227 level.
3228 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003229 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003230 if(uErr != QCBOR_SUCCESS) {
3231 goto Done;
3232 }
3233
Laurence Lundblade02625d42020-06-25 14:41:41 -07003234 /*
3235 This makes the next highest bounded level the current bounded
3236 level. If there is no next highest level, then no bounded mode is
3237 in effect.
3238 */
3239 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003240
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003241 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003242
3243Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003244 return uErr;
3245}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003246
Laurence Lundblade02625d42020-06-25 14:41:41 -07003247
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003248// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003249void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003250{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003251 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003252 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003253 return;
3254 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003255
Laurence Lundblade02625d42020-06-25 14:41:41 -07003256 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003257
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003258 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003259 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003260 goto Done;
3261 }
3262
Laurence Lundblade02625d42020-06-25 14:41:41 -07003263 /*
3264 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003265 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003266 from previous map search, then do a dummy search.
3267 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003268 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003269 QCBORItem Dummy;
3270 Dummy.uLabelType = QCBOR_TYPE_NONE;
3271 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3272 if(uErr != QCBOR_SUCCESS) {
3273 goto Done;
3274 }
3275 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003276
Laurence Lundblade02625d42020-06-25 14:41:41 -07003277 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003278
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003279Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003280 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003281}
3282
3283
Laurence Lundblade1341c592020-04-11 14:19:05 -07003284
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003285static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003286 const QCBORItem *pItem,
3287 uint8_t uTagRequirement,
3288 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003289{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003290 if(pBstr) {
3291 *pBstr = NULLUsefulBufC;
3292 }
3293
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003294 if(pMe->uLastError != QCBOR_SUCCESS) {
3295 // Already in error state; do nothing.
3296 return pMe->uLastError;
3297 }
3298
3299 QCBORError uError = QCBOR_SUCCESS;
3300
3301 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3302 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3303 goto Done;;
3304 }
3305
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003306 const TagSpecification TagSpec =
3307 {
3308 uTagRequirement,
3309 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3310 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3311 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003312
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003313 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003314 if(uError != QCBOR_SUCCESS) {
3315 goto Done;
3316 }
3317
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003318 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003319 // Reverse the decrement done by GetNext() for the bstr so the
3320 // increment in NestLevelAscender() called by ExitBoundedLevel()
3321 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003322 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003323 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003324
3325 if(pBstr) {
3326 *pBstr = pItem->val.string;
3327 }
3328
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003329 // This saves the current length of the UsefulInputBuf and then
3330 // narrows the UsefulInputBuf to start and length of the wrapped
3331 // CBOR that is being entered.
3332 //
3333 // This makes sure the length is less than
3334 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3335 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3336 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3337 // the casts safe. uEndOfBstr will always be less than
3338 // uPreviousLength because of the way UsefulInputBuf works so there
3339 // is no need to check it. There is also a range check in the
3340 // seek.
3341 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003342 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003343 // amount to much code.
3344 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3345 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003346 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003347 goto Done;
3348 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003349 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003350 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003351 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003352
Laurence Lundblade02625d42020-06-25 14:41:41 -07003353 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003354 (uint32_t)uPreviousLength,
3355 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003356Done:
3357 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003358}
3359
3360
Laurence Lundblade02625d42020-06-25 14:41:41 -07003361/*
3362 Public function, see header qcbor/qcbor_decode.h file
3363 */
3364void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003365 uint8_t uTagRequirement,
3366 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003367{
3368 if(pMe->uLastError != QCBOR_SUCCESS) {
3369 // Already in error state; do nothing.
3370 return;
3371 }
3372
3373 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003374 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003375 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3376 if(pMe->uLastError != QCBOR_SUCCESS) {
3377 return;
3378 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003379
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003380 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003381 &Item,
3382 uTagRequirement,
3383 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003384}
3385
3386
Laurence Lundblade02625d42020-06-25 14:41:41 -07003387/*
3388 Public function, see header qcbor/qcbor_decode.h file
3389 */
3390void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003391 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003392 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003393 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003394{
3395 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003396 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003397
Laurence Lundblade93d89472020-10-03 22:30:50 -07003398 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3399 &Item,
3400 uTagRequirement,
3401 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003402}
3403
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003404
Laurence Lundblade02625d42020-06-25 14:41:41 -07003405/*
3406 Public function, see header qcbor/qcbor_decode.h file
3407 */
3408void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003409 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003410 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003411 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003412{
3413 QCBORItem Item;
3414 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3415
Laurence Lundblade93d89472020-10-03 22:30:50 -07003416 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3417 &Item,
3418 uTagRequirement,
3419 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003420}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003421
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003422
Laurence Lundblade02625d42020-06-25 14:41:41 -07003423/*
3424 Public function, see header qcbor/qcbor_decode.h file
3425 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003426void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003427{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003428 if(pMe->uLastError != QCBOR_SUCCESS) {
3429 // Already in error state; do nothing.
3430 return;
3431 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003432
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003433 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003434 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003435 return;
3436 }
3437
3438 /*
3439 Reset the length of the UsefulInputBuf to what it was before
3440 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003441 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003442 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003443 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003444
3445
Laurence Lundblade02625d42020-06-25 14:41:41 -07003446 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003447 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003448}
3449
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003450
Laurence Lundbladee6430642020-03-14 21:15:44 -07003451
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003452
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003453
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003454
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003455
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003456
Laurence Lundblade93d89472020-10-03 22:30:50 -07003457static QCBORError
3458InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003459{
3460 switch(pItem->uDataType) {
3461 case QCBOR_TYPE_TRUE:
3462 *pBool = true;
3463 return QCBOR_SUCCESS;
3464 break;
3465
3466 case QCBOR_TYPE_FALSE:
3467 *pBool = false;
3468 return QCBOR_SUCCESS;
3469 break;
3470
3471 default:
3472 return QCBOR_ERR_UNEXPECTED_TYPE;
3473 break;
3474 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003475 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003476}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003477
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003478
Laurence Lundblade9b334962020-08-27 10:55:53 -07003479
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003480/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003481 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003482*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003483void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003484{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003485 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003486 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003487 return;
3488 }
3489
Laurence Lundbladec4537442020-04-14 18:53:22 -07003490 QCBORError nError;
3491 QCBORItem Item;
3492
3493 nError = QCBORDecode_GetNext(pMe, &Item);
3494 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003495 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003496 return;
3497 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003498 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003499}
3500
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003501
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003502/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003503 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003504*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003505void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003506{
3507 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003508 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003509
Laurence Lundblade9b334962020-08-27 10:55:53 -07003510 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003511}
3512
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003513
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003514/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003515 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003516*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003517void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3518{
3519 QCBORItem Item;
3520 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3521
Laurence Lundblade9b334962020-08-27 10:55:53 -07003522 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003523}
3524
3525
3526
Laurence Lundbladec7114722020-08-13 05:11:40 -07003527
3528static void ProcessEpochDate(QCBORDecodeContext *pMe,
3529 QCBORItem *pItem,
3530 uint8_t uTagRequirement,
3531 int64_t *pnTime)
3532{
3533 if(pMe->uLastError != QCBOR_SUCCESS) {
3534 // Already in error state, do nothing
3535 return;
3536 }
3537
3538 QCBORError uErr;
3539
3540 const TagSpecification TagSpec =
3541 {
3542 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003543 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3544 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003545 };
3546
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003547 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003548 if(uErr != QCBOR_SUCCESS) {
3549 goto Done;
3550 }
3551
3552 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3553 uErr = DecodeDateEpoch(pItem);
3554 if(uErr != QCBOR_SUCCESS) {
3555 goto Done;
3556 }
3557 }
3558
Laurence Lundblade9b334962020-08-27 10:55:53 -07003559 // Save the tags in the last item's tags in the decode context
3560 // for QCBORDecode_GetNthTagOfLast()
3561 CopyTags(pMe, pItem);
3562
Laurence Lundbladec7114722020-08-13 05:11:40 -07003563 *pnTime = pItem->val.epochDate.nSeconds;
3564
3565Done:
3566 pMe->uLastError = (uint8_t)uErr;
3567}
3568
3569
3570void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003571 uint8_t uTagRequirement,
3572 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003573{
3574 if(pMe->uLastError != QCBOR_SUCCESS) {
3575 // Already in error state, do nothing
3576 return;
3577 }
3578
3579 QCBORItem Item;
3580 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3581
3582 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3583}
3584
3585
3586void
3587QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3588 int64_t nLabel,
3589 uint8_t uTagRequirement,
3590 int64_t *pnTime)
3591{
3592 QCBORItem Item;
3593 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3594 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3595}
3596
3597
3598void
3599QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3600 const char *szLabel,
3601 uint8_t uTagRequirement,
3602 int64_t *pnTime)
3603{
3604 QCBORItem Item;
3605 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3606 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3607}
3608
3609
3610
3611
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003612void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3613 TagSpecification TagSpec,
3614 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003615{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003616 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003617 // Already in error state, do nothing
3618 return;
3619 }
3620
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003621 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003622 QCBORItem Item;
3623
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003624 uError = QCBORDecode_GetNext(pMe, &Item);
3625 if(uError != QCBOR_SUCCESS) {
3626 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003627 return;
3628 }
3629
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003630 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003631
3632 if(pMe->uLastError == QCBOR_SUCCESS) {
3633 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003634 } else {
3635 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003636 }
3637}
3638
Laurence Lundbladec4537442020-04-14 18:53:22 -07003639
3640
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003641
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003642static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003643 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003644 UsefulBufC *pValue,
3645 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003646{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003647 const TagSpecification TagSpec =
3648 {
3649 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003650 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3651 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003652 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003653
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003654 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003655 if(uErr != QCBOR_SUCCESS) {
3656 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003657 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003658
3659 *pValue = pItem->val.string;
3660
3661 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3662 *pbIsNegative = false;
3663 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3664 *pbIsNegative = true;
3665 }
3666
3667 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003668}
3669
3670
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003671/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003672 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003673 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003674void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3675 uint8_t uTagRequirement,
3676 UsefulBufC *pValue,
3677 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003678{
3679 if(pMe->uLastError != QCBOR_SUCCESS) {
3680 // Already in error state, do nothing
3681 return;
3682 }
3683
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003684 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003685 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3686 if(uError != QCBOR_SUCCESS) {
3687 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003688 return;
3689 }
3690
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003691 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003692}
3693
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003694
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003695/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003696 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003697*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003698void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3699 int64_t nLabel,
3700 uint8_t uTagRequirement,
3701 UsefulBufC *pValue,
3702 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003703{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003704 QCBORItem Item;
3705 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003706 if(pMe->uLastError != QCBOR_SUCCESS) {
3707 return;
3708 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003709
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003710 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003711}
3712
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003713
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003714/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003715 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003716*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003717void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3718 const char *szLabel,
3719 uint8_t uTagRequirement,
3720 UsefulBufC *pValue,
3721 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003722{
3723 QCBORItem Item;
3724 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003725 if(pMe->uLastError != QCBOR_SUCCESS) {
3726 return;
3727 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003728
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003729 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003730}
3731
3732
3733
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003734
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003735// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003736QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3737 const QCBORItem *pItem,
3738 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003739 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003740{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003741 const TagSpecification TagSpecText =
3742 {
3743 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003744 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3745 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003746 };
3747 const TagSpecification TagSpecBinary =
3748 {
3749 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003750 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3751 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003752 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003753
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003754 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003755
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003756 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003757 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003758 if(pbIsTag257 != NULL) {
3759 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003760 }
3761 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003762 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003763 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003764 if(pbIsTag257 != NULL) {
3765 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003766 }
3767 uReturn = QCBOR_SUCCESS;
3768
3769 } else {
3770 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3771 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003772
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003773 return uReturn;
3774}
3775
Laurence Lundblade93d89472020-10-03 22:30:50 -07003776// Improvement: add methods for wrapped CBOR, a simple alternate
3777// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003778
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003779
3780
3781
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003782#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003783
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003784typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003785
3786
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003787// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003788static QCBORError
3789Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003790{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003791 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003792
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003793 if(uResult != 0) {
3794 /* This loop will run a maximum of 19 times because
3795 * UINT64_MAX < 10 ^^ 19. More than that will cause
3796 * exit with the overflow error
3797 */
3798 for(; nExponent > 0; nExponent--) {
3799 if(uResult > UINT64_MAX / 10) {
3800 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3801 }
3802 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003803 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003804
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003805 for(; nExponent < 0; nExponent++) {
3806 uResult = uResult / 10;
3807 if(uResult == 0) {
3808 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3809 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003810 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003811 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003812 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003813
3814 *puResult = uResult;
3815
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003816 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003817}
3818
3819
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003820// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003821static QCBORError
3822Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003823{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003824 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003825
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003826 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003827
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003828 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003829 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003830 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003831 */
3832 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003833 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003834 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003835 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003836 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003837 nExponent--;
3838 }
3839
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003840 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003841 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003842 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3843 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003844 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003845 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003846 }
3847
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003848 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003849
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003850 return QCBOR_SUCCESS;
3851}
3852
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003853
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003854/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003855 Compute value with signed mantissa and signed result. Works with
3856 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003857 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003858static inline QCBORError ExponentiateNN(int64_t nMantissa,
3859 int64_t nExponent,
3860 int64_t *pnResult,
3861 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003862{
3863 uint64_t uResult;
3864
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003865 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003866 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003867 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3868
3869 // Do the exponentiation of the positive mantissa
3870 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3871 if(uReturn) {
3872 return uReturn;
3873 }
3874
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003875
Laurence Lundblade983500d2020-05-14 11:49:34 -07003876 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3877 of INT64_MIN. This assumes two's compliment representation where
3878 INT64_MIN is one increment farther from 0 than INT64_MAX.
3879 Trying to write -INT64_MIN doesn't work to get this because the
3880 compiler tries to work with an int64_t which can't represent
3881 -INT64_MIN.
3882 */
3883 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3884
3885 // Error out if too large
3886 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003887 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3888 }
3889
3890 // Casts are safe because of checks above
3891 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3892
3893 return QCBOR_SUCCESS;
3894}
3895
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003896
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003897/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003898 Compute value with signed mantissa and unsigned result. Works with
3899 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003900 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003901static inline QCBORError ExponentitateNU(int64_t nMantissa,
3902 int64_t nExponent,
3903 uint64_t *puResult,
3904 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003905{
3906 if(nMantissa < 0) {
3907 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3908 }
3909
3910 // Cast to unsigned is OK because of check for negative
3911 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3912 // Exponentiation is straight forward
3913 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3914}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003915
3916
3917/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003918 Compute value with signed mantissa and unsigned result. Works with
3919 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003920 */
3921static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3922 int64_t nExponent,
3923 uint64_t *puResult,
3924 fExponentiator pfExp)
3925{
3926 return (*pfExp)(uMantissa, nExponent, puResult);
3927}
3928
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003929#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3930
3931
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003932
3933
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003934
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003935static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003936{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003937 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003938
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003939 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003940 const uint8_t *pByte = BigNum.ptr;
3941 size_t uLen = BigNum.len;
3942 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003943 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003944 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003945 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003946 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003947 }
3948
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003949 *pResult = uResult;
3950 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003951}
3952
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003953
Laurence Lundblade887add82020-05-17 05:50:34 -07003954static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003955{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003956 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003957}
3958
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003959
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003960static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003961{
3962 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003963 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3964 if(uError) {
3965 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003966 }
3967 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3968 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003969 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003970}
3971
3972
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003973static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003974{
3975 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003976 /* The negative integer furthest from zero for a C int64_t is
3977 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3978 negative number in CBOR is computed as -n - 1 where n is the
3979 encoded integer, where n is what is in the variable BigNum. When
3980 converting BigNum to a uint64_t, the maximum value is thus
3981 INT64_MAX, so that when it -n - 1 is applied to it the result will
3982 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003983
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003984 -n - 1 <= INT64_MIN.
3985 -n - 1 <= -INT64_MAX - 1
3986 n <= INT64_MAX.
3987 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003988 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003989 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003990 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003991 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003992
3993 /// Now apply -n - 1. The cast is safe because
3994 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3995 // is the largest positive integer that an int64_t can
3996 // represent. */
3997 *pnResult = -(int64_t)uResult - 1;
3998
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003999 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004000}
4001
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004002
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004003
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004004
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004005
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004006/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004007Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004008
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004009\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004010
Laurence Lundblade93d89472020-10-03 22:30:50 -07004011\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4012 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004013
4014\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4015
Laurence Lundblade93d89472020-10-03 22:30:50 -07004016\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4017 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004018*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004019static QCBORError
4020ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004021{
4022 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004023 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004024 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004025#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004026 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004027 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4028 http://www.cplusplus.com/reference/cmath/llround/
4029 */
4030 // Not interested in FE_INEXACT
4031 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004032 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4033 *pnValue = llround(pItem->val.dfnum);
4034 } else {
4035 *pnValue = lroundf(pItem->val.fnum);
4036 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004037 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4038 // llround() shouldn't result in divide by zero, but catch
4039 // it here in case it unexpectedly does. Don't try to
4040 // distinguish between the various exceptions because it seems
4041 // they vary by CPU, compiler and OS.
4042 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004043 }
4044 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004045 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004046 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004047#else
4048 return QCBOR_ERR_HW_FLOAT_DISABLED;
4049#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004050 break;
4051
4052 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004053 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004054 *pnValue = pItem->val.int64;
4055 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004056 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004057 }
4058 break;
4059
4060 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004061 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004062 if(pItem->val.uint64 < INT64_MAX) {
4063 *pnValue = pItem->val.int64;
4064 } else {
4065 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4066 }
4067 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004068 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004069 }
4070 break;
4071
4072 default:
4073 return QCBOR_ERR_UNEXPECTED_TYPE;
4074 }
4075 return QCBOR_SUCCESS;
4076}
4077
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004078
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004079void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004080 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004081 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004082 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004083{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004084 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004085 return;
4086 }
4087
Laurence Lundbladee6430642020-03-14 21:15:44 -07004088 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004089 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4090 if(uError) {
4091 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004092 return;
4093 }
4094
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004095 if(pItem) {
4096 *pItem = Item;
4097 }
4098
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004099 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004100}
4101
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004102
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004103void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4104 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004105 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004106 int64_t *pnValue,
4107 QCBORItem *pItem)
4108{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004109 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004110 if(pMe->uLastError != QCBOR_SUCCESS) {
4111 return;
4112 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004113
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004114 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004115}
4116
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004117
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004118void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4119 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004120 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004121 int64_t *pnValue,
4122 QCBORItem *pItem)
4123{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004124 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004125 if(pMe->uLastError != QCBOR_SUCCESS) {
4126 return;
4127 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004128
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004129 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004130}
4131
4132
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004133/*
4134 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004135
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004136 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004137
Laurence Lundblade93d89472020-10-03 22:30:50 -07004138 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4139 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004140
4141 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4142
Laurence Lundblade93d89472020-10-03 22:30:50 -07004143 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4144 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004145 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004146static QCBORError
4147Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004148{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004149 switch(pItem->uDataType) {
4150
4151 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004152 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004153 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004154 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004155 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004156 }
4157 break;
4158
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004159 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004160 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004161 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004162 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004163 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004164 }
4165 break;
4166
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004167#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4168 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004169 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004170 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004171 pItem->val.expAndMantissa.nExponent,
4172 pnValue,
4173 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004174 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004175 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004176 }
4177 break;
4178
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004179 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004180 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004181 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004182 pItem->val.expAndMantissa.nExponent,
4183 pnValue,
4184 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004185 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004186 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004187 }
4188 break;
4189
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004190 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004191 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004192 int64_t nMantissa;
4193 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004194 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4195 if(uErr) {
4196 return uErr;
4197 }
4198 return ExponentiateNN(nMantissa,
4199 pItem->val.expAndMantissa.nExponent,
4200 pnValue,
4201 Exponentitate10);
4202 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004203 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004204 }
4205 break;
4206
4207 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004208 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004209 int64_t nMantissa;
4210 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004211 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4212 if(uErr) {
4213 return uErr;
4214 }
4215 return ExponentiateNN(nMantissa,
4216 pItem->val.expAndMantissa.nExponent,
4217 pnValue,
4218 Exponentitate10);
4219 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004220 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004221 }
4222 break;
4223
4224 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004225 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004226 int64_t nMantissa;
4227 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004228 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4229 if(uErr) {
4230 return uErr;
4231 }
4232 return ExponentiateNN(nMantissa,
4233 pItem->val.expAndMantissa.nExponent,
4234 pnValue,
4235 Exponentitate2);
4236 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004237 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004238 }
4239 break;
4240
4241 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004242 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004243 int64_t nMantissa;
4244 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004245 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4246 if(uErr) {
4247 return uErr;
4248 }
4249 return ExponentiateNN(nMantissa,
4250 pItem->val.expAndMantissa.nExponent,
4251 pnValue,
4252 Exponentitate2);
4253 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004254 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004255 }
4256 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004257#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4258
Laurence Lundbladee6430642020-03-14 21:15:44 -07004259
Laurence Lundbladec4537442020-04-14 18:53:22 -07004260 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004261 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004262}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004263
4264
Laurence Lundbladec4537442020-04-14 18:53:22 -07004265/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004266 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004267 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004268void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004269{
4270 QCBORItem Item;
4271
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004272 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004273
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004274 if(pMe->uLastError == QCBOR_SUCCESS) {
4275 // The above conversion succeeded
4276 return;
4277 }
4278
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004279 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004280 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004281 return;
4282 }
4283
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004284 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004285}
4286
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004287
4288/*
4289Public function, see header qcbor/qcbor_decode.h file
4290*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004291void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4292 int64_t nLabel,
4293 uint32_t uConvertTypes,
4294 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004295{
4296 QCBORItem Item;
4297
Laurence Lundblade93d89472020-10-03 22:30:50 -07004298 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4299 nLabel,
4300 uConvertTypes,
4301 pnValue,
4302 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004303
4304 if(pMe->uLastError == QCBOR_SUCCESS) {
4305 // The above conversion succeeded
4306 return;
4307 }
4308
4309 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4310 // The above conversion failed in a way that code below can't correct
4311 return;
4312 }
4313
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004314 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004315}
4316
4317
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004318/*
4319Public function, see header qcbor/qcbor_decode.h file
4320*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004321void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4322 const char *szLabel,
4323 uint32_t uConvertTypes,
4324 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004325{
4326 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004327 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4328 szLabel,
4329 uConvertTypes,
4330 pnValue,
4331 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004332
4333 if(pMe->uLastError == QCBOR_SUCCESS) {
4334 // The above conversion succeeded
4335 return;
4336 }
4337
4338 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4339 // The above conversion failed in a way that code below can't correct
4340 return;
4341 }
4342
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004343 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004344}
4345
4346
Laurence Lundblade93d89472020-10-03 22:30:50 -07004347static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004348{
4349 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004350 case QCBOR_TYPE_DOUBLE:
4351 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004352#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004353 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004354 // Can't use llround here because it will not convert values
4355 // greater than INT64_MAX and less than UINT64_MAX that
4356 // need to be converted so it is more complicated.
4357 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4358 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4359 if(isnan(pItem->val.dfnum)) {
4360 return QCBOR_ERR_FLOAT_EXCEPTION;
4361 } else if(pItem->val.dfnum < 0) {
4362 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4363 } else {
4364 double dRounded = round(pItem->val.dfnum);
4365 // See discussion in DecodeDateEpoch() for
4366 // explanation of - 0x7ff
4367 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4368 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4369 }
4370 *puValue = (uint64_t)dRounded;
4371 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004372 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004373 if(isnan(pItem->val.fnum)) {
4374 return QCBOR_ERR_FLOAT_EXCEPTION;
4375 } else if(pItem->val.fnum < 0) {
4376 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4377 } else {
4378 float fRounded = roundf(pItem->val.fnum);
4379 // See discussion in DecodeDateEpoch() for
4380 // explanation of - 0x7ff
4381 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4382 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4383 }
4384 *puValue = (uint64_t)fRounded;
4385 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004386 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004387 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4388 // round() and roundf() shouldn't result in exceptions here, but
4389 // catch them to be robust and thorough. Don't try to
4390 // distinguish between the various exceptions because it seems
4391 // they vary by CPU, compiler and OS.
4392 return QCBOR_ERR_FLOAT_EXCEPTION;
4393 }
4394
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004395 } else {
4396 return QCBOR_ERR_UNEXPECTED_TYPE;
4397 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004398#else
4399 return QCBOR_ERR_HW_FLOAT_DISABLED;
4400#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004401 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004402
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004403 case QCBOR_TYPE_INT64:
4404 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4405 if(pItem->val.int64 >= 0) {
4406 *puValue = (uint64_t)pItem->val.int64;
4407 } else {
4408 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4409 }
4410 } else {
4411 return QCBOR_ERR_UNEXPECTED_TYPE;
4412 }
4413 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004414
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004415 case QCBOR_TYPE_UINT64:
4416 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4417 *puValue = pItem->val.uint64;
4418 } else {
4419 return QCBOR_ERR_UNEXPECTED_TYPE;
4420 }
4421 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004422
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004423 default:
4424 return QCBOR_ERR_UNEXPECTED_TYPE;
4425 }
4426
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004427 return QCBOR_SUCCESS;
4428}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004429
4430
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004431void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004432 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004433 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004434 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004435{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004436 if(pMe->uLastError != QCBOR_SUCCESS) {
4437 return;
4438 }
4439
Laurence Lundbladec4537442020-04-14 18:53:22 -07004440 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004441
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004442 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4443 if(uError) {
4444 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004445 return;
4446 }
4447
Laurence Lundbladea826c502020-05-10 21:07:00 -07004448 if(pItem) {
4449 *pItem = Item;
4450 }
4451
Laurence Lundblade93d89472020-10-03 22:30:50 -07004452 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004453}
4454
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004455
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004456void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004457 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004458 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004459 uint64_t *puValue,
4460 QCBORItem *pItem)
4461{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004462 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004463 if(pMe->uLastError != QCBOR_SUCCESS) {
4464 return;
4465 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004466
Laurence Lundblade93d89472020-10-03 22:30:50 -07004467 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004468}
4469
4470
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004471void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004472 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004473 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004474 uint64_t *puValue,
4475 QCBORItem *pItem)
4476{
4477 if(pMe->uLastError != QCBOR_SUCCESS) {
4478 return;
4479 }
4480
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004481 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004482 if(pMe->uLastError != QCBOR_SUCCESS) {
4483 return;
4484 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004485
Laurence Lundblade93d89472020-10-03 22:30:50 -07004486 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004487}
4488
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004489
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004490
Laurence Lundblade93d89472020-10-03 22:30:50 -07004491static QCBORError
4492UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004493{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004494 switch(pItem->uDataType) {
4495
4496 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004497 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004498 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4499 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004500 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004501 }
4502 break;
4503
4504 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004505 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004506 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4507 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004508 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004509 }
4510 break;
4511
4512#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4513
4514 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004515 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004516 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004517 pItem->val.expAndMantissa.nExponent,
4518 puValue,
4519 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004520 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004521 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004522 }
4523 break;
4524
4525 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004526 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004527 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4528 pItem->val.expAndMantissa.nExponent,
4529 puValue,
4530 Exponentitate2);
4531 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004532 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004533 }
4534 break;
4535
4536 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004537 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004538 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004539 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004540 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004541 if(uErr != QCBOR_SUCCESS) {
4542 return uErr;
4543 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004544 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004545 pItem->val.expAndMantissa.nExponent,
4546 puValue,
4547 Exponentitate10);
4548 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004549 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004550 }
4551 break;
4552
4553 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004554 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004555 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4556 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004557 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004558 }
4559 break;
4560
4561 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004562 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004563 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004564 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004565 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004566 if(uErr != QCBOR_SUCCESS) {
4567 return uErr;
4568 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004569 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004570 pItem->val.expAndMantissa.nExponent,
4571 puValue,
4572 Exponentitate2);
4573 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004574 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004575 }
4576 break;
4577
4578 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004579 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004580 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4581 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004582 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004583 }
4584 break;
4585#endif
4586 default:
4587 return QCBOR_ERR_UNEXPECTED_TYPE;
4588 }
4589}
4590
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004591
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004592/*
4593 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004594 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004595void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004596{
4597 QCBORItem Item;
4598
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004599 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004600
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004601 if(pMe->uLastError == QCBOR_SUCCESS) {
4602 // The above conversion succeeded
4603 return;
4604 }
4605
4606 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4607 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004608 return;
4609 }
4610
Laurence Lundblade93d89472020-10-03 22:30:50 -07004611 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004612}
4613
Laurence Lundbladec4537442020-04-14 18:53:22 -07004614
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004615/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004616 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004617*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004618void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004619 int64_t nLabel,
4620 uint32_t uConvertTypes,
4621 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004622{
4623 QCBORItem Item;
4624
Laurence Lundblade93d89472020-10-03 22:30:50 -07004625 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4626 nLabel,
4627 uConvertTypes,
4628 puValue,
4629 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004630
4631 if(pMe->uLastError == QCBOR_SUCCESS) {
4632 // The above conversion succeeded
4633 return;
4634 }
4635
4636 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4637 // The above conversion failed in a way that code below can't correct
4638 return;
4639 }
4640
Laurence Lundblade93d89472020-10-03 22:30:50 -07004641 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004642}
4643
4644
4645/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004646 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004647*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004648void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004649 const char *szLabel,
4650 uint32_t uConvertTypes,
4651 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004652{
4653 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004654 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4655 szLabel,
4656 uConvertTypes,
4657 puValue,
4658 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004659
4660 if(pMe->uLastError == QCBOR_SUCCESS) {
4661 // The above conversion succeeded
4662 return;
4663 }
4664
4665 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4666 // The above conversion failed in a way that code below can't correct
4667 return;
4668 }
4669
Laurence Lundblade93d89472020-10-03 22:30:50 -07004670 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004671}
4672
4673
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004674
4675
Laurence Lundblade9b334962020-08-27 10:55:53 -07004676static QCBORError ConvertDouble(const QCBORItem *pItem,
4677 uint32_t uConvertTypes,
4678 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004679{
4680 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004681 case QCBOR_TYPE_FLOAT:
4682#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4683 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4684 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004685 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004686 *pdValue = (double)pItem->val.fnum;
4687 } else {
4688 return QCBOR_ERR_UNEXPECTED_TYPE;
4689 }
4690 }
4691#else
4692 return QCBOR_ERR_HW_FLOAT_DISABLED;
4693#endif
4694 break;
4695
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004696 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004697 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4698 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004699 *pdValue = pItem->val.dfnum;
4700 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004701 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004702 }
4703 }
4704 break;
4705
4706 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004707#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004708 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004709 // A simple cast seems to do the job with no worry of exceptions.
4710 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004711 *pdValue = (double)pItem->val.int64;
4712
4713 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004714 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004715 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004716#else
4717 return QCBOR_ERR_HW_FLOAT_DISABLED;
4718#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004719 break;
4720
4721 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004722#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004723 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004724 // A simple cast seems to do the job with no worry of exceptions.
4725 // There will be precision loss for some values.
4726 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004727 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004728 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004729 }
4730 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004731#else
4732 return QCBOR_ERR_HW_FLOAT_DISABLED;
4733#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004734
4735 default:
4736 return QCBOR_ERR_UNEXPECTED_TYPE;
4737 }
4738
4739 return QCBOR_SUCCESS;
4740}
4741
4742
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004743void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004744 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004745 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004746 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004747{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004748 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004749 return;
4750 }
4751
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004752 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004753
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004754 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004755 if(uError) {
4756 pMe->uLastError = (uint8_t)uError;
4757 return;
4758 }
4759
4760 if(pItem) {
4761 *pItem = Item;
4762 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004763
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004764 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004765}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004766
Laurence Lundbladec4537442020-04-14 18:53:22 -07004767
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004768void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4769 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004770 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004771 double *pdValue,
4772 QCBORItem *pItem)
4773{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004774 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004775 if(pMe->uLastError != QCBOR_SUCCESS) {
4776 return;
4777 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004778
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004779 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004780}
4781
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004782
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004783void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4784 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004785 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004786 double *pdValue,
4787 QCBORItem *pItem)
4788{
4789 if(pMe->uLastError != QCBOR_SUCCESS) {
4790 return;
4791 }
4792
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004793 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004794 if(pMe->uLastError != QCBOR_SUCCESS) {
4795 return;
4796 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004797
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004798 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004799}
4800
4801
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004802#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004803static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4804{
4805 double dResult;
4806
4807 dResult = 0.0;
4808 const uint8_t *pByte = BigNum.ptr;
4809 size_t uLen = BigNum.len;
4810 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004811 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004812 while(uLen--) {
4813 dResult = (dResult * 256.0) + (double)*pByte++;
4814 }
4815
4816 return dResult;
4817}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004818#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4819
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004820
Laurence Lundblade93d89472020-10-03 22:30:50 -07004821static QCBORError
4822DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004823{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004824#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004825 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004826 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4827
4828 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004829 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004830
4831#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004832 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004833 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004834 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004835 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4836 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4837 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004838 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004839 }
4840 break;
4841
4842 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004843 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004844 // Underflow gives 0, overflow gives infinity
4845 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4846 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004847 } 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 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004852
4853 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004854 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004855 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4856 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004857 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004858 }
4859 break;
4860
4861 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004862 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004863 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004864 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004865 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004866 }
4867 break;
4868
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004869#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004870 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004871 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004872 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4873 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4874 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004875 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004876 }
4877 break;
4878
4879 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004880 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004881 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4882 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4883 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004884 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004885 }
4886 break;
4887
4888 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004889 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004890 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4891 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4892 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004893 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004894 }
4895 break;
4896
4897 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004898 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004899 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004900 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4901 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004902 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004903 }
4904 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004905#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4906
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004907 default:
4908 return QCBOR_ERR_UNEXPECTED_TYPE;
4909 }
4910
4911 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004912
4913#else
4914 (void)pItem;
4915 (void)uConvertTypes;
4916 (void)pdValue;
4917 return QCBOR_ERR_HW_FLOAT_DISABLED;
4918#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4919
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004920}
4921
4922
4923/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004924 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004925*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004926void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4927 uint32_t uConvertTypes,
4928 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004929{
4930
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004931 QCBORItem Item;
4932
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004933 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004934
4935 if(pMe->uLastError == QCBOR_SUCCESS) {
4936 // The above conversion succeeded
4937 return;
4938 }
4939
4940 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4941 // The above conversion failed in a way that code below can't correct
4942 return;
4943 }
4944
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004945 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004946}
4947
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004948
4949/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004950 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004951*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004952void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4953 int64_t nLabel,
4954 uint32_t uConvertTypes,
4955 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004956{
4957 QCBORItem Item;
4958
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004959 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004960
4961 if(pMe->uLastError == QCBOR_SUCCESS) {
4962 // The above conversion succeeded
4963 return;
4964 }
4965
4966 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4967 // The above conversion failed in a way that code below can't correct
4968 return;
4969 }
4970
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004971 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004972}
4973
4974
4975/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004976 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004977*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004978void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4979 const char *szLabel,
4980 uint32_t uConvertTypes,
4981 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004982{
4983 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004984 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004985
4986 if(pMe->uLastError == QCBOR_SUCCESS) {
4987 // The above conversion succeeded
4988 return;
4989 }
4990
4991 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4992 // The above conversion failed in a way that code below can't correct
4993 return;
4994 }
4995
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004996 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004997}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004998
4999
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005000
5001
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005002#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005003static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5004{
5005 while((uInt & 0xff00000000000000UL) == 0) {
5006 uInt = uInt << 8;
5007 };
5008
5009 UsefulOutBuf UOB;
5010
5011 UsefulOutBuf_Init(&UOB, Buffer);
5012
5013 while(uInt) {
5014 const uint64_t xx = uInt & 0xff00000000000000UL;
5015 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5016 uInt = uInt << 8;
5017 (void)xx;
5018 }
5019
5020 return UsefulOutBuf_OutUBuf(&UOB);
5021}
5022
5023
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005024static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5025 TagSpecification TagSpec,
5026 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005027{
5028 QCBORError uErr;
5029 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005030 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005031 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005032 if(uErr != QCBOR_SUCCESS) {
5033 goto Done;
5034 }
5035
5036 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5037 break; // Successful exit. Moving on to finish decoding.
5038 }
5039
5040 // The item is an array, which means an undecoded
5041 // mantissa and exponent, so decode it. It will then
5042 // have a different type and exit the loop if.
5043 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5044 if(uErr != QCBOR_SUCCESS) {
5045 goto Done;
5046 }
5047
5048 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005049 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005050 }
5051Done:
5052 return uErr;
5053}
5054
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005055
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005056static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005057 TagSpecification TagSpec,
5058 QCBORItem *pItem,
5059 int64_t *pnMantissa,
5060 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005061{
5062 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005063
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005064 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005065 if(uErr != QCBOR_SUCCESS) {
5066 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005067 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005068
Laurence Lundblade9b334962020-08-27 10:55:53 -07005069 switch (pItem->uDataType) {
5070
5071 case QCBOR_TYPE_DECIMAL_FRACTION:
5072 case QCBOR_TYPE_BIGFLOAT:
5073 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5074 *pnExponent = pItem->val.expAndMantissa.nExponent;
5075 break;
5076
5077 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5078 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5079 *pnExponent = pItem->val.expAndMantissa.nExponent;
5080 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5081 break;
5082
5083 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5084 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5085 *pnExponent = pItem->val.expAndMantissa.nExponent;
5086 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5087 break;
5088
5089 default:
5090 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5091 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005092
5093 Done:
5094 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005095}
5096
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005097
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005098static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005099 TagSpecification TagSpec,
5100 QCBORItem *pItem,
5101 UsefulBuf BufferForMantissa,
5102 UsefulBufC *pMantissa,
5103 bool *pbIsNegative,
5104 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005105{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005106 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005107
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005108 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005109 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005110 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005111 }
5112
5113 uint64_t uMantissa;
5114
5115 switch (pItem->uDataType) {
5116
5117 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005118 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005119 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5120 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5121 *pbIsNegative = false;
5122 } else {
5123 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5124 *pbIsNegative = true;
5125 }
5126 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5127 *pnExponent = pItem->val.expAndMantissa.nExponent;
5128 break;
5129
5130 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005131 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005132 *pnExponent = pItem->val.expAndMantissa.nExponent;
5133 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5134 *pbIsNegative = false;
5135 break;
5136
5137 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005138 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005139 *pnExponent = pItem->val.expAndMantissa.nExponent;
5140 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5141 *pbIsNegative = true;
5142 break;
5143
5144 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005145 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005146 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005147
5148Done:
5149 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005150}
5151
5152
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005153/*
5154 Public function, see header qcbor/qcbor_decode.h file
5155*/
5156void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5157 uint8_t uTagRequirement,
5158 int64_t *pnMantissa,
5159 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005160{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005161 if(pMe->uLastError != QCBOR_SUCCESS) {
5162 return;
5163 }
5164
5165 QCBORItem Item;
5166 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5167 if(uError) {
5168 pMe->uLastError = (uint8_t)uError;
5169 return;
5170 }
5171
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005172 const TagSpecification TagSpec =
5173 {
5174 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005175 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5176 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5177 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005178 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005179
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005180 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005181}
5182
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005183
5184/*
5185 Public function, see header qcbor/qcbor_decode.h file
5186*/
5187void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005188 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005189 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005190 int64_t *pnMantissa,
5191 int64_t *pnExponent)
5192{
5193 if(pMe->uLastError != QCBOR_SUCCESS) {
5194 return;
5195 }
5196
5197 QCBORItem Item;
5198 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5199
5200 const TagSpecification TagSpec =
5201 {
5202 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005203 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5204 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5205 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005206 };
5207
5208 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5209}
5210
5211
5212/*
5213 Public function, see header qcbor/qcbor_decode.h file
5214*/
5215void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005216 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005217 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005218 int64_t *pnMantissa,
5219 int64_t *pnExponent)
5220{
5221 if(pMe->uLastError != QCBOR_SUCCESS) {
5222 return;
5223 }
5224
5225 QCBORItem Item;
5226 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5227
5228 const TagSpecification TagSpec =
5229 {
5230 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005231 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5232 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5233 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005234 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005235
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005236 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5237}
5238
5239
5240/*
5241 Public function, see header qcbor/qcbor_decode.h file
5242*/
5243void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5244 uint8_t uTagRequirement,
5245 UsefulBuf MantissaBuffer,
5246 UsefulBufC *pMantissa,
5247 bool *pbMantissaIsNegative,
5248 int64_t *pnExponent)
5249{
5250 if(pMe->uLastError != QCBOR_SUCCESS) {
5251 return;
5252 }
5253
5254 QCBORItem Item;
5255 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5256 if(uError) {
5257 pMe->uLastError = (uint8_t)uError;
5258 return;
5259 }
5260
5261 const TagSpecification TagSpec =
5262 {
5263 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005264 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5265 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5266 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005267 };
5268
Laurence Lundblade93d89472020-10-03 22:30:50 -07005269 ProcessMantissaAndExponentBig(pMe,
5270 TagSpec,
5271 &Item,
5272 MantissaBuffer,
5273 pMantissa,
5274 pbMantissaIsNegative,
5275 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005276}
5277
5278
5279/*
5280 Public function, see header qcbor/qcbor_decode.h file
5281*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005282void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005283 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005284 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005285 UsefulBuf BufferForMantissa,
5286 UsefulBufC *pMantissa,
5287 bool *pbIsNegative,
5288 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005289{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005290 if(pMe->uLastError != QCBOR_SUCCESS) {
5291 return;
5292 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005293
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005294 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005295 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005296 if(pMe->uLastError != QCBOR_SUCCESS) {
5297 return;
5298 }
5299
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005300 const TagSpecification TagSpec =
5301 {
5302 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005303 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5304 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5305 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005306 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005307
Laurence Lundblade93d89472020-10-03 22:30:50 -07005308 ProcessMantissaAndExponentBig(pMe,
5309 TagSpec,
5310 &Item,
5311 BufferForMantissa,
5312 pMantissa,
5313 pbIsNegative,
5314 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005315}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005316
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005317
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005318/*
5319 Public function, see header qcbor/qcbor_decode.h file
5320*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005321void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005322 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005323 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005324 UsefulBuf BufferForMantissa,
5325 UsefulBufC *pMantissa,
5326 bool *pbIsNegative,
5327 int64_t *pnExponent)
5328{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005329 if(pMe->uLastError != QCBOR_SUCCESS) {
5330 return;
5331 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005332
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005333 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005334 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5335 if(pMe->uLastError != QCBOR_SUCCESS) {
5336 return;
5337 }
5338
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005339 const TagSpecification TagSpec =
5340 {
5341 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005342 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5343 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5344 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005345 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005346
5347 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5348}
5349
5350
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005351/*
5352 Public function, see header qcbor/qcbor_decode.h file
5353*/
5354void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5355 uint8_t uTagRequirement,
5356 int64_t *pnMantissa,
5357 int64_t *pnExponent)
5358{
5359 if(pMe->uLastError != QCBOR_SUCCESS) {
5360 return;
5361 }
5362
5363 QCBORItem Item;
5364 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5365 if(uError) {
5366 pMe->uLastError = (uint8_t)uError;
5367 return;
5368 }
5369 const TagSpecification TagSpec =
5370 {
5371 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005372 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5373 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5374 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005375 };
5376
5377 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5378}
5379
5380
5381/*
5382 Public function, see header qcbor/qcbor_decode.h file
5383*/
5384void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005385 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005386 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005387 int64_t *pnMantissa,
5388 int64_t *pnExponent)
5389{
5390 if(pMe->uLastError != QCBOR_SUCCESS) {
5391 return;
5392 }
5393
5394 QCBORItem Item;
5395 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5396 if(pMe->uLastError != QCBOR_SUCCESS) {
5397 return;
5398 }
5399
5400 const TagSpecification TagSpec =
5401 {
5402 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005403 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5404 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5405 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005406 };
5407
5408 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5409}
5410
5411
5412/*
5413 Public function, see header qcbor/qcbor_decode.h file
5414*/
5415void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005416 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005417 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005418 int64_t *pnMantissa,
5419 int64_t *pnExponent)
5420{
5421 if(pMe->uLastError != QCBOR_SUCCESS) {
5422 return;
5423 }
5424
5425 QCBORItem Item;
5426 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5427 if(pMe->uLastError != QCBOR_SUCCESS) {
5428 return;
5429 }
5430
5431 const TagSpecification TagSpec =
5432 {
5433 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005434 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5435 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5436 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005437 };
5438
5439 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5440}
5441
5442
5443/*
5444 Public function, see header qcbor/qcbor_decode.h file
5445*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005446void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5447 uint8_t uTagRequirement,
5448 UsefulBuf MantissaBuffer,
5449 UsefulBufC *pMantissa,
5450 bool *pbMantissaIsNegative,
5451 int64_t *pnExponent)
5452{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005453 if(pMe->uLastError != QCBOR_SUCCESS) {
5454 return;
5455 }
5456
5457 QCBORItem Item;
5458 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5459 if(uError) {
5460 pMe->uLastError = (uint8_t)uError;
5461 return;
5462 }
5463
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005464 const TagSpecification TagSpec =
5465 {
5466 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005467 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5468 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5469 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005470 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005471
5472 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005473}
5474
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005475
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005476/*
5477 Public function, see header qcbor/qcbor_decode.h file
5478*/
5479void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005480 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005481 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005482 UsefulBuf BufferForMantissa,
5483 UsefulBufC *pMantissa,
5484 bool *pbIsNegative,
5485 int64_t *pnExponent)
5486{
5487 if(pMe->uLastError != QCBOR_SUCCESS) {
5488 return;
5489 }
5490
5491 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005492 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5493 if(pMe->uLastError != QCBOR_SUCCESS) {
5494 return;
5495 }
5496
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005497 const TagSpecification TagSpec =
5498 {
5499 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005500 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5501 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5502 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005503 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005504
Laurence Lundblade93d89472020-10-03 22:30:50 -07005505 ProcessMantissaAndExponentBig(pMe,
5506 TagSpec,
5507 &Item,
5508 BufferForMantissa,
5509 pMantissa,
5510 pbIsNegative,
5511 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005512}
5513
5514
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005515/*
5516 Public function, see header qcbor/qcbor_decode.h file
5517*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005518void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005519 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005520 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005521 UsefulBuf BufferForMantissa,
5522 UsefulBufC *pMantissa,
5523 bool *pbIsNegative,
5524 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005525{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005526 if(pMe->uLastError != QCBOR_SUCCESS) {
5527 return;
5528 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005529
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005530 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005531 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5532 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005533 return;
5534 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005535
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005536 const TagSpecification TagSpec =
5537 {
5538 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005539 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5540 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5541 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005542 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005543
Laurence Lundblade93d89472020-10-03 22:30:50 -07005544 ProcessMantissaAndExponentBig(pMe,
5545 TagSpec,
5546 &Item,
5547 BufferForMantissa,
5548 pMantissa,
5549 pbIsNegative,
5550 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005551}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005552
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005553#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */