blob: 7b41ff3efdedc4ed16f4aefcbed6cdc1388b7fdc [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 Lundbladeb69cad72018-09-13 11:09:01 -0700481
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}
519
520
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
547/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700548 Public function, see header file
549 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800550void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
551 QCBORStringAllocate pfAllocateFunction,
552 void *pAllocateContext,
553 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700554{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800555 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
556 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
557 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700558}
559
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800560
561/*
562 Public function, see header file
563 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700564void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800565 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700566{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700567 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700568 (void)pMe;
569 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700570}
571
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700572
573/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800574 This decodes the fundamental part of a CBOR data item, the type and
575 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800576
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700577 This is the counterpart to QCBOREncode_EncodeHead().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800578
Laurence Lundbladeee851742020-01-08 08:37:05 -0800579 This does the network->host byte order conversion. The conversion
580 here also results in the conversion for floats in addition to that
581 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800582
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700583 This returns:
584 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800585
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800586 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800587 tags and floats and length for strings and arrays
588
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800589 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800590 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800591
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800592 The int type is preferred to uint8_t for some variables as this
593 avoids integer promotions, can reduce code size and makes
594 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700595
596 @retval QCBOR_ERR_UNSUPPORTED
597
598 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700599 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700600static inline QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800601 int *pnMajorType,
602 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800603 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700604{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700605 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800606
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700607 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800608 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800609
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700610 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800611 const int nTmpMajorType = nInitialByte >> 5;
612 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800613
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800614 // Where the number or argument accumulates
615 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800616
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800617 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700618 // Need to get 1,2,4 or 8 additional argument bytes. Map
619 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800620 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800621
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800622 // Loop getting all the bytes in the argument
623 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800624 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800625 // This shift and add gives the endian conversion
626 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
627 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800628 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800629 // The reserved and thus-far unused additional info values
630 nReturn = QCBOR_ERR_UNSUPPORTED;
631 goto Done;
632 } else {
633 // Less than 24, additional info is argument or 31, an indefinite length
634 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800635 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700636 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800637
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700638 if(UsefulInputBuf_GetError(pUInBuf)) {
639 nReturn = QCBOR_ERR_HIT_END;
640 goto Done;
641 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800642
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700643 // All successful if we got here.
644 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800645 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800646 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800647 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800648
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700649Done:
650 return nReturn;
651}
652
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800653
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700654/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800655 CBOR doesn't explicitly specify two's compliment for integers but all
656 CPUs use it these days and the test vectors in the RFC are so. All
657 integers in the CBOR structure are positive and the major type
658 indicates positive or negative. CBOR can express positive integers
659 up to 2^x - 1 where x is the number of bits and negative integers
660 down to 2^x. Note that negative numbers can be one more away from
661 zero than positive. Stdint, as far as I can tell, uses two's
662 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800663
Laurence Lundblade9b334962020-08-27 10:55:53 -0700664 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800665 used carefully here, and in particular why it isn't used in the interface.
666 Also see
667 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
668
669 Int is used for values that need less than 16-bits and would be subject
670 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700671
672 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700673 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700674static inline QCBORError
Laurence Lundbladeee851742020-01-08 08:37:05 -0800675DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700676{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700677 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800678
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700679 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
680 if (uNumber <= INT64_MAX) {
681 pDecodedItem->val.int64 = (int64_t)uNumber;
682 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800683
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700684 } else {
685 pDecodedItem->val.uint64 = uNumber;
686 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800687
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700688 }
689 } else {
690 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800691 // CBOR's representation of negative numbers lines up with the
692 // two-compliment representation. A negative integer has one
693 // more in range than a positive integer. INT64_MIN is
694 // equal to (-INT64_MAX) - 1.
695 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700696 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800697
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700698 } else {
699 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000700 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700701 nReturn = QCBOR_ERR_INT_OVERFLOW;
702 }
703 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800704
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700705 return nReturn;
706}
707
708// Make sure #define value line up as DecodeSimple counts on this.
709#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
710#error QCBOR_TYPE_FALSE macro value wrong
711#endif
712
713#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
714#error QCBOR_TYPE_TRUE macro value wrong
715#endif
716
717#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
718#error QCBOR_TYPE_NULL macro value wrong
719#endif
720
721#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
722#error QCBOR_TYPE_UNDEF macro value wrong
723#endif
724
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700725#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
726#error QCBOR_TYPE_BREAK macro value wrong
727#endif
728
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700729#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
730#error QCBOR_TYPE_DOUBLE macro value wrong
731#endif
732
733#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
734#error QCBOR_TYPE_FLOAT macro value wrong
735#endif
736
737/*
738 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700739
740 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
741
742 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700743 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700744static inline QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800745DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700746{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700747 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800748
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700749 // uAdditionalInfo is 5 bits from the initial byte. Compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800750 // above make sure uAdditionalInfo values line up with uDataType values.
Laurence Lundblade93d89472020-10-03 22:30:50 -0700751 // DecodeTypeAndNumber() never returns an AdditionalInfo > 0x1f so cast
752 // is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800753 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800754
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800755 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800756 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
757 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800758
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700759 case HALF_PREC_FLOAT: // 25
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700760#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700761 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700762 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700763 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700764 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
765 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700766#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700767 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700768#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700769 break;
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700770 case SINGLE_PREC_FLOAT: // 26
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700771 // Single precision is normally returned as a double
772 // since double is widely supported, there is no loss of
773 // precision, it makes it easy for the caller in
774 // most cases and it can be converted back to single
775 // with no loss of precision
776 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700777 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700778 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700779 {
780 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
781#ifndef QCBOR_DISABLE_FLOAT_HW_USE
782 // In the normal case, use HW to convert float to double.
783 pDecodedItem->val.dfnum = (double)f;
784 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700785#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700786 // Use of float HW is disabled, return as a float.
787 pDecodedItem->val.fnum = f;
788 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
789
790 // IEEE754_FloatToDouble() could be used here to return
791 // as a double, but it adds object code and most likely
792 // anyone disabling FLOAT HW use doesn't care about
793 // floats and wants to save object code.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700794#endif
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700795 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700796 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700797
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700798 case DOUBLE_PREC_FLOAT: // 27
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700799 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700800 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700801 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800802
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700803 case CBOR_SIMPLEV_FALSE: // 20
804 case CBOR_SIMPLEV_TRUE: // 21
805 case CBOR_SIMPLEV_NULL: // 22
806 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700807 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700808 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800809
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700810 case CBOR_SIMPLEV_ONEBYTE: // 24
811 if(uNumber <= CBOR_SIMPLE_BREAK) {
812 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700813 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700814 goto Done;
815 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800816 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700817 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800818
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700819 default: // 0-19
820 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800821 /*
822 DecodeTypeAndNumber will make uNumber equal to
823 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
824 safe because the 2, 4 and 8 byte lengths of uNumber are in
825 the double/float cases above
826 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700827 pDecodedItem->val.uSimple = (uint8_t)uNumber;
828 break;
829 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800830
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700831Done:
832 return nReturn;
833}
834
835
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700836/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530837 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700838
839 @retval QCBOR_ERR_HIT_END
840
841 @retval QCBOR_ERR_STRING_ALLOCATE
842
843 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700844 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700845static inline QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800846 int nMajorType,
847 uint64_t uStrLen,
848 UsefulInputBuf *pUInBuf,
849 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700850{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700851 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800852
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800853 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
854 // This check makes the casts to size_t below safe.
855
856 // 4 bytes less than the largest sizeof() so this can be tested by
857 // putting a SIZE_MAX length in the CBOR test input (no one will
858 // care the limit on strings is 4 bytes shorter).
859 if(uStrLen > SIZE_MAX-4) {
860 nReturn = QCBOR_ERR_STRING_TOO_LONG;
861 goto Done;
862 }
863
864 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530865 if(UsefulBuf_IsNULLC(Bytes)) {
866 // Failed to get the bytes for this string item
867 nReturn = QCBOR_ERR_HIT_END;
868 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700869 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530870
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800871 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530872 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800873 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530874 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700875 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530876 goto Done;
877 }
878 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800879 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530880 } else {
881 // Normal case with no string allocator
882 pDecodedItem->val.string = Bytes;
883 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800884 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800885 // Cast because ternary operator causes promotion to integer
886 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
887 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800888
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530889Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700890 return nReturn;
891}
892
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700893
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800894
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700895
896
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700897
898
Laurence Lundbladeee851742020-01-08 08:37:05 -0800899// Make sure the constants align as this is assumed by
900// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700901#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
902#error QCBOR_TYPE_ARRAY value not lined up with major type
903#endif
904#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
905#error QCBOR_TYPE_MAP value not lined up with major type
906#endif
907
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700908/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800909 This gets a single data item and decodes it including preceding
910 optional tagging. This does not deal with arrays and maps and nesting
911 except to decode the data item introducing them. Arrays and maps are
912 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800913
Laurence Lundbladeee851742020-01-08 08:37:05 -0800914 Errors detected here include: an array that is too long to decode,
915 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700916
917 @retval QCBOR_ERR_UNSUPPORTED
918
919 @retval QCBOR_ERR_HIT_END
920
921 @retval QCBOR_ERR_INT_OVERFLOW
922
923 @retval QCBOR_ERR_STRING_ALLOCATE
924
925 @retval QCBOR_ERR_STRING_TOO_LONG
926
927 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
928
929 @retval QCBOR_ERR_BAD_TYPE_7
930
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700931 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800932static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
933 QCBORItem *pDecodedItem,
934 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700935{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700936 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800937
Laurence Lundbladeee851742020-01-08 08:37:05 -0800938 /*
939 Get the major type and the number. Number could be length of more
940 bytes or the value depending on the major type nAdditionalInfo is
941 an encoding of the length of the uNumber and is needed to decode
942 floats and doubles
943 */
Rob Gilton47cc9562020-08-10 12:03:38 +0100944 int nMajorType = 0;
945 uint64_t uNumber = 0;
946 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800947
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700948 memset(pDecodedItem, 0, sizeof(QCBORItem));
949
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800950 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800951
Laurence Lundbladeee851742020-01-08 08:37:05 -0800952 // Error out here if we got into trouble on the type and number. The
953 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700954 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700955 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700956 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800957
Laurence Lundbladeee851742020-01-08 08:37:05 -0800958 // At this point the major type and the value are valid. We've got
959 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800960 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700961 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
962 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800963 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700964 nReturn = QCBOR_ERR_BAD_INT;
965 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800966 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700967 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700968 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800969
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700970 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
971 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800972 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
973 const bool bIsBstr = (nMajorType == CBOR_MAJOR_TYPE_BYTE_STRING);
974 pDecodedItem->uDataType = (uint8_t)(bIsBstr ? QCBOR_TYPE_BYTE_STRING
975 : QCBOR_TYPE_TEXT_STRING);
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530976 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700977 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800978 nReturn = DecodeBytes(pAllocator, nMajorType, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700979 }
980 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800981
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700982 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
983 case CBOR_MAJOR_TYPE_MAP: // Major type 5
984 // Record the number of items in the array or map
985 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700986 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700987 goto Done;
988 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800989 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700990 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700991 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800992 // type conversion OK because of check above
993 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700994 }
Laurence Lundbladeee851742020-01-08 08:37:05 -0800995 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800996 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
997 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700998 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800999
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001000 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001001 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001002 nReturn = QCBOR_ERR_BAD_INT;
1003 } else {
1004 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001005 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001006 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001007 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001008
Laurence Lundbladeee851742020-01-08 08:37:05 -08001009 case CBOR_MAJOR_TYPE_SIMPLE:
1010 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001011 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001012 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001013
Laurence Lundbladeee851742020-01-08 08:37:05 -08001014 default:
1015 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001016 nReturn = QCBOR_ERR_UNSUPPORTED;
1017 break;
1018 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001019
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001020Done:
1021 return nReturn;
1022}
1023
1024
1025
1026/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001027 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001028 individual chunk items together into one QCBORItem using the string
1029 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001030
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301031 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade9b334962020-08-27 10:55:53 -07001032
1033 @retval QCBOR_ERR_UNSUPPORTED
1034
1035 @retval QCBOR_ERR_HIT_END
1036
1037 @retval QCBOR_ERR_INT_OVERFLOW
1038
1039 @retval QCBOR_ERR_STRING_ALLOCATE
1040
1041 @retval QCBOR_ERR_STRING_TOO_LONG
1042
1043 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1044
1045 @retval QCBOR_ERR_BAD_TYPE_7
1046
1047 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1048
1049 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001050 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001051static inline QCBORError
1052GetNext_FullItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001053{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001054 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001055
1056 // Get pointer to string allocator. First use is to pass it to
1057 // GetNext_Item() when option is set to allocate for *every* string.
1058 // Second use here is to allocate space to coallese indefinite
1059 // length string items into one.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001060 const QCORInternalAllocator *pAllocator = me->StringAllocator.pfAllocator ?
1061 &(me->StringAllocator) :
1062 NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001063
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001064 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001065 nReturn = GetNext_Item(&(me->InBuf),
1066 pDecodedItem,
1067 me->bStringAllocateAll ? pAllocator: NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001068 if(nReturn) {
1069 goto Done;
1070 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001071
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001072 // To reduce code size by removing support for indefinite length strings, the
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301073 // code in this function from here down can be eliminated. Run tests, except
1074 // indefinite length string tests, to be sure all is OK if this is removed.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001075
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001076 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001077 const uint8_t uStringType = pDecodedItem->uDataType;
1078 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001079 goto Done; // no need to do any work here on non-string types
1080 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001081
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001082 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301083 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001084 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001085 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001086
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301087 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001088 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001089 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1090 goto Done;
1091 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001092
Laurence Lundblade4b270642020-08-14 12:53:07 -07001093 // Loop getting chunks of the indefinite length string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001094 UsefulBufC FullString = NULLUsefulBufC;
1095
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001096 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001097 // Get item for next chunk
1098 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001099 // NULL string allocator passed here. Do not need to allocate
1100 // chunks even if bStringAllocateAll is set.
Laurence Lundbladefae26bf2019-02-18 11:15:43 -08001101 nReturn = GetNext_Item(&(me->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001102 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001103 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001104 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001105
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301106 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001107 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001108 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001109 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301110 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001111 break;
1112 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001113
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001114 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301115 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001116 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001117 if(StringChunkItem.uDataType != uStringType ||
1118 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001119 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001120 break;
1121 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001122
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301123 // Alloc new buffer or expand previously allocated buffer so it can fit
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001124 // The first time throurgh FullString.ptr is NULL and this is
1125 // equivalent to StringAllocator_Allocate()
1126 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1127 UNCONST_POINTER(FullString.ptr),
1128 FullString.len + StringChunkItem.val.string.len);
1129
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001130 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301131 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001132 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001133 break;
1134 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001135
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001136 // Copy new string chunk at the end of string so far.
1137 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001138 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001139
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001140 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1141 // Getting the item failed, clean up the allocated memory
1142 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001143 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001144
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001145Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001146 return nReturn;
1147}
1148
Laurence Lundblade9b334962020-08-27 10:55:53 -07001149static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001150 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001151 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001152 } else if(uTagVal == CBOR_TAG_INVALID16) {
1153 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001154 } else {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001155 // This won't be negative because of code below in GetNext_TaggedItem()
1156 const unsigned uIndex = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
1157 return me->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001158 }
1159}
1160
Laurence Lundblade9b334962020-08-27 10:55:53 -07001161
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001162/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001163 Gets all optional tag data items preceding a data item that is not an
1164 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001165
1166 @retval QCBOR_ERR_UNSUPPORTED
1167
1168 @retval QCBOR_ERR_HIT_END
1169
1170 @retval QCBOR_ERR_INT_OVERFLOW
1171
1172 @retval QCBOR_ERR_STRING_ALLOCATE
1173
1174 @retval QCBOR_ERR_STRING_TOO_LONG
1175
1176 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1177
1178 @retval QCBOR_ERR_BAD_TYPE_7
1179
1180 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1181
1182 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1183
1184 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001185 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001186static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001187GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001188{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001189 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1190 CBOR_TAG_INVALID16,
1191 CBOR_TAG_INVALID16,
1192 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001193
Laurence Lundblade9b334962020-08-27 10:55:53 -07001194 QCBORError uReturn = QCBOR_SUCCESS;
1195
Laurence Lundblade59289e52019-12-30 13:44:37 -08001196 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001197 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001198 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1199 if(uErr != QCBOR_SUCCESS) {
1200 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001201 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001202 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001203
Laurence Lundblade9b334962020-08-27 10:55:53 -07001204 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001205 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001206 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001207 break;
1208 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001209
Laurence Lundblade9b334962020-08-27 10:55:53 -07001210 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1211 // No room in the tag list
1212 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1213 // Continue on to get all tags on this item even though
1214 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001215 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001216 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001217 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001218 // Slide tags over one in the array to make room at index 0
1219 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1220 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001221 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001222
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001223 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001224 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001225 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001226 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001227 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001228 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001229 break;
1230 }
1231 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1232 break;
1233 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001234 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001235 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1236 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001237 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1238 // Continue on to get all tags on this item even though
1239 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001240 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001241 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001242 }
1243
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001244 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001245 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001246 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001247
1248 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001249 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001250 }
1251 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001252
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001253Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001254 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001255}
1256
1257
1258/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001259 This layer takes care of map entries. It combines the label and data
1260 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001261
1262 @retval QCBOR_ERR_UNSUPPORTED
1263
1264 @retval QCBOR_ERR_HIT_END
1265
1266 @retval QCBOR_ERR_INT_OVERFLOW
1267
1268 @retval QCBOR_ERR_STRING_ALLOCATE
1269
1270 @retval QCBOR_ERR_STRING_TOO_LONG
1271
1272 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1273
1274 @retval QCBOR_ERR_BAD_TYPE_7
1275
1276 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1277
1278 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1279
1280 @retval QCBOR_ERR_TOO_MANY_TAGS
1281
1282 @retval QCBOR_ERR_MAP_LABEL_TYPE
1283
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001284 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001285 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001286static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001287GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001288{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001289 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001290 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001291 if(nReturn)
1292 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001293
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001294 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001295 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001296 goto Done;
1297 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001298
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001299 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1300 // In a map and caller wants maps decoded, not treated as arrays
1301
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001302 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001303 // If in a map and the right decoding mode, get the label
1304
Laurence Lundbladeee851742020-01-08 08:37:05 -08001305 // Save label in pDecodedItem and get the next which will
1306 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001307 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001308 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001309 if(QCBORDecode_IsUnrecoverableError(nReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001310 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001311 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001312
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301313 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001314
1315 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1316 // strings are always good labels
1317 pDecodedItem->label.string = LabelItem.val.string;
1318 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1319 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001320 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001321 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1322 goto Done;
1323 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1324 pDecodedItem->label.int64 = LabelItem.val.int64;
1325 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1326 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1327 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1328 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1329 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1330 pDecodedItem->label.string = LabelItem.val.string;
1331 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1332 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1333 } else {
1334 // label is not an int or a string. It is an arrray
1335 // or a float or such and this implementation doesn't handle that.
1336 // Also, tags on labels are ignored.
1337 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1338 goto Done;
1339 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001340 }
1341 } else {
1342 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001343 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001344 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001345 goto Done;
1346 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001347 // Decoding a map as an array
1348 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001349 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1350 // Cast is needed because of integer promotion
1351 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001352 }
1353 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001354
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001355Done:
1356 return nReturn;
1357}
1358
1359
Laurence Lundblade02625d42020-06-25 14:41:41 -07001360/*
1361 See if next item is a CBOR break. If it is, it is consumed,
1362 if not it is not consumed.
1363*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001364static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001365NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1366{
1367 *pbNextIsBreak = false;
1368 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001369 QCBORItem Peek;
1370 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1371 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1372 if(uReturn != QCBOR_SUCCESS) {
1373 return uReturn;
1374 }
1375 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001376 // It is not a break, rewind so it can be processed normally.
1377 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001378 } else {
1379 *pbNextIsBreak = true;
1380 }
1381 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001382
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001383 return QCBOR_SUCCESS;
1384}
1385
1386
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001387/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001388 An item was just consumed, now figure out if it was the
1389 end of an array or map that can be closed out. That
1390 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001391*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001392static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001393{
1394 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001395
Laurence Lundblade642282a2020-06-23 12:00:33 -07001396 /* This loops ascending nesting levels as long as there is ascending to do */
1397 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1398
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001399 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001400 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001401 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1402 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001403 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001404 break;
1405 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07001406 /* All of a definite length array was consumed; fall through to
1407 ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001408
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001409 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001410 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001411 bool bIsBreak = false;
1412 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1413 if(uReturn != QCBOR_SUCCESS) {
1414 goto Done;
1415 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001416
1417 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001418 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001419 break;
1420 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001421
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001422 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001423 /*
1424 Break occurred inside a bstr-wrapped CBOR or
1425 in the top level sequence. This is always an
1426 error because neither are an indefinte length
1427 map/array.
1428 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001429 uReturn = QCBOR_ERR_BAD_BREAK;
1430 goto Done;
1431 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001432
Laurence Lundblade02625d42020-06-25 14:41:41 -07001433 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001434 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001435
Laurence Lundblade02625d42020-06-25 14:41:41 -07001436 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001437
Laurence Lundblade93d89472020-10-03 22:30:50 -07001438 /* But ascent in bounded mode is only by explicit call to
1439 QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001440 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001441 /* Set the count to zero for definite length arrays to indicate
1442 cursor is at end of bounded map / array */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001443 if(bMarkEnd) {
1444 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001445 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001446
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001447 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001448 break;
1449 }
1450
1451 /* Finally, actually ascend one level. */
1452 DecodeNesting_Ascend(&(pMe->nesting));
1453 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001454
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001455 uReturn = QCBOR_SUCCESS;
1456
1457Done:
1458 return uReturn;
1459}
1460
1461
1462/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001463 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001464 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1465 indefinte length maps and arrays by looking at the item count or
1466 finding CBOR breaks. It detects the ends of the top-level sequence
1467 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001468
1469 @retval QCBOR_ERR_UNSUPPORTED X
1470
1471 @retval QCBOR_ERR_HIT_END
1472
1473 @retval QCBOR_ERR_INT_OVERFLOW X
1474
1475 @retval QCBOR_ERR_STRING_ALLOCATE
1476
1477 @retval QCBOR_ERR_STRING_TOO_LONG
1478
1479 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1480
1481 @retval QCBOR_ERR_BAD_TYPE_7 X
1482
1483 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1484
1485 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1486
1487 @retval QCBOR_ERR_TOO_MANY_TAGS
1488
1489 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1490
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001491 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001492
1493 @retval QCBOR_ERR_NO_MORE_ITEMS
1494
1495 @retval QCBOR_ERR_BAD_BREAK
1496
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001497 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001498static QCBORError
1499QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001500{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001501 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001502 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001503
Laurence Lundblade642282a2020-06-23 12:00:33 -07001504 /*
1505 If out of bytes to consume, it is either the end of the top-level
1506 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001507
Laurence Lundblade642282a2020-06-23 12:00:33 -07001508 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1509 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1510 CBOR is exited, the length is set back to the top-level's length
1511 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001512 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001513 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001514 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001515 goto Done;
1516 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001517
Laurence Lundblade642282a2020-06-23 12:00:33 -07001518 /*
1519 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001520 array. The check for the end of an indefinite length array is
1521 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001522 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001523 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001524 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001525 goto Done;
1526 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001527
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001528 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001529 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001530 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1531 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001532 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001533 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301534
Laurence Lundblade642282a2020-06-23 12:00:33 -07001535 /*
1536 Breaks ending arrays/maps are always processed at the end of this
1537 function. They should never show up here.
1538 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301539 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001540 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301541 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301542 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001543
Laurence Lundblade642282a2020-06-23 12:00:33 -07001544 /*
1545 Record the nesting level for this data item before processing any
1546 of decrementing and descending.
1547 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001548 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001549
Laurence Lundblade642282a2020-06-23 12:00:33 -07001550
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001551 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001552 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001553 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001554 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001555
Laurence Lundblade93d89472020-10-03 22:30:50 -07001556 Empty indefinite length maps and arrays are descended into, but
1557 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001558
1559 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001560 encloses them so a decrement needs to be done for them too, but
1561 that is done only when all the items in them have been
1562 processed, not when they are opened with the exception of an
1563 empty map or array.
1564 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001565 QCBORError uDescendErr;
1566 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001567 pDecodedItem->uDataType,
1568 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001569 if(uDescendErr != QCBOR_SUCCESS) {
1570 /* This error is probably a traversal error and it
1571 overrides the non-traversal error. */
1572 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001573 goto Done;
1574 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001575 }
1576
Laurence Lundblade02625d42020-06-25 14:41:41 -07001577 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1578 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1579 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001580 /*
1581 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001582 - A non-aggregate like an integer or string
1583 - An empty definite length map or array
1584 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001585
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001586 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001587 definite length map/array and break detection for an indefinite
1588 length map/array. If the end of the map/array was reached, then
1589 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001590 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001591 QCBORError uAscendErr;
1592 uAscendErr = NestLevelAscender(me, true);
1593 if(uAscendErr != QCBOR_SUCCESS) {
1594 /* This error is probably a traversal error and it
1595 overrides the non-traversal error. */
1596 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001597 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001598 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301599 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001600
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001601 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001602 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001603 Tell the caller what level is next. This tells them what
1604 maps/arrays were closed out and makes it possible for them to
1605 reconstruct the tree with just the information returned in
1606 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001607 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001608 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001609 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001610 pDecodedItem->uNextNestLevel = 0;
1611 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001612 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001613 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001614
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001615Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001616 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001617}
1618
Laurence Lundblade9b334962020-08-27 10:55:53 -07001619static void ShiftTags(QCBORItem *pDecodedItem)
1620{
1621 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1622 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1623 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1624 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1625}
1626
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001627
Laurence Lundblade59289e52019-12-30 13:44:37 -08001628/*
1629 Mostly just assign the right data type for the date string.
1630 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001631static inline QCBORError DecodeDateString(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001632{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001633 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1634 return QCBOR_ERR_BAD_OPT_TAG;
1635 }
1636
1637 const UsefulBufC Temp = pDecodedItem->val.string;
1638 pDecodedItem->val.dateString = Temp;
1639 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001640 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001641 return QCBOR_SUCCESS;
1642}
1643
1644
Laurence Lundblade9b334962020-08-27 10:55:53 -07001645
Laurence Lundblade59289e52019-12-30 13:44:37 -08001646/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001647 The epoch formatted date. Turns lots of different forms of encoding
1648 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001649 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001650static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001651{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001652 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001653
1654 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1655
1656 switch (pDecodedItem->uDataType) {
1657
1658 case QCBOR_TYPE_INT64:
1659 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1660 break;
1661
1662 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001663 // This only happens for CBOR type 0 > INT64_MAX so it is
1664 // always an overflow.
1665 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1666 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001667 break;
1668
1669 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001670 case QCBOR_TYPE_FLOAT:
1671#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001672 {
1673 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001674 // conversion to an int64_t to be able to detect doubles that
1675 // are too large to fit into an int64_t. A double has 52
1676 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1677 // to a double actually causes a round up which is bad and
1678 // wrong for the comparison because it will allow conversion
1679 // of doubles that can't fit into a uint64_t. To remedy this
1680 // INT64_MAX - 0x7ff is used as the cutoff point because if
1681 // that value rounds up in conversion to double it will still
1682 // be less than INT64_MAX. 0x7ff is picked because it has 11
1683 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001684 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001685 // INT64_MAX seconds is on the order of 10 billion years, and
1686 // the earth is less than 5 billion years old, so for most
1687 // uses this conversion error won't occur even though doubles
1688 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001689 //
1690 // Without the 0x7ff there is a ~30 minute range of time
1691 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001692 // where this code would go wrong. Some compilers
1693 // will generate warnings or errors without the 0x7ff
1694 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001695 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1696 pDecodedItem->val.dfnum :
1697 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001698 if(isnan(d) ||
1699 d > (double)(INT64_MAX - 0x7ff) ||
1700 d < (double)(INT64_MIN + 0x7ff)) {
1701 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001702 goto Done;
1703 }
1704 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001705 pDecodedItem->val.epochDate.fSecondsFraction =
1706 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001707 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001708#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001709
Laurence Lundbladec7114722020-08-13 05:11:40 -07001710 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001711 goto Done;
1712
Laurence Lundblade9682a532020-06-06 18:33:04 -07001713#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001714 break;
1715
1716 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001717 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001718 goto Done;
1719 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001720
Laurence Lundblade59289e52019-12-30 13:44:37 -08001721 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1722
1723Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001724 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001725}
1726
1727
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001728/*
1729 Mostly just assign the right data type for the bignum.
1730 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001731static inline QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001732{
1733 // Stack Use: UsefulBuf 1 -- 16
1734 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1735 return QCBOR_ERR_BAD_OPT_TAG;
1736 }
1737 const UsefulBufC Temp = pDecodedItem->val.string;
1738 pDecodedItem->val.bigNum = Temp;
1739 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1740 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1741 : QCBOR_TYPE_NEGBIGNUM);
1742 return QCBOR_SUCCESS;
1743}
1744
1745
Laurence Lundblade59289e52019-12-30 13:44:37 -08001746#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1747/*
1748 Decode decimal fractions and big floats.
1749
1750 When called pDecodedItem must be the array that is tagged as a big
1751 float or decimal fraction, the array that has the two members, the
1752 exponent and mantissa.
1753
1754 This will fetch and decode the exponent and mantissa and put the
1755 result back into pDecodedItem.
1756 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001757static inline QCBORError
Laurence Lundblade59289e52019-12-30 13:44:37 -08001758QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1759{
1760 QCBORError nReturn;
1761
1762 // --- Make sure it is an array; track nesting level of members ---
1763 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1764 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1765 goto Done;
1766 }
1767
1768 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001769 // definite length arrays, but not for indefnite. Instead remember
1770 // the nesting level the two integers must be at, which is one
1771 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001772 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1773
1774 // --- Is it a decimal fraction or a bigfloat? ---
1775 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1776 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1777
1778 // --- Get the exponent ---
1779 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001780 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001781 if(nReturn != QCBOR_SUCCESS) {
1782 goto Done;
1783 }
1784 if(exponentItem.uNestingLevel != nNestLevel) {
1785 // Array is empty or a map/array encountered when expecting an int
1786 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1787 goto Done;
1788 }
1789 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1790 // Data arriving as an unsigned int < INT64_MAX has been converted
1791 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1792 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1793 // will be too large for this to handle and thus an error that will
1794 // get handled in the next else.
1795 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1796 } else {
1797 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1798 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1799 goto Done;
1800 }
1801
1802 // --- Get the mantissa ---
1803 QCBORItem mantissaItem;
1804 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1805 if(nReturn != QCBOR_SUCCESS) {
1806 goto Done;
1807 }
1808 if(mantissaItem.uNestingLevel != nNestLevel) {
1809 // Mantissa missing or map/array encountered when expecting number
1810 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1811 goto Done;
1812 }
1813 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1814 // Data arriving as an unsigned int < INT64_MAX has been converted
1815 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1816 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1817 // will be too large for this to handle and thus an error that
1818 // will get handled in an else below.
1819 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001820 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
1821 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001822 // Got a good big num mantissa
1823 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1824 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001825 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1826 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1827 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001828 } else {
1829 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1830 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1831 goto Done;
1832 }
1833
1834 // --- Check that array only has the two numbers ---
1835 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001836 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001837 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1838 goto Done;
1839 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001840 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001841
1842Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001843 return nReturn;
1844}
1845#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1846
1847
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001848static inline QCBORError DecodeURI(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001849{
1850 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1851 return QCBOR_ERR_BAD_OPT_TAG;
1852 }
1853 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1854 return QCBOR_SUCCESS;
1855}
1856
1857
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001858static inline QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001859{
1860 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1861 return QCBOR_ERR_BAD_OPT_TAG;
1862 }
1863 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001864
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001865 return QCBOR_SUCCESS;
1866}
1867
1868
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001869static inline QCBORError DecodeB64(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001870{
1871 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1872 return QCBOR_ERR_BAD_OPT_TAG;
1873 }
1874 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001875
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001876 return QCBOR_SUCCESS;
1877}
1878
1879
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001880static inline QCBORError DecodeRegex(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001881{
1882 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1883 return QCBOR_ERR_BAD_OPT_TAG;
1884 }
1885 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001886
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001887 return QCBOR_SUCCESS;
1888}
1889
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001890
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001891static inline QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001892{
1893 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1894 return QCBOR_ERR_BAD_OPT_TAG;
1895 }
1896 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001897
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001898 return QCBOR_SUCCESS;
1899}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001900
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001901
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001902static inline QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001903{
1904 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1905 return QCBOR_ERR_BAD_OPT_TAG;
1906 }
1907 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001908
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001909 return QCBOR_SUCCESS;
1910}
1911
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001912
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001913static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001914{
1915 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1916 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001917 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001918 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1919 } else {
1920 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001921
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001922 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001923
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001924 return QCBOR_SUCCESS;
1925}
1926
1927
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001928static inline QCBORError DecodeUUID(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001929{
1930 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1931 return QCBOR_ERR_BAD_OPT_TAG;
1932 }
1933 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001934
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001935 return QCBOR_SUCCESS;
1936}
1937
1938
Laurence Lundblade59289e52019-12-30 13:44:37 -08001939/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001940 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001941 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001942static QCBORError
1943QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001944{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001945 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001946
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001947 uReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
1948 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001949 goto Done;
1950 }
1951
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001952 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
1953 switch(pDecodedItem->uTags[uTagIndex]) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001954
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001955 // Many of the functions here only just map a CBOR tag to
1956 // a QCBOR_TYPE for a string and could probably be
1957 // implemented with less object code. This implementation
1958 // of string types takes about 120 bytes of object code
1959 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001960 case CBOR_TAG_DATE_STRING:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001961 uReturn = DecodeDateString(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001962 break;
1963
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001964 case CBOR_TAG_DATE_EPOCH:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001965 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001966 break;
1967
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001968 case CBOR_TAG_POS_BIGNUM:
1969 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001970 uReturn = DecodeBigNum(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001971 break;
1972
Laurence Lundblade93d89472020-10-03 22:30:50 -07001973#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001974 case CBOR_TAG_DECIMAL_FRACTION:
1975 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001976 // For aggregate tagged types, what goes into pTags is only collected
1977 // from the surrounding data item, not the contents, so pTags is not
1978 // passed on here.
1979
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001980 uReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001981 break;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001982#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001983
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001984 case CBOR_TAG_CBOR:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001985 uReturn = DecodeWrappedCBOR(pDecodedItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001986 break;
1987
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001988 case CBOR_TAG_CBOR_SEQUENCE:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001989 uReturn = DecodeWrappedCBORSequence(pDecodedItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001990 break;
1991
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001992 case CBOR_TAG_URI:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001993 uReturn = DecodeURI(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001994 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001995
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001996 case CBOR_TAG_B64URL:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001997 uReturn = DecodeB64URL(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001998 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001999
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002000 case CBOR_TAG_B64:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002001 uReturn = DecodeB64(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002002 break;
2003
2004 case CBOR_TAG_MIME:
2005 case CBOR_TAG_BINARY_MIME:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002006 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002007 break;
2008
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002009 case CBOR_TAG_REGEX:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002010 uReturn = DecodeRegex(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002011 break;
2012
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002013 case CBOR_TAG_BIN_UUID:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002014 uReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002015 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002016
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002017 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002018 // The end of the tag list or no tags
2019 // Successful exit from the loop.
2020 goto Done;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002021
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002022 default:
2023 // A tag that is not understood
2024 // A successful exit from the loop
2025 goto Done;
2026
2027 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002028 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002029 goto Done;
2030 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002031 // A tag was successfully processed, shift it
2032 // out of the list of tags returned.
2033 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002034 }
2035
2036Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002037 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002038}
2039
2040
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002041/*
2042 Public function, see header qcbor/qcbor_decode.h file
2043 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002044QCBORError
2045QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2046{
2047 QCBORError uErr;
2048 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2049 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002050 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2051 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2052 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002053 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002054}
2055
2056
2057/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002058 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002059 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002060QCBORError
2061QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2062{
2063 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2064 const UsefulInputBuf Save = pMe->InBuf;
2065
2066 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2067
2068 pMe->nesting = SaveNesting;
2069 pMe->InBuf = Save;
2070
2071 return uErr;
2072}
2073
2074
2075/*
2076 Public function, see header qcbor/qcbor_decode.h file
2077 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002078void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2079{
2080 if(pMe->uLastError != QCBOR_SUCCESS) {
2081 return;
2082 }
2083
2084 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2085}
2086
2087
2088/*
2089 Public function, see header qcbor/qcbor_decode.h file
2090 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002091QCBORError
2092QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2093 QCBORItem *pDecodedItem,
2094 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002095{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002096 QCBORError nReturn;
2097
2098 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2099 if(nReturn != QCBOR_SUCCESS) {
2100 return nReturn;
2101 }
2102
2103 if(pTags != NULL) {
2104 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002105 // Reverse the order because pTags is reverse of
2106 // QCBORItem.uTags.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002107 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2108 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002109 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002110 }
2111 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2112 return QCBOR_ERR_TOO_MANY_TAGS;
2113 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002114 pTags->puTags[pTags->uNumUsed] = ConvertTag(me,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002115 pTags->uNumUsed++;
2116 }
2117 }
2118
2119 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002120}
2121
2122
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002123/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302124 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302125 next one down. If a layer has no work to do for a particular item
2126 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002127
Laurence Lundblade59289e52019-12-30 13:44:37 -08002128 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2129 tagged data items, turning them into the local C representation.
2130 For the most simple it is just associating a QCBOR_TYPE with the data. For
2131 the complex ones that an aggregate of data items, there is some further
2132 decoding and a little bit of recursion.
2133
2134 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302135 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302136 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002137 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002138
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302139 - GetNext_MapEntry -- This handles the combining of two
2140 items, the label and the data, that make up a map entry.
2141 It only does work on maps. It combines the label and data
2142 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002143
Laurence Lundblade59289e52019-12-30 13:44:37 -08002144 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2145 tags into bit flags associated with the data item. No actual decoding
2146 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002147
Laurence Lundblade59289e52019-12-30 13:44:37 -08002148 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302149 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302150 string allocater to create contiguous space for the item. It
2151 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002152
Laurence Lundblade59289e52019-12-30 13:44:37 -08002153 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2154 atomic data item has a "major type", an integer "argument" and optionally
2155 some content. For text and byte strings, the content is the bytes
2156 that make up the string. These are the smallest data items that are
2157 considered to be well-formed. The content may also be other data items in
2158 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002159
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002160 Roughly this takes 300 bytes of stack for vars. Need to
2161 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002162
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302163 */
2164
2165
2166/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002167 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002168 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002169bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002170 const QCBORItem *pItem,
2171 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002172{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002173 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2174 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002175 break;
2176 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002177 if(ConvertTag(me, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002178 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002179 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002180 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002181
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002182 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002183}
2184
2185
2186/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002187 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002188 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002189QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002190{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002191 QCBORError uReturn = me->uLastError;
2192
2193 if(uReturn != QCBOR_SUCCESS) {
2194 goto Done;
2195 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002196
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002197 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002198 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002199 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002200 goto Done;
2201 }
2202
2203 // Error out if not all the bytes are consumed
2204 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002205 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002206 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002207
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002208Done:
Laurence Lundblade6de37062018-10-15 12:22:42 +05302209 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002210 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002211 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002212
Laurence Lundblade085d7952020-07-24 10:26:30 -07002213 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002214}
2215
2216
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002217/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002218 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002219*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002220// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002221uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2222 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002223 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002224{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002225 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2226 return CBOR_TAG_INVALID64;
2227 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002228 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2229 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002230 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002231 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002232 }
2233}
2234
Laurence Lundblade9b334962020-08-27 10:55:53 -07002235/*
2236 Public function, see header qcbor/qcbor_decode.h file
2237*/
2238uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2239 uint32_t uIndex)
2240{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002241 if(pMe->uLastError != QCBOR_SUCCESS) {
2242 return CBOR_TAG_INVALID64;
2243 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002244 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2245 return CBOR_TAG_INVALID64;
2246 } else {
2247 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2248 }
2249}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002250
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002251/*
2252
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002253Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002254
Laurence Lundbladeee851742020-01-08 08:37:05 -08002255 - Hit end of input before it was expected while decoding type and
2256 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002257
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002258 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002259
Laurence Lundbladeee851742020-01-08 08:37:05 -08002260 - Hit end of input while decoding a text or byte string
2261 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002262
Laurence Lundbladeee851742020-01-08 08:37:05 -08002263 - Encountered conflicting tags -- e.g., an item is tagged both a date
2264 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002265
Laurence Lundbladeee851742020-01-08 08:37:05 -08002266 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002267 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002268
Laurence Lundbladeee851742020-01-08 08:37:05 -08002269 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002270 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002271
Laurence Lundbladeee851742020-01-08 08:37:05 -08002272 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2273 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002274
Laurence Lundbladeee851742020-01-08 08:37:05 -08002275 - The type of a map label is not a string or int
2276 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002277
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002278 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002279
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002280 */
2281
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002282
2283
Laurence Lundbladef6531662018-12-04 10:42:22 +09002284
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002285/* ===========================================================================
2286 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002287
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002288 This implements a simple sting allocator for indefinite length
2289 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2290 implements the function type QCBORStringAllocate and allows easy
2291 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002292
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002293 This particular allocator is built-in for convenience. The caller
2294 can implement their own. All of this following code will get
2295 dead-stripped if QCBORDecode_SetMemPool() is not called.
2296
2297 This is a very primitive memory allocator. It does not track
2298 individual allocations, only a high-water mark. A free or
2299 reallocation must be of the last chunk allocated.
2300
2301 The size of the pool and offset to free memory are packed into the
2302 first 8 bytes of the memory pool so we don't have to keep them in
2303 the decode context. Since the address of the pool may not be
2304 aligned, they have to be packed and unpacked as if they were
2305 serialized data of the wire or such.
2306
2307 The sizes packed in are uint32_t to be the same on all CPU types
2308 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002309 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002310
2311
Laurence Lundbladeee851742020-01-08 08:37:05 -08002312static inline int
2313MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002314{
2315 // Use of UsefulInputBuf is overkill, but it is convenient.
2316 UsefulInputBuf UIB;
2317
Laurence Lundbladeee851742020-01-08 08:37:05 -08002318 // Just assume the size here. It was checked during SetUp so
2319 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002320 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002321 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2322 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2323 return UsefulInputBuf_GetError(&UIB);
2324}
2325
2326
Laurence Lundbladeee851742020-01-08 08:37:05 -08002327static inline int
2328MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002329{
2330 // Use of UsefulOutBuf is overkill, but convenient. The
2331 // length check performed here is useful.
2332 UsefulOutBuf UOB;
2333
2334 UsefulOutBuf_Init(&UOB, Pool);
2335 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2336 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2337 return UsefulOutBuf_GetError(&UOB);
2338}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002339
2340
2341/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002342 Internal function for an allocation, reallocation free and destuct.
2343
2344 Having only one function rather than one each per mode saves space in
2345 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002346
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002347 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2348 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002349static UsefulBuf
2350MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002351{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002352 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002353
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002354 uint32_t uPoolSize;
2355 uint32_t uFreeOffset;
2356
2357 if(uNewSize > UINT32_MAX) {
2358 // This allocator is only good up to 4GB. This check should
2359 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2360 goto Done;
2361 }
2362 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2363
2364 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2365 goto Done;
2366 }
2367
2368 if(uNewSize) {
2369 if(pMem) {
2370 // REALLOCATION MODE
2371 // Calculate pointer to the end of the memory pool. It is
2372 // assumed that pPool + uPoolSize won't wrap around by
2373 // assuming the caller won't pass a pool buffer in that is
2374 // not in legitimate memory space.
2375 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2376
2377 // Check that the pointer for reallocation is in the range of the
2378 // pool. This also makes sure that pointer math further down
2379 // doesn't wrap under or over.
2380 if(pMem >= pPool && pMem < pPoolEnd) {
2381 // Offset to start of chunk for reallocation. This won't
2382 // wrap under because of check that pMem >= pPool. Cast
2383 // is safe because the pool is always less than UINT32_MAX
2384 // because of check in QCBORDecode_SetMemPool().
2385 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2386
2387 // Check to see if the allocation will fit. uPoolSize -
2388 // uMemOffset will not wrap under because of check that
2389 // pMem is in the range of the uPoolSize by check above.
2390 if(uNewSize <= uPoolSize - uMemOffset) {
2391 ReturnValue.ptr = pMem;
2392 ReturnValue.len = uNewSize;
2393
2394 // Addition won't wrap around over because uNewSize was
2395 // checked to be sure it is less than the pool size.
2396 uFreeOffset = uMemOffset + uNewSize32;
2397 }
2398 }
2399 } else {
2400 // ALLOCATION MODE
2401 // uPoolSize - uFreeOffset will not underflow because this
2402 // pool implementation makes sure uFreeOffset is always
2403 // smaller than uPoolSize through this check here and
2404 // reallocation case.
2405 if(uNewSize <= uPoolSize - uFreeOffset) {
2406 ReturnValue.len = uNewSize;
2407 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002408 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002409 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002410 }
2411 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002412 if(pMem) {
2413 // FREE MODE
2414 // Cast is safe because of limit on pool size in
2415 // QCBORDecode_SetMemPool()
2416 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2417 } else {
2418 // DESTRUCT MODE
2419 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002420 }
2421 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002422
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002423 UsefulBuf Pool = {pPool, uPoolSize};
2424 MemPool_Pack(Pool, uFreeOffset);
2425
2426Done:
2427 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002428}
2429
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002430
Laurence Lundbladef6531662018-12-04 10:42:22 +09002431/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002432 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002433 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002434QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2435 UsefulBuf Pool,
2436 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002437{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002438 // The pool size and free mem offset are packed into the beginning
2439 // of the pool memory. This compile time check make sure the
2440 // constant in the header is correct. This check should optimize
2441 // down to nothing.
2442 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002443 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002444 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002445
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002446 // The pool size and free offset packed in to the beginning of pool
2447 // memory are only 32-bits. This check will optimize out on 32-bit
2448 // machines.
2449 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002450 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002451 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002452
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002453 // This checks that the pool buffer given is big enough.
2454 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002455 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002456 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002457
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002458 pMe->StringAllocator.pfAllocator = MemPool_Function;
2459 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2460 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002461
Laurence Lundblade30816f22018-11-10 13:40:22 +07002462 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002463}
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002464
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002465
2466
Laurence Lundblade9b334962020-08-27 10:55:53 -07002467static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2468{
2469 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2470}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002471
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002472
2473/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002474 Consume an entire map or array (and do next to
2475 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002476 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002477static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002478ConsumeItem(QCBORDecodeContext *pMe,
2479 const QCBORItem *pItemToConsume,
2480 uint_fast8_t *puNextNestLevel)
2481{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002482 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002483 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002484
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002485 // If it is a map or array, this will tell if it is empty.
2486 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2487
2488 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2489 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002490
Laurence Lundblade1341c592020-04-11 14:19:05 -07002491 /* This works for definite and indefinite length
2492 * maps and arrays by using the nesting level
2493 */
2494 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002495 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002496 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002497 goto Done;
2498 }
2499 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002500
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002501 *puNextNestLevel = Item.uNextNestLevel;
2502
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002503 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002504
Laurence Lundblade1341c592020-04-11 14:19:05 -07002505 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002506 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002507 /* Just pass the nesting level through */
2508 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2509
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002510 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002511 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002512
2513Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002514 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002515}
2516
2517
Laurence Lundblade1341c592020-04-11 14:19:05 -07002518/* Return true if the labels in Item1 and Item2 are the same.
2519 Works only for integer and string labels. Returns false
2520 for any other type. */
2521static inline bool
2522MatchLabel(QCBORItem Item1, QCBORItem Item2)
2523{
2524 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2525 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2526 return true;
2527 }
2528 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002529 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002530 return true;
2531 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002532 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002533 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2534 return true;
2535 }
2536 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2537 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2538 return true;
2539 }
2540 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002541
Laurence Lundblade1341c592020-04-11 14:19:05 -07002542 /* Other label types are never matched */
2543 return false;
2544}
2545
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002546
2547/*
2548 Returns true if Item1 and Item2 are the same type
2549 or if either are of QCBOR_TYPE_ANY.
2550 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002551static inline bool
2552MatchType(QCBORItem Item1, QCBORItem Item2)
2553{
2554 if(Item1.uDataType == Item2.uDataType) {
2555 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002556 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002557 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002558 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002559 return true;
2560 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002561 return false;
2562}
2563
2564
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002565/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002566 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002567
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002568 @param[in] pMe The decode context to search.
2569 @param[in,out] pItemArray The items to search for and the items found.
2570 @param[out] puOffset Byte offset of last item matched.
2571 @param[in] pCBContext Context for the not-found item call back.
2572 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002573
2574 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2575
Laurence Lundblade93d89472020-10-03 22:30:50 -07002576 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2577 were found for one of the labels being
2578 search for. This duplicate detection is
2579 only performed for items in pItemArray,
2580 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002581
Laurence Lundblade93d89472020-10-03 22:30:50 -07002582 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2583 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002584
2585 @retval Also errors returned by QCBORDecode_GetNext().
2586
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002587 On input pItemArray contains a list of labels and data types
2588 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002589
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002590 On output the fully retrieved items are filled in with
2591 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002592
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002593 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002594
2595 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002596 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002597static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002598MapSearch(QCBORDecodeContext *pMe,
2599 QCBORItem *pItemArray,
2600 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002601 void *pCBContext,
2602 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002603{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002604 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002605 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002606
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002607 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002608 uReturn = pMe->uLastError;
2609 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002610 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002611
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002612 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002613 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2614 /* QCBOR_TYPE_NONE as first item indicates just looking
2615 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002616 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2617 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002618 }
2619
Laurence Lundblade085d7952020-07-24 10:26:30 -07002620 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2621 // It is an empty bounded array or map
2622 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2623 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002624 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002625 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002626 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002627 // Nothing is ever found in an empty array or map. All items
2628 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002629 uReturn = QCBOR_SUCCESS;
2630 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002631 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002632 }
2633
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002634 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002635 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2636
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002637 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002638 UsefulInputBuf_Seek(&(pMe->InBuf),
2639 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002640
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002641 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002642 Loop over all the items in the map or array. Each item
2643 could be a map or array, but label matching is only at
2644 the main level. This handles definite and indefinite
2645 length maps and arrays. The only reason this is ever
2646 called on arrays is to find their end position.
2647
2648 This will always run over all items in order to do
2649 duplicate detection.
2650
2651 This will exit with failure if it encounters an
2652 unrecoverable error, but continue on for recoverable
2653 errors.
2654
2655 If a recoverable error occurs on a matched item, then
2656 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002657 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002658 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002659 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002660 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002661 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002662 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002663
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002664 /* Get the item */
2665 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002666 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2667 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002668 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002669 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002670 goto Done;
2671 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002672 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002673 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002674 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002675 goto Done;
2676 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002677
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002678 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002679 bool bMatched = false;
2680 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2681 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002682 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002683 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2684 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002685 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002686 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002687 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002688 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002689 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002690 goto Done;
2691 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002692
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002693 if(uResult != QCBOR_SUCCESS) {
2694 uReturn = uResult;
2695 goto Done;
2696 }
2697
Laurence Lundblade1341c592020-04-11 14:19:05 -07002698 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002699 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002700 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002701 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002702 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002703 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002704 bMatched = true;
2705 }
2706 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002707
2708
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002709 if(!bMatched && pfCallback != NULL) {
2710 /*
2711 Call the callback on unmatched labels.
2712 (It is tempting to do duplicate detection here, but that would
2713 require dynamic memory allocation because the number of labels
2714 that might be encountered is unbounded.)
2715 */
2716 uReturn = (*pfCallback)(pCBContext, &Item);
2717 if(uReturn != QCBOR_SUCCESS) {
2718 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002719 }
2720 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002721
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002722 /*
2723 Consume the item whether matched or not. This
2724 does the work of traversing maps and array and
2725 everything in them. In this loop only the
2726 items at the current nesting level are examined
2727 to match the labels.
2728 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002729 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002730 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002731 goto Done;
2732 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002733
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002734 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002735
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002736 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002737
2738 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002739
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002740 // Check here makes sure that this won't accidentally be
2741 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002742 // QCBOR_MAX_DECODE_INPUT_SIZE.
2743 if(uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
2744 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2745 goto Done;
2746 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002747 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2748 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002749
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002750 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002751 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2752
2753 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002754 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002755 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002756 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002757 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2758 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002759 }
2760 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002761
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002762 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002763}
2764
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002765
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002766/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002767 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002768*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002769void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2770 int64_t nLabel,
2771 uint8_t uQcborType,
2772 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002773{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002774 if(pMe->uLastError != QCBOR_SUCCESS) {
2775 return;
2776 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002777
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002778 QCBORItem OneItemSeach[2];
2779 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2780 OneItemSeach[0].label.int64 = nLabel;
2781 OneItemSeach[0].uDataType = uQcborType;
2782 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002783
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002784 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002785
2786 *pItem = OneItemSeach[0];
2787
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002788 if(uReturn != QCBOR_SUCCESS) {
2789 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002790 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002791 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002792 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002793 }
2794
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002795 Done:
2796 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002797}
2798
2799
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002800/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002801 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002802*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002803void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2804 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002805 uint8_t uQcborType,
2806 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002807{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002808 if(pMe->uLastError != QCBOR_SUCCESS) {
2809 return;
2810 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002811
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002812 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002813 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2814 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2815 OneItemSeach[0].uDataType = uQcborType;
2816 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002817
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002818 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2819 if(uReturn != QCBOR_SUCCESS) {
2820 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002821 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002822 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002823 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002824 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002825 }
2826
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002827 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002828
2829Done:
2830 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002831}
2832
2833
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002834
Laurence Lundblade93d89472020-10-03 22:30:50 -07002835static QCBORError
2836CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002837{
2838 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2839 if(uDataType == puTypeList[i]) {
2840 return QCBOR_SUCCESS;
2841 }
2842 }
2843 return QCBOR_ERR_UNEXPECTED_TYPE;
2844}
2845
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002846
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002847/**
2848 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002849 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002850
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002851 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2852 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002853
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002854 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
2855 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002856 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002857static QCBORError
2858CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002859{
2860 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2861 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2862 /* There are tags that QCBOR couldn't process on this item and
2863 the caller has told us there should not be. */
2864 return QCBOR_ERR_UNEXPECTED_TYPE;
2865 }
2866
2867 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2868 const int nItemType = pItem->uDataType;
2869
2870 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2871 // Must match the tag and only the tag
2872 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2873 }
2874
2875 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2876 if(uReturn == QCBOR_SUCCESS) {
2877 return QCBOR_SUCCESS;
2878 }
2879
2880 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2881 /* Must match the content type and only the content type.
2882 There was no match just above so it is a fail. */
2883 return QCBOR_ERR_UNEXPECTED_TYPE;
2884 }
2885
2886 /* If here it can match either the tag or the content
2887 and it hasn't matched the content, so the end
2888 result is whether it matches the tag. This is
2889 also the case that the CBOR standard discourages. */
2890
2891 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2892}
2893
Laurence Lundblade9b334962020-08-27 10:55:53 -07002894
Laurence Lundblade9b334962020-08-27 10:55:53 -07002895
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002896// This could be semi-private if need be
2897static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002898void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2899 int64_t nLabel,
2900 TagSpecification TagSpec,
2901 QCBORItem *pItem)
2902{
2903 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2904 if(pMe->uLastError != QCBOR_SUCCESS) {
2905 return;
2906 }
2907
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002908 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002909}
2910
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002911
2912// This could be semi-private if need be
2913static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002914void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2915 const char *szLabel,
2916 TagSpecification TagSpec,
2917 QCBORItem *pItem)
2918{
2919 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2920 if(pMe->uLastError != QCBOR_SUCCESS) {
2921 return;
2922 }
2923
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002924 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002925}
2926
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002927// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002928void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2929 int64_t nLabel,
2930 TagSpecification TagSpec,
2931 UsefulBufC *pString)
2932{
2933 QCBORItem Item;
2934 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2935 if(pMe->uLastError == QCBOR_SUCCESS) {
2936 *pString = Item.val.string;
2937 }
2938}
2939
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002940// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002941void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2942 const char * szLabel,
2943 TagSpecification TagSpec,
2944 UsefulBufC *pString)
2945{
2946 QCBORItem Item;
2947 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2948 if(pMe->uLastError == QCBOR_SUCCESS) {
2949 *pString = Item.val.string;
2950 }
2951}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002952
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002953/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002954 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002955*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002956void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002957{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002958 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
2959 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002960}
2961
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002962/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002963 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002964*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002965void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
2966 QCBORItem *pItemList,
2967 void *pCallbackCtx,
2968 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002969{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002970 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
2971 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002972}
2973
2974
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08002975/**
2976 * @brief Search for a map/array by label and enter it
2977 *
2978 * @param[in] pMe The decode context.
2979 * @param[in] pSearch The map/array to search for.
2980 *
2981 * @c pSearch is expected to contain one item of type map or array
2982 * with the label specified. The current bounded map will be searched for
2983 * this and if found will be entered.
2984 *
2985 * If the label is not found, or the item found is not a map or array,
2986 * the error state is set.
2987 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002988static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002989{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002990 // The first item in pSearch is the one that is to be
2991 // entered. It should be the only one filled in. Any other
2992 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07002993 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002994 return;
2995 }
2996
2997 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002998 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002999 if(pMe->uLastError != QCBOR_SUCCESS) {
3000 return;
3001 }
3002
Laurence Lundblade9b334962020-08-27 10:55:53 -07003003 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003004 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003005 return;
3006 }
3007
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003008 /*
3009 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3010 * next item for the pre-order traversal cursor to be the map/array
3011 * found by MapSearch(). The next few lines of code force the
3012 * cursor to that.
3013 *
3014 * There is no need to retain the old cursor because
3015 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3016 * beginning of the map/array being entered.
3017 *
3018 * The cursor is forced by: 1) setting the input buffer position to
3019 * the item offset found by MapSearch(), 2) setting the map/array
3020 * counter to the total in the map/array, 3) setting the nesting
3021 * level. Setting the map/array counter to the total is not
3022 * strictly correct, but this is OK because this cursor only needs
3023 * to be used to get one item and MapSearch() has already found it
3024 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003025 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003026 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003027
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003028 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3029
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003030 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003031
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003032 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003033}
3034
3035
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003036/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003037 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003038*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003039void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003040{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003041 QCBORItem OneItemSeach[2];
3042 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3043 OneItemSeach[0].label.int64 = nLabel;
3044 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3045 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003046
Laurence Lundblade9b334962020-08-27 10:55:53 -07003047 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003048 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003049}
3050
3051
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003052/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003053 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003054*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003055void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003056{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003057 QCBORItem OneItemSeach[2];
3058 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3059 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3060 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3061 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003062
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003063 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003064}
3065
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003066/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003067 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003068*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003069void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003070{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003071 QCBORItem OneItemSeach[2];
3072 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3073 OneItemSeach[0].label.int64 = nLabel;
3074 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3075 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003076
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003077 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003078}
3079
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003080/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003081 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003082*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003083void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3084{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003085 QCBORItem OneItemSeach[2];
3086 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3087 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3088 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3089 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003090
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003091 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003092}
3093
3094
Laurence Lundblade02625d42020-06-25 14:41:41 -07003095// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003096void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003097{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003098 QCBORError uErr;
3099
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003100 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003101 if(pMe->uLastError != QCBOR_SUCCESS) {
3102 // Already in error state; do nothing.
3103 return;
3104 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003105
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003106 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003107 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003108 uErr = QCBORDecode_GetNext(pMe, &Item);
3109 if(uErr != QCBOR_SUCCESS) {
3110 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003111 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003112 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003113 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3114 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003115 }
3116
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003117 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003118
3119
Laurence Lundbladef0499502020-08-01 11:55:57 -07003120 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003121 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003122 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3123 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003124 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003125 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3126 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003127 // Special case to increment nesting level for zero-length maps
3128 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003129 DecodeNesting_Descend(&(pMe->nesting), uType);
3130 }
3131
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003132 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003133
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003134 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3135 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003136
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003137 if(pItem != NULL) {
3138 *pItem = Item;
3139 }
3140
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003141Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003142 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003143}
3144
Laurence Lundblade02625d42020-06-25 14:41:41 -07003145
3146/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003147 This is the common work for exiting a level that is a bounded map,
3148 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003149
3150 One chunk of work is to set up the pre-order traversal so it is at
3151 the item just after the bounded map, array or bstr that is being
3152 exited. This is somewhat complex.
3153
3154 The other work is to level-up the bounded mode to next higest bounded
3155 mode or the top level if there isn't one.
3156 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003157static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003158ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003159{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003160 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003161
Laurence Lundblade02625d42020-06-25 14:41:41 -07003162 /*
3163 First the pre-order-traversal byte offset is positioned to the
3164 item just after the bounded mode item that was just consumed.
3165 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003166 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3167
Laurence Lundblade02625d42020-06-25 14:41:41 -07003168 /*
3169 Next, set the current nesting level to one above the bounded level
3170 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003171
Laurence Lundblade02625d42020-06-25 14:41:41 -07003172 DecodeNesting_CheckBoundedType() is always called before this and
3173 makes sure pCurrentBounded is valid.
3174 */
3175 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3176
3177 /*
3178 This does the complex work of leveling up the pre-order traversal
3179 when the end of a map or array or another bounded level is
3180 reached. It may do nothing, or ascend all the way to the top
3181 level.
3182 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003183 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003184 if(uErr != QCBOR_SUCCESS) {
3185 goto Done;
3186 }
3187
Laurence Lundblade02625d42020-06-25 14:41:41 -07003188 /*
3189 This makes the next highest bounded level the current bounded
3190 level. If there is no next highest level, then no bounded mode is
3191 in effect.
3192 */
3193 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003194
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003195 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003196
3197Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003198 return uErr;
3199}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003200
Laurence Lundblade02625d42020-06-25 14:41:41 -07003201
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003202// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003203void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003204{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003205 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003206 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003207 return;
3208 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003209
Laurence Lundblade02625d42020-06-25 14:41:41 -07003210 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003211
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003212 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003213 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003214 goto Done;
3215 }
3216
Laurence Lundblade02625d42020-06-25 14:41:41 -07003217 /*
3218 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003219 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003220 from previous map search, then do a dummy search.
3221 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003222 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003223 QCBORItem Dummy;
3224 Dummy.uLabelType = QCBOR_TYPE_NONE;
3225 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3226 if(uErr != QCBOR_SUCCESS) {
3227 goto Done;
3228 }
3229 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003230
Laurence Lundblade02625d42020-06-25 14:41:41 -07003231 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003232
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003233Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003234 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003235}
3236
3237
Laurence Lundblade1341c592020-04-11 14:19:05 -07003238
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003239static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003240 const QCBORItem *pItem,
3241 uint8_t uTagRequirement,
3242 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003243{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003244 if(pBstr) {
3245 *pBstr = NULLUsefulBufC;
3246 }
3247
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003248 if(pMe->uLastError != QCBOR_SUCCESS) {
3249 // Already in error state; do nothing.
3250 return pMe->uLastError;
3251 }
3252
3253 QCBORError uError = QCBOR_SUCCESS;
3254
3255 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3256 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3257 goto Done;;
3258 }
3259
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003260 const TagSpecification TagSpec =
3261 {
3262 uTagRequirement,
3263 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3264 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3265 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003266
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003267 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003268 if(uError != QCBOR_SUCCESS) {
3269 goto Done;
3270 }
3271
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003272 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003273 // Reverse the decrement done by GetNext() for the bstr so the
3274 // increment in NestLevelAscender() called by ExitBoundedLevel()
3275 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003276 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003277 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003278
3279 if(pBstr) {
3280 *pBstr = pItem->val.string;
3281 }
3282
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003283 // This saves the current length of the UsefulInputBuf and then
3284 // narrows the UsefulInputBuf to start and length of the wrapped
3285 // CBOR that is being entered.
3286 //
3287 // This makes sure the length is less than
3288 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3289 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3290 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3291 // the casts safe. uEndOfBstr will always be less than
3292 // uPreviousLength because of the way UsefulInputBuf works so there
3293 // is no need to check it. There is also a range check in the
3294 // seek.
3295 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003296 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003297 // amount to much code.
3298 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3299 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003300 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003301 goto Done;
3302 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003303 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003304 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003305 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003306
Laurence Lundblade02625d42020-06-25 14:41:41 -07003307 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003308 (uint32_t)uPreviousLength,
3309 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003310Done:
3311 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003312}
3313
3314
Laurence Lundblade02625d42020-06-25 14:41:41 -07003315/*
3316 Public function, see header qcbor/qcbor_decode.h file
3317 */
3318void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003319 uint8_t uTagRequirement,
3320 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003321{
3322 if(pMe->uLastError != QCBOR_SUCCESS) {
3323 // Already in error state; do nothing.
3324 return;
3325 }
3326
3327 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003328 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003329 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3330 if(pMe->uLastError != QCBOR_SUCCESS) {
3331 return;
3332 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003333
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003334 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003335 &Item,
3336 uTagRequirement,
3337 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003338}
3339
3340
Laurence Lundblade02625d42020-06-25 14:41:41 -07003341/*
3342 Public function, see header qcbor/qcbor_decode.h file
3343 */
3344void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003345 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003346 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003347 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003348{
3349 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003350 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003351
Laurence Lundblade93d89472020-10-03 22:30:50 -07003352 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3353 &Item,
3354 uTagRequirement,
3355 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003356}
3357
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003358
Laurence Lundblade02625d42020-06-25 14:41:41 -07003359/*
3360 Public function, see header qcbor/qcbor_decode.h file
3361 */
3362void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003363 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003364 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003365 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003366{
3367 QCBORItem Item;
3368 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3369
Laurence Lundblade93d89472020-10-03 22:30:50 -07003370 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3371 &Item,
3372 uTagRequirement,
3373 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003374}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003375
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003376
Laurence Lundblade02625d42020-06-25 14:41:41 -07003377/*
3378 Public function, see header qcbor/qcbor_decode.h file
3379 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003380void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003381{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003382 if(pMe->uLastError != QCBOR_SUCCESS) {
3383 // Already in error state; do nothing.
3384 return;
3385 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003386
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003387 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003388 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003389 return;
3390 }
3391
3392 /*
3393 Reset the length of the UsefulInputBuf to what it was before
3394 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003395 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003396 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003397 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003398
3399
Laurence Lundblade02625d42020-06-25 14:41:41 -07003400 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003401 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003402}
3403
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003404
Laurence Lundbladee6430642020-03-14 21:15:44 -07003405
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003406
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003407
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003408
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003409
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003410
Laurence Lundblade93d89472020-10-03 22:30:50 -07003411static QCBORError
3412InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003413{
3414 switch(pItem->uDataType) {
3415 case QCBOR_TYPE_TRUE:
3416 *pBool = true;
3417 return QCBOR_SUCCESS;
3418 break;
3419
3420 case QCBOR_TYPE_FALSE:
3421 *pBool = false;
3422 return QCBOR_SUCCESS;
3423 break;
3424
3425 default:
3426 return QCBOR_ERR_UNEXPECTED_TYPE;
3427 break;
3428 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003429 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003430}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003431
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003432
Laurence Lundblade9b334962020-08-27 10:55:53 -07003433
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003434/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003435 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003436*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003437void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003438{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003439 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003440 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003441 return;
3442 }
3443
Laurence Lundbladec4537442020-04-14 18:53:22 -07003444 QCBORError nError;
3445 QCBORItem Item;
3446
3447 nError = QCBORDecode_GetNext(pMe, &Item);
3448 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003449 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003450 return;
3451 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003452 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003453}
3454
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003455
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003456/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003457 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003458*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003459void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003460{
3461 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003462 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003463
Laurence Lundblade9b334962020-08-27 10:55:53 -07003464 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003465}
3466
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003467
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003468/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003469 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003470*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003471void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3472{
3473 QCBORItem Item;
3474 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3475
Laurence Lundblade9b334962020-08-27 10:55:53 -07003476 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003477}
3478
3479
3480
Laurence Lundbladec7114722020-08-13 05:11:40 -07003481
3482static void ProcessEpochDate(QCBORDecodeContext *pMe,
3483 QCBORItem *pItem,
3484 uint8_t uTagRequirement,
3485 int64_t *pnTime)
3486{
3487 if(pMe->uLastError != QCBOR_SUCCESS) {
3488 // Already in error state, do nothing
3489 return;
3490 }
3491
3492 QCBORError uErr;
3493
3494 const TagSpecification TagSpec =
3495 {
3496 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003497 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3498 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003499 };
3500
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003501 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003502 if(uErr != QCBOR_SUCCESS) {
3503 goto Done;
3504 }
3505
3506 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3507 uErr = DecodeDateEpoch(pItem);
3508 if(uErr != QCBOR_SUCCESS) {
3509 goto Done;
3510 }
3511 }
3512
Laurence Lundblade9b334962020-08-27 10:55:53 -07003513 // Save the tags in the last item's tags in the decode context
3514 // for QCBORDecode_GetNthTagOfLast()
3515 CopyTags(pMe, pItem);
3516
Laurence Lundbladec7114722020-08-13 05:11:40 -07003517 *pnTime = pItem->val.epochDate.nSeconds;
3518
3519Done:
3520 pMe->uLastError = (uint8_t)uErr;
3521}
3522
3523
3524void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003525 uint8_t uTagRequirement,
3526 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003527{
3528 if(pMe->uLastError != QCBOR_SUCCESS) {
3529 // Already in error state, do nothing
3530 return;
3531 }
3532
3533 QCBORItem Item;
3534 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3535
3536 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3537}
3538
3539
3540void
3541QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3542 int64_t nLabel,
3543 uint8_t uTagRequirement,
3544 int64_t *pnTime)
3545{
3546 QCBORItem Item;
3547 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3548 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3549}
3550
3551
3552void
3553QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3554 const char *szLabel,
3555 uint8_t uTagRequirement,
3556 int64_t *pnTime)
3557{
3558 QCBORItem Item;
3559 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3560 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3561}
3562
3563
3564
3565
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003566void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3567 TagSpecification TagSpec,
3568 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003569{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003570 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003571 // Already in error state, do nothing
3572 return;
3573 }
3574
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003575 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003576 QCBORItem Item;
3577
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003578 uError = QCBORDecode_GetNext(pMe, &Item);
3579 if(uError != QCBOR_SUCCESS) {
3580 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003581 return;
3582 }
3583
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003584 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003585
3586 if(pMe->uLastError == QCBOR_SUCCESS) {
3587 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003588 } else {
3589 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003590 }
3591}
3592
Laurence Lundbladec4537442020-04-14 18:53:22 -07003593
3594
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003595
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003596static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003597 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003598 UsefulBufC *pValue,
3599 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003600{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003601 const TagSpecification TagSpec =
3602 {
3603 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003604 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3605 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003606 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003607
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003608 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003609 if(uErr != QCBOR_SUCCESS) {
3610 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003611 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003612
3613 *pValue = pItem->val.string;
3614
3615 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3616 *pbIsNegative = false;
3617 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3618 *pbIsNegative = true;
3619 }
3620
3621 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003622}
3623
3624
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003625/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003626 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003627 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003628void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3629 uint8_t uTagRequirement,
3630 UsefulBufC *pValue,
3631 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003632{
3633 if(pMe->uLastError != QCBOR_SUCCESS) {
3634 // Already in error state, do nothing
3635 return;
3636 }
3637
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003638 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003639 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3640 if(uError != QCBOR_SUCCESS) {
3641 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003642 return;
3643 }
3644
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003645 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003646}
3647
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003648
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003649/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003650 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003651*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003652void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3653 int64_t nLabel,
3654 uint8_t uTagRequirement,
3655 UsefulBufC *pValue,
3656 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003657{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003658 QCBORItem Item;
3659 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003660 if(pMe->uLastError != QCBOR_SUCCESS) {
3661 return;
3662 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003663
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003664 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003665}
3666
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003667
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003668/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003669 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003670*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003671void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3672 const char *szLabel,
3673 uint8_t uTagRequirement,
3674 UsefulBufC *pValue,
3675 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003676{
3677 QCBORItem Item;
3678 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003679 if(pMe->uLastError != QCBOR_SUCCESS) {
3680 return;
3681 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003682
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003683 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003684}
3685
3686
3687
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003688
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003689// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003690QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3691 const QCBORItem *pItem,
3692 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003693 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003694{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003695 const TagSpecification TagSpecText =
3696 {
3697 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003698 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3699 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003700 };
3701 const TagSpecification TagSpecBinary =
3702 {
3703 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003704 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3705 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003706 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003707
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003708 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003709
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003710 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003711 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003712 if(pbIsTag257 != NULL) {
3713 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003714 }
3715 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003716 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003717 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003718 if(pbIsTag257 != NULL) {
3719 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003720 }
3721 uReturn = QCBOR_SUCCESS;
3722
3723 } else {
3724 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3725 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003726
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003727 return uReturn;
3728}
3729
Laurence Lundblade93d89472020-10-03 22:30:50 -07003730// Improvement: add methods for wrapped CBOR, a simple alternate
3731// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003732
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003733
3734
3735
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003736#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003737
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003738typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003739
3740
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003741// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003742static QCBORError
3743Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003744{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003745 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003746
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003747 if(uResult != 0) {
3748 /* This loop will run a maximum of 19 times because
3749 * UINT64_MAX < 10 ^^ 19. More than that will cause
3750 * exit with the overflow error
3751 */
3752 for(; nExponent > 0; nExponent--) {
3753 if(uResult > UINT64_MAX / 10) {
3754 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3755 }
3756 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003757 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003758
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003759 for(; nExponent < 0; nExponent++) {
3760 uResult = uResult / 10;
3761 if(uResult == 0) {
3762 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3763 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003764 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003765 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003766 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003767
3768 *puResult = uResult;
3769
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003770 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003771}
3772
3773
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003774// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003775static QCBORError
3776Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003777{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003778 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003779
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003780 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003781
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003782 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003783 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003784 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003785 */
3786 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003787 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003788 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003789 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003790 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003791 nExponent--;
3792 }
3793
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003794 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003795 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003796 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3797 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003798 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003799 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003800 }
3801
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003802 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003803
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003804 return QCBOR_SUCCESS;
3805}
3806
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003807
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003808/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003809 Compute value with signed mantissa and signed result. Works with
3810 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003811 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003812static inline QCBORError ExponentiateNN(int64_t nMantissa,
3813 int64_t nExponent,
3814 int64_t *pnResult,
3815 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003816{
3817 uint64_t uResult;
3818
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003819 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003820 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003821 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3822
3823 // Do the exponentiation of the positive mantissa
3824 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3825 if(uReturn) {
3826 return uReturn;
3827 }
3828
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003829
Laurence Lundblade983500d2020-05-14 11:49:34 -07003830 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3831 of INT64_MIN. This assumes two's compliment representation where
3832 INT64_MIN is one increment farther from 0 than INT64_MAX.
3833 Trying to write -INT64_MIN doesn't work to get this because the
3834 compiler tries to work with an int64_t which can't represent
3835 -INT64_MIN.
3836 */
3837 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3838
3839 // Error out if too large
3840 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003841 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3842 }
3843
3844 // Casts are safe because of checks above
3845 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3846
3847 return QCBOR_SUCCESS;
3848}
3849
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003850
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003851/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003852 Compute value with signed mantissa and unsigned result. Works with
3853 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003854 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003855static inline QCBORError ExponentitateNU(int64_t nMantissa,
3856 int64_t nExponent,
3857 uint64_t *puResult,
3858 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003859{
3860 if(nMantissa < 0) {
3861 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3862 }
3863
3864 // Cast to unsigned is OK because of check for negative
3865 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3866 // Exponentiation is straight forward
3867 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3868}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003869
3870
3871/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003872 Compute value with signed mantissa and unsigned result. Works with
3873 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003874 */
3875static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3876 int64_t nExponent,
3877 uint64_t *puResult,
3878 fExponentiator pfExp)
3879{
3880 return (*pfExp)(uMantissa, nExponent, puResult);
3881}
3882
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003883#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3884
3885
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003886
3887
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003888
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003889static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003890{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003891 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003892
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003893 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003894 const uint8_t *pByte = BigNum.ptr;
3895 size_t uLen = BigNum.len;
3896 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003897 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003898 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003899 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003900 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003901 }
3902
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003903 *pResult = uResult;
3904 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003905}
3906
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003907
Laurence Lundblade887add82020-05-17 05:50:34 -07003908static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003909{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003910 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003911}
3912
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003913
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003914static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003915{
3916 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003917 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3918 if(uError) {
3919 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003920 }
3921 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3922 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003923 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003924}
3925
3926
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003927static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003928{
3929 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003930 /* The negative integer furthest from zero for a C int64_t is
3931 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3932 negative number in CBOR is computed as -n - 1 where n is the
3933 encoded integer, where n is what is in the variable BigNum. When
3934 converting BigNum to a uint64_t, the maximum value is thus
3935 INT64_MAX, so that when it -n - 1 is applied to it the result will
3936 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003937
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003938 -n - 1 <= INT64_MIN.
3939 -n - 1 <= -INT64_MAX - 1
3940 n <= INT64_MAX.
3941 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003942 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003943 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003944 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003945 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003946
3947 /// Now apply -n - 1. The cast is safe because
3948 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3949 // is the largest positive integer that an int64_t can
3950 // represent. */
3951 *pnResult = -(int64_t)uResult - 1;
3952
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003953 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003954}
3955
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003956
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003957
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003958
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003959
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003960/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003961Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003962
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003963\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003964
Laurence Lundblade93d89472020-10-03 22:30:50 -07003965\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
3966 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003967
3968\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3969
Laurence Lundblade93d89472020-10-03 22:30:50 -07003970\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
3971 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003972*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07003973static QCBORError
3974ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003975{
3976 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003977 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003978 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003979#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003980 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003981 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
3982 http://www.cplusplus.com/reference/cmath/llround/
3983 */
3984 // Not interested in FE_INEXACT
3985 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003986 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
3987 *pnValue = llround(pItem->val.dfnum);
3988 } else {
3989 *pnValue = lroundf(pItem->val.fnum);
3990 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003991 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
3992 // llround() shouldn't result in divide by zero, but catch
3993 // it here in case it unexpectedly does. Don't try to
3994 // distinguish between the various exceptions because it seems
3995 // they vary by CPU, compiler and OS.
3996 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003997 }
3998 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003999 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004000 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004001#else
4002 return QCBOR_ERR_HW_FLOAT_DISABLED;
4003#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004004 break;
4005
4006 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004007 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004008 *pnValue = pItem->val.int64;
4009 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004010 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004011 }
4012 break;
4013
4014 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004015 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004016 if(pItem->val.uint64 < INT64_MAX) {
4017 *pnValue = pItem->val.int64;
4018 } else {
4019 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4020 }
4021 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004022 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004023 }
4024 break;
4025
4026 default:
4027 return QCBOR_ERR_UNEXPECTED_TYPE;
4028 }
4029 return QCBOR_SUCCESS;
4030}
4031
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004032
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004033void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004034 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004035 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004036 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004037{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004038 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004039 return;
4040 }
4041
Laurence Lundbladee6430642020-03-14 21:15:44 -07004042 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004043 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4044 if(uError) {
4045 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004046 return;
4047 }
4048
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004049 if(pItem) {
4050 *pItem = Item;
4051 }
4052
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004053 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004054}
4055
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004056
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004057void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4058 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004059 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004060 int64_t *pnValue,
4061 QCBORItem *pItem)
4062{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004063 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004064 if(pMe->uLastError != QCBOR_SUCCESS) {
4065 return;
4066 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004067
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004068 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004069}
4070
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004071
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004072void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4073 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004074 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004075 int64_t *pnValue,
4076 QCBORItem *pItem)
4077{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004078 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004079 if(pMe->uLastError != QCBOR_SUCCESS) {
4080 return;
4081 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004082
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004083 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004084}
4085
4086
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004087/*
4088 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004089
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004090 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004091
Laurence Lundblade93d89472020-10-03 22:30:50 -07004092 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4093 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004094
4095 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4096
Laurence Lundblade93d89472020-10-03 22:30:50 -07004097 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4098 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004099 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004100static QCBORError
4101Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004102{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004103 switch(pItem->uDataType) {
4104
4105 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004106 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004107 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004108 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004109 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004110 }
4111 break;
4112
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004113 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004114 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004115 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004116 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004117 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004118 }
4119 break;
4120
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004121#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4122 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004123 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004124 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004125 pItem->val.expAndMantissa.nExponent,
4126 pnValue,
4127 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004128 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004129 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004130 }
4131 break;
4132
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004133 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004134 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004135 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004136 pItem->val.expAndMantissa.nExponent,
4137 pnValue,
4138 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004139 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004140 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004141 }
4142 break;
4143
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004144 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004145 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004146 int64_t nMantissa;
4147 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004148 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4149 if(uErr) {
4150 return uErr;
4151 }
4152 return ExponentiateNN(nMantissa,
4153 pItem->val.expAndMantissa.nExponent,
4154 pnValue,
4155 Exponentitate10);
4156 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004157 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004158 }
4159 break;
4160
4161 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004162 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004163 int64_t nMantissa;
4164 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004165 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4166 if(uErr) {
4167 return uErr;
4168 }
4169 return ExponentiateNN(nMantissa,
4170 pItem->val.expAndMantissa.nExponent,
4171 pnValue,
4172 Exponentitate10);
4173 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004174 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004175 }
4176 break;
4177
4178 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004179 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004180 int64_t nMantissa;
4181 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004182 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4183 if(uErr) {
4184 return uErr;
4185 }
4186 return ExponentiateNN(nMantissa,
4187 pItem->val.expAndMantissa.nExponent,
4188 pnValue,
4189 Exponentitate2);
4190 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004191 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004192 }
4193 break;
4194
4195 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004196 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004197 int64_t nMantissa;
4198 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004199 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4200 if(uErr) {
4201 return uErr;
4202 }
4203 return ExponentiateNN(nMantissa,
4204 pItem->val.expAndMantissa.nExponent,
4205 pnValue,
4206 Exponentitate2);
4207 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004208 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004209 }
4210 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004211#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4212
Laurence Lundbladee6430642020-03-14 21:15:44 -07004213
Laurence Lundbladec4537442020-04-14 18:53:22 -07004214 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004215 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004216}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004217
4218
Laurence Lundbladec4537442020-04-14 18:53:22 -07004219/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004220 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004221 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004222void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004223{
4224 QCBORItem Item;
4225
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004226 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004227
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004228 if(pMe->uLastError == QCBOR_SUCCESS) {
4229 // The above conversion succeeded
4230 return;
4231 }
4232
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004233 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004234 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004235 return;
4236 }
4237
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004238 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004239}
4240
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004241
4242/*
4243Public function, see header qcbor/qcbor_decode.h file
4244*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004245void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4246 int64_t nLabel,
4247 uint32_t uConvertTypes,
4248 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004249{
4250 QCBORItem Item;
4251
Laurence Lundblade93d89472020-10-03 22:30:50 -07004252 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4253 nLabel,
4254 uConvertTypes,
4255 pnValue,
4256 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004257
4258 if(pMe->uLastError == QCBOR_SUCCESS) {
4259 // The above conversion succeeded
4260 return;
4261 }
4262
4263 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4264 // The above conversion failed in a way that code below can't correct
4265 return;
4266 }
4267
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004268 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004269}
4270
4271
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004272/*
4273Public function, see header qcbor/qcbor_decode.h file
4274*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004275void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4276 const char *szLabel,
4277 uint32_t uConvertTypes,
4278 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004279{
4280 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004281 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4282 szLabel,
4283 uConvertTypes,
4284 pnValue,
4285 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004286
4287 if(pMe->uLastError == QCBOR_SUCCESS) {
4288 // The above conversion succeeded
4289 return;
4290 }
4291
4292 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4293 // The above conversion failed in a way that code below can't correct
4294 return;
4295 }
4296
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004297 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004298}
4299
4300
Laurence Lundblade93d89472020-10-03 22:30:50 -07004301static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004302{
4303 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004304 case QCBOR_TYPE_DOUBLE:
4305 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004306#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004307 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004308 // Can't use llround here because it will not convert values
4309 // greater than INT64_MAX and less than UINT64_MAX that
4310 // need to be converted so it is more complicated.
4311 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4312 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4313 if(isnan(pItem->val.dfnum)) {
4314 return QCBOR_ERR_FLOAT_EXCEPTION;
4315 } else if(pItem->val.dfnum < 0) {
4316 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4317 } else {
4318 double dRounded = round(pItem->val.dfnum);
4319 // See discussion in DecodeDateEpoch() for
4320 // explanation of - 0x7ff
4321 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4322 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4323 }
4324 *puValue = (uint64_t)dRounded;
4325 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004326 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004327 if(isnan(pItem->val.fnum)) {
4328 return QCBOR_ERR_FLOAT_EXCEPTION;
4329 } else if(pItem->val.fnum < 0) {
4330 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4331 } else {
4332 float fRounded = roundf(pItem->val.fnum);
4333 // See discussion in DecodeDateEpoch() for
4334 // explanation of - 0x7ff
4335 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4336 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4337 }
4338 *puValue = (uint64_t)fRounded;
4339 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004340 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004341 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4342 // round() and roundf() shouldn't result in exceptions here, but
4343 // catch them to be robust and thorough. Don't try to
4344 // distinguish between the various exceptions because it seems
4345 // they vary by CPU, compiler and OS.
4346 return QCBOR_ERR_FLOAT_EXCEPTION;
4347 }
4348
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004349 } else {
4350 return QCBOR_ERR_UNEXPECTED_TYPE;
4351 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004352#else
4353 return QCBOR_ERR_HW_FLOAT_DISABLED;
4354#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004355 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004356
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004357 case QCBOR_TYPE_INT64:
4358 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4359 if(pItem->val.int64 >= 0) {
4360 *puValue = (uint64_t)pItem->val.int64;
4361 } else {
4362 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4363 }
4364 } else {
4365 return QCBOR_ERR_UNEXPECTED_TYPE;
4366 }
4367 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004368
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004369 case QCBOR_TYPE_UINT64:
4370 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4371 *puValue = pItem->val.uint64;
4372 } else {
4373 return QCBOR_ERR_UNEXPECTED_TYPE;
4374 }
4375 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004376
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004377 default:
4378 return QCBOR_ERR_UNEXPECTED_TYPE;
4379 }
4380
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004381 return QCBOR_SUCCESS;
4382}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004383
4384
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004385void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004386 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004387 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004388 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004389{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004390 if(pMe->uLastError != QCBOR_SUCCESS) {
4391 return;
4392 }
4393
Laurence Lundbladec4537442020-04-14 18:53:22 -07004394 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004395
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004396 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4397 if(uError) {
4398 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004399 return;
4400 }
4401
Laurence Lundbladea826c502020-05-10 21:07:00 -07004402 if(pItem) {
4403 *pItem = Item;
4404 }
4405
Laurence Lundblade93d89472020-10-03 22:30:50 -07004406 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004407}
4408
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004409
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004410void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004411 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004412 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004413 uint64_t *puValue,
4414 QCBORItem *pItem)
4415{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004416 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004417 if(pMe->uLastError != QCBOR_SUCCESS) {
4418 return;
4419 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004420
Laurence Lundblade93d89472020-10-03 22:30:50 -07004421 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004422}
4423
4424
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004425void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004426 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004427 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004428 uint64_t *puValue,
4429 QCBORItem *pItem)
4430{
4431 if(pMe->uLastError != QCBOR_SUCCESS) {
4432 return;
4433 }
4434
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004435 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004436 if(pMe->uLastError != QCBOR_SUCCESS) {
4437 return;
4438 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004439
Laurence Lundblade93d89472020-10-03 22:30:50 -07004440 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004441}
4442
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004443
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004444
Laurence Lundblade93d89472020-10-03 22:30:50 -07004445static QCBORError
4446UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004447{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004448 switch(pItem->uDataType) {
4449
4450 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004451 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004452 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4453 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004454 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004455 }
4456 break;
4457
4458 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004459 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004460 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4461 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004462 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004463 }
4464 break;
4465
4466#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4467
4468 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004469 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004470 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004471 pItem->val.expAndMantissa.nExponent,
4472 puValue,
4473 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004474 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004475 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004476 }
4477 break;
4478
4479 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004480 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004481 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4482 pItem->val.expAndMantissa.nExponent,
4483 puValue,
4484 Exponentitate2);
4485 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004486 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004487 }
4488 break;
4489
4490 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004491 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004492 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004493 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004494 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004495 if(uErr != QCBOR_SUCCESS) {
4496 return uErr;
4497 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004498 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004499 pItem->val.expAndMantissa.nExponent,
4500 puValue,
4501 Exponentitate10);
4502 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004503 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004504 }
4505 break;
4506
4507 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004508 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004509 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4510 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004511 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004512 }
4513 break;
4514
4515 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004516 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004517 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004518 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004519 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004520 if(uErr != QCBOR_SUCCESS) {
4521 return uErr;
4522 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004523 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004524 pItem->val.expAndMantissa.nExponent,
4525 puValue,
4526 Exponentitate2);
4527 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004528 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004529 }
4530 break;
4531
4532 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004533 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004534 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4535 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004536 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004537 }
4538 break;
4539#endif
4540 default:
4541 return QCBOR_ERR_UNEXPECTED_TYPE;
4542 }
4543}
4544
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004545
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004546/*
4547 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004548 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004549void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004550{
4551 QCBORItem Item;
4552
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004553 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004554
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004555 if(pMe->uLastError == QCBOR_SUCCESS) {
4556 // The above conversion succeeded
4557 return;
4558 }
4559
4560 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4561 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004562 return;
4563 }
4564
Laurence Lundblade93d89472020-10-03 22:30:50 -07004565 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004566}
4567
Laurence Lundbladec4537442020-04-14 18:53:22 -07004568
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004569/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004570 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004571*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004572void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004573 int64_t nLabel,
4574 uint32_t uConvertTypes,
4575 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004576{
4577 QCBORItem Item;
4578
Laurence Lundblade93d89472020-10-03 22:30:50 -07004579 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4580 nLabel,
4581 uConvertTypes,
4582 puValue,
4583 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004584
4585 if(pMe->uLastError == QCBOR_SUCCESS) {
4586 // The above conversion succeeded
4587 return;
4588 }
4589
4590 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4591 // The above conversion failed in a way that code below can't correct
4592 return;
4593 }
4594
Laurence Lundblade93d89472020-10-03 22:30:50 -07004595 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004596}
4597
4598
4599/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004600 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004601*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004602void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004603 const char *szLabel,
4604 uint32_t uConvertTypes,
4605 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004606{
4607 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004608 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4609 szLabel,
4610 uConvertTypes,
4611 puValue,
4612 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004613
4614 if(pMe->uLastError == QCBOR_SUCCESS) {
4615 // The above conversion succeeded
4616 return;
4617 }
4618
4619 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4620 // The above conversion failed in a way that code below can't correct
4621 return;
4622 }
4623
Laurence Lundblade93d89472020-10-03 22:30:50 -07004624 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004625}
4626
4627
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004628
4629
Laurence Lundblade9b334962020-08-27 10:55:53 -07004630static QCBORError ConvertDouble(const QCBORItem *pItem,
4631 uint32_t uConvertTypes,
4632 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004633{
4634 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004635 case QCBOR_TYPE_FLOAT:
4636#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4637 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4638 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004639 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004640 *pdValue = (double)pItem->val.fnum;
4641 } else {
4642 return QCBOR_ERR_UNEXPECTED_TYPE;
4643 }
4644 }
4645#else
4646 return QCBOR_ERR_HW_FLOAT_DISABLED;
4647#endif
4648 break;
4649
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004650 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004651 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4652 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004653 *pdValue = pItem->val.dfnum;
4654 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004655 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004656 }
4657 }
4658 break;
4659
4660 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004661#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004662 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004663 // A simple cast seems to do the job with no worry of exceptions.
4664 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004665 *pdValue = (double)pItem->val.int64;
4666
4667 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004668 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004669 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004670#else
4671 return QCBOR_ERR_HW_FLOAT_DISABLED;
4672#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004673 break;
4674
4675 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004676#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004677 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004678 // A simple cast seems to do the job with no worry of exceptions.
4679 // There will be precision loss for some values.
4680 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004681 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004682 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004683 }
4684 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004685#else
4686 return QCBOR_ERR_HW_FLOAT_DISABLED;
4687#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004688
4689 default:
4690 return QCBOR_ERR_UNEXPECTED_TYPE;
4691 }
4692
4693 return QCBOR_SUCCESS;
4694}
4695
4696
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004697void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004698 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004699 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004700 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004701{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004702 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004703 return;
4704 }
4705
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004706 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004707
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004708 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004709 if(uError) {
4710 pMe->uLastError = (uint8_t)uError;
4711 return;
4712 }
4713
4714 if(pItem) {
4715 *pItem = Item;
4716 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004717
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004718 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004719}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004720
Laurence Lundbladec4537442020-04-14 18:53:22 -07004721
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004722void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4723 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004724 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004725 double *pdValue,
4726 QCBORItem *pItem)
4727{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004728 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004729 if(pMe->uLastError != QCBOR_SUCCESS) {
4730 return;
4731 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004732
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004733 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004734}
4735
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004736
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004737void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4738 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004739 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004740 double *pdValue,
4741 QCBORItem *pItem)
4742{
4743 if(pMe->uLastError != QCBOR_SUCCESS) {
4744 return;
4745 }
4746
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004747 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004748 if(pMe->uLastError != QCBOR_SUCCESS) {
4749 return;
4750 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004751
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004752 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004753}
4754
4755
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004756#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004757static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4758{
4759 double dResult;
4760
4761 dResult = 0.0;
4762 const uint8_t *pByte = BigNum.ptr;
4763 size_t uLen = BigNum.len;
4764 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004765 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004766 while(uLen--) {
4767 dResult = (dResult * 256.0) + (double)*pByte++;
4768 }
4769
4770 return dResult;
4771}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004772#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4773
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004774
Laurence Lundblade93d89472020-10-03 22:30:50 -07004775static QCBORError
4776DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004777{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004778#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004779 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004780 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4781
4782 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004783 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004784
4785#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004786 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004787 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004788 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004789 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4790 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4791 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004792 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004793 }
4794 break;
4795
4796 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004797 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004798 // Underflow gives 0, overflow gives infinity
4799 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4800 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004801 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004802 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004803 }
4804 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004805#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004806
4807 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004808 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004809 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4810 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004811 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004812 }
4813 break;
4814
4815 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004816 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004817 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004818 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004819 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004820 }
4821 break;
4822
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004823#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004824 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004825 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004826 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4827 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4828 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004829 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004830 }
4831 break;
4832
4833 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004834 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004835 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4836 *pdValue = dMantissa * pow(10, (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_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004843 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004844 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4845 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4846 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004847 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004848 }
4849 break;
4850
4851 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004852 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004853 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004854 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4855 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004856 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004857 }
4858 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004859#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4860
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004861 default:
4862 return QCBOR_ERR_UNEXPECTED_TYPE;
4863 }
4864
4865 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004866
4867#else
4868 (void)pItem;
4869 (void)uConvertTypes;
4870 (void)pdValue;
4871 return QCBOR_ERR_HW_FLOAT_DISABLED;
4872#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4873
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004874}
4875
4876
4877/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004878 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004879*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004880void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4881 uint32_t uConvertTypes,
4882 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004883{
4884
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004885 QCBORItem Item;
4886
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004887 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004888
4889 if(pMe->uLastError == QCBOR_SUCCESS) {
4890 // The above conversion succeeded
4891 return;
4892 }
4893
4894 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4895 // The above conversion failed in a way that code below can't correct
4896 return;
4897 }
4898
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004899 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004900}
4901
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004902
4903/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004904 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004905*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004906void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4907 int64_t nLabel,
4908 uint32_t uConvertTypes,
4909 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004910{
4911 QCBORItem Item;
4912
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004913 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004914
4915 if(pMe->uLastError == QCBOR_SUCCESS) {
4916 // The above conversion succeeded
4917 return;
4918 }
4919
4920 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4921 // The above conversion failed in a way that code below can't correct
4922 return;
4923 }
4924
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004925 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004926}
4927
4928
4929/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004930 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004931*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004932void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4933 const char *szLabel,
4934 uint32_t uConvertTypes,
4935 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004936{
4937 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004938 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004939
4940 if(pMe->uLastError == QCBOR_SUCCESS) {
4941 // The above conversion succeeded
4942 return;
4943 }
4944
4945 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4946 // The above conversion failed in a way that code below can't correct
4947 return;
4948 }
4949
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004950 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004951}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004952
4953
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004954
4955
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004956#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004957static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4958{
4959 while((uInt & 0xff00000000000000UL) == 0) {
4960 uInt = uInt << 8;
4961 };
4962
4963 UsefulOutBuf UOB;
4964
4965 UsefulOutBuf_Init(&UOB, Buffer);
4966
4967 while(uInt) {
4968 const uint64_t xx = uInt & 0xff00000000000000UL;
4969 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4970 uInt = uInt << 8;
4971 (void)xx;
4972 }
4973
4974 return UsefulOutBuf_OutUBuf(&UOB);
4975}
4976
4977
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004978static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4979 TagSpecification TagSpec,
4980 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004981{
4982 QCBORError uErr;
4983 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004984 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004985 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004986 if(uErr != QCBOR_SUCCESS) {
4987 goto Done;
4988 }
4989
4990 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4991 break; // Successful exit. Moving on to finish decoding.
4992 }
4993
4994 // The item is an array, which means an undecoded
4995 // mantissa and exponent, so decode it. It will then
4996 // have a different type and exit the loop if.
4997 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4998 if(uErr != QCBOR_SUCCESS) {
4999 goto Done;
5000 }
5001
5002 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005003 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005004 }
5005Done:
5006 return uErr;
5007}
5008
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005009
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005010static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005011 TagSpecification TagSpec,
5012 QCBORItem *pItem,
5013 int64_t *pnMantissa,
5014 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005015{
5016 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005017
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005018 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005019 if(uErr != QCBOR_SUCCESS) {
5020 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005021 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005022
Laurence Lundblade9b334962020-08-27 10:55:53 -07005023 switch (pItem->uDataType) {
5024
5025 case QCBOR_TYPE_DECIMAL_FRACTION:
5026 case QCBOR_TYPE_BIGFLOAT:
5027 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5028 *pnExponent = pItem->val.expAndMantissa.nExponent;
5029 break;
5030
5031 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5032 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5033 *pnExponent = pItem->val.expAndMantissa.nExponent;
5034 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5035 break;
5036
5037 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5038 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5039 *pnExponent = pItem->val.expAndMantissa.nExponent;
5040 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5041 break;
5042
5043 default:
5044 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5045 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005046
5047 Done:
5048 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005049}
5050
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005051
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005052static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005053 TagSpecification TagSpec,
5054 QCBORItem *pItem,
5055 UsefulBuf BufferForMantissa,
5056 UsefulBufC *pMantissa,
5057 bool *pbIsNegative,
5058 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005059{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005060 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005061
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005062 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005063 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005064 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005065 }
5066
5067 uint64_t uMantissa;
5068
5069 switch (pItem->uDataType) {
5070
5071 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005072 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005073 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5074 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5075 *pbIsNegative = false;
5076 } else {
5077 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5078 *pbIsNegative = true;
5079 }
5080 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5081 *pnExponent = pItem->val.expAndMantissa.nExponent;
5082 break;
5083
5084 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005085 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005086 *pnExponent = pItem->val.expAndMantissa.nExponent;
5087 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5088 *pbIsNegative = false;
5089 break;
5090
5091 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005092 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005093 *pnExponent = pItem->val.expAndMantissa.nExponent;
5094 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5095 *pbIsNegative = true;
5096 break;
5097
5098 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005099 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005100 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005101
5102Done:
5103 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005104}
5105
5106
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005107/*
5108 Public function, see header qcbor/qcbor_decode.h file
5109*/
5110void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5111 uint8_t uTagRequirement,
5112 int64_t *pnMantissa,
5113 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005114{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005115 if(pMe->uLastError != QCBOR_SUCCESS) {
5116 return;
5117 }
5118
5119 QCBORItem Item;
5120 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5121 if(uError) {
5122 pMe->uLastError = (uint8_t)uError;
5123 return;
5124 }
5125
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005126 const TagSpecification TagSpec =
5127 {
5128 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005129 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5130 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5131 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005132 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005133
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005134 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005135}
5136
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005137
5138/*
5139 Public function, see header qcbor/qcbor_decode.h file
5140*/
5141void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005142 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005143 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005144 int64_t *pnMantissa,
5145 int64_t *pnExponent)
5146{
5147 if(pMe->uLastError != QCBOR_SUCCESS) {
5148 return;
5149 }
5150
5151 QCBORItem Item;
5152 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5153
5154 const TagSpecification TagSpec =
5155 {
5156 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005157 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5158 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5159 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005160 };
5161
5162 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5163}
5164
5165
5166/*
5167 Public function, see header qcbor/qcbor_decode.h file
5168*/
5169void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005170 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005171 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005172 int64_t *pnMantissa,
5173 int64_t *pnExponent)
5174{
5175 if(pMe->uLastError != QCBOR_SUCCESS) {
5176 return;
5177 }
5178
5179 QCBORItem Item;
5180 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5181
5182 const TagSpecification TagSpec =
5183 {
5184 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005185 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5186 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5187 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005188 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005189
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005190 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5191}
5192
5193
5194/*
5195 Public function, see header qcbor/qcbor_decode.h file
5196*/
5197void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5198 uint8_t uTagRequirement,
5199 UsefulBuf MantissaBuffer,
5200 UsefulBufC *pMantissa,
5201 bool *pbMantissaIsNegative,
5202 int64_t *pnExponent)
5203{
5204 if(pMe->uLastError != QCBOR_SUCCESS) {
5205 return;
5206 }
5207
5208 QCBORItem Item;
5209 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5210 if(uError) {
5211 pMe->uLastError = (uint8_t)uError;
5212 return;
5213 }
5214
5215 const TagSpecification TagSpec =
5216 {
5217 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005218 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5219 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5220 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005221 };
5222
Laurence Lundblade93d89472020-10-03 22:30:50 -07005223 ProcessMantissaAndExponentBig(pMe,
5224 TagSpec,
5225 &Item,
5226 MantissaBuffer,
5227 pMantissa,
5228 pbMantissaIsNegative,
5229 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005230}
5231
5232
5233/*
5234 Public function, see header qcbor/qcbor_decode.h file
5235*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005236void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005237 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005238 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005239 UsefulBuf BufferForMantissa,
5240 UsefulBufC *pMantissa,
5241 bool *pbIsNegative,
5242 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005243{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005244 if(pMe->uLastError != QCBOR_SUCCESS) {
5245 return;
5246 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005247
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005248 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005249 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005250 if(pMe->uLastError != QCBOR_SUCCESS) {
5251 return;
5252 }
5253
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005254 const TagSpecification TagSpec =
5255 {
5256 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005257 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5258 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5259 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005260 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005261
Laurence Lundblade93d89472020-10-03 22:30:50 -07005262 ProcessMantissaAndExponentBig(pMe,
5263 TagSpec,
5264 &Item,
5265 BufferForMantissa,
5266 pMantissa,
5267 pbIsNegative,
5268 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005269}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005270
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005271
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005272/*
5273 Public function, see header qcbor/qcbor_decode.h file
5274*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005275void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005276 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005277 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005278 UsefulBuf BufferForMantissa,
5279 UsefulBufC *pMantissa,
5280 bool *pbIsNegative,
5281 int64_t *pnExponent)
5282{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005283 if(pMe->uLastError != QCBOR_SUCCESS) {
5284 return;
5285 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005286
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005287 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005288 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5289 if(pMe->uLastError != QCBOR_SUCCESS) {
5290 return;
5291 }
5292
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005293 const TagSpecification TagSpec =
5294 {
5295 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005296 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5297 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5298 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005299 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005300
5301 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5302}
5303
5304
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005305/*
5306 Public function, see header qcbor/qcbor_decode.h file
5307*/
5308void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5309 uint8_t uTagRequirement,
5310 int64_t *pnMantissa,
5311 int64_t *pnExponent)
5312{
5313 if(pMe->uLastError != QCBOR_SUCCESS) {
5314 return;
5315 }
5316
5317 QCBORItem Item;
5318 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5319 if(uError) {
5320 pMe->uLastError = (uint8_t)uError;
5321 return;
5322 }
5323 const TagSpecification TagSpec =
5324 {
5325 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005326 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5327 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5328 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005329 };
5330
5331 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5332}
5333
5334
5335/*
5336 Public function, see header qcbor/qcbor_decode.h file
5337*/
5338void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005339 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005340 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005341 int64_t *pnMantissa,
5342 int64_t *pnExponent)
5343{
5344 if(pMe->uLastError != QCBOR_SUCCESS) {
5345 return;
5346 }
5347
5348 QCBORItem Item;
5349 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5350 if(pMe->uLastError != QCBOR_SUCCESS) {
5351 return;
5352 }
5353
5354 const TagSpecification TagSpec =
5355 {
5356 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005357 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5358 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5359 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005360 };
5361
5362 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5363}
5364
5365
5366/*
5367 Public function, see header qcbor/qcbor_decode.h file
5368*/
5369void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005370 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005371 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005372 int64_t *pnMantissa,
5373 int64_t *pnExponent)
5374{
5375 if(pMe->uLastError != QCBOR_SUCCESS) {
5376 return;
5377 }
5378
5379 QCBORItem Item;
5380 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5381 if(pMe->uLastError != QCBOR_SUCCESS) {
5382 return;
5383 }
5384
5385 const TagSpecification TagSpec =
5386 {
5387 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005388 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5389 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5390 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005391 };
5392
5393 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5394}
5395
5396
5397/*
5398 Public function, see header qcbor/qcbor_decode.h file
5399*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005400void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5401 uint8_t uTagRequirement,
5402 UsefulBuf MantissaBuffer,
5403 UsefulBufC *pMantissa,
5404 bool *pbMantissaIsNegative,
5405 int64_t *pnExponent)
5406{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005407 if(pMe->uLastError != QCBOR_SUCCESS) {
5408 return;
5409 }
5410
5411 QCBORItem Item;
5412 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5413 if(uError) {
5414 pMe->uLastError = (uint8_t)uError;
5415 return;
5416 }
5417
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005418 const TagSpecification TagSpec =
5419 {
5420 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005421 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5422 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5423 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005424 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005425
5426 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005427}
5428
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005429
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005430/*
5431 Public function, see header qcbor/qcbor_decode.h file
5432*/
5433void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005434 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005435 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005436 UsefulBuf BufferForMantissa,
5437 UsefulBufC *pMantissa,
5438 bool *pbIsNegative,
5439 int64_t *pnExponent)
5440{
5441 if(pMe->uLastError != QCBOR_SUCCESS) {
5442 return;
5443 }
5444
5445 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005446 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5447 if(pMe->uLastError != QCBOR_SUCCESS) {
5448 return;
5449 }
5450
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005451 const TagSpecification TagSpec =
5452 {
5453 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005454 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5455 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5456 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005457 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005458
Laurence Lundblade93d89472020-10-03 22:30:50 -07005459 ProcessMantissaAndExponentBig(pMe,
5460 TagSpec,
5461 &Item,
5462 BufferForMantissa,
5463 pMantissa,
5464 pbIsNegative,
5465 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005466}
5467
5468
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005469/*
5470 Public function, see header qcbor/qcbor_decode.h file
5471*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005472void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005473 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005474 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005475 UsefulBuf BufferForMantissa,
5476 UsefulBufC *pMantissa,
5477 bool *pbIsNegative,
5478 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005479{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005480 if(pMe->uLastError != QCBOR_SUCCESS) {
5481 return;
5482 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005483
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005484 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005485 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5486 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005487 return;
5488 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005489
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005490 const TagSpecification TagSpec =
5491 {
5492 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005493 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5494 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5495 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005496 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005497
Laurence Lundblade93d89472020-10-03 22:30:50 -07005498 ProcessMantissaAndExponentBig(pMe,
5499 TagSpec,
5500 &Item,
5501 BufferForMantissa,
5502 pMantissa,
5503 pbIsNegative,
5504 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005505}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005506
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005507#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */