blob: 452cd17c15dba1dbb3a42ba6adcfa0b4eb7278a8 [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 Lundblade12721ba2020-11-24 22:29:57 -0800481#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800482/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800483 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
484
485 The following four functions are pretty wrappers for invocation of
486 the string allocator supplied by the caller.
487
Laurence Lundbladeee851742020-01-08 08:37:05 -0800488 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800489
Laurence Lundbladeee851742020-01-08 08:37:05 -0800490static inline void
491StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800492{
493 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
494}
495
Laurence Lundbladeee851742020-01-08 08:37:05 -0800496// StringAllocator_Reallocate called with pMem NULL is
497// equal to StringAllocator_Allocate()
498static inline UsefulBuf
499StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
500 void *pMem,
501 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800502{
503 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
504}
505
Laurence Lundbladeee851742020-01-08 08:37:05 -0800506static inline UsefulBuf
507StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800508{
509 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
510}
511
Laurence Lundbladeee851742020-01-08 08:37:05 -0800512static inline void
513StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800514{
515 if(pMe->pfAllocator) {
516 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
517 }
518}
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800519#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800520
521
Laurence Lundbladeee851742020-01-08 08:37:05 -0800522/*===========================================================================
523 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700524
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800525 See qcbor/qcbor_decode.h for definition of the object
526 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800527 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700528/*
529 Public function, see header file
530 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800531void QCBORDecode_Init(QCBORDecodeContext *me,
532 UsefulBufC EncodedCBOR,
533 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700534{
535 memset(me, 0, sizeof(QCBORDecodeContext));
536 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800537 // Don't bother with error check on decode mode. If a bad value is
538 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700539 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700540 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700541 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700542 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700543 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700544}
545
546
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800547#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
548
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700549/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700550 Public function, see header file
551 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800552void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
553 QCBORStringAllocate pfAllocateFunction,
554 void *pAllocateContext,
555 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700556{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800557 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
558 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
559 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700560}
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800561#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700562
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800563
564/*
565 Public function, see header file
566 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700567void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800568 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700569{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700570 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700571 (void)pMe;
572 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700573}
574
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700575
576/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800577 This decodes the fundamental part of a CBOR data item, the type and
578 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800579
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700580 This is the counterpart to QCBOREncode_EncodeHead().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800581
Laurence Lundbladeee851742020-01-08 08:37:05 -0800582 This does the network->host byte order conversion. The conversion
583 here also results in the conversion for floats in addition to that
584 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800585
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700586 This returns:
587 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800588
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800589 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800590 tags and floats and length for strings and arrays
591
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800592 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800593 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800594
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800595 The int type is preferred to uint8_t for some variables as this
596 avoids integer promotions, can reduce code size and makes
597 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700598
599 @retval QCBOR_ERR_UNSUPPORTED
600
601 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700602 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700603static inline QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800604 int *pnMajorType,
605 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800606 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700607{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700608 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800609
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700610 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800611 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800612
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700613 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800614 const int nTmpMajorType = nInitialByte >> 5;
615 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800616
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800617 // Where the number or argument accumulates
618 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800619
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800620 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700621 // Need to get 1,2,4 or 8 additional argument bytes. Map
622 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800623 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800624
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800625 // Loop getting all the bytes in the argument
626 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800627 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800628 // This shift and add gives the endian conversion
629 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
630 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800631 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800632 // The reserved and thus-far unused additional info values
633 nReturn = QCBOR_ERR_UNSUPPORTED;
634 goto Done;
635 } else {
636 // Less than 24, additional info is argument or 31, an indefinite length
637 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800638 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700639 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800640
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700641 if(UsefulInputBuf_GetError(pUInBuf)) {
642 nReturn = QCBOR_ERR_HIT_END;
643 goto Done;
644 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800645
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700646 // All successful if we got here.
647 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800648 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800649 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800650 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800651
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700652Done:
653 return nReturn;
654}
655
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800656
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700657/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800658 CBOR doesn't explicitly specify two's compliment for integers but all
659 CPUs use it these days and the test vectors in the RFC are so. All
660 integers in the CBOR structure are positive and the major type
661 indicates positive or negative. CBOR can express positive integers
662 up to 2^x - 1 where x is the number of bits and negative integers
663 down to 2^x. Note that negative numbers can be one more away from
664 zero than positive. Stdint, as far as I can tell, uses two's
665 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800666
Laurence Lundblade9b334962020-08-27 10:55:53 -0700667 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800668 used carefully here, and in particular why it isn't used in the interface.
669 Also see
670 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
671
672 Int is used for values that need less than 16-bits and would be subject
673 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700674
675 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700676 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700677static inline QCBORError
Laurence Lundbladeee851742020-01-08 08:37:05 -0800678DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700679{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700680 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800681
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700682 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
683 if (uNumber <= INT64_MAX) {
684 pDecodedItem->val.int64 = (int64_t)uNumber;
685 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800686
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700687 } else {
688 pDecodedItem->val.uint64 = uNumber;
689 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800690
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700691 }
692 } else {
693 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800694 // CBOR's representation of negative numbers lines up with the
695 // two-compliment representation. A negative integer has one
696 // more in range than a positive integer. INT64_MIN is
697 // equal to (-INT64_MAX) - 1.
698 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700699 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800700
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700701 } else {
702 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000703 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700704 nReturn = QCBOR_ERR_INT_OVERFLOW;
705 }
706 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800707
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700708 return nReturn;
709}
710
711// Make sure #define value line up as DecodeSimple counts on this.
712#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
713#error QCBOR_TYPE_FALSE macro value wrong
714#endif
715
716#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
717#error QCBOR_TYPE_TRUE macro value wrong
718#endif
719
720#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
721#error QCBOR_TYPE_NULL macro value wrong
722#endif
723
724#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
725#error QCBOR_TYPE_UNDEF macro value wrong
726#endif
727
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700728#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
729#error QCBOR_TYPE_BREAK macro value wrong
730#endif
731
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700732#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
733#error QCBOR_TYPE_DOUBLE macro value wrong
734#endif
735
736#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
737#error QCBOR_TYPE_FLOAT macro value wrong
738#endif
739
740/*
741 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700742
743 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
744
745 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700746 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700747static inline QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800748DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700749{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700750 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800751
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700752 // uAdditionalInfo is 5 bits from the initial byte. Compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800753 // above make sure uAdditionalInfo values line up with uDataType values.
Laurence Lundblade93d89472020-10-03 22:30:50 -0700754 // DecodeTypeAndNumber() never returns an AdditionalInfo > 0x1f so cast
755 // is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800756 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800757
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800758 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800759 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
760 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800761
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700762 case HALF_PREC_FLOAT: // 25
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700763#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700764 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700765 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700766 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700767 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
768 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700769#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700770 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700771#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700772 break;
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700773 case SINGLE_PREC_FLOAT: // 26
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700774 // Single precision is normally returned as a double
775 // since double is widely supported, there is no loss of
776 // precision, it makes it easy for the caller in
777 // most cases and it can be converted back to single
778 // with no loss of precision
779 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700780 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700781 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700782 {
783 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
784#ifndef QCBOR_DISABLE_FLOAT_HW_USE
785 // In the normal case, use HW to convert float to double.
786 pDecodedItem->val.dfnum = (double)f;
787 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700788#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700789 // Use of float HW is disabled, return as a float.
790 pDecodedItem->val.fnum = f;
791 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
792
793 // IEEE754_FloatToDouble() could be used here to return
794 // as a double, but it adds object code and most likely
795 // anyone disabling FLOAT HW use doesn't care about
796 // floats and wants to save object code.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700797#endif
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700798 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700799 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700800
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700801 case DOUBLE_PREC_FLOAT: // 27
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700802 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700803 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700804 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800805
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700806 case CBOR_SIMPLEV_FALSE: // 20
807 case CBOR_SIMPLEV_TRUE: // 21
808 case CBOR_SIMPLEV_NULL: // 22
809 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700810 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700811 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800812
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700813 case CBOR_SIMPLEV_ONEBYTE: // 24
814 if(uNumber <= CBOR_SIMPLE_BREAK) {
815 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700816 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700817 goto Done;
818 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800819 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700820 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800821
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700822 default: // 0-19
823 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800824 /*
825 DecodeTypeAndNumber will make uNumber equal to
826 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
827 safe because the 2, 4 and 8 byte lengths of uNumber are in
828 the double/float cases above
829 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700830 pDecodedItem->val.uSimple = (uint8_t)uNumber;
831 break;
832 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800833
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700834Done:
835 return nReturn;
836}
837
838
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700839/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530840 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700841
842 @retval QCBOR_ERR_HIT_END
843
844 @retval QCBOR_ERR_STRING_ALLOCATE
845
846 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700847 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700848static inline QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800849 uint64_t uStrLen,
850 UsefulInputBuf *pUInBuf,
851 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700852{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700853 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800854
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800855 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
856 // This check makes the casts to size_t below safe.
857
858 // 4 bytes less than the largest sizeof() so this can be tested by
859 // putting a SIZE_MAX length in the CBOR test input (no one will
860 // care the limit on strings is 4 bytes shorter).
861 if(uStrLen > SIZE_MAX-4) {
862 nReturn = QCBOR_ERR_STRING_TOO_LONG;
863 goto Done;
864 }
865
866 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530867 if(UsefulBuf_IsNULLC(Bytes)) {
868 // Failed to get the bytes for this string item
869 nReturn = QCBOR_ERR_HIT_END;
870 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700871 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530872
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800873#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800874 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530875 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800876 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530877 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700878 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530879 goto Done;
880 }
881 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800882 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800883 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530884 }
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800885#else
886 (void)pAllocator;
887#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
888
889 // Normal case with no string allocator
890 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800891
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530892Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700893 return nReturn;
894}
895
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700896
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800897/* Map the CBOR major types for strings to the QCBOR types for strngs */
898static inline uint8_t MapStringMajorTypes(int nCBORMajorType)
899{
900 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
901 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
902 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800903
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800904 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
905 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
906 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700907
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800908 return (uint8_t)(nCBORMajorType + 4);
909}
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700910
911
Laurence Lundbladeee851742020-01-08 08:37:05 -0800912// Make sure the constants align as this is assumed by
913// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700914#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
915#error QCBOR_TYPE_ARRAY value not lined up with major type
916#endif
917#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
918#error QCBOR_TYPE_MAP value not lined up with major type
919#endif
920
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700921/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800922 This gets a single data item and decodes it including preceding
923 optional tagging. This does not deal with arrays and maps and nesting
924 except to decode the data item introducing them. Arrays and maps are
925 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800926
Laurence Lundbladeee851742020-01-08 08:37:05 -0800927 Errors detected here include: an array that is too long to decode,
928 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700929
930 @retval QCBOR_ERR_UNSUPPORTED
931
932 @retval QCBOR_ERR_HIT_END
933
934 @retval QCBOR_ERR_INT_OVERFLOW
935
936 @retval QCBOR_ERR_STRING_ALLOCATE
937
938 @retval QCBOR_ERR_STRING_TOO_LONG
939
940 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
941
942 @retval QCBOR_ERR_BAD_TYPE_7
943
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700944 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800945static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
946 QCBORItem *pDecodedItem,
947 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700948{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700949 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800950
Laurence Lundbladeee851742020-01-08 08:37:05 -0800951 /*
952 Get the major type and the number. Number could be length of more
953 bytes or the value depending on the major type nAdditionalInfo is
954 an encoding of the length of the uNumber and is needed to decode
955 floats and doubles
956 */
Rob Gilton47cc9562020-08-10 12:03:38 +0100957 int nMajorType = 0;
958 uint64_t uNumber = 0;
959 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800960
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700961 memset(pDecodedItem, 0, sizeof(QCBORItem));
962
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800963 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800964
Laurence Lundbladeee851742020-01-08 08:37:05 -0800965 // Error out here if we got into trouble on the type and number. The
966 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700967 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700968 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700969 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800970
Laurence Lundbladeee851742020-01-08 08:37:05 -0800971 // At this point the major type and the value are valid. We've got
972 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800973 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700974 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
975 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800976 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700977 nReturn = QCBOR_ERR_BAD_INT;
978 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800979 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700980 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700981 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800982
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700983 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
984 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800985 pDecodedItem->uDataType = (uint8_t)MapStringMajorTypes(nMajorType);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800986 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladea44d5062018-10-17 18:45:12 +0530987 pDecodedItem->val.string = (UsefulBufC){NULL, SIZE_MAX};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700988 } else {
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800989 nReturn = DecodeBytes(pAllocator, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700990 }
991 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800992
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700993 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
994 case CBOR_MAJOR_TYPE_MAP: // Major type 5
995 // Record the number of items in the array or map
996 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700997 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700998 goto Done;
999 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001000 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001001 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001002 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001003 // type conversion OK because of check above
1004 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001005 }
Laurence Lundbladeee851742020-01-08 08:37:05 -08001006 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001007 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001008 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001009 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001010
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001011 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001012 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001013 nReturn = QCBOR_ERR_BAD_INT;
1014 } else {
1015 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001016 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001017 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001018 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001019
Laurence Lundbladeee851742020-01-08 08:37:05 -08001020 case CBOR_MAJOR_TYPE_SIMPLE:
1021 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001022 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001023 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001024
Laurence Lundbladeee851742020-01-08 08:37:05 -08001025 default:
1026 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001027 nReturn = QCBOR_ERR_UNSUPPORTED;
1028 break;
1029 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001030
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001031Done:
1032 return nReturn;
1033}
1034
1035
1036
1037/*
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001038 This layer deals with indefinite length strings. It pulls all the
Laurence Lundbladeee851742020-01-08 08:37:05 -08001039 individual chunk items together into one QCBORItem using the string
1040 allocator.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001041
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301042 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade9b334962020-08-27 10:55:53 -07001043
1044 @retval QCBOR_ERR_UNSUPPORTED
1045
1046 @retval QCBOR_ERR_HIT_END
1047
1048 @retval QCBOR_ERR_INT_OVERFLOW
1049
1050 @retval QCBOR_ERR_STRING_ALLOCATE
1051
1052 @retval QCBOR_ERR_STRING_TOO_LONG
1053
1054 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1055
1056 @retval QCBOR_ERR_BAD_TYPE_7
1057
1058 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1059
1060 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001061 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001062static inline QCBORError
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001063GetNext_FullItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001064{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001065 // Stack usage; int/ptr 2 UsefulBuf 2 QCBORItem -- 96
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001066
1067 // Get pointer to string allocator. First use is to pass it to
1068 // GetNext_Item() when option is set to allocate for *every* string.
1069 // Second use here is to allocate space to coallese indefinite
1070 // length string items into one.
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001071 const QCORInternalAllocator *pAllocatorForGetNext = NULL;
1072
1073#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1074 const QCORInternalAllocator *pAllocator = NULL;
1075
1076 if(pMe->StringAllocator.pfAllocator) {
1077 pAllocator = &(pMe->StringAllocator);
1078 if(pMe->bStringAllocateAll ) {
1079 pAllocatorForGetNext = pAllocator;
1080 }
1081 }
1082#endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001083
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001084 QCBORError nReturn;
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001085 nReturn = GetNext_Item(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001086 if(nReturn) {
1087 goto Done;
1088 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001089
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001090 // Only do indefinite length processing on strings
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001091 const uint8_t uStringType = pDecodedItem->uDataType;
1092 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001093 goto Done; // no need to do any work here on non-string types
1094 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001095
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001096 // Is this a string with an indefinite length?
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301097 if(pDecodedItem->val.string.len != SIZE_MAX) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001098 goto Done; // length is not indefinite, so no work to do here
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001099 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001100
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001101#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301102 // Can't do indefinite length strings without a string allocator
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001103 if(pAllocator == NULL) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001104 nReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1105 goto Done;
1106 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001107
Laurence Lundblade4b270642020-08-14 12:53:07 -07001108 // Loop getting chunks of the indefinite length string
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001109 UsefulBufC FullString = NULLUsefulBufC;
1110
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001111 for(;;) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001112 // Get item for next chunk
1113 QCBORItem StringChunkItem;
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001114 // NULL string allocator passed here. Do not need to allocate
1115 // chunks even if bStringAllocateAll is set.
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001116 nReturn = GetNext_Item(&(pMe->InBuf), &StringChunkItem, NULL);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001117 if(nReturn) {
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001118 break; // Error getting the next chunk
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001119 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001120
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301121 // See if it is a marker at end of indefinite length string
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001122 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001123 // String is complete
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001124 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301125 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001126 break;
1127 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001128
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001129 // Match data type of chunk to type at beginning.
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301130 // Also catches error of other non-string types that don't belong.
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001131 // Also catches indefinite length strings inside indefinite length strings
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001132 // TODO: what is SIZE_MAX here?
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001133 if(StringChunkItem.uDataType != uStringType ||
1134 StringChunkItem.val.string.len == SIZE_MAX) {
Laurence Lundblade30816f22018-11-10 13:40:22 +07001135 nReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001136 break;
1137 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001138
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001139 // Alloc new buffer or expand previously allocated buffer so it can fit.
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001140 // The first time throurgh FullString.ptr is NULL and this is
1141 // equivalent to StringAllocator_Allocate()
1142 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1143 UNCONST_POINTER(FullString.ptr),
1144 FullString.len + StringChunkItem.val.string.len);
1145
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001146 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301147 // Allocation of memory for the string failed
Laurence Lundblade30816f22018-11-10 13:40:22 +07001148 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001149 break;
1150 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001151
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001152 // Copy new string chunk at the end of string so far.
1153 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001154 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001155
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001156 if(nReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1157 // Getting the item failed, clean up the allocated memory
1158 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001159 }
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001160#else
1161 nReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1162#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001163
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001164Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001165 return nReturn;
1166}
1167
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001168
Laurence Lundblade9b334962020-08-27 10:55:53 -07001169static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001170 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001171 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001172 } else if(uTagVal == CBOR_TAG_INVALID16) {
1173 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001174 } else {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001175 // This won't be negative because of code below in GetNext_TaggedItem()
1176 const unsigned uIndex = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
1177 return me->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001178 }
1179}
1180
Laurence Lundblade9b334962020-08-27 10:55:53 -07001181
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001182/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001183 Gets all optional tag data items preceding a data item that is not an
1184 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001185
1186 @retval QCBOR_ERR_UNSUPPORTED
1187
1188 @retval QCBOR_ERR_HIT_END
1189
1190 @retval QCBOR_ERR_INT_OVERFLOW
1191
1192 @retval QCBOR_ERR_STRING_ALLOCATE
1193
1194 @retval QCBOR_ERR_STRING_TOO_LONG
1195
1196 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1197
1198 @retval QCBOR_ERR_BAD_TYPE_7
1199
1200 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1201
1202 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1203
1204 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001205 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001206static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001207GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001208{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001209 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1210 CBOR_TAG_INVALID16,
1211 CBOR_TAG_INVALID16,
1212 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001213
Laurence Lundblade9b334962020-08-27 10:55:53 -07001214 QCBORError uReturn = QCBOR_SUCCESS;
1215
Laurence Lundblade59289e52019-12-30 13:44:37 -08001216 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001217 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001218 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1219 if(uErr != QCBOR_SUCCESS) {
1220 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001221 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001222 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001223
Laurence Lundblade9b334962020-08-27 10:55:53 -07001224 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001225 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001226 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001227 break;
1228 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001229
Laurence Lundblade9b334962020-08-27 10:55:53 -07001230 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1231 // No room in the tag list
1232 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1233 // Continue on to get all tags on this item even though
1234 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001235 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001236 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001237 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001238 // Slide tags over one in the array to make room at index 0
1239 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1240 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001241 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001242
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001243 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001244 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001245 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001246 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001247 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001248 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001249 break;
1250 }
1251 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1252 break;
1253 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001254 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001255 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1256 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001257 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1258 // Continue on to get all tags on this item even though
1259 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001260 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001261 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001262 }
1263
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001264 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001265 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001266 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001267
1268 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001269 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001270 }
1271 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001272
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001273Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001274 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001275}
1276
1277
1278/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001279 This layer takes care of map entries. It combines the label and data
1280 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001281
1282 @retval QCBOR_ERR_UNSUPPORTED
1283
1284 @retval QCBOR_ERR_HIT_END
1285
1286 @retval QCBOR_ERR_INT_OVERFLOW
1287
1288 @retval QCBOR_ERR_STRING_ALLOCATE
1289
1290 @retval QCBOR_ERR_STRING_TOO_LONG
1291
1292 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1293
1294 @retval QCBOR_ERR_BAD_TYPE_7
1295
1296 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1297
1298 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1299
1300 @retval QCBOR_ERR_TOO_MANY_TAGS
1301
1302 @retval QCBOR_ERR_MAP_LABEL_TYPE
1303
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001304 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001305 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001306static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001307GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001308{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001309 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001310 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001311 if(nReturn)
1312 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001313
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001314 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001315 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001316 goto Done;
1317 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001318
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001319 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1320 // In a map and caller wants maps decoded, not treated as arrays
1321
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001322 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001323 // If in a map and the right decoding mode, get the label
1324
Laurence Lundbladeee851742020-01-08 08:37:05 -08001325 // Save label in pDecodedItem and get the next which will
1326 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001327 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001328 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001329 if(QCBORDecode_IsUnrecoverableError(nReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001330 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001331 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001332
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301333 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001334
1335 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1336 // strings are always good labels
1337 pDecodedItem->label.string = LabelItem.val.string;
1338 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1339 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001340 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001341 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1342 goto Done;
1343 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1344 pDecodedItem->label.int64 = LabelItem.val.int64;
1345 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1346 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1347 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1348 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1349 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1350 pDecodedItem->label.string = LabelItem.val.string;
1351 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1352 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1353 } else {
1354 // label is not an int or a string. It is an arrray
1355 // or a float or such and this implementation doesn't handle that.
1356 // Also, tags on labels are ignored.
1357 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1358 goto Done;
1359 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001360 }
1361 } else {
1362 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001363 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001364 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001365 goto Done;
1366 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001367 // Decoding a map as an array
1368 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001369 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1370 // Cast is needed because of integer promotion
1371 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001372 }
1373 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001374
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001375Done:
1376 return nReturn;
1377}
1378
1379
Laurence Lundblade02625d42020-06-25 14:41:41 -07001380/*
1381 See if next item is a CBOR break. If it is, it is consumed,
1382 if not it is not consumed.
1383*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001384static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001385NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1386{
1387 *pbNextIsBreak = false;
1388 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001389 QCBORItem Peek;
1390 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1391 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1392 if(uReturn != QCBOR_SUCCESS) {
1393 return uReturn;
1394 }
1395 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001396 // It is not a break, rewind so it can be processed normally.
1397 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001398 } else {
1399 *pbNextIsBreak = true;
1400 }
1401 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001402
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001403 return QCBOR_SUCCESS;
1404}
1405
1406
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001407/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001408 An item was just consumed, now figure out if it was the
1409 end of an array or map that can be closed out. That
1410 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001411*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001412static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001413{
1414 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001415
Laurence Lundblade642282a2020-06-23 12:00:33 -07001416 /* This loops ascending nesting levels as long as there is ascending to do */
1417 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1418
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001419 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001420 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001421 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1422 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001423 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001424 break;
1425 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07001426 /* All of a definite length array was consumed; fall through to
1427 ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001428
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001429 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001430 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001431 bool bIsBreak = false;
1432 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1433 if(uReturn != QCBOR_SUCCESS) {
1434 goto Done;
1435 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001436
1437 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001438 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001439 break;
1440 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001441
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001442 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001443 /*
1444 Break occurred inside a bstr-wrapped CBOR or
1445 in the top level sequence. This is always an
1446 error because neither are an indefinte length
1447 map/array.
1448 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001449 uReturn = QCBOR_ERR_BAD_BREAK;
1450 goto Done;
1451 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001452
Laurence Lundblade02625d42020-06-25 14:41:41 -07001453 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001454 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001455
Laurence Lundblade02625d42020-06-25 14:41:41 -07001456 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001457
Laurence Lundblade93d89472020-10-03 22:30:50 -07001458 /* But ascent in bounded mode is only by explicit call to
1459 QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001460 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001461 /* Set the count to zero for definite length arrays to indicate
1462 cursor is at end of bounded map / array */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001463 if(bMarkEnd) {
1464 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001465 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001466
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001467 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001468 break;
1469 }
1470
1471 /* Finally, actually ascend one level. */
1472 DecodeNesting_Ascend(&(pMe->nesting));
1473 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001474
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001475 uReturn = QCBOR_SUCCESS;
1476
1477Done:
1478 return uReturn;
1479}
1480
1481
1482/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001483 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001484 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1485 indefinte length maps and arrays by looking at the item count or
1486 finding CBOR breaks. It detects the ends of the top-level sequence
1487 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001488
1489 @retval QCBOR_ERR_UNSUPPORTED X
1490
1491 @retval QCBOR_ERR_HIT_END
1492
1493 @retval QCBOR_ERR_INT_OVERFLOW X
1494
1495 @retval QCBOR_ERR_STRING_ALLOCATE
1496
1497 @retval QCBOR_ERR_STRING_TOO_LONG
1498
1499 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1500
1501 @retval QCBOR_ERR_BAD_TYPE_7 X
1502
1503 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1504
1505 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1506
1507 @retval QCBOR_ERR_TOO_MANY_TAGS
1508
1509 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1510
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001511 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001512
1513 @retval QCBOR_ERR_NO_MORE_ITEMS
1514
1515 @retval QCBOR_ERR_BAD_BREAK
1516
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001517 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001518static QCBORError
1519QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001520{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001521 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001522 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001523
Laurence Lundblade642282a2020-06-23 12:00:33 -07001524 /*
1525 If out of bytes to consume, it is either the end of the top-level
1526 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001527
Laurence Lundblade642282a2020-06-23 12:00:33 -07001528 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1529 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1530 CBOR is exited, the length is set back to the top-level's length
1531 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001532 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001533 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001534 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001535 goto Done;
1536 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001537
Laurence Lundblade642282a2020-06-23 12:00:33 -07001538 /*
1539 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001540 array. The check for the end of an indefinite length array is
1541 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001542 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001543 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001544 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001545 goto Done;
1546 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001547
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001548 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001549 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001550 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1551 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001552 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001553 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301554
Laurence Lundblade642282a2020-06-23 12:00:33 -07001555 /*
1556 Breaks ending arrays/maps are always processed at the end of this
1557 function. They should never show up here.
1558 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301559 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001560 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301561 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301562 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001563
Laurence Lundblade642282a2020-06-23 12:00:33 -07001564 /*
1565 Record the nesting level for this data item before processing any
1566 of decrementing and descending.
1567 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001568 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001569
Laurence Lundblade642282a2020-06-23 12:00:33 -07001570
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001571 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001572 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001573 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001574 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001575
Laurence Lundblade93d89472020-10-03 22:30:50 -07001576 Empty indefinite length maps and arrays are descended into, but
1577 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001578
1579 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001580 encloses them so a decrement needs to be done for them too, but
1581 that is done only when all the items in them have been
1582 processed, not when they are opened with the exception of an
1583 empty map or array.
1584 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001585 QCBORError uDescendErr;
1586 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001587 pDecodedItem->uDataType,
1588 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001589 if(uDescendErr != QCBOR_SUCCESS) {
1590 /* This error is probably a traversal error and it
1591 overrides the non-traversal error. */
1592 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001593 goto Done;
1594 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001595 }
1596
Laurence Lundblade02625d42020-06-25 14:41:41 -07001597 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1598 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1599 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001600 /*
1601 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001602 - A non-aggregate like an integer or string
1603 - An empty definite length map or array
1604 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001605
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001606 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001607 definite length map/array and break detection for an indefinite
1608 length map/array. If the end of the map/array was reached, then
1609 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001610 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001611 QCBORError uAscendErr;
1612 uAscendErr = NestLevelAscender(me, true);
1613 if(uAscendErr != QCBOR_SUCCESS) {
1614 /* This error is probably a traversal error and it
1615 overrides the non-traversal error. */
1616 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001617 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001618 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301619 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001620
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001621 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001622 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001623 Tell the caller what level is next. This tells them what
1624 maps/arrays were closed out and makes it possible for them to
1625 reconstruct the tree with just the information returned in
1626 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001627 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001628 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001629 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001630 pDecodedItem->uNextNestLevel = 0;
1631 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001632 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001633 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001634
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001635Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001636 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001637}
1638
Laurence Lundblade9b334962020-08-27 10:55:53 -07001639static void ShiftTags(QCBORItem *pDecodedItem)
1640{
1641 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1642 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1643 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1644 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1645}
1646
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001647
Laurence Lundblade59289e52019-12-30 13:44:37 -08001648/*
1649 Mostly just assign the right data type for the date string.
1650 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001651static inline QCBORError DecodeDateString(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001652{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001653 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1654 return QCBOR_ERR_BAD_OPT_TAG;
1655 }
1656
1657 const UsefulBufC Temp = pDecodedItem->val.string;
1658 pDecodedItem->val.dateString = Temp;
1659 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001660 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001661 return QCBOR_SUCCESS;
1662}
1663
1664
Laurence Lundblade9b334962020-08-27 10:55:53 -07001665
Laurence Lundblade59289e52019-12-30 13:44:37 -08001666/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001667 The epoch formatted date. Turns lots of different forms of encoding
1668 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001669 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001670static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001671{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001672 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001673
1674 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1675
1676 switch (pDecodedItem->uDataType) {
1677
1678 case QCBOR_TYPE_INT64:
1679 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1680 break;
1681
1682 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001683 // This only happens for CBOR type 0 > INT64_MAX so it is
1684 // always an overflow.
1685 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1686 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001687 break;
1688
1689 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001690 case QCBOR_TYPE_FLOAT:
1691#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001692 {
1693 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001694 // conversion to an int64_t to be able to detect doubles that
1695 // are too large to fit into an int64_t. A double has 52
1696 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1697 // to a double actually causes a round up which is bad and
1698 // wrong for the comparison because it will allow conversion
1699 // of doubles that can't fit into a uint64_t. To remedy this
1700 // INT64_MAX - 0x7ff is used as the cutoff point because if
1701 // that value rounds up in conversion to double it will still
1702 // be less than INT64_MAX. 0x7ff is picked because it has 11
1703 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001704 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001705 // INT64_MAX seconds is on the order of 10 billion years, and
1706 // the earth is less than 5 billion years old, so for most
1707 // uses this conversion error won't occur even though doubles
1708 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001709 //
1710 // Without the 0x7ff there is a ~30 minute range of time
1711 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001712 // where this code would go wrong. Some compilers
1713 // will generate warnings or errors without the 0x7ff
1714 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001715 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1716 pDecodedItem->val.dfnum :
1717 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001718 if(isnan(d) ||
1719 d > (double)(INT64_MAX - 0x7ff) ||
1720 d < (double)(INT64_MIN + 0x7ff)) {
1721 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001722 goto Done;
1723 }
1724 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001725 pDecodedItem->val.epochDate.fSecondsFraction =
1726 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001727 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001728#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001729
Laurence Lundbladec7114722020-08-13 05:11:40 -07001730 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001731 goto Done;
1732
Laurence Lundblade9682a532020-06-06 18:33:04 -07001733#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001734 break;
1735
1736 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001737 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001738 goto Done;
1739 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001740
Laurence Lundblade59289e52019-12-30 13:44:37 -08001741 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1742
1743Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001744 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001745}
1746
1747
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001748/*
1749 Mostly just assign the right data type for the bignum.
1750 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001751static inline QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001752{
1753 // Stack Use: UsefulBuf 1 -- 16
1754 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1755 return QCBOR_ERR_BAD_OPT_TAG;
1756 }
1757 const UsefulBufC Temp = pDecodedItem->val.string;
1758 pDecodedItem->val.bigNum = Temp;
1759 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1760 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1761 : QCBOR_TYPE_NEGBIGNUM);
1762 return QCBOR_SUCCESS;
1763}
1764
1765
Laurence Lundblade59289e52019-12-30 13:44:37 -08001766#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1767/*
1768 Decode decimal fractions and big floats.
1769
1770 When called pDecodedItem must be the array that is tagged as a big
1771 float or decimal fraction, the array that has the two members, the
1772 exponent and mantissa.
1773
1774 This will fetch and decode the exponent and mantissa and put the
1775 result back into pDecodedItem.
1776 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001777static inline QCBORError
Laurence Lundblade59289e52019-12-30 13:44:37 -08001778QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1779{
1780 QCBORError nReturn;
1781
1782 // --- Make sure it is an array; track nesting level of members ---
1783 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1784 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1785 goto Done;
1786 }
1787
1788 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001789 // definite length arrays, but not for indefnite. Instead remember
1790 // the nesting level the two integers must be at, which is one
1791 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001792 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1793
1794 // --- Is it a decimal fraction or a bigfloat? ---
1795 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1796 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1797
1798 // --- Get the exponent ---
1799 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001800 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001801 if(nReturn != QCBOR_SUCCESS) {
1802 goto Done;
1803 }
1804 if(exponentItem.uNestingLevel != nNestLevel) {
1805 // Array is empty or a map/array encountered when expecting an int
1806 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1807 goto Done;
1808 }
1809 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1810 // Data arriving as an unsigned int < INT64_MAX has been converted
1811 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1812 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1813 // will be too large for this to handle and thus an error that will
1814 // get handled in the next else.
1815 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1816 } else {
1817 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1818 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1819 goto Done;
1820 }
1821
1822 // --- Get the mantissa ---
1823 QCBORItem mantissaItem;
1824 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1825 if(nReturn != QCBOR_SUCCESS) {
1826 goto Done;
1827 }
1828 if(mantissaItem.uNestingLevel != nNestLevel) {
1829 // Mantissa missing or map/array encountered when expecting number
1830 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1831 goto Done;
1832 }
1833 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1834 // Data arriving as an unsigned int < INT64_MAX has been converted
1835 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1836 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1837 // will be too large for this to handle and thus an error that
1838 // will get handled in an else below.
1839 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001840 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
1841 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001842 // Got a good big num mantissa
1843 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1844 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001845 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1846 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1847 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001848 } else {
1849 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1850 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1851 goto Done;
1852 }
1853
1854 // --- Check that array only has the two numbers ---
1855 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001856 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001857 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1858 goto Done;
1859 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001860 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001861
1862Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001863 return nReturn;
1864}
1865#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1866
1867
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001868static inline QCBORError DecodeURI(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001869{
1870 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1871 return QCBOR_ERR_BAD_OPT_TAG;
1872 }
1873 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1874 return QCBOR_SUCCESS;
1875}
1876
1877
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001878static inline QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001879{
1880 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1881 return QCBOR_ERR_BAD_OPT_TAG;
1882 }
1883 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001884
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001885 return QCBOR_SUCCESS;
1886}
1887
1888
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001889static inline QCBORError DecodeB64(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001890{
1891 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1892 return QCBOR_ERR_BAD_OPT_TAG;
1893 }
1894 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001895
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001896 return QCBOR_SUCCESS;
1897}
1898
1899
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001900static inline QCBORError DecodeRegex(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001901{
1902 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1903 return QCBOR_ERR_BAD_OPT_TAG;
1904 }
1905 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001906
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001907 return QCBOR_SUCCESS;
1908}
1909
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001910
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001911static inline QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001912{
1913 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1914 return QCBOR_ERR_BAD_OPT_TAG;
1915 }
1916 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001917
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001918 return QCBOR_SUCCESS;
1919}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001920
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001921
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001922static inline QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001923{
1924 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1925 return QCBOR_ERR_BAD_OPT_TAG;
1926 }
1927 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001928
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001929 return QCBOR_SUCCESS;
1930}
1931
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001932
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001933static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001934{
1935 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1936 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001937 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001938 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1939 } else {
1940 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001941
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001942 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001943
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001944 return QCBOR_SUCCESS;
1945}
1946
1947
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001948static inline QCBORError DecodeUUID(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001949{
1950 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1951 return QCBOR_ERR_BAD_OPT_TAG;
1952 }
1953 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001954
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001955 return QCBOR_SUCCESS;
1956}
1957
1958
Laurence Lundblade59289e52019-12-30 13:44:37 -08001959/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001960 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001961 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001962static QCBORError
1963QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001964{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001965 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001966
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001967 uReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
1968 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001969 goto Done;
1970 }
1971
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001972 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
1973 switch(pDecodedItem->uTags[uTagIndex]) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001974
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001975 // Many of the functions here only just map a CBOR tag to
1976 // a QCBOR_TYPE for a string and could probably be
1977 // implemented with less object code. This implementation
1978 // of string types takes about 120 bytes of object code
1979 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001980 case CBOR_TAG_DATE_STRING:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001981 uReturn = DecodeDateString(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001982 break;
1983
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001984 case CBOR_TAG_DATE_EPOCH:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001985 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001986 break;
1987
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001988 case CBOR_TAG_POS_BIGNUM:
1989 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001990 uReturn = DecodeBigNum(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001991 break;
1992
Laurence Lundblade93d89472020-10-03 22:30:50 -07001993#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001994 case CBOR_TAG_DECIMAL_FRACTION:
1995 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001996 // For aggregate tagged types, what goes into pTags is only collected
1997 // from the surrounding data item, not the contents, so pTags is not
1998 // passed on here.
1999
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002000 uReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002001 break;
Laurence Lundblade93d89472020-10-03 22:30:50 -07002002#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002003
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002004 case CBOR_TAG_CBOR:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002005 uReturn = DecodeWrappedCBOR(pDecodedItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002006 break;
2007
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002008 case CBOR_TAG_CBOR_SEQUENCE:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002009 uReturn = DecodeWrappedCBORSequence(pDecodedItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002010 break;
2011
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002012 case CBOR_TAG_URI:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002013 uReturn = DecodeURI(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002014 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002015
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002016 case CBOR_TAG_B64URL:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002017 uReturn = DecodeB64URL(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002018 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002019
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002020 case CBOR_TAG_B64:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002021 uReturn = DecodeB64(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002022 break;
2023
2024 case CBOR_TAG_MIME:
2025 case CBOR_TAG_BINARY_MIME:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002026 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002027 break;
2028
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002029 case CBOR_TAG_REGEX:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002030 uReturn = DecodeRegex(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002031 break;
2032
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002033 case CBOR_TAG_BIN_UUID:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002034 uReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002035 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002036
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002037 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002038 // The end of the tag list or no tags
2039 // Successful exit from the loop.
2040 goto Done;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002041
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002042 default:
2043 // A tag that is not understood
2044 // A successful exit from the loop
2045 goto Done;
2046
2047 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002048 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002049 goto Done;
2050 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002051 // A tag was successfully processed, shift it
2052 // out of the list of tags returned.
2053 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002054 }
2055
2056Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002057 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002058}
2059
2060
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002061/*
2062 Public function, see header qcbor/qcbor_decode.h file
2063 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002064QCBORError
2065QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2066{
2067 QCBORError uErr;
2068 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2069 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002070 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2071 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2072 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002073 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002074}
2075
2076
2077/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002078 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002079 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002080QCBORError
2081QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2082{
2083 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2084 const UsefulInputBuf Save = pMe->InBuf;
2085
2086 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2087
2088 pMe->nesting = SaveNesting;
2089 pMe->InBuf = Save;
2090
2091 return uErr;
2092}
2093
2094
2095/*
2096 Public function, see header qcbor/qcbor_decode.h file
2097 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002098void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2099{
2100 if(pMe->uLastError != QCBOR_SUCCESS) {
2101 return;
2102 }
2103
2104 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2105}
2106
2107
2108/*
2109 Public function, see header qcbor/qcbor_decode.h file
2110 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002111QCBORError
2112QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2113 QCBORItem *pDecodedItem,
2114 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002115{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002116 QCBORError nReturn;
2117
2118 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2119 if(nReturn != QCBOR_SUCCESS) {
2120 return nReturn;
2121 }
2122
2123 if(pTags != NULL) {
2124 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002125 // Reverse the order because pTags is reverse of
2126 // QCBORItem.uTags.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002127 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2128 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002129 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002130 }
2131 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2132 return QCBOR_ERR_TOO_MANY_TAGS;
2133 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002134 pTags->puTags[pTags->uNumUsed] = ConvertTag(me,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002135 pTags->uNumUsed++;
2136 }
2137 }
2138
2139 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002140}
2141
2142
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002143/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302144 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302145 next one down. If a layer has no work to do for a particular item
2146 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002147
Laurence Lundblade59289e52019-12-30 13:44:37 -08002148 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2149 tagged data items, turning them into the local C representation.
2150 For the most simple it is just associating a QCBOR_TYPE with the data. For
2151 the complex ones that an aggregate of data items, there is some further
2152 decoding and a little bit of recursion.
2153
2154 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302155 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302156 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002157 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002158
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302159 - GetNext_MapEntry -- This handles the combining of two
2160 items, the label and the data, that make up a map entry.
2161 It only does work on maps. It combines the label and data
2162 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002163
Laurence Lundblade59289e52019-12-30 13:44:37 -08002164 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2165 tags into bit flags associated with the data item. No actual decoding
2166 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002167
Laurence Lundblade59289e52019-12-30 13:44:37 -08002168 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302169 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302170 string allocater to create contiguous space for the item. It
2171 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002172
Laurence Lundblade59289e52019-12-30 13:44:37 -08002173 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2174 atomic data item has a "major type", an integer "argument" and optionally
2175 some content. For text and byte strings, the content is the bytes
2176 that make up the string. These are the smallest data items that are
2177 considered to be well-formed. The content may also be other data items in
2178 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002179
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002180 Roughly this takes 300 bytes of stack for vars. Need to
2181 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002182
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302183 */
2184
2185
2186/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002187 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002188 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002189bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002190 const QCBORItem *pItem,
2191 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002192{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002193 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2194 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002195 break;
2196 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002197 if(ConvertTag(me, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002198 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002199 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002200 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002201
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002202 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002203}
2204
2205
2206/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002207 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002208 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002209QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002210{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002211 QCBORError uReturn = me->uLastError;
2212
2213 if(uReturn != QCBOR_SUCCESS) {
2214 goto Done;
2215 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002216
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002217 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002218 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002219 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002220 goto Done;
2221 }
2222
2223 // Error out if not all the bytes are consumed
2224 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002225 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002226 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002227
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002228Done:
Laurence Lundblade12721ba2020-11-24 22:29:57 -08002229#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade6de37062018-10-15 12:22:42 +05302230 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002231 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002232 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade12721ba2020-11-24 22:29:57 -08002233#endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002234
Laurence Lundblade085d7952020-07-24 10:26:30 -07002235 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002236}
2237
2238
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002239/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002240 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002241*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002242// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002243uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2244 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002245 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002246{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002247 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2248 return CBOR_TAG_INVALID64;
2249 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002250 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2251 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002252 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002253 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002254 }
2255}
2256
Laurence Lundblade9b334962020-08-27 10:55:53 -07002257/*
2258 Public function, see header qcbor/qcbor_decode.h file
2259*/
2260uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2261 uint32_t uIndex)
2262{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002263 if(pMe->uLastError != QCBOR_SUCCESS) {
2264 return CBOR_TAG_INVALID64;
2265 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002266 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2267 return CBOR_TAG_INVALID64;
2268 } else {
2269 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2270 }
2271}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002272
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002273/*
2274
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002275Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002276
Laurence Lundbladeee851742020-01-08 08:37:05 -08002277 - Hit end of input before it was expected while decoding type and
2278 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002279
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002280 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002281
Laurence Lundbladeee851742020-01-08 08:37:05 -08002282 - Hit end of input while decoding a text or byte string
2283 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002284
Laurence Lundbladeee851742020-01-08 08:37:05 -08002285 - Encountered conflicting tags -- e.g., an item is tagged both a date
2286 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002287
Laurence Lundbladeee851742020-01-08 08:37:05 -08002288 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002289 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002290
Laurence Lundbladeee851742020-01-08 08:37:05 -08002291 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002292 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002293
Laurence Lundbladeee851742020-01-08 08:37:05 -08002294 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2295 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002296
Laurence Lundbladeee851742020-01-08 08:37:05 -08002297 - The type of a map label is not a string or int
2298 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002299
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002300 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002301
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002302 */
2303
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002304
2305
Laurence Lundblade12721ba2020-11-24 22:29:57 -08002306#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002307
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002308/* ===========================================================================
2309 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002310
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002311 This implements a simple sting allocator for indefinite length
2312 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2313 implements the function type QCBORStringAllocate and allows easy
2314 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002315
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002316 This particular allocator is built-in for convenience. The caller
2317 can implement their own. All of this following code will get
2318 dead-stripped if QCBORDecode_SetMemPool() is not called.
2319
2320 This is a very primitive memory allocator. It does not track
2321 individual allocations, only a high-water mark. A free or
2322 reallocation must be of the last chunk allocated.
2323
2324 The size of the pool and offset to free memory are packed into the
2325 first 8 bytes of the memory pool so we don't have to keep them in
2326 the decode context. Since the address of the pool may not be
2327 aligned, they have to be packed and unpacked as if they were
2328 serialized data of the wire or such.
2329
2330 The sizes packed in are uint32_t to be the same on all CPU types
2331 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002332 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002333
2334
Laurence Lundbladeee851742020-01-08 08:37:05 -08002335static inline int
2336MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002337{
2338 // Use of UsefulInputBuf is overkill, but it is convenient.
2339 UsefulInputBuf UIB;
2340
Laurence Lundbladeee851742020-01-08 08:37:05 -08002341 // Just assume the size here. It was checked during SetUp so
2342 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002343 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002344 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2345 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2346 return UsefulInputBuf_GetError(&UIB);
2347}
2348
2349
Laurence Lundbladeee851742020-01-08 08:37:05 -08002350static inline int
2351MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002352{
2353 // Use of UsefulOutBuf is overkill, but convenient. The
2354 // length check performed here is useful.
2355 UsefulOutBuf UOB;
2356
2357 UsefulOutBuf_Init(&UOB, Pool);
2358 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2359 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2360 return UsefulOutBuf_GetError(&UOB);
2361}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002362
2363
2364/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002365 Internal function for an allocation, reallocation free and destuct.
2366
2367 Having only one function rather than one each per mode saves space in
2368 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002369
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002370 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2371 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002372static UsefulBuf
2373MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002374{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002375 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002376
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002377 uint32_t uPoolSize;
2378 uint32_t uFreeOffset;
2379
2380 if(uNewSize > UINT32_MAX) {
2381 // This allocator is only good up to 4GB. This check should
2382 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2383 goto Done;
2384 }
2385 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2386
2387 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2388 goto Done;
2389 }
2390
2391 if(uNewSize) {
2392 if(pMem) {
2393 // REALLOCATION MODE
2394 // Calculate pointer to the end of the memory pool. It is
2395 // assumed that pPool + uPoolSize won't wrap around by
2396 // assuming the caller won't pass a pool buffer in that is
2397 // not in legitimate memory space.
2398 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2399
2400 // Check that the pointer for reallocation is in the range of the
2401 // pool. This also makes sure that pointer math further down
2402 // doesn't wrap under or over.
2403 if(pMem >= pPool && pMem < pPoolEnd) {
2404 // Offset to start of chunk for reallocation. This won't
2405 // wrap under because of check that pMem >= pPool. Cast
2406 // is safe because the pool is always less than UINT32_MAX
2407 // because of check in QCBORDecode_SetMemPool().
2408 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2409
2410 // Check to see if the allocation will fit. uPoolSize -
2411 // uMemOffset will not wrap under because of check that
2412 // pMem is in the range of the uPoolSize by check above.
2413 if(uNewSize <= uPoolSize - uMemOffset) {
2414 ReturnValue.ptr = pMem;
2415 ReturnValue.len = uNewSize;
2416
2417 // Addition won't wrap around over because uNewSize was
2418 // checked to be sure it is less than the pool size.
2419 uFreeOffset = uMemOffset + uNewSize32;
2420 }
2421 }
2422 } else {
2423 // ALLOCATION MODE
2424 // uPoolSize - uFreeOffset will not underflow because this
2425 // pool implementation makes sure uFreeOffset is always
2426 // smaller than uPoolSize through this check here and
2427 // reallocation case.
2428 if(uNewSize <= uPoolSize - uFreeOffset) {
2429 ReturnValue.len = uNewSize;
2430 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002431 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002432 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002433 }
2434 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002435 if(pMem) {
2436 // FREE MODE
2437 // Cast is safe because of limit on pool size in
2438 // QCBORDecode_SetMemPool()
2439 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2440 } else {
2441 // DESTRUCT MODE
2442 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002443 }
2444 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002445
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002446 UsefulBuf Pool = {pPool, uPoolSize};
2447 MemPool_Pack(Pool, uFreeOffset);
2448
2449Done:
2450 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002451}
2452
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002453
Laurence Lundbladef6531662018-12-04 10:42:22 +09002454/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002455 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002456 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002457QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2458 UsefulBuf Pool,
2459 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002460{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002461 // The pool size and free mem offset are packed into the beginning
2462 // of the pool memory. This compile time check make sure the
2463 // constant in the header is correct. This check should optimize
2464 // down to nothing.
2465 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002466 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002467 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002468
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002469 // The pool size and free offset packed in to the beginning of pool
2470 // memory are only 32-bits. This check will optimize out on 32-bit
2471 // machines.
2472 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002473 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002474 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002475
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002476 // This checks that the pool buffer given is big enough.
2477 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002478 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002479 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002480
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002481 pMe->StringAllocator.pfAllocator = MemPool_Function;
2482 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2483 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002484
Laurence Lundblade30816f22018-11-10 13:40:22 +07002485 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002486}
Laurence Lundblade12721ba2020-11-24 22:29:57 -08002487#endif
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002488
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002489
2490
Laurence Lundblade9b334962020-08-27 10:55:53 -07002491static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2492{
2493 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2494}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002495
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002496
2497/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002498 Consume an entire map or array (and do next to
2499 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002500 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002501static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002502ConsumeItem(QCBORDecodeContext *pMe,
2503 const QCBORItem *pItemToConsume,
2504 uint_fast8_t *puNextNestLevel)
2505{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002506 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002507 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002508
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002509 // If it is a map or array, this will tell if it is empty.
2510 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2511
2512 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2513 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002514
Laurence Lundblade1341c592020-04-11 14:19:05 -07002515 /* This works for definite and indefinite length
2516 * maps and arrays by using the nesting level
2517 */
2518 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002519 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002520 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002521 goto Done;
2522 }
2523 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002524
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002525 *puNextNestLevel = Item.uNextNestLevel;
2526
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002527 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002528
Laurence Lundblade1341c592020-04-11 14:19:05 -07002529 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002530 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002531 /* Just pass the nesting level through */
2532 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2533
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002534 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002535 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002536
2537Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002538 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002539}
2540
2541
Laurence Lundblade1341c592020-04-11 14:19:05 -07002542/* Return true if the labels in Item1 and Item2 are the same.
2543 Works only for integer and string labels. Returns false
2544 for any other type. */
2545static inline bool
2546MatchLabel(QCBORItem Item1, QCBORItem Item2)
2547{
2548 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2549 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2550 return true;
2551 }
2552 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002553 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002554 return true;
2555 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002556 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002557 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2558 return true;
2559 }
2560 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2561 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2562 return true;
2563 }
2564 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002565
Laurence Lundblade1341c592020-04-11 14:19:05 -07002566 /* Other label types are never matched */
2567 return false;
2568}
2569
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002570
2571/*
2572 Returns true if Item1 and Item2 are the same type
2573 or if either are of QCBOR_TYPE_ANY.
2574 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002575static inline bool
2576MatchType(QCBORItem Item1, QCBORItem Item2)
2577{
2578 if(Item1.uDataType == Item2.uDataType) {
2579 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002580 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002581 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002582 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002583 return true;
2584 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002585 return false;
2586}
2587
2588
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002589/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002590 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002591
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002592 @param[in] pMe The decode context to search.
2593 @param[in,out] pItemArray The items to search for and the items found.
2594 @param[out] puOffset Byte offset of last item matched.
2595 @param[in] pCBContext Context for the not-found item call back.
2596 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002597
2598 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2599
Laurence Lundblade93d89472020-10-03 22:30:50 -07002600 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2601 were found for one of the labels being
2602 search for. This duplicate detection is
2603 only performed for items in pItemArray,
2604 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002605
Laurence Lundblade93d89472020-10-03 22:30:50 -07002606 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2607 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002608
2609 @retval Also errors returned by QCBORDecode_GetNext().
2610
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002611 On input pItemArray contains a list of labels and data types
2612 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002613
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002614 On output the fully retrieved items are filled in with
2615 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002616
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002617 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002618
2619 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002620 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002621static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002622MapSearch(QCBORDecodeContext *pMe,
2623 QCBORItem *pItemArray,
2624 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002625 void *pCBContext,
2626 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002627{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002628 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002629 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002630
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002631 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002632 uReturn = pMe->uLastError;
2633 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002634 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002635
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002636 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002637 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2638 /* QCBOR_TYPE_NONE as first item indicates just looking
2639 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002640 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2641 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002642 }
2643
Laurence Lundblade085d7952020-07-24 10:26:30 -07002644 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2645 // It is an empty bounded array or map
2646 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2647 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002648 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002649 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002650 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002651 // Nothing is ever found in an empty array or map. All items
2652 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002653 uReturn = QCBOR_SUCCESS;
2654 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002655 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002656 }
2657
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002658 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002659 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2660
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002661 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002662 UsefulInputBuf_Seek(&(pMe->InBuf),
2663 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002664
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002665 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002666 Loop over all the items in the map or array. Each item
2667 could be a map or array, but label matching is only at
2668 the main level. This handles definite and indefinite
2669 length maps and arrays. The only reason this is ever
2670 called on arrays is to find their end position.
2671
2672 This will always run over all items in order to do
2673 duplicate detection.
2674
2675 This will exit with failure if it encounters an
2676 unrecoverable error, but continue on for recoverable
2677 errors.
2678
2679 If a recoverable error occurs on a matched item, then
2680 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002681 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002682 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002683 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002684 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002685 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002686 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002687
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002688 /* Get the item */
2689 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002690 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2691 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002692 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002693 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002694 goto Done;
2695 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002696 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002697 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002698 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002699 goto Done;
2700 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002701
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002702 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002703 bool bMatched = false;
2704 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2705 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002706 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002707 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2708 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002709 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002710 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002711 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002712 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002713 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002714 goto Done;
2715 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002716
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002717 if(uResult != QCBOR_SUCCESS) {
2718 uReturn = uResult;
2719 goto Done;
2720 }
2721
Laurence Lundblade1341c592020-04-11 14:19:05 -07002722 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002723 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002724 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002725 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002726 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002727 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002728 bMatched = true;
2729 }
2730 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002731
2732
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002733 if(!bMatched && pfCallback != NULL) {
2734 /*
2735 Call the callback on unmatched labels.
2736 (It is tempting to do duplicate detection here, but that would
2737 require dynamic memory allocation because the number of labels
2738 that might be encountered is unbounded.)
2739 */
2740 uReturn = (*pfCallback)(pCBContext, &Item);
2741 if(uReturn != QCBOR_SUCCESS) {
2742 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002743 }
2744 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002745
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002746 /*
2747 Consume the item whether matched or not. This
2748 does the work of traversing maps and array and
2749 everything in them. In this loop only the
2750 items at the current nesting level are examined
2751 to match the labels.
2752 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002753 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002754 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002755 goto Done;
2756 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002757
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002758 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002759
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002760 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002761
2762 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002763
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002764 // Check here makes sure that this won't accidentally be
2765 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002766 // QCBOR_MAX_DECODE_INPUT_SIZE.
2767 if(uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
2768 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2769 goto Done;
2770 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002771 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2772 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002773
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002774 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002775 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2776
2777 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002778 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002779 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002780 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002781 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2782 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002783 }
2784 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002785
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002786 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002787}
2788
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002789
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002790/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002791 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002792*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002793void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2794 int64_t nLabel,
2795 uint8_t uQcborType,
2796 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002797{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002798 if(pMe->uLastError != QCBOR_SUCCESS) {
2799 return;
2800 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002801
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002802 QCBORItem OneItemSeach[2];
2803 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2804 OneItemSeach[0].label.int64 = nLabel;
2805 OneItemSeach[0].uDataType = uQcborType;
2806 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002807
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002808 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002809
2810 *pItem = OneItemSeach[0];
2811
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002812 if(uReturn != QCBOR_SUCCESS) {
2813 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002814 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002815 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002816 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002817 }
2818
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002819 Done:
2820 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002821}
2822
2823
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002824/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002825 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002826*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002827void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2828 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002829 uint8_t uQcborType,
2830 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002831{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002832 if(pMe->uLastError != QCBOR_SUCCESS) {
2833 return;
2834 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002835
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002836 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002837 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2838 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2839 OneItemSeach[0].uDataType = uQcborType;
2840 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002841
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002842 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2843 if(uReturn != QCBOR_SUCCESS) {
2844 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002845 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002846 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002847 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002848 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002849 }
2850
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002851 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002852
2853Done:
2854 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002855}
2856
2857
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002858
Laurence Lundblade93d89472020-10-03 22:30:50 -07002859static QCBORError
2860CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002861{
2862 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2863 if(uDataType == puTypeList[i]) {
2864 return QCBOR_SUCCESS;
2865 }
2866 }
2867 return QCBOR_ERR_UNEXPECTED_TYPE;
2868}
2869
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002870
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002871/**
2872 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002873 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002874
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002875 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2876 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002877
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002878 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
2879 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002880 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002881static QCBORError
2882CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002883{
2884 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2885 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2886 /* There are tags that QCBOR couldn't process on this item and
2887 the caller has told us there should not be. */
2888 return QCBOR_ERR_UNEXPECTED_TYPE;
2889 }
2890
2891 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2892 const int nItemType = pItem->uDataType;
2893
2894 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2895 // Must match the tag and only the tag
2896 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2897 }
2898
2899 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2900 if(uReturn == QCBOR_SUCCESS) {
2901 return QCBOR_SUCCESS;
2902 }
2903
2904 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2905 /* Must match the content type and only the content type.
2906 There was no match just above so it is a fail. */
2907 return QCBOR_ERR_UNEXPECTED_TYPE;
2908 }
2909
2910 /* If here it can match either the tag or the content
2911 and it hasn't matched the content, so the end
2912 result is whether it matches the tag. This is
2913 also the case that the CBOR standard discourages. */
2914
2915 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2916}
2917
Laurence Lundblade9b334962020-08-27 10:55:53 -07002918
Laurence Lundblade9b334962020-08-27 10:55:53 -07002919
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002920// This could be semi-private if need be
2921static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002922void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2923 int64_t nLabel,
2924 TagSpecification TagSpec,
2925 QCBORItem *pItem)
2926{
2927 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2928 if(pMe->uLastError != QCBOR_SUCCESS) {
2929 return;
2930 }
2931
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002932 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002933}
2934
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002935
2936// This could be semi-private if need be
2937static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002938void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2939 const char *szLabel,
2940 TagSpecification TagSpec,
2941 QCBORItem *pItem)
2942{
2943 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2944 if(pMe->uLastError != QCBOR_SUCCESS) {
2945 return;
2946 }
2947
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002948 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002949}
2950
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002951// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002952void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2953 int64_t nLabel,
2954 TagSpecification TagSpec,
2955 UsefulBufC *pString)
2956{
2957 QCBORItem Item;
2958 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2959 if(pMe->uLastError == QCBOR_SUCCESS) {
2960 *pString = Item.val.string;
2961 }
2962}
2963
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002964// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002965void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2966 const char * szLabel,
2967 TagSpecification TagSpec,
2968 UsefulBufC *pString)
2969{
2970 QCBORItem Item;
2971 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2972 if(pMe->uLastError == QCBOR_SUCCESS) {
2973 *pString = Item.val.string;
2974 }
2975}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002976
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002977/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002978 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002979*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002980void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002981{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002982 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
2983 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002984}
2985
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002986/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002987 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002988*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002989void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
2990 QCBORItem *pItemList,
2991 void *pCallbackCtx,
2992 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002993{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002994 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
2995 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002996}
2997
2998
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08002999/**
3000 * @brief Search for a map/array by label and enter it
3001 *
3002 * @param[in] pMe The decode context.
3003 * @param[in] pSearch The map/array to search for.
3004 *
3005 * @c pSearch is expected to contain one item of type map or array
3006 * with the label specified. The current bounded map will be searched for
3007 * this and if found will be entered.
3008 *
3009 * If the label is not found, or the item found is not a map or array,
3010 * the error state is set.
3011 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003012static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003013{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003014 // The first item in pSearch is the one that is to be
3015 // entered. It should be the only one filled in. Any other
3016 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003017 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003018 return;
3019 }
3020
3021 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003022 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003023 if(pMe->uLastError != QCBOR_SUCCESS) {
3024 return;
3025 }
3026
Laurence Lundblade9b334962020-08-27 10:55:53 -07003027 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003028 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003029 return;
3030 }
3031
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003032 /*
3033 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3034 * next item for the pre-order traversal cursor to be the map/array
3035 * found by MapSearch(). The next few lines of code force the
3036 * cursor to that.
3037 *
3038 * There is no need to retain the old cursor because
3039 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3040 * beginning of the map/array being entered.
3041 *
3042 * The cursor is forced by: 1) setting the input buffer position to
3043 * the item offset found by MapSearch(), 2) setting the map/array
3044 * counter to the total in the map/array, 3) setting the nesting
3045 * level. Setting the map/array counter to the total is not
3046 * strictly correct, but this is OK because this cursor only needs
3047 * to be used to get one item and MapSearch() has already found it
3048 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003049 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003050 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003051
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003052 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3053
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003054 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003055
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003056 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003057}
3058
3059
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003060/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003061 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003062*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003063void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003064{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003065 QCBORItem OneItemSeach[2];
3066 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3067 OneItemSeach[0].label.int64 = nLabel;
3068 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3069 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003070
Laurence Lundblade9b334962020-08-27 10:55:53 -07003071 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003072 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003073}
3074
3075
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003076/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003077 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003078*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003079void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003080{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003081 QCBORItem OneItemSeach[2];
3082 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3083 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3084 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3085 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003086
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003087 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003088}
3089
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003090/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003091 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003092*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003093void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003094{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003095 QCBORItem OneItemSeach[2];
3096 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3097 OneItemSeach[0].label.int64 = nLabel;
3098 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3099 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003100
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003101 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003102}
3103
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003104/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003105 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003106*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003107void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3108{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003109 QCBORItem OneItemSeach[2];
3110 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3111 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3112 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3113 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003114
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003115 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003116}
3117
3118
Laurence Lundblade02625d42020-06-25 14:41:41 -07003119// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003120void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003121{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003122 QCBORError uErr;
3123
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003124 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003125 if(pMe->uLastError != QCBOR_SUCCESS) {
3126 // Already in error state; do nothing.
3127 return;
3128 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003129
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003130 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003131 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003132 uErr = QCBORDecode_GetNext(pMe, &Item);
3133 if(uErr != QCBOR_SUCCESS) {
3134 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003135 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003136 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003137 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3138 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003139 }
3140
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003141 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003142
3143
Laurence Lundbladef0499502020-08-01 11:55:57 -07003144 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003145 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003146 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3147 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003148 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003149 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3150 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003151 // Special case to increment nesting level for zero-length maps
3152 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003153 DecodeNesting_Descend(&(pMe->nesting), uType);
3154 }
3155
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003156 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003157
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003158 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3159 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003160
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003161 if(pItem != NULL) {
3162 *pItem = Item;
3163 }
3164
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003165Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003166 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003167}
3168
Laurence Lundblade02625d42020-06-25 14:41:41 -07003169
3170/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003171 This is the common work for exiting a level that is a bounded map,
3172 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003173
3174 One chunk of work is to set up the pre-order traversal so it is at
3175 the item just after the bounded map, array or bstr that is being
3176 exited. This is somewhat complex.
3177
3178 The other work is to level-up the bounded mode to next higest bounded
3179 mode or the top level if there isn't one.
3180 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003181static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003182ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003183{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003184 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003185
Laurence Lundblade02625d42020-06-25 14:41:41 -07003186 /*
3187 First the pre-order-traversal byte offset is positioned to the
3188 item just after the bounded mode item that was just consumed.
3189 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003190 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3191
Laurence Lundblade02625d42020-06-25 14:41:41 -07003192 /*
3193 Next, set the current nesting level to one above the bounded level
3194 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003195
Laurence Lundblade02625d42020-06-25 14:41:41 -07003196 DecodeNesting_CheckBoundedType() is always called before this and
3197 makes sure pCurrentBounded is valid.
3198 */
3199 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3200
3201 /*
3202 This does the complex work of leveling up the pre-order traversal
3203 when the end of a map or array or another bounded level is
3204 reached. It may do nothing, or ascend all the way to the top
3205 level.
3206 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003207 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003208 if(uErr != QCBOR_SUCCESS) {
3209 goto Done;
3210 }
3211
Laurence Lundblade02625d42020-06-25 14:41:41 -07003212 /*
3213 This makes the next highest bounded level the current bounded
3214 level. If there is no next highest level, then no bounded mode is
3215 in effect.
3216 */
3217 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003218
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003219 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003220
3221Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003222 return uErr;
3223}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003224
Laurence Lundblade02625d42020-06-25 14:41:41 -07003225
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003226// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003227void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003228{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003229 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003230 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003231 return;
3232 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003233
Laurence Lundblade02625d42020-06-25 14:41:41 -07003234 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003235
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003236 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003237 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003238 goto Done;
3239 }
3240
Laurence Lundblade02625d42020-06-25 14:41:41 -07003241 /*
3242 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003243 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003244 from previous map search, then do a dummy search.
3245 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003246 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003247 QCBORItem Dummy;
3248 Dummy.uLabelType = QCBOR_TYPE_NONE;
3249 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3250 if(uErr != QCBOR_SUCCESS) {
3251 goto Done;
3252 }
3253 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003254
Laurence Lundblade02625d42020-06-25 14:41:41 -07003255 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003256
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003257Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003258 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003259}
3260
3261
Laurence Lundblade1341c592020-04-11 14:19:05 -07003262
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003263static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003264 const QCBORItem *pItem,
3265 uint8_t uTagRequirement,
3266 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003267{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003268 if(pBstr) {
3269 *pBstr = NULLUsefulBufC;
3270 }
3271
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003272 if(pMe->uLastError != QCBOR_SUCCESS) {
3273 // Already in error state; do nothing.
3274 return pMe->uLastError;
3275 }
3276
3277 QCBORError uError = QCBOR_SUCCESS;
3278
3279 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3280 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3281 goto Done;;
3282 }
3283
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003284 const TagSpecification TagSpec =
3285 {
3286 uTagRequirement,
3287 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3288 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3289 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003290
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003291 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003292 if(uError != QCBOR_SUCCESS) {
3293 goto Done;
3294 }
3295
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003296 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003297 // Reverse the decrement done by GetNext() for the bstr so the
3298 // increment in NestLevelAscender() called by ExitBoundedLevel()
3299 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003300 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003301 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003302
3303 if(pBstr) {
3304 *pBstr = pItem->val.string;
3305 }
3306
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003307 // This saves the current length of the UsefulInputBuf and then
3308 // narrows the UsefulInputBuf to start and length of the wrapped
3309 // CBOR that is being entered.
3310 //
3311 // This makes sure the length is less than
3312 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3313 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3314 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3315 // the casts safe. uEndOfBstr will always be less than
3316 // uPreviousLength because of the way UsefulInputBuf works so there
3317 // is no need to check it. There is also a range check in the
3318 // seek.
3319 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003320 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003321 // amount to much code.
3322 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3323 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003324 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003325 goto Done;
3326 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003327 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003328 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003329 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003330
Laurence Lundblade02625d42020-06-25 14:41:41 -07003331 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003332 (uint32_t)uPreviousLength,
3333 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003334Done:
3335 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003336}
3337
3338
Laurence Lundblade02625d42020-06-25 14:41:41 -07003339/*
3340 Public function, see header qcbor/qcbor_decode.h file
3341 */
3342void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003343 uint8_t uTagRequirement,
3344 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003345{
3346 if(pMe->uLastError != QCBOR_SUCCESS) {
3347 // Already in error state; do nothing.
3348 return;
3349 }
3350
3351 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003352 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003353 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3354 if(pMe->uLastError != QCBOR_SUCCESS) {
3355 return;
3356 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003357
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003358 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003359 &Item,
3360 uTagRequirement,
3361 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003362}
3363
3364
Laurence Lundblade02625d42020-06-25 14:41:41 -07003365/*
3366 Public function, see header qcbor/qcbor_decode.h file
3367 */
3368void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003369 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003370 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003371 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003372{
3373 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003374 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003375
Laurence Lundblade93d89472020-10-03 22:30:50 -07003376 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3377 &Item,
3378 uTagRequirement,
3379 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003380}
3381
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003382
Laurence Lundblade02625d42020-06-25 14:41:41 -07003383/*
3384 Public function, see header qcbor/qcbor_decode.h file
3385 */
3386void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003387 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003388 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003389 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003390{
3391 QCBORItem Item;
3392 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3393
Laurence Lundblade93d89472020-10-03 22:30:50 -07003394 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3395 &Item,
3396 uTagRequirement,
3397 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003398}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003399
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003400
Laurence Lundblade02625d42020-06-25 14:41:41 -07003401/*
3402 Public function, see header qcbor/qcbor_decode.h file
3403 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003404void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003405{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003406 if(pMe->uLastError != QCBOR_SUCCESS) {
3407 // Already in error state; do nothing.
3408 return;
3409 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003410
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003411 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003412 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003413 return;
3414 }
3415
3416 /*
3417 Reset the length of the UsefulInputBuf to what it was before
3418 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003419 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003420 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003421 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003422
3423
Laurence Lundblade02625d42020-06-25 14:41:41 -07003424 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003425 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003426}
3427
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003428
Laurence Lundbladee6430642020-03-14 21:15:44 -07003429
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003430
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003431
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003432
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003433
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003434
Laurence Lundblade93d89472020-10-03 22:30:50 -07003435static QCBORError
3436InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003437{
3438 switch(pItem->uDataType) {
3439 case QCBOR_TYPE_TRUE:
3440 *pBool = true;
3441 return QCBOR_SUCCESS;
3442 break;
3443
3444 case QCBOR_TYPE_FALSE:
3445 *pBool = false;
3446 return QCBOR_SUCCESS;
3447 break;
3448
3449 default:
3450 return QCBOR_ERR_UNEXPECTED_TYPE;
3451 break;
3452 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003453 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003454}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003455
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003456
Laurence Lundblade9b334962020-08-27 10:55:53 -07003457
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003458/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003459 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003460*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003461void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003462{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003463 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003464 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003465 return;
3466 }
3467
Laurence Lundbladec4537442020-04-14 18:53:22 -07003468 QCBORError nError;
3469 QCBORItem Item;
3470
3471 nError = QCBORDecode_GetNext(pMe, &Item);
3472 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003473 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003474 return;
3475 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003476 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003477}
3478
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003479
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003480/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003481 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003482*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003483void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003484{
3485 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003486 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003487
Laurence Lundblade9b334962020-08-27 10:55:53 -07003488 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003489}
3490
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003491
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003492/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003493 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003494*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003495void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3496{
3497 QCBORItem Item;
3498 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3499
Laurence Lundblade9b334962020-08-27 10:55:53 -07003500 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003501}
3502
3503
3504
Laurence Lundbladec7114722020-08-13 05:11:40 -07003505
3506static void ProcessEpochDate(QCBORDecodeContext *pMe,
3507 QCBORItem *pItem,
3508 uint8_t uTagRequirement,
3509 int64_t *pnTime)
3510{
3511 if(pMe->uLastError != QCBOR_SUCCESS) {
3512 // Already in error state, do nothing
3513 return;
3514 }
3515
3516 QCBORError uErr;
3517
3518 const TagSpecification TagSpec =
3519 {
3520 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003521 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3522 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003523 };
3524
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003525 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003526 if(uErr != QCBOR_SUCCESS) {
3527 goto Done;
3528 }
3529
3530 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3531 uErr = DecodeDateEpoch(pItem);
3532 if(uErr != QCBOR_SUCCESS) {
3533 goto Done;
3534 }
3535 }
3536
Laurence Lundblade9b334962020-08-27 10:55:53 -07003537 // Save the tags in the last item's tags in the decode context
3538 // for QCBORDecode_GetNthTagOfLast()
3539 CopyTags(pMe, pItem);
3540
Laurence Lundbladec7114722020-08-13 05:11:40 -07003541 *pnTime = pItem->val.epochDate.nSeconds;
3542
3543Done:
3544 pMe->uLastError = (uint8_t)uErr;
3545}
3546
3547
3548void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003549 uint8_t uTagRequirement,
3550 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003551{
3552 if(pMe->uLastError != QCBOR_SUCCESS) {
3553 // Already in error state, do nothing
3554 return;
3555 }
3556
3557 QCBORItem Item;
3558 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3559
3560 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3561}
3562
3563
3564void
3565QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3566 int64_t nLabel,
3567 uint8_t uTagRequirement,
3568 int64_t *pnTime)
3569{
3570 QCBORItem Item;
3571 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3572 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3573}
3574
3575
3576void
3577QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3578 const char *szLabel,
3579 uint8_t uTagRequirement,
3580 int64_t *pnTime)
3581{
3582 QCBORItem Item;
3583 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3584 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3585}
3586
3587
3588
3589
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003590void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3591 TagSpecification TagSpec,
3592 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003593{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003594 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003595 // Already in error state, do nothing
3596 return;
3597 }
3598
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003599 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003600 QCBORItem Item;
3601
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003602 uError = QCBORDecode_GetNext(pMe, &Item);
3603 if(uError != QCBOR_SUCCESS) {
3604 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003605 return;
3606 }
3607
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003608 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003609
3610 if(pMe->uLastError == QCBOR_SUCCESS) {
3611 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003612 } else {
3613 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003614 }
3615}
3616
Laurence Lundbladec4537442020-04-14 18:53:22 -07003617
3618
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003619
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003620static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003621 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003622 UsefulBufC *pValue,
3623 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003624{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003625 const TagSpecification TagSpec =
3626 {
3627 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003628 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3629 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003630 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003631
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003632 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003633 if(uErr != QCBOR_SUCCESS) {
3634 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003635 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003636
3637 *pValue = pItem->val.string;
3638
3639 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3640 *pbIsNegative = false;
3641 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3642 *pbIsNegative = true;
3643 }
3644
3645 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003646}
3647
3648
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003649/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003650 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003651 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003652void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3653 uint8_t uTagRequirement,
3654 UsefulBufC *pValue,
3655 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003656{
3657 if(pMe->uLastError != QCBOR_SUCCESS) {
3658 // Already in error state, do nothing
3659 return;
3660 }
3661
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003662 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003663 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3664 if(uError != QCBOR_SUCCESS) {
3665 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003666 return;
3667 }
3668
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003669 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003670}
3671
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003672
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003673/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003674 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003675*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003676void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3677 int64_t nLabel,
3678 uint8_t uTagRequirement,
3679 UsefulBufC *pValue,
3680 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003681{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003682 QCBORItem Item;
3683 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003684 if(pMe->uLastError != QCBOR_SUCCESS) {
3685 return;
3686 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003687
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003688 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003689}
3690
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003691
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003692/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003693 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003694*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003695void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3696 const char *szLabel,
3697 uint8_t uTagRequirement,
3698 UsefulBufC *pValue,
3699 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003700{
3701 QCBORItem Item;
3702 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003703 if(pMe->uLastError != QCBOR_SUCCESS) {
3704 return;
3705 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003706
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003707 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003708}
3709
3710
3711
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003712
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003713// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003714QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3715 const QCBORItem *pItem,
3716 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003717 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003718{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003719 const TagSpecification TagSpecText =
3720 {
3721 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003722 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3723 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003724 };
3725 const TagSpecification TagSpecBinary =
3726 {
3727 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003728 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3729 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003730 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003731
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003732 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003733
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003734 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003735 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003736 if(pbIsTag257 != NULL) {
3737 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003738 }
3739 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003740 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003741 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003742 if(pbIsTag257 != NULL) {
3743 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003744 }
3745 uReturn = QCBOR_SUCCESS;
3746
3747 } else {
3748 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3749 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003750
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003751 return uReturn;
3752}
3753
Laurence Lundblade93d89472020-10-03 22:30:50 -07003754// Improvement: add methods for wrapped CBOR, a simple alternate
3755// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003756
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003757
3758
3759
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003760#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003761
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003762typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003763
3764
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003765// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003766static QCBORError
3767Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003768{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003769 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003770
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003771 if(uResult != 0) {
3772 /* This loop will run a maximum of 19 times because
3773 * UINT64_MAX < 10 ^^ 19. More than that will cause
3774 * exit with the overflow error
3775 */
3776 for(; nExponent > 0; nExponent--) {
3777 if(uResult > UINT64_MAX / 10) {
3778 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3779 }
3780 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003781 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003782
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003783 for(; nExponent < 0; nExponent++) {
3784 uResult = uResult / 10;
3785 if(uResult == 0) {
3786 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3787 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003788 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003789 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003790 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003791
3792 *puResult = uResult;
3793
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003794 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003795}
3796
3797
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003798// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003799static QCBORError
3800Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003801{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003802 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003803
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003804 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003805
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003806 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003807 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003808 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003809 */
3810 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003811 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003812 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003813 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003814 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003815 nExponent--;
3816 }
3817
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003818 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003819 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003820 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3821 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003822 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003823 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003824 }
3825
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003826 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003827
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003828 return QCBOR_SUCCESS;
3829}
3830
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003831
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003832/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003833 Compute value with signed mantissa and signed result. Works with
3834 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003835 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003836static inline QCBORError ExponentiateNN(int64_t nMantissa,
3837 int64_t nExponent,
3838 int64_t *pnResult,
3839 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003840{
3841 uint64_t uResult;
3842
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003843 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003844 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003845 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3846
3847 // Do the exponentiation of the positive mantissa
3848 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3849 if(uReturn) {
3850 return uReturn;
3851 }
3852
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003853
Laurence Lundblade983500d2020-05-14 11:49:34 -07003854 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3855 of INT64_MIN. This assumes two's compliment representation where
3856 INT64_MIN is one increment farther from 0 than INT64_MAX.
3857 Trying to write -INT64_MIN doesn't work to get this because the
3858 compiler tries to work with an int64_t which can't represent
3859 -INT64_MIN.
3860 */
3861 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3862
3863 // Error out if too large
3864 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003865 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3866 }
3867
3868 // Casts are safe because of checks above
3869 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3870
3871 return QCBOR_SUCCESS;
3872}
3873
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003874
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003875/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003876 Compute value with signed mantissa and unsigned result. Works with
3877 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003878 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003879static inline QCBORError ExponentitateNU(int64_t nMantissa,
3880 int64_t nExponent,
3881 uint64_t *puResult,
3882 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003883{
3884 if(nMantissa < 0) {
3885 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3886 }
3887
3888 // Cast to unsigned is OK because of check for negative
3889 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3890 // Exponentiation is straight forward
3891 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3892}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003893
3894
3895/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003896 Compute value with signed mantissa and unsigned result. Works with
3897 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003898 */
3899static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3900 int64_t nExponent,
3901 uint64_t *puResult,
3902 fExponentiator pfExp)
3903{
3904 return (*pfExp)(uMantissa, nExponent, puResult);
3905}
3906
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003907#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3908
3909
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003910
3911
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003912
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003913static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003914{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003915 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003916
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003917 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003918 const uint8_t *pByte = BigNum.ptr;
3919 size_t uLen = BigNum.len;
3920 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003921 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003922 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003923 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003924 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003925 }
3926
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003927 *pResult = uResult;
3928 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003929}
3930
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003931
Laurence Lundblade887add82020-05-17 05:50:34 -07003932static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003933{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003934 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003935}
3936
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003937
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003938static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003939{
3940 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003941 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3942 if(uError) {
3943 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003944 }
3945 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3946 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003947 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003948}
3949
3950
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003951static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003952{
3953 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003954 /* The negative integer furthest from zero for a C int64_t is
3955 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3956 negative number in CBOR is computed as -n - 1 where n is the
3957 encoded integer, where n is what is in the variable BigNum. When
3958 converting BigNum to a uint64_t, the maximum value is thus
3959 INT64_MAX, so that when it -n - 1 is applied to it the result will
3960 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003961
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003962 -n - 1 <= INT64_MIN.
3963 -n - 1 <= -INT64_MAX - 1
3964 n <= INT64_MAX.
3965 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003966 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003967 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003968 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003969 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003970
3971 /// Now apply -n - 1. The cast is safe because
3972 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3973 // is the largest positive integer that an int64_t can
3974 // represent. */
3975 *pnResult = -(int64_t)uResult - 1;
3976
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003977 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003978}
3979
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003980
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003981
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003982
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003983
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003984/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003985Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003986
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003987\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003988
Laurence Lundblade93d89472020-10-03 22:30:50 -07003989\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
3990 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003991
3992\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3993
Laurence Lundblade93d89472020-10-03 22:30:50 -07003994\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
3995 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003996*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07003997static QCBORError
3998ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003999{
4000 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004001 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004002 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004003#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004004 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004005 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4006 http://www.cplusplus.com/reference/cmath/llround/
4007 */
4008 // Not interested in FE_INEXACT
4009 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004010 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4011 *pnValue = llround(pItem->val.dfnum);
4012 } else {
4013 *pnValue = lroundf(pItem->val.fnum);
4014 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004015 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4016 // llround() shouldn't result in divide by zero, but catch
4017 // it here in case it unexpectedly does. Don't try to
4018 // distinguish between the various exceptions because it seems
4019 // they vary by CPU, compiler and OS.
4020 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004021 }
4022 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004023 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004024 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004025#else
4026 return QCBOR_ERR_HW_FLOAT_DISABLED;
4027#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004028 break;
4029
4030 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004031 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004032 *pnValue = pItem->val.int64;
4033 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004034 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004035 }
4036 break;
4037
4038 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004039 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004040 if(pItem->val.uint64 < INT64_MAX) {
4041 *pnValue = pItem->val.int64;
4042 } else {
4043 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4044 }
4045 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004046 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004047 }
4048 break;
4049
4050 default:
4051 return QCBOR_ERR_UNEXPECTED_TYPE;
4052 }
4053 return QCBOR_SUCCESS;
4054}
4055
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004056
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004057void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004058 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004059 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004060 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004061{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004062 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004063 return;
4064 }
4065
Laurence Lundbladee6430642020-03-14 21:15:44 -07004066 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004067 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4068 if(uError) {
4069 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004070 return;
4071 }
4072
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004073 if(pItem) {
4074 *pItem = Item;
4075 }
4076
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004077 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004078}
4079
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004080
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004081void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4082 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004083 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004084 int64_t *pnValue,
4085 QCBORItem *pItem)
4086{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004087 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004088 if(pMe->uLastError != QCBOR_SUCCESS) {
4089 return;
4090 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004091
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004092 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004093}
4094
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004095
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004096void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4097 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004098 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004099 int64_t *pnValue,
4100 QCBORItem *pItem)
4101{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004102 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004103 if(pMe->uLastError != QCBOR_SUCCESS) {
4104 return;
4105 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004106
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004107 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004108}
4109
4110
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004111/*
4112 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004113
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004114 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004115
Laurence Lundblade93d89472020-10-03 22:30:50 -07004116 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4117 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004118
4119 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4120
Laurence Lundblade93d89472020-10-03 22:30:50 -07004121 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4122 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004123 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004124static QCBORError
4125Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004126{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004127 switch(pItem->uDataType) {
4128
4129 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004130 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004131 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004132 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004133 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004134 }
4135 break;
4136
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004137 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004138 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004139 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004140 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004141 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004142 }
4143 break;
4144
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004145#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4146 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004147 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004148 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004149 pItem->val.expAndMantissa.nExponent,
4150 pnValue,
4151 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004152 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004153 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004154 }
4155 break;
4156
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004157 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004158 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004159 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004160 pItem->val.expAndMantissa.nExponent,
4161 pnValue,
4162 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004163 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004164 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004165 }
4166 break;
4167
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004168 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004169 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004170 int64_t nMantissa;
4171 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004172 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4173 if(uErr) {
4174 return uErr;
4175 }
4176 return ExponentiateNN(nMantissa,
4177 pItem->val.expAndMantissa.nExponent,
4178 pnValue,
4179 Exponentitate10);
4180 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004181 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004182 }
4183 break;
4184
4185 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004186 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004187 int64_t nMantissa;
4188 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004189 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4190 if(uErr) {
4191 return uErr;
4192 }
4193 return ExponentiateNN(nMantissa,
4194 pItem->val.expAndMantissa.nExponent,
4195 pnValue,
4196 Exponentitate10);
4197 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004198 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004199 }
4200 break;
4201
4202 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004203 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004204 int64_t nMantissa;
4205 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004206 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4207 if(uErr) {
4208 return uErr;
4209 }
4210 return ExponentiateNN(nMantissa,
4211 pItem->val.expAndMantissa.nExponent,
4212 pnValue,
4213 Exponentitate2);
4214 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004215 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004216 }
4217 break;
4218
4219 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004220 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004221 int64_t nMantissa;
4222 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004223 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4224 if(uErr) {
4225 return uErr;
4226 }
4227 return ExponentiateNN(nMantissa,
4228 pItem->val.expAndMantissa.nExponent,
4229 pnValue,
4230 Exponentitate2);
4231 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004232 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004233 }
4234 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004235#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4236
Laurence Lundbladee6430642020-03-14 21:15:44 -07004237
Laurence Lundbladec4537442020-04-14 18:53:22 -07004238 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004239 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004240}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004241
4242
Laurence Lundbladec4537442020-04-14 18:53:22 -07004243/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004244 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004245 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004246void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004247{
4248 QCBORItem Item;
4249
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004250 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004251
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004252 if(pMe->uLastError == QCBOR_SUCCESS) {
4253 // The above conversion succeeded
4254 return;
4255 }
4256
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004257 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004258 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004259 return;
4260 }
4261
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004262 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004263}
4264
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004265
4266/*
4267Public function, see header qcbor/qcbor_decode.h file
4268*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004269void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4270 int64_t nLabel,
4271 uint32_t uConvertTypes,
4272 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004273{
4274 QCBORItem Item;
4275
Laurence Lundblade93d89472020-10-03 22:30:50 -07004276 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4277 nLabel,
4278 uConvertTypes,
4279 pnValue,
4280 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004281
4282 if(pMe->uLastError == QCBOR_SUCCESS) {
4283 // The above conversion succeeded
4284 return;
4285 }
4286
4287 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4288 // The above conversion failed in a way that code below can't correct
4289 return;
4290 }
4291
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004292 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004293}
4294
4295
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004296/*
4297Public function, see header qcbor/qcbor_decode.h file
4298*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004299void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4300 const char *szLabel,
4301 uint32_t uConvertTypes,
4302 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004303{
4304 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004305 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4306 szLabel,
4307 uConvertTypes,
4308 pnValue,
4309 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004310
4311 if(pMe->uLastError == QCBOR_SUCCESS) {
4312 // The above conversion succeeded
4313 return;
4314 }
4315
4316 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4317 // The above conversion failed in a way that code below can't correct
4318 return;
4319 }
4320
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004321 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004322}
4323
4324
Laurence Lundblade93d89472020-10-03 22:30:50 -07004325static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004326{
4327 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004328 case QCBOR_TYPE_DOUBLE:
4329 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004330#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004331 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004332 // Can't use llround here because it will not convert values
4333 // greater than INT64_MAX and less than UINT64_MAX that
4334 // need to be converted so it is more complicated.
4335 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4336 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4337 if(isnan(pItem->val.dfnum)) {
4338 return QCBOR_ERR_FLOAT_EXCEPTION;
4339 } else if(pItem->val.dfnum < 0) {
4340 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4341 } else {
4342 double dRounded = round(pItem->val.dfnum);
4343 // See discussion in DecodeDateEpoch() for
4344 // explanation of - 0x7ff
4345 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4346 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4347 }
4348 *puValue = (uint64_t)dRounded;
4349 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004350 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004351 if(isnan(pItem->val.fnum)) {
4352 return QCBOR_ERR_FLOAT_EXCEPTION;
4353 } else if(pItem->val.fnum < 0) {
4354 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4355 } else {
4356 float fRounded = roundf(pItem->val.fnum);
4357 // See discussion in DecodeDateEpoch() for
4358 // explanation of - 0x7ff
4359 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4360 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4361 }
4362 *puValue = (uint64_t)fRounded;
4363 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004364 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004365 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4366 // round() and roundf() shouldn't result in exceptions here, but
4367 // catch them to be robust and thorough. Don't try to
4368 // distinguish between the various exceptions because it seems
4369 // they vary by CPU, compiler and OS.
4370 return QCBOR_ERR_FLOAT_EXCEPTION;
4371 }
4372
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004373 } else {
4374 return QCBOR_ERR_UNEXPECTED_TYPE;
4375 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004376#else
4377 return QCBOR_ERR_HW_FLOAT_DISABLED;
4378#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004379 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004380
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004381 case QCBOR_TYPE_INT64:
4382 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4383 if(pItem->val.int64 >= 0) {
4384 *puValue = (uint64_t)pItem->val.int64;
4385 } else {
4386 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4387 }
4388 } else {
4389 return QCBOR_ERR_UNEXPECTED_TYPE;
4390 }
4391 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004392
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004393 case QCBOR_TYPE_UINT64:
4394 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4395 *puValue = pItem->val.uint64;
4396 } else {
4397 return QCBOR_ERR_UNEXPECTED_TYPE;
4398 }
4399 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004400
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004401 default:
4402 return QCBOR_ERR_UNEXPECTED_TYPE;
4403 }
4404
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004405 return QCBOR_SUCCESS;
4406}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004407
4408
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004409void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004410 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004411 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004412 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004413{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004414 if(pMe->uLastError != QCBOR_SUCCESS) {
4415 return;
4416 }
4417
Laurence Lundbladec4537442020-04-14 18:53:22 -07004418 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004419
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004420 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4421 if(uError) {
4422 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004423 return;
4424 }
4425
Laurence Lundbladea826c502020-05-10 21:07:00 -07004426 if(pItem) {
4427 *pItem = Item;
4428 }
4429
Laurence Lundblade93d89472020-10-03 22:30:50 -07004430 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004431}
4432
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004433
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004434void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004435 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004436 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004437 uint64_t *puValue,
4438 QCBORItem *pItem)
4439{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004440 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004441 if(pMe->uLastError != QCBOR_SUCCESS) {
4442 return;
4443 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004444
Laurence Lundblade93d89472020-10-03 22:30:50 -07004445 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004446}
4447
4448
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004449void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004450 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004451 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004452 uint64_t *puValue,
4453 QCBORItem *pItem)
4454{
4455 if(pMe->uLastError != QCBOR_SUCCESS) {
4456 return;
4457 }
4458
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004459 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004460 if(pMe->uLastError != QCBOR_SUCCESS) {
4461 return;
4462 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004463
Laurence Lundblade93d89472020-10-03 22:30:50 -07004464 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004465}
4466
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004467
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004468
Laurence Lundblade93d89472020-10-03 22:30:50 -07004469static QCBORError
4470UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004471{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004472 switch(pItem->uDataType) {
4473
4474 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004475 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004476 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4477 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004478 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004479 }
4480 break;
4481
4482 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004483 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004484 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
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#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4491
4492 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004493 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004494 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004495 pItem->val.expAndMantissa.nExponent,
4496 puValue,
4497 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004498 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004499 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004500 }
4501 break;
4502
4503 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004504 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004505 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4506 pItem->val.expAndMantissa.nExponent,
4507 puValue,
4508 Exponentitate2);
4509 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004510 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004511 }
4512 break;
4513
4514 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004515 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004516 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004517 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004518 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004519 if(uErr != QCBOR_SUCCESS) {
4520 return uErr;
4521 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004522 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004523 pItem->val.expAndMantissa.nExponent,
4524 puValue,
4525 Exponentitate10);
4526 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004527 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004528 }
4529 break;
4530
4531 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004532 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004533 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4534 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004535 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004536 }
4537 break;
4538
4539 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004540 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004541 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004542 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004543 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004544 if(uErr != QCBOR_SUCCESS) {
4545 return uErr;
4546 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004547 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004548 pItem->val.expAndMantissa.nExponent,
4549 puValue,
4550 Exponentitate2);
4551 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004552 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004553 }
4554 break;
4555
4556 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004557 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004558 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4559 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004560 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004561 }
4562 break;
4563#endif
4564 default:
4565 return QCBOR_ERR_UNEXPECTED_TYPE;
4566 }
4567}
4568
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004569
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004570/*
4571 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004572 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004573void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004574{
4575 QCBORItem Item;
4576
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004577 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004578
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004579 if(pMe->uLastError == QCBOR_SUCCESS) {
4580 // The above conversion succeeded
4581 return;
4582 }
4583
4584 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4585 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004586 return;
4587 }
4588
Laurence Lundblade93d89472020-10-03 22:30:50 -07004589 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004590}
4591
Laurence Lundbladec4537442020-04-14 18:53:22 -07004592
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004593/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004594 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004595*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004596void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004597 int64_t nLabel,
4598 uint32_t uConvertTypes,
4599 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004600{
4601 QCBORItem Item;
4602
Laurence Lundblade93d89472020-10-03 22:30:50 -07004603 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4604 nLabel,
4605 uConvertTypes,
4606 puValue,
4607 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004608
4609 if(pMe->uLastError == QCBOR_SUCCESS) {
4610 // The above conversion succeeded
4611 return;
4612 }
4613
4614 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4615 // The above conversion failed in a way that code below can't correct
4616 return;
4617 }
4618
Laurence Lundblade93d89472020-10-03 22:30:50 -07004619 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004620}
4621
4622
4623/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004624 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004625*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004626void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004627 const char *szLabel,
4628 uint32_t uConvertTypes,
4629 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004630{
4631 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004632 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4633 szLabel,
4634 uConvertTypes,
4635 puValue,
4636 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004637
4638 if(pMe->uLastError == QCBOR_SUCCESS) {
4639 // The above conversion succeeded
4640 return;
4641 }
4642
4643 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4644 // The above conversion failed in a way that code below can't correct
4645 return;
4646 }
4647
Laurence Lundblade93d89472020-10-03 22:30:50 -07004648 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004649}
4650
4651
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004652
4653
Laurence Lundblade9b334962020-08-27 10:55:53 -07004654static QCBORError ConvertDouble(const QCBORItem *pItem,
4655 uint32_t uConvertTypes,
4656 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004657{
4658 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004659 case QCBOR_TYPE_FLOAT:
4660#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4661 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4662 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004663 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004664 *pdValue = (double)pItem->val.fnum;
4665 } else {
4666 return QCBOR_ERR_UNEXPECTED_TYPE;
4667 }
4668 }
4669#else
4670 return QCBOR_ERR_HW_FLOAT_DISABLED;
4671#endif
4672 break;
4673
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004674 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004675 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4676 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004677 *pdValue = pItem->val.dfnum;
4678 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004679 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004680 }
4681 }
4682 break;
4683
4684 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004685#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004686 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004687 // A simple cast seems to do the job with no worry of exceptions.
4688 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004689 *pdValue = (double)pItem->val.int64;
4690
4691 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004692 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004693 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004694#else
4695 return QCBOR_ERR_HW_FLOAT_DISABLED;
4696#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004697 break;
4698
4699 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004700#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004701 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004702 // A simple cast seems to do the job with no worry of exceptions.
4703 // There will be precision loss for some values.
4704 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004705 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004706 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004707 }
4708 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004709#else
4710 return QCBOR_ERR_HW_FLOAT_DISABLED;
4711#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004712
4713 default:
4714 return QCBOR_ERR_UNEXPECTED_TYPE;
4715 }
4716
4717 return QCBOR_SUCCESS;
4718}
4719
4720
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004721void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004722 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004723 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004724 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004725{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004726 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004727 return;
4728 }
4729
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004730 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004731
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004732 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004733 if(uError) {
4734 pMe->uLastError = (uint8_t)uError;
4735 return;
4736 }
4737
4738 if(pItem) {
4739 *pItem = Item;
4740 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004741
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004742 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004743}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004744
Laurence Lundbladec4537442020-04-14 18:53:22 -07004745
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004746void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4747 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004748 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004749 double *pdValue,
4750 QCBORItem *pItem)
4751{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004752 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004753 if(pMe->uLastError != QCBOR_SUCCESS) {
4754 return;
4755 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004756
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004757 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004758}
4759
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004760
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004761void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4762 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004763 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004764 double *pdValue,
4765 QCBORItem *pItem)
4766{
4767 if(pMe->uLastError != QCBOR_SUCCESS) {
4768 return;
4769 }
4770
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004771 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004772 if(pMe->uLastError != QCBOR_SUCCESS) {
4773 return;
4774 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004775
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004776 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004777}
4778
4779
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004780#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004781static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4782{
4783 double dResult;
4784
4785 dResult = 0.0;
4786 const uint8_t *pByte = BigNum.ptr;
4787 size_t uLen = BigNum.len;
4788 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004789 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004790 while(uLen--) {
4791 dResult = (dResult * 256.0) + (double)*pByte++;
4792 }
4793
4794 return dResult;
4795}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004796#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4797
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004798
Laurence Lundblade93d89472020-10-03 22:30:50 -07004799static QCBORError
4800DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004801{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004802#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004803 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004804 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4805
4806 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004807 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004808
4809#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004810 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004811 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004812 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004813 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4814 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4815 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004816 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004817 }
4818 break;
4819
4820 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004821 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004822 // Underflow gives 0, overflow gives infinity
4823 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4824 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004825 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004826 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004827 }
4828 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004829#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004830
4831 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004832 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004833 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4834 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004835 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004836 }
4837 break;
4838
4839 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004840 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004841 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004842 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004843 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004844 }
4845 break;
4846
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004847#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004848 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004849 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004850 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4851 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4852 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004853 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004854 }
4855 break;
4856
4857 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004858 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004859 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4860 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4861 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004862 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004863 }
4864 break;
4865
4866 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004867 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004868 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4869 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4870 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004871 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004872 }
4873 break;
4874
4875 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004876 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004877 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004878 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4879 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004880 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004881 }
4882 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004883#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4884
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004885 default:
4886 return QCBOR_ERR_UNEXPECTED_TYPE;
4887 }
4888
4889 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004890
4891#else
4892 (void)pItem;
4893 (void)uConvertTypes;
4894 (void)pdValue;
4895 return QCBOR_ERR_HW_FLOAT_DISABLED;
4896#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4897
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004898}
4899
4900
4901/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004902 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004903*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004904void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4905 uint32_t uConvertTypes,
4906 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004907{
4908
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004909 QCBORItem Item;
4910
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004911 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004912
4913 if(pMe->uLastError == QCBOR_SUCCESS) {
4914 // The above conversion succeeded
4915 return;
4916 }
4917
4918 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4919 // The above conversion failed in a way that code below can't correct
4920 return;
4921 }
4922
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004923 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004924}
4925
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004926
4927/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004928 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004929*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004930void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4931 int64_t nLabel,
4932 uint32_t uConvertTypes,
4933 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004934{
4935 QCBORItem Item;
4936
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004937 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004938
4939 if(pMe->uLastError == QCBOR_SUCCESS) {
4940 // The above conversion succeeded
4941 return;
4942 }
4943
4944 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4945 // The above conversion failed in a way that code below can't correct
4946 return;
4947 }
4948
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004949 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004950}
4951
4952
4953/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004954 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004955*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004956void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4957 const char *szLabel,
4958 uint32_t uConvertTypes,
4959 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004960{
4961 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004962 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004963
4964 if(pMe->uLastError == QCBOR_SUCCESS) {
4965 // The above conversion succeeded
4966 return;
4967 }
4968
4969 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4970 // The above conversion failed in a way that code below can't correct
4971 return;
4972 }
4973
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004974 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004975}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004976
4977
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004978
4979
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004980#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004981static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4982{
4983 while((uInt & 0xff00000000000000UL) == 0) {
4984 uInt = uInt << 8;
4985 };
4986
4987 UsefulOutBuf UOB;
4988
4989 UsefulOutBuf_Init(&UOB, Buffer);
4990
4991 while(uInt) {
4992 const uint64_t xx = uInt & 0xff00000000000000UL;
4993 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4994 uInt = uInt << 8;
4995 (void)xx;
4996 }
4997
4998 return UsefulOutBuf_OutUBuf(&UOB);
4999}
5000
5001
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005002static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5003 TagSpecification TagSpec,
5004 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005005{
5006 QCBORError uErr;
5007 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005008 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005009 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005010 if(uErr != QCBOR_SUCCESS) {
5011 goto Done;
5012 }
5013
5014 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5015 break; // Successful exit. Moving on to finish decoding.
5016 }
5017
5018 // The item is an array, which means an undecoded
5019 // mantissa and exponent, so decode it. It will then
5020 // have a different type and exit the loop if.
5021 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5022 if(uErr != QCBOR_SUCCESS) {
5023 goto Done;
5024 }
5025
5026 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005027 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005028 }
5029Done:
5030 return uErr;
5031}
5032
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005033
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005034static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005035 TagSpecification TagSpec,
5036 QCBORItem *pItem,
5037 int64_t *pnMantissa,
5038 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005039{
5040 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005041
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005042 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005043 if(uErr != QCBOR_SUCCESS) {
5044 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005045 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005046
Laurence Lundblade9b334962020-08-27 10:55:53 -07005047 switch (pItem->uDataType) {
5048
5049 case QCBOR_TYPE_DECIMAL_FRACTION:
5050 case QCBOR_TYPE_BIGFLOAT:
5051 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5052 *pnExponent = pItem->val.expAndMantissa.nExponent;
5053 break;
5054
5055 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5056 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5057 *pnExponent = pItem->val.expAndMantissa.nExponent;
5058 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5059 break;
5060
5061 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5062 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5063 *pnExponent = pItem->val.expAndMantissa.nExponent;
5064 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5065 break;
5066
5067 default:
5068 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5069 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005070
5071 Done:
5072 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005073}
5074
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005075
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005076static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005077 TagSpecification TagSpec,
5078 QCBORItem *pItem,
5079 UsefulBuf BufferForMantissa,
5080 UsefulBufC *pMantissa,
5081 bool *pbIsNegative,
5082 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005083{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005084 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005085
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005086 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005087 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005088 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005089 }
5090
5091 uint64_t uMantissa;
5092
5093 switch (pItem->uDataType) {
5094
5095 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005096 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005097 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5098 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5099 *pbIsNegative = false;
5100 } else {
5101 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5102 *pbIsNegative = true;
5103 }
5104 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5105 *pnExponent = pItem->val.expAndMantissa.nExponent;
5106 break;
5107
5108 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005109 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005110 *pnExponent = pItem->val.expAndMantissa.nExponent;
5111 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5112 *pbIsNegative = false;
5113 break;
5114
5115 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005116 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005117 *pnExponent = pItem->val.expAndMantissa.nExponent;
5118 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5119 *pbIsNegative = true;
5120 break;
5121
5122 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005123 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005124 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005125
5126Done:
5127 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005128}
5129
5130
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005131/*
5132 Public function, see header qcbor/qcbor_decode.h file
5133*/
5134void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5135 uint8_t uTagRequirement,
5136 int64_t *pnMantissa,
5137 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005138{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005139 if(pMe->uLastError != QCBOR_SUCCESS) {
5140 return;
5141 }
5142
5143 QCBORItem Item;
5144 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5145 if(uError) {
5146 pMe->uLastError = (uint8_t)uError;
5147 return;
5148 }
5149
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005150 const TagSpecification TagSpec =
5151 {
5152 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005153 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5154 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5155 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005156 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005157
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005158 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005159}
5160
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005161
5162/*
5163 Public function, see header qcbor/qcbor_decode.h file
5164*/
5165void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005166 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005167 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005168 int64_t *pnMantissa,
5169 int64_t *pnExponent)
5170{
5171 if(pMe->uLastError != QCBOR_SUCCESS) {
5172 return;
5173 }
5174
5175 QCBORItem Item;
5176 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5177
5178 const TagSpecification TagSpec =
5179 {
5180 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005181 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5182 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5183 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005184 };
5185
5186 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5187}
5188
5189
5190/*
5191 Public function, see header qcbor/qcbor_decode.h file
5192*/
5193void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005194 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005195 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005196 int64_t *pnMantissa,
5197 int64_t *pnExponent)
5198{
5199 if(pMe->uLastError != QCBOR_SUCCESS) {
5200 return;
5201 }
5202
5203 QCBORItem Item;
5204 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5205
5206 const TagSpecification TagSpec =
5207 {
5208 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005209 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5210 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5211 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005212 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005213
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005214 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5215}
5216
5217
5218/*
5219 Public function, see header qcbor/qcbor_decode.h file
5220*/
5221void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5222 uint8_t uTagRequirement,
5223 UsefulBuf MantissaBuffer,
5224 UsefulBufC *pMantissa,
5225 bool *pbMantissaIsNegative,
5226 int64_t *pnExponent)
5227{
5228 if(pMe->uLastError != QCBOR_SUCCESS) {
5229 return;
5230 }
5231
5232 QCBORItem Item;
5233 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5234 if(uError) {
5235 pMe->uLastError = (uint8_t)uError;
5236 return;
5237 }
5238
5239 const TagSpecification TagSpec =
5240 {
5241 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005242 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5243 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5244 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005245 };
5246
Laurence Lundblade93d89472020-10-03 22:30:50 -07005247 ProcessMantissaAndExponentBig(pMe,
5248 TagSpec,
5249 &Item,
5250 MantissaBuffer,
5251 pMantissa,
5252 pbMantissaIsNegative,
5253 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005254}
5255
5256
5257/*
5258 Public function, see header qcbor/qcbor_decode.h file
5259*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005260void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005261 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005262 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005263 UsefulBuf BufferForMantissa,
5264 UsefulBufC *pMantissa,
5265 bool *pbIsNegative,
5266 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005267{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005268 if(pMe->uLastError != QCBOR_SUCCESS) {
5269 return;
5270 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005271
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005272 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005273 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005274 if(pMe->uLastError != QCBOR_SUCCESS) {
5275 return;
5276 }
5277
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005278 const TagSpecification TagSpec =
5279 {
5280 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005281 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5282 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5283 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005284 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005285
Laurence Lundblade93d89472020-10-03 22:30:50 -07005286 ProcessMantissaAndExponentBig(pMe,
5287 TagSpec,
5288 &Item,
5289 BufferForMantissa,
5290 pMantissa,
5291 pbIsNegative,
5292 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005293}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005294
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005295
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005296/*
5297 Public function, see header qcbor/qcbor_decode.h file
5298*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005299void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005300 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005301 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005302 UsefulBuf BufferForMantissa,
5303 UsefulBufC *pMantissa,
5304 bool *pbIsNegative,
5305 int64_t *pnExponent)
5306{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005307 if(pMe->uLastError != QCBOR_SUCCESS) {
5308 return;
5309 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005310
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005311 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005312 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5313 if(pMe->uLastError != QCBOR_SUCCESS) {
5314 return;
5315 }
5316
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005317 const TagSpecification TagSpec =
5318 {
5319 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005320 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5321 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5322 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005323 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005324
5325 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5326}
5327
5328
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005329/*
5330 Public function, see header qcbor/qcbor_decode.h file
5331*/
5332void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5333 uint8_t uTagRequirement,
5334 int64_t *pnMantissa,
5335 int64_t *pnExponent)
5336{
5337 if(pMe->uLastError != QCBOR_SUCCESS) {
5338 return;
5339 }
5340
5341 QCBORItem Item;
5342 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5343 if(uError) {
5344 pMe->uLastError = (uint8_t)uError;
5345 return;
5346 }
5347 const TagSpecification TagSpec =
5348 {
5349 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005350 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5351 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5352 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005353 };
5354
5355 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5356}
5357
5358
5359/*
5360 Public function, see header qcbor/qcbor_decode.h file
5361*/
5362void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005363 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005364 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005365 int64_t *pnMantissa,
5366 int64_t *pnExponent)
5367{
5368 if(pMe->uLastError != QCBOR_SUCCESS) {
5369 return;
5370 }
5371
5372 QCBORItem Item;
5373 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5374 if(pMe->uLastError != QCBOR_SUCCESS) {
5375 return;
5376 }
5377
5378 const TagSpecification TagSpec =
5379 {
5380 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005381 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5382 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5383 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005384 };
5385
5386 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5387}
5388
5389
5390/*
5391 Public function, see header qcbor/qcbor_decode.h file
5392*/
5393void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005394 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005395 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005396 int64_t *pnMantissa,
5397 int64_t *pnExponent)
5398{
5399 if(pMe->uLastError != QCBOR_SUCCESS) {
5400 return;
5401 }
5402
5403 QCBORItem Item;
5404 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5405 if(pMe->uLastError != QCBOR_SUCCESS) {
5406 return;
5407 }
5408
5409 const TagSpecification TagSpec =
5410 {
5411 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005412 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5413 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5414 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005415 };
5416
5417 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5418}
5419
5420
5421/*
5422 Public function, see header qcbor/qcbor_decode.h file
5423*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005424void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5425 uint8_t uTagRequirement,
5426 UsefulBuf MantissaBuffer,
5427 UsefulBufC *pMantissa,
5428 bool *pbMantissaIsNegative,
5429 int64_t *pnExponent)
5430{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005431 if(pMe->uLastError != QCBOR_SUCCESS) {
5432 return;
5433 }
5434
5435 QCBORItem Item;
5436 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5437 if(uError) {
5438 pMe->uLastError = (uint8_t)uError;
5439 return;
5440 }
5441
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005442 const TagSpecification TagSpec =
5443 {
5444 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005445 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5446 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5447 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005448 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005449
5450 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005451}
5452
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005453
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005454/*
5455 Public function, see header qcbor/qcbor_decode.h file
5456*/
5457void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005458 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005459 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005460 UsefulBuf BufferForMantissa,
5461 UsefulBufC *pMantissa,
5462 bool *pbIsNegative,
5463 int64_t *pnExponent)
5464{
5465 if(pMe->uLastError != QCBOR_SUCCESS) {
5466 return;
5467 }
5468
5469 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005470 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5471 if(pMe->uLastError != QCBOR_SUCCESS) {
5472 return;
5473 }
5474
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005475 const TagSpecification TagSpec =
5476 {
5477 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005478 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5479 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5480 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005481 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005482
Laurence Lundblade93d89472020-10-03 22:30:50 -07005483 ProcessMantissaAndExponentBig(pMe,
5484 TagSpec,
5485 &Item,
5486 BufferForMantissa,
5487 pMantissa,
5488 pbIsNegative,
5489 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005490}
5491
5492
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005493/*
5494 Public function, see header qcbor/qcbor_decode.h file
5495*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005496void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005497 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005498 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005499 UsefulBuf BufferForMantissa,
5500 UsefulBufC *pMantissa,
5501 bool *pbIsNegative,
5502 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005503{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005504 if(pMe->uLastError != QCBOR_SUCCESS) {
5505 return;
5506 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005507
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005508 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005509 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5510 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005511 return;
5512 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005513
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005514 const TagSpecification TagSpec =
5515 {
5516 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005517 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5518 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5519 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005520 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005521
Laurence Lundblade93d89472020-10-03 22:30:50 -07005522 ProcessMantissaAndExponentBig(pMe,
5523 TagSpec,
5524 &Item,
5525 BufferForMantissa,
5526 pMantissa,
5527 pbIsNegative,
5528 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005529}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005530
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005531#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */