blob: 4e25faff921d33ffb1207139b56c93dbf07de33b [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladeee851742020-01-08 08:37:05 -08003 Copyright (c) 2018-2020, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070035#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundbladec7114722020-08-13 05:11:40 -070036#include "ieee754.h" // Does not use math.h
37
38#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade323f8a92020-09-06 19:43:09 -070039#include <math.h> // For isnan(), llround(), llroudf(), round(), roundf(),
40 // pow(), exp2()
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -070041#include <fenv.h> // feclearexcept(), fetestexcept()
Laurence Lundbladec7114722020-08-13 05:11:40 -070042#endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070043
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070044
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053045/*
46 This casts away the const-ness of a pointer, usually so it can be
47 freed or realloced.
48 */
49#define UNCONST_POINTER(ptr) ((void *)(ptr))
50
Laurence Lundbladea9489f82020-09-12 13:50:56 -070051#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070052
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070053
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070054static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070055QCBORItem_IsMapOrArray(const QCBORItem *pMe)
56{
57 const uint8_t uDataType = pMe->uDataType;
58 return uDataType == QCBOR_TYPE_MAP ||
59 uDataType == QCBOR_TYPE_ARRAY ||
60 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
61}
62
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070063static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070064QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
65{
66 if(!QCBORItem_IsMapOrArray(pMe)){
67 return false;
68 }
69
70 if(pMe->val.uCount != 0) {
71 return false;
72 }
73 return true;
74}
75
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070076static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070077QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
78{
79 if(!QCBORItem_IsMapOrArray(pMe)){
80 return false;
81 }
82
83 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
84 return false;
85 }
86 return true;
87}
88
89
Laurence Lundbladeee851742020-01-08 08:37:05 -080090/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070091 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080092 ===========================================================================*/
93
Laurence Lundblade9c905e82020-04-25 11:31:38 -070094/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070095 See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
Laurence Lundblade93d89472020-10-03 22:30:50 -070096 the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -070097 */
98
Laurence Lundblade24d509a2020-06-06 18:43:15 -070099
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700100static inline uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700101DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700102{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700103 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700104 /*
105 Limit in DecodeNesting_Descend against more than
106 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
107 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700108 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700109}
110
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700111
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700112static inline uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700113DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700114{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700115 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700116 /*
117 Limit in DecodeNesting_Descend against more than
118 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
119 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700120 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700121}
122
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700123
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700124static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700125DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700126{
127 return pNesting->pCurrentBounded->u.ma.uStartOffset;
128}
129
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700130
Laurence Lundblade085d7952020-07-24 10:26:30 -0700131static inline bool
132DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
133{
134 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
135 return true;
136 } else {
137 return false;
138 }
139}
140
141
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700142static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700143DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700144{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700145 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700146 return true;
147 } else {
148 return false;
149 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700150}
151
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700152
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700153static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700154DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700155{
156 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700157 // Not a map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700158 return false;
159 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700160 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700161 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700162 return false;
163 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700164 // All checks passed; is a definte length map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700165 return true;
166}
167
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700168
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700169static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700170DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700171{
172 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700173 // is a byte string
Laurence Lundblade642282a2020-06-23 12:00:33 -0700174 return true;
175 }
176 return false;
177}
178
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700179
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700180static inline bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700181{
182 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
183 return true;
184 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700185 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700186 return true;
187 }
188 return false;
189}
190
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700191
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700192static inline void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700193{
194 // Should be only called on maps and arrays
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700195 /*
196 DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
197 larger than DecodeNesting_EnterBoundedMode which keeps it less than
198 uin32_t so the cast is safe.
199 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700200 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700201
202 if(bIsEmpty) {
203 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
204 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700205}
206
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700207
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700208static inline void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700209{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700210 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700211}
212
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700213
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700214static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700215DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700216{
217 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700218 // No bounded map or array set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700219 return false;
220 }
221 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700222 // Not a map or array; end of those is by byte count
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700223 return false;
224 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700225 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
226 // In a traveral at a level deeper than the bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700227 return false;
228 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700229 // Works for both definite and indefinite length maps/arrays
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800230 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
231 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700232 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700233 return false;
234 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700235 // All checks passed, got to the end of an array or map
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700236 return true;
237}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700238
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700239
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700240static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700241DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700242{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700243 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700244 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
245 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700246 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700247 return false;
248 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700249}
250
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700251
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700252static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700253DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700254{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700255 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
256 return true;
257 } else {
258 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700259 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700260}
261
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700262
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700263static inline bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700264DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700265{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700266 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700267 return false;
268 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700269
270 if(pNesting->pCurrentBounded->uLevelType != uType) {
271 return false;
272 }
273
274 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700275}
276
Laurence Lundblade02625d42020-06-25 14:41:41 -0700277
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700278static inline void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700279DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700280{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700281 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700282 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700283}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700284
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700285
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700286static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700287DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
288{
289 // Only call on a defnite length array / map
290 pNesting->pCurrent->u.ma.uCountCursor++;
291}
292
293
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700294static inline void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700295DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
296{
297 pNesting->pCurrent--;
298}
299
Laurence Lundblade02625d42020-06-25 14:41:41 -0700300
301static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700302DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700303{
304 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700305 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700306 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700307 }
308
309 // The actual descend
310 pNesting->pCurrent++;
311
312 pNesting->pCurrent->uLevelType = uType;
313
314 return QCBOR_SUCCESS;
315}
316
317
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700318static inline QCBORError
Laurence Lundblade085d7952020-07-24 10:26:30 -0700319DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700320{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700321 /*
322 Should only be called on map/array.
323
324 Have descended into this before this is called. The job here is
325 just to mark it in bounded mode.
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700326
327 Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
328 uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700329 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700330 if(uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700331 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700332 }
333
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700334 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700335
336 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700337
338 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700339}
340
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700341
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700342static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700343DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700344 uint8_t uQCBORType,
345 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700346{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700347 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700348
349 if(uCount == 0) {
350 // Nothing to do for empty definite lenth arrays. They are just are
351 // effectively the same as an item that is not a map or array
352 goto Done;
353 // Empty indefinite length maps and arrays are handled elsewhere
354 }
355
356 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700357 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
358 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700359 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700360 goto Done;
361 }
362
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700363 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700364 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700365 goto Done;
366 }
367
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700368 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700369 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
370 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700371
372 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700373
374Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700375 return uError;;
376}
377
378
379static inline void
380DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
381{
382 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
383}
384
385
386static inline void
387DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
388{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700389 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700390 pNesting->pCurrentBounded--;
391 if(DecodeNesting_IsCurrentBounded(pNesting)) {
392 break;
393 }
394 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700395}
396
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700397static inline void
398DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
399{
400 pNesting->pCurrent = pNesting->pCurrentBounded;
401}
402
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700403
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700404static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700405DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700406 uint32_t uEndOffset,
407 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700408{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700409 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700410
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700411 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700412 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700413 goto Done;
414 }
415
Laurence Lundblade02625d42020-06-25 14:41:41 -0700416 // Fill in the new byte string level
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700417 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
418 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700419
Laurence Lundblade02625d42020-06-25 14:41:41 -0700420 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700421 pNesting->pCurrentBounded = pNesting->pCurrent;
422
423Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700424 return uError;;
425}
426
Laurence Lundbladed0304932020-06-27 10:59:38 -0700427
428static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700429DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700430{
431 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700432}
433
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700434
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700435static inline void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800436DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
437{
438 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
439}
440
441
442static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700443DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700444{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700445 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700446 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
447 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700448}
449
450
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700451static inline void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700452DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700453{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700454 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700455 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800456 DecodeNesting_ResetMapOrArrayCount(pNesting);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700457}
458
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700459
Laurence Lundblade02625d42020-06-25 14:41:41 -0700460static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700461DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700462{
463 *pNesting = *pSave;
464}
465
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700466
Laurence Lundblade02625d42020-06-25 14:41:41 -0700467static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700468DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700469{
470 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
471}
472
473
Laurence Lundblade02625d42020-06-25 14:41:41 -0700474static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700475DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700476{
477 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
478}
479
480
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800481#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800482/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800483 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
484
485 The following four functions are pretty wrappers for invocation of
486 the string allocator supplied by the caller.
487
Laurence Lundbladeee851742020-01-08 08:37:05 -0800488 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800489
Laurence Lundbladeee851742020-01-08 08:37:05 -0800490static inline void
491StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800492{
493 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
494}
495
Laurence Lundbladeee851742020-01-08 08:37:05 -0800496// StringAllocator_Reallocate called with pMem NULL is
497// equal to StringAllocator_Allocate()
498static inline UsefulBuf
499StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
500 void *pMem,
501 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800502{
503 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
504}
505
Laurence Lundbladeee851742020-01-08 08:37:05 -0800506static inline UsefulBuf
507StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800508{
509 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
510}
511
Laurence Lundbladeee851742020-01-08 08:37:05 -0800512static inline void
513StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800514{
515 if(pMe->pfAllocator) {
516 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
517 }
518}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800519#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800520
521
Laurence Lundbladeee851742020-01-08 08:37:05 -0800522/*===========================================================================
523 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700524
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800525 See qcbor/qcbor_decode.h for definition of the object
526 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800527 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700528/*
529 Public function, see header file
530 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800531void QCBORDecode_Init(QCBORDecodeContext *me,
532 UsefulBufC EncodedCBOR,
533 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700534{
535 memset(me, 0, sizeof(QCBORDecodeContext));
536 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800537 // Don't bother with error check on decode mode. If a bad value is
538 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700539 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700540 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700541 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700542 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700543 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700544}
545
546
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800547#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
548
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700549/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700550 Public function, see header file
551 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800552void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
553 QCBORStringAllocate pfAllocateFunction,
554 void *pAllocateContext,
555 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700556{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800557 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
558 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
559 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700560}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800561#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700562
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800563
564/*
565 Public function, see header file
566 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700567void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800568 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700569{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700570 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700571 (void)pMe;
572 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700573}
574
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700575
576/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800577 This decodes the fundamental part of a CBOR data item, the type and
578 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800579
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700580 This is the counterpart to QCBOREncode_EncodeHead().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800581
Laurence Lundbladeee851742020-01-08 08:37:05 -0800582 This does the network->host byte order conversion. The conversion
583 here also results in the conversion for floats in addition to that
584 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800585
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700586 This returns:
587 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800588
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800589 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800590 tags and floats and length for strings and arrays
591
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800592 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800593 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800594
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800595 The int type is preferred to uint8_t for some variables as this
596 avoids integer promotions, can reduce code size and makes
597 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700598
599 @retval QCBOR_ERR_UNSUPPORTED
600
601 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700602 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700603static inline QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800604 int *pnMajorType,
605 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800606 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700607{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700608 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800609
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700610 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800611 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800612
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700613 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800614 const int nTmpMajorType = nInitialByte >> 5;
615 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800616
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800617 // Where the number or argument accumulates
618 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800619
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800620 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700621 // Need to get 1,2,4 or 8 additional argument bytes. Map
622 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800623 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800624
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800625 // Loop getting all the bytes in the argument
626 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800627 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800628 // This shift and add gives the endian conversion
629 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
630 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800631 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800632 // The reserved and thus-far unused additional info values
633 nReturn = QCBOR_ERR_UNSUPPORTED;
634 goto Done;
635 } else {
636 // Less than 24, additional info is argument or 31, an indefinite length
637 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800638 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700639 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800640
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700641 if(UsefulInputBuf_GetError(pUInBuf)) {
642 nReturn = QCBOR_ERR_HIT_END;
643 goto Done;
644 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800645
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700646 // All successful if we got here.
647 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800648 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800649 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800650 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800651
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700652Done:
653 return nReturn;
654}
655
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800656
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700657/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800658 CBOR doesn't explicitly specify two's compliment for integers but all
659 CPUs use it these days and the test vectors in the RFC are so. All
660 integers in the CBOR structure are positive and the major type
661 indicates positive or negative. CBOR can express positive integers
662 up to 2^x - 1 where x is the number of bits and negative integers
663 down to 2^x. Note that negative numbers can be one more away from
664 zero than positive. Stdint, as far as I can tell, uses two's
665 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800666
Laurence Lundblade9b334962020-08-27 10:55:53 -0700667 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800668 used carefully here, and in particular why it isn't used in the interface.
669 Also see
670 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
671
672 Int is used for values that need less than 16-bits and would be subject
673 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700674
675 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700676 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700677static inline QCBORError
Laurence Lundbladeee851742020-01-08 08:37:05 -0800678DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700679{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700680 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800681
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700682 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
683 if (uNumber <= INT64_MAX) {
684 pDecodedItem->val.int64 = (int64_t)uNumber;
685 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800686
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700687 } else {
688 pDecodedItem->val.uint64 = uNumber;
689 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800690
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700691 }
692 } else {
693 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800694 // CBOR's representation of negative numbers lines up with the
695 // two-compliment representation. A negative integer has one
696 // more in range than a positive integer. INT64_MIN is
697 // equal to (-INT64_MAX) - 1.
698 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700699 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800700
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700701 } else {
702 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000703 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700704 nReturn = QCBOR_ERR_INT_OVERFLOW;
705 }
706 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800707
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700708 return nReturn;
709}
710
711// Make sure #define value line up as DecodeSimple counts on this.
712#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
713#error QCBOR_TYPE_FALSE macro value wrong
714#endif
715
716#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
717#error QCBOR_TYPE_TRUE macro value wrong
718#endif
719
720#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
721#error QCBOR_TYPE_NULL macro value wrong
722#endif
723
724#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
725#error QCBOR_TYPE_UNDEF macro value wrong
726#endif
727
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700728#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
729#error QCBOR_TYPE_BREAK macro value wrong
730#endif
731
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700732#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
733#error QCBOR_TYPE_DOUBLE macro value wrong
734#endif
735
736#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
737#error QCBOR_TYPE_FLOAT macro value wrong
738#endif
739
740/*
741 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700742
743 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
744
745 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700746 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700747static inline QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800748DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700749{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700750 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800751
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700752 // uAdditionalInfo is 5 bits from the initial byte. Compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800753 // above make sure uAdditionalInfo values line up with uDataType values.
Laurence Lundblade93d89472020-10-03 22:30:50 -0700754 // DecodeTypeAndNumber() never returns an AdditionalInfo > 0x1f so cast
755 // is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800756 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800757
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800758 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800759 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
760 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800761
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700762 case HALF_PREC_FLOAT: // 25
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700763#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700764 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700765 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700766 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700767 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
768 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700769#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700770 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700771#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700772 break;
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700773 case SINGLE_PREC_FLOAT: // 26
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700774 // Single precision is normally returned as a double
775 // since double is widely supported, there is no loss of
776 // precision, it makes it easy for the caller in
777 // most cases and it can be converted back to single
778 // with no loss of precision
779 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700780 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700781 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700782 {
783 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
784#ifndef QCBOR_DISABLE_FLOAT_HW_USE
785 // In the normal case, use HW to convert float to double.
786 pDecodedItem->val.dfnum = (double)f;
787 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700788#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700789 // Use of float HW is disabled, return as a float.
790 pDecodedItem->val.fnum = f;
791 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
792
793 // IEEE754_FloatToDouble() could be used here to return
794 // as a double, but it adds object code and most likely
795 // anyone disabling FLOAT HW use doesn't care about
796 // floats and wants to save object code.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700797#endif
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700798 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700799 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700800
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700801 case DOUBLE_PREC_FLOAT: // 27
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700802 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700803 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700804 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800805
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700806 case CBOR_SIMPLEV_FALSE: // 20
807 case CBOR_SIMPLEV_TRUE: // 21
808 case CBOR_SIMPLEV_NULL: // 22
809 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700810 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700811 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800812
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700813 case CBOR_SIMPLEV_ONEBYTE: // 24
814 if(uNumber <= CBOR_SIMPLE_BREAK) {
815 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700816 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700817 goto Done;
818 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800819 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700820 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800821
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700822 default: // 0-19
823 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800824 /*
825 DecodeTypeAndNumber will make uNumber equal to
826 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
827 safe because the 2, 4 and 8 byte lengths of uNumber are in
828 the double/float cases above
829 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700830 pDecodedItem->val.uSimple = (uint8_t)uNumber;
831 break;
832 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800833
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700834Done:
835 return nReturn;
836}
837
838
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700839/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530840 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700841
842 @retval QCBOR_ERR_HIT_END
843
844 @retval QCBOR_ERR_STRING_ALLOCATE
845
846 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700847 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700848static inline QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800849 uint64_t uStrLen,
850 UsefulInputBuf *pUInBuf,
851 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700852{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700853 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800854
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800855 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
856 // This check makes the casts to size_t below safe.
857
858 // 4 bytes less than the largest sizeof() so this can be tested by
859 // putting a SIZE_MAX length in the CBOR test input (no one will
860 // care the limit on strings is 4 bytes shorter).
861 if(uStrLen > SIZE_MAX-4) {
862 nReturn = QCBOR_ERR_STRING_TOO_LONG;
863 goto Done;
864 }
865
866 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530867 if(UsefulBuf_IsNULLC(Bytes)) {
868 // Failed to get the bytes for this string item
869 nReturn = QCBOR_ERR_HIT_END;
870 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700871 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530872
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800873#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800874 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530875 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800876 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530877 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700878 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530879 goto Done;
880 }
881 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800882 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800883 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530884 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800885#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
886 (void)pAllocator;
887#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
888
889 // Normal case with no string allocator
890 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800891
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530892Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700893 return nReturn;
894}
895
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700896
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800897/* Map the CBOR major types for strings to the QCBOR types for strngs */
898static inline uint8_t MapStringMajorTypes(int nCBORMajorType)
899{
900 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
901 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
902 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800903
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800904 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
905 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
906 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700907
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800908 return (uint8_t)(nCBORMajorType + 4);
909}
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700910
911
Laurence Lundbladeee851742020-01-08 08:37:05 -0800912// Make sure the constants align as this is assumed by
913// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700914#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
915#error QCBOR_TYPE_ARRAY value not lined up with major type
916#endif
917#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
918#error QCBOR_TYPE_MAP value not lined up with major type
919#endif
920
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700921/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800922 This gets a single data item and decodes it including preceding
923 optional tagging. This does not deal with arrays and maps and nesting
924 except to decode the data item introducing them. Arrays and maps are
925 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800926
Laurence Lundbladeee851742020-01-08 08:37:05 -0800927 Errors detected here include: an array that is too long to decode,
928 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700929
930 @retval QCBOR_ERR_UNSUPPORTED
931
932 @retval QCBOR_ERR_HIT_END
933
934 @retval QCBOR_ERR_INT_OVERFLOW
935
936 @retval QCBOR_ERR_STRING_ALLOCATE
937
938 @retval QCBOR_ERR_STRING_TOO_LONG
939
940 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
941
942 @retval QCBOR_ERR_BAD_TYPE_7
943
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700944 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800945static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
946 QCBORItem *pDecodedItem,
947 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700948{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700949 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800950
Laurence Lundbladeee851742020-01-08 08:37:05 -0800951 /*
952 Get the major type and the number. Number could be length of more
953 bytes or the value depending on the major type nAdditionalInfo is
954 an encoding of the length of the uNumber and is needed to decode
955 floats and doubles
956 */
Rob Gilton47cc9562020-08-10 12:03:38 +0100957 int nMajorType = 0;
958 uint64_t uNumber = 0;
959 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800960
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700961 memset(pDecodedItem, 0, sizeof(QCBORItem));
962
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800963 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800964
Laurence Lundbladeee851742020-01-08 08:37:05 -0800965 // Error out here if we got into trouble on the type and number. The
966 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700967 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700968 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700969 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800970
Laurence Lundbladeee851742020-01-08 08:37:05 -0800971 // At this point the major type and the value are valid. We've got
972 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800973 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700974 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
975 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800976 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700977 nReturn = QCBOR_ERR_BAD_INT;
978 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800979 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700980 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700981 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800982
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700983 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
984 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800985 pDecodedItem->uDataType = MapStringMajorTypes(nMajorType);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800986 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800987 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700988 } else {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800989 nReturn = DecodeBytes(pAllocator, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700990 }
991 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800992
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700993 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
994 case CBOR_MAJOR_TYPE_MAP: // Major type 5
995 // Record the number of items in the array or map
996 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700997 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700998 goto Done;
999 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001000 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001001 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001002 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001003 // type conversion OK because of check above
1004 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001005 }
Laurence Lundbladeee851742020-01-08 08:37:05 -08001006 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001007 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001008 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001009 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001010
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001011 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001012 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001013 nReturn = QCBOR_ERR_BAD_INT;
1014 } else {
1015 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001016 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001017 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001018 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001019
Laurence Lundbladeee851742020-01-08 08:37:05 -08001020 case CBOR_MAJOR_TYPE_SIMPLE:
1021 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001022 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001023 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001024
Laurence Lundbladeee851742020-01-08 08:37:05 -08001025 default:
1026 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001027 nReturn = QCBOR_ERR_UNSUPPORTED;
1028 break;
1029 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001030
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001031Done:
1032 return nReturn;
1033}
1034
1035
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001036/**
1037 * @brief Process indefinite length strings
1038 *
1039 * @param[in] pMe Decoder context
1040 * @param[in,out] pDecodedItem The decoded item that work is done on.
1041 *
1042 * @retval QCBOR_ERR_UNSUPPORTED
1043 * @retval QCBOR_ERR_HIT_END
1044 * @retval QCBOR_ERR_INT_OVERFLOW
1045 * @retval QCBOR_ERR_STRING_ALLOCATE
1046 * @retval QCBOR_ERR_STRING_TOO_LONG
1047 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1048 * @retval QCBOR_ERR_BAD_TYPE_7
1049 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1050 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1051 *
1052 * If @c pDecodedItem is not an indefinite length string, this does nothing.
1053 *
1054 * If it is, this loops getting the subsequent chunks that make up the
1055 * string. The string allocator is used to make a contiguous buffer for
1056 * the chunks. When this completes @c pDecodedItem contains the
1057 * put-together string.
1058 *
1059 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001060 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001061static inline QCBORError
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001062GetNext_FullItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001063{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001064 /* Aproximate stack usage
1065 * 64-bit 32-bit
1066 * local vars 32 16
1067 * 2 UsefulBufs 32 16
1068 * QCBORItem 56 52
1069 * TOTAL 120 74
1070 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001071
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001072 /* The string allocator is used here for two purposes: 1)
1073 * coalescing the chunks of an indefinite length string, 2)
1074 * allocating storage for every string returned.
1075 *
1076 * The first use is below in this function. Indefinite length
1077 * strings cannot be processed at all without a string allocator.
1078 *
1079 * The second used is in DecodeBytes() which is called by
1080 * GetNext_Item() below. This second use unneccessary for most use
1081 * and only happens when requested in the call to
1082 * QCBORDecode_SetMemPool(). If the second use not requested then
1083 * NULL is passed for the string allocator to GetNext_Item().
1084 *
1085 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1086 * allocator altogether and thus both of these uses. It reduced the
1087 * decoder object code by about 400 bytes.
1088 */
1089 const QCORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001090
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001091#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1092 const QCORInternalAllocator *pAllocator = NULL;
1093
1094 if(pMe->StringAllocator.pfAllocator) {
1095 pAllocator = &(pMe->StringAllocator);
1096 if(pMe->bStringAllocateAll) {
1097 pAllocatorForGetNext = pAllocator;
1098 }
1099 }
1100#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1101
1102 QCBORError uReturn;
1103 uReturn = GetNext_Item(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
1104 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001105 goto Done;
1106 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001107
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001108 /* Only do indefinite length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001109 const uint8_t uStringType = pDecodedItem->uDataType;
1110 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001111 goto Done;
1112 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001113
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001114 /* Is this a string with an indefinite length? */
1115 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1116 goto Done;
1117 }
1118
1119#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1120 /* Can't do indefinite length strings without a string allocator */
1121 if(pAllocator == NULL) {
1122 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1123 goto Done;
1124 }
1125
1126 /* Loop getting chunks of the indefinite length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001127 UsefulBufC FullString = NULLUsefulBufC;
1128
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001129 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001130 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001131 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001132 /* Pass a NULL string allocator to GetNext_Item() because the
1133 * individual string chunks in an indefinite length should not
1134 * be allocated. They are always copied in the the contiguous
1135 * buffer allocated here.
1136 */
1137 uReturn = GetNext_Item(&(pMe->InBuf), &StringChunkItem, NULL);
1138 if(uReturn) {
1139 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001140 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001141
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001142 /* Is item is the marker for end of the indefinite length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001143 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001144 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001145 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301146 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001147 break;
1148 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001149
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001150 /* All chunks must be of the same type, the type of the item
1151 * that introduces the indefinite length string. This also
1152 * catches errors where the chunk is not a string at all and an
1153 * indefinite length string inside an indefinite length string.
1154 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001155 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001156 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1157 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001158 break;
1159 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001160
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001161 /* The first time throurgh FullString.ptr is NULL and this is
1162 * equivalent to StringAllocator_Allocate(). Subsequently it is
1163 * not NULL and a reallocation happens.
1164 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001165 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1166 UNCONST_POINTER(FullString.ptr),
1167 FullString.len + StringChunkItem.val.string.len);
1168
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001169 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001170 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001171 break;
1172 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001173
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001174 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001175 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001176 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001177
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001178 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1179 /* Getting the item failed, clean up the allocated memory */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001180 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001181 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001182#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1183 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1184#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001185
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001186Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001187 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001188}
1189
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001190
Laurence Lundblade9b334962020-08-27 10:55:53 -07001191static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001192 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001193 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001194 } else if(uTagVal == CBOR_TAG_INVALID16) {
1195 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001196 } else {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001197 // This won't be negative because of code below in GetNext_TaggedItem()
1198 const unsigned uIndex = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
1199 return me->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001200 }
1201}
1202
Laurence Lundblade9b334962020-08-27 10:55:53 -07001203
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001204/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001205 Gets all optional tag data items preceding a data item that is not an
1206 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001207
1208 @retval QCBOR_ERR_UNSUPPORTED
1209
1210 @retval QCBOR_ERR_HIT_END
1211
1212 @retval QCBOR_ERR_INT_OVERFLOW
1213
1214 @retval QCBOR_ERR_STRING_ALLOCATE
1215
1216 @retval QCBOR_ERR_STRING_TOO_LONG
1217
1218 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1219
1220 @retval QCBOR_ERR_BAD_TYPE_7
1221
1222 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1223
1224 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1225
1226 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001227 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001228static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001229GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001230{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001231 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1232 CBOR_TAG_INVALID16,
1233 CBOR_TAG_INVALID16,
1234 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001235
Laurence Lundblade9b334962020-08-27 10:55:53 -07001236 QCBORError uReturn = QCBOR_SUCCESS;
1237
Laurence Lundblade59289e52019-12-30 13:44:37 -08001238 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001239 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001240 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1241 if(uErr != QCBOR_SUCCESS) {
1242 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001243 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001244 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001245
Laurence Lundblade9b334962020-08-27 10:55:53 -07001246 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001247 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001248 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001249 break;
1250 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001251
Laurence Lundblade9b334962020-08-27 10:55:53 -07001252 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1253 // No room in the tag list
1254 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1255 // Continue on to get all tags on this item even though
1256 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001257 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001258 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001259 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001260 // Slide tags over one in the array to make room at index 0
1261 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1262 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001263 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001264
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001265 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001266 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001267 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001268 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001269 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001270 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001271 break;
1272 }
1273 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1274 break;
1275 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001276 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001277 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1278 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001279 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1280 // Continue on to get all tags on this item even though
1281 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001282 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001283 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001284 }
1285
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001286 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001287 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001288 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001289
1290 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001291 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001292 }
1293 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001294
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001295Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001296 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001297}
1298
1299
1300/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001301 This layer takes care of map entries. It combines the label and data
1302 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001303
1304 @retval QCBOR_ERR_UNSUPPORTED
1305
1306 @retval QCBOR_ERR_HIT_END
1307
1308 @retval QCBOR_ERR_INT_OVERFLOW
1309
1310 @retval QCBOR_ERR_STRING_ALLOCATE
1311
1312 @retval QCBOR_ERR_STRING_TOO_LONG
1313
1314 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1315
1316 @retval QCBOR_ERR_BAD_TYPE_7
1317
1318 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1319
1320 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1321
1322 @retval QCBOR_ERR_TOO_MANY_TAGS
1323
1324 @retval QCBOR_ERR_MAP_LABEL_TYPE
1325
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001326 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001327 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001328static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001329GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001330{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001331 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001332 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001333 if(nReturn)
1334 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001335
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001336 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001337 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001338 goto Done;
1339 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001340
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001341 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1342 // In a map and caller wants maps decoded, not treated as arrays
1343
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001344 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001345 // If in a map and the right decoding mode, get the label
1346
Laurence Lundbladeee851742020-01-08 08:37:05 -08001347 // Save label in pDecodedItem and get the next which will
1348 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001349 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001350 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001351 if(QCBORDecode_IsUnrecoverableError(nReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001352 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001353 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001354
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301355 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001356
1357 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1358 // strings are always good labels
1359 pDecodedItem->label.string = LabelItem.val.string;
1360 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1361 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001362 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001363 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1364 goto Done;
1365 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1366 pDecodedItem->label.int64 = LabelItem.val.int64;
1367 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1368 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1369 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1370 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1371 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1372 pDecodedItem->label.string = LabelItem.val.string;
1373 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1374 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1375 } else {
1376 // label is not an int or a string. It is an arrray
1377 // or a float or such and this implementation doesn't handle that.
1378 // Also, tags on labels are ignored.
1379 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1380 goto Done;
1381 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001382 }
1383 } else {
1384 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001385 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001386 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001387 goto Done;
1388 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001389 // Decoding a map as an array
1390 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001391 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1392 // Cast is needed because of integer promotion
1393 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001394 }
1395 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001396
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001397Done:
1398 return nReturn;
1399}
1400
1401
Laurence Lundblade02625d42020-06-25 14:41:41 -07001402/*
1403 See if next item is a CBOR break. If it is, it is consumed,
1404 if not it is not consumed.
1405*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001406static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001407NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1408{
1409 *pbNextIsBreak = false;
1410 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001411 QCBORItem Peek;
1412 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1413 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1414 if(uReturn != QCBOR_SUCCESS) {
1415 return uReturn;
1416 }
1417 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001418 // It is not a break, rewind so it can be processed normally.
1419 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001420 } else {
1421 *pbNextIsBreak = true;
1422 }
1423 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001424
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001425 return QCBOR_SUCCESS;
1426}
1427
1428
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001429/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001430 An item was just consumed, now figure out if it was the
1431 end of an array or map that can be closed out. That
1432 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001433*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001434static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001435{
1436 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001437
Laurence Lundblade642282a2020-06-23 12:00:33 -07001438 /* This loops ascending nesting levels as long as there is ascending to do */
1439 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1440
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001441 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001442 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001443 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1444 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001445 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001446 break;
1447 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07001448 /* All of a definite length array was consumed; fall through to
1449 ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001450
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001451 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001452 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001453 bool bIsBreak = false;
1454 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1455 if(uReturn != QCBOR_SUCCESS) {
1456 goto Done;
1457 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001458
1459 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001460 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001461 break;
1462 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001463
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001464 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001465 /*
1466 Break occurred inside a bstr-wrapped CBOR or
1467 in the top level sequence. This is always an
1468 error because neither are an indefinte length
1469 map/array.
1470 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001471 uReturn = QCBOR_ERR_BAD_BREAK;
1472 goto Done;
1473 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001474
Laurence Lundblade02625d42020-06-25 14:41:41 -07001475 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001476 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001477
Laurence Lundblade02625d42020-06-25 14:41:41 -07001478 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001479
Laurence Lundblade93d89472020-10-03 22:30:50 -07001480 /* But ascent in bounded mode is only by explicit call to
1481 QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001482 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001483 /* Set the count to zero for definite length arrays to indicate
1484 cursor is at end of bounded map / array */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001485 if(bMarkEnd) {
1486 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001487 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001488
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001489 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001490 break;
1491 }
1492
1493 /* Finally, actually ascend one level. */
1494 DecodeNesting_Ascend(&(pMe->nesting));
1495 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001496
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001497 uReturn = QCBOR_SUCCESS;
1498
1499Done:
1500 return uReturn;
1501}
1502
1503
1504/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001505 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001506 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1507 indefinte length maps and arrays by looking at the item count or
1508 finding CBOR breaks. It detects the ends of the top-level sequence
1509 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001510
1511 @retval QCBOR_ERR_UNSUPPORTED X
1512
1513 @retval QCBOR_ERR_HIT_END
1514
1515 @retval QCBOR_ERR_INT_OVERFLOW X
1516
1517 @retval QCBOR_ERR_STRING_ALLOCATE
1518
1519 @retval QCBOR_ERR_STRING_TOO_LONG
1520
1521 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1522
1523 @retval QCBOR_ERR_BAD_TYPE_7 X
1524
1525 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1526
1527 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1528
1529 @retval QCBOR_ERR_TOO_MANY_TAGS
1530
1531 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1532
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001533 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001534
1535 @retval QCBOR_ERR_NO_MORE_ITEMS
1536
1537 @retval QCBOR_ERR_BAD_BREAK
1538
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001539 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001540static QCBORError
1541QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001542{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001543 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001544 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001545
Laurence Lundblade642282a2020-06-23 12:00:33 -07001546 /*
1547 If out of bytes to consume, it is either the end of the top-level
1548 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001549
Laurence Lundblade642282a2020-06-23 12:00:33 -07001550 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1551 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1552 CBOR is exited, the length is set back to the top-level's length
1553 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001554 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001555 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001556 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001557 goto Done;
1558 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001559
Laurence Lundblade642282a2020-06-23 12:00:33 -07001560 /*
1561 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001562 array. The check for the end of an indefinite length array is
1563 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001564 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001565 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001566 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001567 goto Done;
1568 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001569
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001570 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001571 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001572 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1573 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001574 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001575 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301576
Laurence Lundblade642282a2020-06-23 12:00:33 -07001577 /*
1578 Breaks ending arrays/maps are always processed at the end of this
1579 function. They should never show up here.
1580 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301581 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001582 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301583 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301584 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001585
Laurence Lundblade642282a2020-06-23 12:00:33 -07001586 /*
1587 Record the nesting level for this data item before processing any
1588 of decrementing and descending.
1589 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001590 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001591
Laurence Lundblade642282a2020-06-23 12:00:33 -07001592
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001593 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001594 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001595 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001596 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001597
Laurence Lundblade93d89472020-10-03 22:30:50 -07001598 Empty indefinite length maps and arrays are descended into, but
1599 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001600
1601 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001602 encloses them so a decrement needs to be done for them too, but
1603 that is done only when all the items in them have been
1604 processed, not when they are opened with the exception of an
1605 empty map or array.
1606 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001607 QCBORError uDescendErr;
1608 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001609 pDecodedItem->uDataType,
1610 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001611 if(uDescendErr != QCBOR_SUCCESS) {
1612 /* This error is probably a traversal error and it
1613 overrides the non-traversal error. */
1614 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001615 goto Done;
1616 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001617 }
1618
Laurence Lundblade02625d42020-06-25 14:41:41 -07001619 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1620 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1621 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001622 /*
1623 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001624 - A non-aggregate like an integer or string
1625 - An empty definite length map or array
1626 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001627
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001628 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001629 definite length map/array and break detection for an indefinite
1630 length map/array. If the end of the map/array was reached, then
1631 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001632 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001633 QCBORError uAscendErr;
1634 uAscendErr = NestLevelAscender(me, true);
1635 if(uAscendErr != QCBOR_SUCCESS) {
1636 /* This error is probably a traversal error and it
1637 overrides the non-traversal error. */
1638 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001639 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001640 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301641 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001642
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001643 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001644 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001645 Tell the caller what level is next. This tells them what
1646 maps/arrays were closed out and makes it possible for them to
1647 reconstruct the tree with just the information returned in
1648 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001649 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001650 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001651 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001652 pDecodedItem->uNextNestLevel = 0;
1653 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001654 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001655 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001656
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001657Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001658 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001659}
1660
Laurence Lundblade9b334962020-08-27 10:55:53 -07001661static void ShiftTags(QCBORItem *pDecodedItem)
1662{
1663 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1664 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1665 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1666 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1667}
1668
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001669
Laurence Lundblade9b334962020-08-27 10:55:53 -07001670
Laurence Lundblade59289e52019-12-30 13:44:37 -08001671/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001672 The epoch formatted date. Turns lots of different forms of encoding
1673 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001674 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001675static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001676{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001677 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001678
1679 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1680
1681 switch (pDecodedItem->uDataType) {
1682
1683 case QCBOR_TYPE_INT64:
1684 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1685 break;
1686
1687 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001688 // This only happens for CBOR type 0 > INT64_MAX so it is
1689 // always an overflow.
1690 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1691 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001692 break;
1693
1694 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001695 case QCBOR_TYPE_FLOAT:
1696#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001697 {
1698 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001699 // conversion to an int64_t to be able to detect doubles that
1700 // are too large to fit into an int64_t. A double has 52
1701 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1702 // to a double actually causes a round up which is bad and
1703 // wrong for the comparison because it will allow conversion
1704 // of doubles that can't fit into a uint64_t. To remedy this
1705 // INT64_MAX - 0x7ff is used as the cutoff point because if
1706 // that value rounds up in conversion to double it will still
1707 // be less than INT64_MAX. 0x7ff is picked because it has 11
1708 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001709 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001710 // INT64_MAX seconds is on the order of 10 billion years, and
1711 // the earth is less than 5 billion years old, so for most
1712 // uses this conversion error won't occur even though doubles
1713 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001714 //
1715 // Without the 0x7ff there is a ~30 minute range of time
1716 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001717 // where this code would go wrong. Some compilers
1718 // will generate warnings or errors without the 0x7ff
1719 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001720 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1721 pDecodedItem->val.dfnum :
1722 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001723 if(isnan(d) ||
1724 d > (double)(INT64_MAX - 0x7ff) ||
1725 d < (double)(INT64_MIN + 0x7ff)) {
1726 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001727 goto Done;
1728 }
1729 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001730 pDecodedItem->val.epochDate.fSecondsFraction =
1731 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001732 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001733#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001734
Laurence Lundbladec7114722020-08-13 05:11:40 -07001735 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001736 goto Done;
1737
Laurence Lundblade9682a532020-06-06 18:33:04 -07001738#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001739 break;
1740
1741 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001742 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001743 goto Done;
1744 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001745
Laurence Lundblade59289e52019-12-30 13:44:37 -08001746 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1747
1748Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001749 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001750}
1751
1752
1753#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1754/*
1755 Decode decimal fractions and big floats.
1756
1757 When called pDecodedItem must be the array that is tagged as a big
1758 float or decimal fraction, the array that has the two members, the
1759 exponent and mantissa.
1760
1761 This will fetch and decode the exponent and mantissa and put the
1762 result back into pDecodedItem.
1763 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001764static inline QCBORError
Laurence Lundblade59289e52019-12-30 13:44:37 -08001765QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1766{
1767 QCBORError nReturn;
1768
1769 // --- Make sure it is an array; track nesting level of members ---
1770 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1771 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1772 goto Done;
1773 }
1774
1775 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001776 // definite length arrays, but not for indefnite. Instead remember
1777 // the nesting level the two integers must be at, which is one
1778 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001779 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1780
1781 // --- Is it a decimal fraction or a bigfloat? ---
1782 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1783 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1784
1785 // --- Get the exponent ---
1786 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001787 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001788 if(nReturn != QCBOR_SUCCESS) {
1789 goto Done;
1790 }
1791 if(exponentItem.uNestingLevel != nNestLevel) {
1792 // Array is empty or a map/array encountered when expecting an int
1793 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1794 goto Done;
1795 }
1796 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1797 // Data arriving as an unsigned int < INT64_MAX has been converted
1798 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1799 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1800 // will be too large for this to handle and thus an error that will
1801 // get handled in the next else.
1802 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1803 } else {
1804 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1805 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1806 goto Done;
1807 }
1808
1809 // --- Get the mantissa ---
1810 QCBORItem mantissaItem;
1811 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1812 if(nReturn != QCBOR_SUCCESS) {
1813 goto Done;
1814 }
1815 if(mantissaItem.uNestingLevel != nNestLevel) {
1816 // Mantissa missing or map/array encountered when expecting number
1817 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1818 goto Done;
1819 }
1820 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1821 // Data arriving as an unsigned int < INT64_MAX has been converted
1822 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1823 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1824 // will be too large for this to handle and thus an error that
1825 // will get handled in an else below.
1826 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001827 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
1828 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001829 // Got a good big num mantissa
1830 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1831 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001832 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1833 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1834 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001835 } else {
1836 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1837 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1838 goto Done;
1839 }
1840
1841 // --- Check that array only has the two numbers ---
1842 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001843 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001844 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1845 goto Done;
1846 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001847 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001848
1849Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001850 return nReturn;
1851}
1852#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1853
1854
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001855static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001856{
1857 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1858 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001859 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001860 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1861 } else {
1862 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001863
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001864 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001865
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001866 return QCBOR_SUCCESS;
1867}
1868
1869
Laurence Lundblade99615302020-11-29 11:19:47 -08001870/*
1871 * Table of CBOR tags whose content is either a text string or a byte
1872 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
1873 * of uQCBORtype indicates the content should be a byte string rather
1874 * than a text string
1875 */
1876struct StringTagMapEntry {
1877 uint16_t uTagNumber;
1878 uint8_t uQCBORtype;
1879};
1880
1881#define IS_BYTE_STRING_BIT 0x80
1882#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
1883
1884static const struct StringTagMapEntry StringTagMap[] = {
1885 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
1886 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
1887 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
1888 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
1889 {CBOR_TAG_URI, QCBOR_TYPE_URI},
1890 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
1891 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
1892 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
1893 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
1894 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
1895 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
1896};
1897
1898
1899/*
1900 * Process the CBOR tags that whose content is a byte string or a text
1901 * string and for which the string is just passed on to the caller.
1902 *
1903 * This maps the CBOR tag to the QCBOR type and checks the content
1904 * type. Nothing more. It may not be the most important
Laurence Lundblade38b5e292020-12-04 22:09:51 -08001905 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08001906 * possible.
1907 *
1908 * This returns QCBOR_SUCCESS if the tag was procssed,
1909 * QCBOR_ERR_UNSUPPORTED if the tag was not processed and
1910 * QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
1911 */
1912static inline
1913QCBORError ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001914{
Laurence Lundblade99615302020-11-29 11:19:47 -08001915 /* This only works on tags that were not mapped; no need for other yet */
1916 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
1917 return QCBOR_ERR_UNSUPPORTED;
1918 }
1919
1920 unsigned uIndex;
1921 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
1922 if(StringTagMap[uIndex].uTagNumber == uTag) {
1923 break;
1924 }
1925 }
1926
1927 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
1928 if(uQCBORType == QCBOR_TYPE_NONE) {
1929 /* repurpose this error to mean, not handled here */
1930 return QCBOR_ERR_UNSUPPORTED;
1931 }
1932
1933 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
1934 if(uQCBORType & IS_BYTE_STRING_BIT) {
1935 uExpectedType = QCBOR_TYPE_BYTE_STRING;
1936 }
1937
1938 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001939 return QCBOR_ERR_BAD_OPT_TAG;
1940 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001941
Laurence Lundblade99615302020-11-29 11:19:47 -08001942 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001943 return QCBOR_SUCCESS;
1944}
1945
1946
Laurence Lundblade59289e52019-12-30 13:44:37 -08001947/*
Laurence Lundblade99615302020-11-29 11:19:47 -08001948 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
1949 * but the whole tag was not decoded. Here, the whole tags (tag number
1950 * and tag content) that are supported by QCBOR are decoded. This is a
1951 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001952 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001953static QCBORError
1954QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001955{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001956 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001957
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001958 uReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
1959 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001960 goto Done;
1961 }
1962
Laurence Lundblade99615302020-11-29 11:19:47 -08001963 /* When there are no tag numbers for the item, this exits first
1964 * thing and effectively does nothing.
1965 *
1966 * This loops over all the tag numbers accumulated for this item
1967 * trying to decode and interpret them. This stops at the end of
1968 * the list or at the first tag number that can't be interpreted by
1969 * this code. This is effectively a recursive processing of the
1970 * tags number list that handles nested tags.
1971 */
1972 while(1) {
1973 /* Don't bother to unmap tags via QCBORITem.uTags since this
1974 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
1975 */
1976 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08001977
Laurence Lundblade99615302020-11-29 11:19:47 -08001978 if(uTagToProcess == CBOR_TAG_INVALID16) {
1979 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001980 break;
1981
Laurence Lundblade99615302020-11-29 11:19:47 -08001982 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001983 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001984
Laurence Lundblade93d89472020-10-03 22:30:50 -07001985#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08001986 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
1987 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001988 uReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
Laurence Lundblade93d89472020-10-03 22:30:50 -07001989#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001990
Laurence Lundblade99615302020-11-29 11:19:47 -08001991 } else if(uTagToProcess == CBOR_TAG_MIME ||
1992 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001993 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001994
Laurence Lundblade99615302020-11-29 11:19:47 -08001995 } else {
1996 /* See if it is a pass-through byte/text string tag; process if so */
1997 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001998
Laurence Lundblade99615302020-11-29 11:19:47 -08001999 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
2000 /* It wasn't a pass-through byte/text string tag so it is
2001 * an unknown tag. This is the exit from the loop on the
2002 * first unknown tag. It is a successful exit.
2003 */
2004 uReturn = QCBOR_SUCCESS;
2005 break;
2006 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002007 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002008
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002009 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002010 /* Error exit from the loop */
2011 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002012 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002013
2014 /* A tag was successfully processed, shift it out of the list of
2015 * tags returned. This is the loop increment.
2016 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002017 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002018 }
2019
2020Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002021 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002022}
2023
2024
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002025/*
2026 Public function, see header qcbor/qcbor_decode.h file
2027 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002028QCBORError
2029QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2030{
2031 QCBORError uErr;
2032 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2033 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002034 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2035 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2036 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002037 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002038}
2039
2040
2041/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002042 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002043 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002044QCBORError
2045QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2046{
2047 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2048 const UsefulInputBuf Save = pMe->InBuf;
2049
2050 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2051
2052 pMe->nesting = SaveNesting;
2053 pMe->InBuf = Save;
2054
2055 return uErr;
2056}
2057
2058
2059/*
2060 Public function, see header qcbor/qcbor_decode.h file
2061 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002062void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2063{
2064 if(pMe->uLastError != QCBOR_SUCCESS) {
2065 return;
2066 }
2067
2068 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2069}
2070
2071
2072/*
2073 Public function, see header qcbor/qcbor_decode.h file
2074 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002075QCBORError
2076QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2077 QCBORItem *pDecodedItem,
2078 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002079{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002080 QCBORError nReturn;
2081
2082 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2083 if(nReturn != QCBOR_SUCCESS) {
2084 return nReturn;
2085 }
2086
2087 if(pTags != NULL) {
2088 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002089 // Reverse the order because pTags is reverse of
2090 // QCBORItem.uTags.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002091 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2092 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002093 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002094 }
2095 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2096 return QCBOR_ERR_TOO_MANY_TAGS;
2097 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002098 pTags->puTags[pTags->uNumUsed] = ConvertTag(me,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002099 pTags->uNumUsed++;
2100 }
2101 }
2102
2103 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002104}
2105
2106
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002107/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302108 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302109 next one down. If a layer has no work to do for a particular item
2110 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002111
Laurence Lundblade59289e52019-12-30 13:44:37 -08002112 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2113 tagged data items, turning them into the local C representation.
2114 For the most simple it is just associating a QCBOR_TYPE with the data. For
2115 the complex ones that an aggregate of data items, there is some further
2116 decoding and a little bit of recursion.
2117
2118 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302119 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302120 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002121 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002122
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302123 - GetNext_MapEntry -- This handles the combining of two
2124 items, the label and the data, that make up a map entry.
2125 It only does work on maps. It combines the label and data
2126 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002127
Laurence Lundblade59289e52019-12-30 13:44:37 -08002128 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2129 tags into bit flags associated with the data item. No actual decoding
2130 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002131
Laurence Lundblade59289e52019-12-30 13:44:37 -08002132 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302133 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302134 string allocater to create contiguous space for the item. It
2135 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002136
Laurence Lundblade59289e52019-12-30 13:44:37 -08002137 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2138 atomic data item has a "major type", an integer "argument" and optionally
2139 some content. For text and byte strings, the content is the bytes
2140 that make up the string. These are the smallest data items that are
2141 considered to be well-formed. The content may also be other data items in
2142 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002143
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002144 Roughly this takes 300 bytes of stack for vars. Need to
2145 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002146
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302147 */
2148
2149
2150/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002151 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002152 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002153bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002154 const QCBORItem *pItem,
2155 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002156{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002157 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2158 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002159 break;
2160 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002161 if(ConvertTag(me, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002162 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002163 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002164 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002165
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002166 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002167}
2168
2169
2170/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002171 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002172 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002173QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002174{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002175 QCBORError uReturn = me->uLastError;
2176
2177 if(uReturn != QCBOR_SUCCESS) {
2178 goto Done;
2179 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002180
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002181 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002182 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002183 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002184 goto Done;
2185 }
2186
2187 // Error out if not all the bytes are consumed
2188 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002189 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002190 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002191
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002192Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002193#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade6de37062018-10-15 12:22:42 +05302194 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002195 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002196 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002197#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002198
Laurence Lundblade085d7952020-07-24 10:26:30 -07002199 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002200}
2201
2202
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002203/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002204 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002205*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002206// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002207uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2208 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002209 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002210{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002211 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2212 return CBOR_TAG_INVALID64;
2213 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002214 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2215 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002216 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002217 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002218 }
2219}
2220
Laurence Lundblade9b334962020-08-27 10:55:53 -07002221/*
2222 Public function, see header qcbor/qcbor_decode.h file
2223*/
2224uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2225 uint32_t uIndex)
2226{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002227 if(pMe->uLastError != QCBOR_SUCCESS) {
2228 return CBOR_TAG_INVALID64;
2229 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002230 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2231 return CBOR_TAG_INVALID64;
2232 } else {
2233 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2234 }
2235}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002236
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002237/*
2238
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002239Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002240
Laurence Lundbladeee851742020-01-08 08:37:05 -08002241 - Hit end of input before it was expected while decoding type and
2242 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002243
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002244 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002245
Laurence Lundbladeee851742020-01-08 08:37:05 -08002246 - Hit end of input while decoding a text or byte string
2247 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002248
Laurence Lundbladeee851742020-01-08 08:37:05 -08002249 - Encountered conflicting tags -- e.g., an item is tagged both a date
2250 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002251
Laurence Lundbladeee851742020-01-08 08:37:05 -08002252 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002253 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002254
Laurence Lundbladeee851742020-01-08 08:37:05 -08002255 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002256 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002257
Laurence Lundbladeee851742020-01-08 08:37:05 -08002258 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2259 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002260
Laurence Lundbladeee851742020-01-08 08:37:05 -08002261 - The type of a map label is not a string or int
2262 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002263
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002264 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002265
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002266 */
2267
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002268
2269
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002270#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002271
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002272/* ===========================================================================
2273 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002274
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002275 This implements a simple sting allocator for indefinite length
2276 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2277 implements the function type QCBORStringAllocate and allows easy
2278 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002279
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002280 This particular allocator is built-in for convenience. The caller
2281 can implement their own. All of this following code will get
2282 dead-stripped if QCBORDecode_SetMemPool() is not called.
2283
2284 This is a very primitive memory allocator. It does not track
2285 individual allocations, only a high-water mark. A free or
2286 reallocation must be of the last chunk allocated.
2287
2288 The size of the pool and offset to free memory are packed into the
2289 first 8 bytes of the memory pool so we don't have to keep them in
2290 the decode context. Since the address of the pool may not be
2291 aligned, they have to be packed and unpacked as if they were
2292 serialized data of the wire or such.
2293
2294 The sizes packed in are uint32_t to be the same on all CPU types
2295 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002296 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002297
2298
Laurence Lundbladeee851742020-01-08 08:37:05 -08002299static inline int
2300MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002301{
2302 // Use of UsefulInputBuf is overkill, but it is convenient.
2303 UsefulInputBuf UIB;
2304
Laurence Lundbladeee851742020-01-08 08:37:05 -08002305 // Just assume the size here. It was checked during SetUp so
2306 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002307 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002308 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2309 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2310 return UsefulInputBuf_GetError(&UIB);
2311}
2312
2313
Laurence Lundbladeee851742020-01-08 08:37:05 -08002314static inline int
2315MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002316{
2317 // Use of UsefulOutBuf is overkill, but convenient. The
2318 // length check performed here is useful.
2319 UsefulOutBuf UOB;
2320
2321 UsefulOutBuf_Init(&UOB, Pool);
2322 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2323 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2324 return UsefulOutBuf_GetError(&UOB);
2325}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002326
2327
2328/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002329 Internal function for an allocation, reallocation free and destuct.
2330
2331 Having only one function rather than one each per mode saves space in
2332 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002333
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002334 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2335 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002336static UsefulBuf
2337MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002338{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002339 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002340
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002341 uint32_t uPoolSize;
2342 uint32_t uFreeOffset;
2343
2344 if(uNewSize > UINT32_MAX) {
2345 // This allocator is only good up to 4GB. This check should
2346 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2347 goto Done;
2348 }
2349 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2350
2351 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2352 goto Done;
2353 }
2354
2355 if(uNewSize) {
2356 if(pMem) {
2357 // REALLOCATION MODE
2358 // Calculate pointer to the end of the memory pool. It is
2359 // assumed that pPool + uPoolSize won't wrap around by
2360 // assuming the caller won't pass a pool buffer in that is
2361 // not in legitimate memory space.
2362 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2363
2364 // Check that the pointer for reallocation is in the range of the
2365 // pool. This also makes sure that pointer math further down
2366 // doesn't wrap under or over.
2367 if(pMem >= pPool && pMem < pPoolEnd) {
2368 // Offset to start of chunk for reallocation. This won't
2369 // wrap under because of check that pMem >= pPool. Cast
2370 // is safe because the pool is always less than UINT32_MAX
2371 // because of check in QCBORDecode_SetMemPool().
2372 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2373
2374 // Check to see if the allocation will fit. uPoolSize -
2375 // uMemOffset will not wrap under because of check that
2376 // pMem is in the range of the uPoolSize by check above.
2377 if(uNewSize <= uPoolSize - uMemOffset) {
2378 ReturnValue.ptr = pMem;
2379 ReturnValue.len = uNewSize;
2380
2381 // Addition won't wrap around over because uNewSize was
2382 // checked to be sure it is less than the pool size.
2383 uFreeOffset = uMemOffset + uNewSize32;
2384 }
2385 }
2386 } else {
2387 // ALLOCATION MODE
2388 // uPoolSize - uFreeOffset will not underflow because this
2389 // pool implementation makes sure uFreeOffset is always
2390 // smaller than uPoolSize through this check here and
2391 // reallocation case.
2392 if(uNewSize <= uPoolSize - uFreeOffset) {
2393 ReturnValue.len = uNewSize;
2394 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002395 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002396 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002397 }
2398 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002399 if(pMem) {
2400 // FREE MODE
2401 // Cast is safe because of limit on pool size in
2402 // QCBORDecode_SetMemPool()
2403 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2404 } else {
2405 // DESTRUCT MODE
2406 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002407 }
2408 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002409
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002410 UsefulBuf Pool = {pPool, uPoolSize};
2411 MemPool_Pack(Pool, uFreeOffset);
2412
2413Done:
2414 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002415}
2416
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002417
Laurence Lundbladef6531662018-12-04 10:42:22 +09002418/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002419 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002420 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002421QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2422 UsefulBuf Pool,
2423 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002424{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002425 // The pool size and free mem offset are packed into the beginning
2426 // of the pool memory. This compile time check make sure the
2427 // constant in the header is correct. This check should optimize
2428 // down to nothing.
2429 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002430 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002431 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002432
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002433 // The pool size and free offset packed in to the beginning of pool
2434 // memory are only 32-bits. This check will optimize out on 32-bit
2435 // machines.
2436 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002437 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002438 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002439
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002440 // This checks that the pool buffer given is big enough.
2441 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002442 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002443 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002444
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002445 pMe->StringAllocator.pfAllocator = MemPool_Function;
2446 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2447 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002448
Laurence Lundblade30816f22018-11-10 13:40:22 +07002449 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002450}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002451#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002452
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002453
2454
Laurence Lundblade9b334962020-08-27 10:55:53 -07002455static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2456{
2457 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2458}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002459
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002460
2461/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002462 Consume an entire map or array (and do next to
2463 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002464 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002465static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002466ConsumeItem(QCBORDecodeContext *pMe,
2467 const QCBORItem *pItemToConsume,
2468 uint_fast8_t *puNextNestLevel)
2469{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002470 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002471 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002472
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002473 // If it is a map or array, this will tell if it is empty.
2474 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2475
2476 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2477 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002478
Laurence Lundblade1341c592020-04-11 14:19:05 -07002479 /* This works for definite and indefinite length
2480 * maps and arrays by using the nesting level
2481 */
2482 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002483 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002484 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002485 goto Done;
2486 }
2487 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002488
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002489 *puNextNestLevel = Item.uNextNestLevel;
2490
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002491 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002492
Laurence Lundblade1341c592020-04-11 14:19:05 -07002493 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002494 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002495 /* Just pass the nesting level through */
2496 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2497
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002498 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002499 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002500
2501Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002502 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002503}
2504
2505
Laurence Lundblade1341c592020-04-11 14:19:05 -07002506/* Return true if the labels in Item1 and Item2 are the same.
2507 Works only for integer and string labels. Returns false
2508 for any other type. */
2509static inline bool
2510MatchLabel(QCBORItem Item1, QCBORItem Item2)
2511{
2512 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2513 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2514 return true;
2515 }
2516 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002517 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002518 return true;
2519 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002520 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002521 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2522 return true;
2523 }
2524 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2525 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2526 return true;
2527 }
2528 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002529
Laurence Lundblade1341c592020-04-11 14:19:05 -07002530 /* Other label types are never matched */
2531 return false;
2532}
2533
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002534
2535/*
2536 Returns true if Item1 and Item2 are the same type
2537 or if either are of QCBOR_TYPE_ANY.
2538 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002539static inline bool
2540MatchType(QCBORItem Item1, QCBORItem Item2)
2541{
2542 if(Item1.uDataType == Item2.uDataType) {
2543 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002544 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002545 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002546 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002547 return true;
2548 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002549 return false;
2550}
2551
2552
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002553/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002554 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002555
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002556 @param[in] pMe The decode context to search.
2557 @param[in,out] pItemArray The items to search for and the items found.
2558 @param[out] puOffset Byte offset of last item matched.
2559 @param[in] pCBContext Context for the not-found item call back.
2560 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002561
2562 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2563
Laurence Lundblade93d89472020-10-03 22:30:50 -07002564 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2565 were found for one of the labels being
2566 search for. This duplicate detection is
2567 only performed for items in pItemArray,
2568 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002569
Laurence Lundblade93d89472020-10-03 22:30:50 -07002570 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2571 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002572
2573 @retval Also errors returned by QCBORDecode_GetNext().
2574
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002575 On input pItemArray contains a list of labels and data types
2576 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002577
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002578 On output the fully retrieved items are filled in with
2579 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002580
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002581 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002582
2583 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002584 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002585static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002586MapSearch(QCBORDecodeContext *pMe,
2587 QCBORItem *pItemArray,
2588 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002589 void *pCBContext,
2590 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002591{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002592 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002593 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002594
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002595 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002596 uReturn = pMe->uLastError;
2597 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002598 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002599
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002600 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002601 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2602 /* QCBOR_TYPE_NONE as first item indicates just looking
2603 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002604 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2605 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002606 }
2607
Laurence Lundblade085d7952020-07-24 10:26:30 -07002608 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2609 // It is an empty bounded array or map
2610 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2611 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002612 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002613 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002614 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002615 // Nothing is ever found in an empty array or map. All items
2616 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002617 uReturn = QCBOR_SUCCESS;
2618 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002619 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002620 }
2621
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002622 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002623 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2624
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002625 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002626 UsefulInputBuf_Seek(&(pMe->InBuf),
2627 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002628
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002629 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002630 Loop over all the items in the map or array. Each item
2631 could be a map or array, but label matching is only at
2632 the main level. This handles definite and indefinite
2633 length maps and arrays. The only reason this is ever
2634 called on arrays is to find their end position.
2635
2636 This will always run over all items in order to do
2637 duplicate detection.
2638
2639 This will exit with failure if it encounters an
2640 unrecoverable error, but continue on for recoverable
2641 errors.
2642
2643 If a recoverable error occurs on a matched item, then
2644 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002645 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002646 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002647 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002648 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002649 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002650 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002651
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002652 /* Get the item */
2653 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002654 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2655 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002656 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002657 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002658 goto Done;
2659 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002660 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002661 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002662 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002663 goto Done;
2664 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002665
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002666 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002667 bool bMatched = false;
2668 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2669 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002670 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002671 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2672 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002673 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002674 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002675 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002676 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002677 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002678 goto Done;
2679 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002680
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002681 if(uResult != QCBOR_SUCCESS) {
2682 uReturn = uResult;
2683 goto Done;
2684 }
2685
Laurence Lundblade1341c592020-04-11 14:19:05 -07002686 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002687 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002688 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002689 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002690 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002691 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002692 bMatched = true;
2693 }
2694 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002695
2696
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002697 if(!bMatched && pfCallback != NULL) {
2698 /*
2699 Call the callback on unmatched labels.
2700 (It is tempting to do duplicate detection here, but that would
2701 require dynamic memory allocation because the number of labels
2702 that might be encountered is unbounded.)
2703 */
2704 uReturn = (*pfCallback)(pCBContext, &Item);
2705 if(uReturn != QCBOR_SUCCESS) {
2706 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002707 }
2708 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002709
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002710 /*
2711 Consume the item whether matched or not. This
2712 does the work of traversing maps and array and
2713 everything in them. In this loop only the
2714 items at the current nesting level are examined
2715 to match the labels.
2716 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002717 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002718 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002719 goto Done;
2720 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002721
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002722 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002723
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002724 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002725
2726 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002727
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002728 // Check here makes sure that this won't accidentally be
2729 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002730 // QCBOR_MAX_DECODE_INPUT_SIZE.
2731 if(uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
2732 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2733 goto Done;
2734 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002735 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2736 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002737
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002738 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002739 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2740
2741 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002742 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002743 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002744 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002745 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2746 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002747 }
2748 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002749
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002750 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002751}
2752
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002753
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002754/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002755 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002756*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002757void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2758 int64_t nLabel,
2759 uint8_t uQcborType,
2760 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002761{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002762 if(pMe->uLastError != QCBOR_SUCCESS) {
2763 return;
2764 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002765
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002766 QCBORItem OneItemSeach[2];
2767 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2768 OneItemSeach[0].label.int64 = nLabel;
2769 OneItemSeach[0].uDataType = uQcborType;
2770 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002771
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002772 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002773
2774 *pItem = OneItemSeach[0];
2775
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002776 if(uReturn != QCBOR_SUCCESS) {
2777 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002778 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002779 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002780 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002781 }
2782
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002783 Done:
2784 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002785}
2786
2787
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002788/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002789 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002790*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002791void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2792 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002793 uint8_t uQcborType,
2794 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002795{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002796 if(pMe->uLastError != QCBOR_SUCCESS) {
2797 return;
2798 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002799
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002800 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002801 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2802 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2803 OneItemSeach[0].uDataType = uQcborType;
2804 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002805
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002806 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2807 if(uReturn != QCBOR_SUCCESS) {
2808 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002809 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002810 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002811 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002812 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002813 }
2814
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002815 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002816
2817Done:
2818 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002819}
2820
2821
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002822
Laurence Lundblade93d89472020-10-03 22:30:50 -07002823static QCBORError
2824CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002825{
2826 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2827 if(uDataType == puTypeList[i]) {
2828 return QCBOR_SUCCESS;
2829 }
2830 }
2831 return QCBOR_ERR_UNEXPECTED_TYPE;
2832}
2833
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002834
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002835/**
2836 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002837 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002838
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002839 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2840 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002841
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002842 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
2843 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002844 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002845static QCBORError
2846CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002847{
2848 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2849 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2850 /* There are tags that QCBOR couldn't process on this item and
2851 the caller has told us there should not be. */
2852 return QCBOR_ERR_UNEXPECTED_TYPE;
2853 }
2854
2855 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2856 const int nItemType = pItem->uDataType;
2857
2858 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2859 // Must match the tag and only the tag
2860 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2861 }
2862
2863 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2864 if(uReturn == QCBOR_SUCCESS) {
2865 return QCBOR_SUCCESS;
2866 }
2867
2868 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2869 /* Must match the content type and only the content type.
2870 There was no match just above so it is a fail. */
2871 return QCBOR_ERR_UNEXPECTED_TYPE;
2872 }
2873
2874 /* If here it can match either the tag or the content
2875 and it hasn't matched the content, so the end
2876 result is whether it matches the tag. This is
2877 also the case that the CBOR standard discourages. */
2878
2879 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2880}
2881
Laurence Lundblade9b334962020-08-27 10:55:53 -07002882
Laurence Lundblade9b334962020-08-27 10:55:53 -07002883
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002884// This could be semi-private if need be
2885static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002886void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2887 int64_t nLabel,
2888 TagSpecification TagSpec,
2889 QCBORItem *pItem)
2890{
2891 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2892 if(pMe->uLastError != QCBOR_SUCCESS) {
2893 return;
2894 }
2895
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002896 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002897}
2898
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002899
2900// This could be semi-private if need be
2901static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002902void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2903 const char *szLabel,
2904 TagSpecification TagSpec,
2905 QCBORItem *pItem)
2906{
2907 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2908 if(pMe->uLastError != QCBOR_SUCCESS) {
2909 return;
2910 }
2911
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002912 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002913}
2914
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002915// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002916void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2917 int64_t nLabel,
2918 TagSpecification TagSpec,
2919 UsefulBufC *pString)
2920{
2921 QCBORItem Item;
2922 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2923 if(pMe->uLastError == QCBOR_SUCCESS) {
2924 *pString = Item.val.string;
2925 }
2926}
2927
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002928// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002929void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2930 const char * szLabel,
2931 TagSpecification TagSpec,
2932 UsefulBufC *pString)
2933{
2934 QCBORItem Item;
2935 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2936 if(pMe->uLastError == QCBOR_SUCCESS) {
2937 *pString = Item.val.string;
2938 }
2939}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002940
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002941/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002942 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002943*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002944void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002945{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002946 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
2947 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002948}
2949
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002950/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002951 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002952*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002953void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
2954 QCBORItem *pItemList,
2955 void *pCallbackCtx,
2956 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002957{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002958 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
2959 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002960}
2961
2962
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08002963/**
2964 * @brief Search for a map/array by label and enter it
2965 *
2966 * @param[in] pMe The decode context.
2967 * @param[in] pSearch The map/array to search for.
2968 *
2969 * @c pSearch is expected to contain one item of type map or array
2970 * with the label specified. The current bounded map will be searched for
2971 * this and if found will be entered.
2972 *
2973 * If the label is not found, or the item found is not a map or array,
2974 * the error state is set.
2975 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07002976static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07002977{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002978 // The first item in pSearch is the one that is to be
2979 // entered. It should be the only one filled in. Any other
2980 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07002981 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07002982 return;
2983 }
2984
2985 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002986 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07002987 if(pMe->uLastError != QCBOR_SUCCESS) {
2988 return;
2989 }
2990
Laurence Lundblade9b334962020-08-27 10:55:53 -07002991 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002992 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002993 return;
2994 }
2995
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08002996 /*
2997 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
2998 * next item for the pre-order traversal cursor to be the map/array
2999 * found by MapSearch(). The next few lines of code force the
3000 * cursor to that.
3001 *
3002 * There is no need to retain the old cursor because
3003 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3004 * beginning of the map/array being entered.
3005 *
3006 * The cursor is forced by: 1) setting the input buffer position to
3007 * the item offset found by MapSearch(), 2) setting the map/array
3008 * counter to the total in the map/array, 3) setting the nesting
3009 * level. Setting the map/array counter to the total is not
3010 * strictly correct, but this is OK because this cursor only needs
3011 * to be used to get one item and MapSearch() has already found it
3012 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003013 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003014 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003015
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003016 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3017
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003018 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003019
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003020 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003021}
3022
3023
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003024/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003025 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003026*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003027void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003028{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003029 QCBORItem OneItemSeach[2];
3030 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3031 OneItemSeach[0].label.int64 = nLabel;
3032 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3033 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003034
Laurence Lundblade9b334962020-08-27 10:55:53 -07003035 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003036 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003037}
3038
3039
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003040/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003041 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003042*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003043void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003044{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003045 QCBORItem OneItemSeach[2];
3046 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3047 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3048 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3049 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003050
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003051 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003052}
3053
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003054/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003055 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003056*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003057void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003058{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003059 QCBORItem OneItemSeach[2];
3060 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3061 OneItemSeach[0].label.int64 = nLabel;
3062 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3063 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003064
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003065 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003066}
3067
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003068/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003069 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003070*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003071void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3072{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003073 QCBORItem OneItemSeach[2];
3074 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3075 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3076 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3077 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003078
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003079 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003080}
3081
3082
Laurence Lundblade02625d42020-06-25 14:41:41 -07003083// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003084void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003085{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003086 QCBORError uErr;
3087
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003088 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003089 if(pMe->uLastError != QCBOR_SUCCESS) {
3090 // Already in error state; do nothing.
3091 return;
3092 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003093
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003094 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003095 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003096 uErr = QCBORDecode_GetNext(pMe, &Item);
3097 if(uErr != QCBOR_SUCCESS) {
3098 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003099 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003100 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003101 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3102 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003103 }
3104
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003105 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003106
3107
Laurence Lundbladef0499502020-08-01 11:55:57 -07003108 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003109 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003110 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3111 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003112 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003113 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3114 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003115 // Special case to increment nesting level for zero-length maps
3116 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003117 DecodeNesting_Descend(&(pMe->nesting), uType);
3118 }
3119
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003120 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003121
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003122 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3123 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003124
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003125 if(pItem != NULL) {
3126 *pItem = Item;
3127 }
3128
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003129Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003130 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003131}
3132
Laurence Lundblade02625d42020-06-25 14:41:41 -07003133
3134/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003135 This is the common work for exiting a level that is a bounded map,
3136 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003137
3138 One chunk of work is to set up the pre-order traversal so it is at
3139 the item just after the bounded map, array or bstr that is being
3140 exited. This is somewhat complex.
3141
3142 The other work is to level-up the bounded mode to next higest bounded
3143 mode or the top level if there isn't one.
3144 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003145static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003146ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003147{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003148 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003149
Laurence Lundblade02625d42020-06-25 14:41:41 -07003150 /*
3151 First the pre-order-traversal byte offset is positioned to the
3152 item just after the bounded mode item that was just consumed.
3153 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003154 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3155
Laurence Lundblade02625d42020-06-25 14:41:41 -07003156 /*
3157 Next, set the current nesting level to one above the bounded level
3158 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003159
Laurence Lundblade02625d42020-06-25 14:41:41 -07003160 DecodeNesting_CheckBoundedType() is always called before this and
3161 makes sure pCurrentBounded is valid.
3162 */
3163 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3164
3165 /*
3166 This does the complex work of leveling up the pre-order traversal
3167 when the end of a map or array or another bounded level is
3168 reached. It may do nothing, or ascend all the way to the top
3169 level.
3170 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003171 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003172 if(uErr != QCBOR_SUCCESS) {
3173 goto Done;
3174 }
3175
Laurence Lundblade02625d42020-06-25 14:41:41 -07003176 /*
3177 This makes the next highest bounded level the current bounded
3178 level. If there is no next highest level, then no bounded mode is
3179 in effect.
3180 */
3181 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003182
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003183 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003184
3185Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003186 return uErr;
3187}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003188
Laurence Lundblade02625d42020-06-25 14:41:41 -07003189
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003190// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003191void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003192{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003193 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003194 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003195 return;
3196 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003197
Laurence Lundblade02625d42020-06-25 14:41:41 -07003198 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003199
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003200 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003201 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003202 goto Done;
3203 }
3204
Laurence Lundblade02625d42020-06-25 14:41:41 -07003205 /*
3206 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003207 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003208 from previous map search, then do a dummy search.
3209 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003210 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003211 QCBORItem Dummy;
3212 Dummy.uLabelType = QCBOR_TYPE_NONE;
3213 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3214 if(uErr != QCBOR_SUCCESS) {
3215 goto Done;
3216 }
3217 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003218
Laurence Lundblade02625d42020-06-25 14:41:41 -07003219 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003220
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003221Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003222 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003223}
3224
3225
Laurence Lundblade1341c592020-04-11 14:19:05 -07003226
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003227static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003228 const QCBORItem *pItem,
3229 uint8_t uTagRequirement,
3230 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003231{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003232 if(pBstr) {
3233 *pBstr = NULLUsefulBufC;
3234 }
3235
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003236 if(pMe->uLastError != QCBOR_SUCCESS) {
3237 // Already in error state; do nothing.
3238 return pMe->uLastError;
3239 }
3240
3241 QCBORError uError = QCBOR_SUCCESS;
3242
3243 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3244 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3245 goto Done;;
3246 }
3247
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003248 const TagSpecification TagSpec =
3249 {
3250 uTagRequirement,
3251 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3252 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3253 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003254
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003255 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003256 if(uError != QCBOR_SUCCESS) {
3257 goto Done;
3258 }
3259
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003260 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003261 // Reverse the decrement done by GetNext() for the bstr so the
3262 // increment in NestLevelAscender() called by ExitBoundedLevel()
3263 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003264 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003265 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003266
3267 if(pBstr) {
3268 *pBstr = pItem->val.string;
3269 }
3270
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003271 // This saves the current length of the UsefulInputBuf and then
3272 // narrows the UsefulInputBuf to start and length of the wrapped
3273 // CBOR that is being entered.
3274 //
3275 // This makes sure the length is less than
3276 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3277 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3278 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3279 // the casts safe. uEndOfBstr will always be less than
3280 // uPreviousLength because of the way UsefulInputBuf works so there
3281 // is no need to check it. There is also a range check in the
3282 // seek.
3283 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003284 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003285 // amount to much code.
3286 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3287 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003288 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003289 goto Done;
3290 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003291 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003292 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003293 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003294
Laurence Lundblade02625d42020-06-25 14:41:41 -07003295 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003296 (uint32_t)uPreviousLength,
3297 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003298Done:
3299 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003300}
3301
3302
Laurence Lundblade02625d42020-06-25 14:41:41 -07003303/*
3304 Public function, see header qcbor/qcbor_decode.h file
3305 */
3306void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003307 uint8_t uTagRequirement,
3308 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003309{
3310 if(pMe->uLastError != QCBOR_SUCCESS) {
3311 // Already in error state; do nothing.
3312 return;
3313 }
3314
3315 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003316 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003317 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3318 if(pMe->uLastError != QCBOR_SUCCESS) {
3319 return;
3320 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003321
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003322 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003323 &Item,
3324 uTagRequirement,
3325 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003326}
3327
3328
Laurence Lundblade02625d42020-06-25 14:41:41 -07003329/*
3330 Public function, see header qcbor/qcbor_decode.h file
3331 */
3332void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003333 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003334 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003335 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003336{
3337 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003338 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003339
Laurence Lundblade93d89472020-10-03 22:30:50 -07003340 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3341 &Item,
3342 uTagRequirement,
3343 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003344}
3345
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003346
Laurence Lundblade02625d42020-06-25 14:41:41 -07003347/*
3348 Public function, see header qcbor/qcbor_decode.h file
3349 */
3350void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003351 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003352 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003353 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003354{
3355 QCBORItem Item;
3356 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3357
Laurence Lundblade93d89472020-10-03 22:30:50 -07003358 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3359 &Item,
3360 uTagRequirement,
3361 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003362}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003363
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003364
Laurence Lundblade02625d42020-06-25 14:41:41 -07003365/*
3366 Public function, see header qcbor/qcbor_decode.h file
3367 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003368void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003369{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003370 if(pMe->uLastError != QCBOR_SUCCESS) {
3371 // Already in error state; do nothing.
3372 return;
3373 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003374
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003375 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003376 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003377 return;
3378 }
3379
3380 /*
3381 Reset the length of the UsefulInputBuf to what it was before
3382 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003383 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003384 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003385 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003386
3387
Laurence Lundblade02625d42020-06-25 14:41:41 -07003388 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003389 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003390}
3391
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003392
Laurence Lundbladee6430642020-03-14 21:15:44 -07003393
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003394
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003395
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003396
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003397
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003398
Laurence Lundblade93d89472020-10-03 22:30:50 -07003399static QCBORError
3400InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003401{
3402 switch(pItem->uDataType) {
3403 case QCBOR_TYPE_TRUE:
3404 *pBool = true;
3405 return QCBOR_SUCCESS;
3406 break;
3407
3408 case QCBOR_TYPE_FALSE:
3409 *pBool = false;
3410 return QCBOR_SUCCESS;
3411 break;
3412
3413 default:
3414 return QCBOR_ERR_UNEXPECTED_TYPE;
3415 break;
3416 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003417 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003418}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003419
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003420
Laurence Lundblade9b334962020-08-27 10:55:53 -07003421
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003422/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003423 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003424*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003425void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003426{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003427 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003428 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003429 return;
3430 }
3431
Laurence Lundbladec4537442020-04-14 18:53:22 -07003432 QCBORError nError;
3433 QCBORItem Item;
3434
3435 nError = QCBORDecode_GetNext(pMe, &Item);
3436 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003437 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003438 return;
3439 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003440 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003441}
3442
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003443
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003444/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003445 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003446*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003447void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003448{
3449 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003450 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003451
Laurence Lundblade9b334962020-08-27 10:55:53 -07003452 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003453}
3454
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003455
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003456/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003457 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003458*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003459void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3460{
3461 QCBORItem Item;
3462 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3463
Laurence Lundblade9b334962020-08-27 10:55:53 -07003464 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003465}
3466
3467
3468
Laurence Lundbladec7114722020-08-13 05:11:40 -07003469
3470static void ProcessEpochDate(QCBORDecodeContext *pMe,
3471 QCBORItem *pItem,
3472 uint8_t uTagRequirement,
3473 int64_t *pnTime)
3474{
3475 if(pMe->uLastError != QCBOR_SUCCESS) {
3476 // Already in error state, do nothing
3477 return;
3478 }
3479
3480 QCBORError uErr;
3481
3482 const TagSpecification TagSpec =
3483 {
3484 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003485 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3486 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003487 };
3488
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003489 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003490 if(uErr != QCBOR_SUCCESS) {
3491 goto Done;
3492 }
3493
3494 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3495 uErr = DecodeDateEpoch(pItem);
3496 if(uErr != QCBOR_SUCCESS) {
3497 goto Done;
3498 }
3499 }
3500
Laurence Lundblade9b334962020-08-27 10:55:53 -07003501 // Save the tags in the last item's tags in the decode context
3502 // for QCBORDecode_GetNthTagOfLast()
3503 CopyTags(pMe, pItem);
3504
Laurence Lundbladec7114722020-08-13 05:11:40 -07003505 *pnTime = pItem->val.epochDate.nSeconds;
3506
3507Done:
3508 pMe->uLastError = (uint8_t)uErr;
3509}
3510
3511
3512void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003513 uint8_t uTagRequirement,
3514 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003515{
3516 if(pMe->uLastError != QCBOR_SUCCESS) {
3517 // Already in error state, do nothing
3518 return;
3519 }
3520
3521 QCBORItem Item;
3522 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3523
3524 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3525}
3526
3527
3528void
3529QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3530 int64_t nLabel,
3531 uint8_t uTagRequirement,
3532 int64_t *pnTime)
3533{
3534 QCBORItem Item;
3535 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3536 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3537}
3538
3539
3540void
3541QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3542 const char *szLabel,
3543 uint8_t uTagRequirement,
3544 int64_t *pnTime)
3545{
3546 QCBORItem Item;
3547 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3548 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3549}
3550
3551
3552
3553
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003554void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3555 TagSpecification TagSpec,
3556 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003557{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003558 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003559 // Already in error state, do nothing
3560 return;
3561 }
3562
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003563 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003564 QCBORItem Item;
3565
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003566 uError = QCBORDecode_GetNext(pMe, &Item);
3567 if(uError != QCBOR_SUCCESS) {
3568 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003569 return;
3570 }
3571
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003572 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003573
3574 if(pMe->uLastError == QCBOR_SUCCESS) {
3575 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003576 } else {
3577 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003578 }
3579}
3580
Laurence Lundbladec4537442020-04-14 18:53:22 -07003581
3582
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003583
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003584static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003585 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003586 UsefulBufC *pValue,
3587 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003588{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003589 const TagSpecification TagSpec =
3590 {
3591 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003592 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3593 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003594 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003595
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003596 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003597 if(uErr != QCBOR_SUCCESS) {
3598 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003599 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003600
3601 *pValue = pItem->val.string;
3602
3603 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3604 *pbIsNegative = false;
3605 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3606 *pbIsNegative = true;
3607 }
3608
3609 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003610}
3611
3612
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003613/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003614 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003615 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003616void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3617 uint8_t uTagRequirement,
3618 UsefulBufC *pValue,
3619 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003620{
3621 if(pMe->uLastError != QCBOR_SUCCESS) {
3622 // Already in error state, do nothing
3623 return;
3624 }
3625
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003626 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003627 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3628 if(uError != QCBOR_SUCCESS) {
3629 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003630 return;
3631 }
3632
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003633 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003634}
3635
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003636
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003637/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003638 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003639*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003640void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3641 int64_t nLabel,
3642 uint8_t uTagRequirement,
3643 UsefulBufC *pValue,
3644 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003645{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003646 QCBORItem Item;
3647 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003648 if(pMe->uLastError != QCBOR_SUCCESS) {
3649 return;
3650 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003651
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003652 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003653}
3654
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003655
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003656/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003657 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003658*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003659void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3660 const char *szLabel,
3661 uint8_t uTagRequirement,
3662 UsefulBufC *pValue,
3663 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003664{
3665 QCBORItem Item;
3666 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003667 if(pMe->uLastError != QCBOR_SUCCESS) {
3668 return;
3669 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003670
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003671 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003672}
3673
3674
3675
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003676
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003677// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003678QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3679 const QCBORItem *pItem,
3680 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003681 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003682{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003683 const TagSpecification TagSpecText =
3684 {
3685 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003686 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3687 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003688 };
3689 const TagSpecification TagSpecBinary =
3690 {
3691 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003692 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3693 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003694 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003695
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003696 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003697
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003698 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003699 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003700 if(pbIsTag257 != NULL) {
3701 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003702 }
3703 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003704 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003705 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003706 if(pbIsTag257 != NULL) {
3707 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003708 }
3709 uReturn = QCBOR_SUCCESS;
3710
3711 } else {
3712 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3713 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003714
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003715 return uReturn;
3716}
3717
Laurence Lundblade93d89472020-10-03 22:30:50 -07003718// Improvement: add methods for wrapped CBOR, a simple alternate
3719// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003720
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003721
3722
3723
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003724#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003725
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003726typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003727
3728
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003729// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003730static QCBORError
3731Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003732{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003733 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003734
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003735 if(uResult != 0) {
3736 /* This loop will run a maximum of 19 times because
3737 * UINT64_MAX < 10 ^^ 19. More than that will cause
3738 * exit with the overflow error
3739 */
3740 for(; nExponent > 0; nExponent--) {
3741 if(uResult > UINT64_MAX / 10) {
3742 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3743 }
3744 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003745 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003746
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003747 for(; nExponent < 0; nExponent++) {
3748 uResult = uResult / 10;
3749 if(uResult == 0) {
3750 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3751 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003752 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003753 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003754 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003755
3756 *puResult = uResult;
3757
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003758 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003759}
3760
3761
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003762// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003763static QCBORError
3764Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003765{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003766 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003767
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003768 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003769
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003770 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003771 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003772 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003773 */
3774 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003775 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003776 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003777 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003778 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003779 nExponent--;
3780 }
3781
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003782 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003783 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003784 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3785 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003786 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003787 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003788 }
3789
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003790 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003791
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003792 return QCBOR_SUCCESS;
3793}
3794
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003795
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003796/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003797 Compute value with signed mantissa and signed result. Works with
3798 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003799 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003800static inline QCBORError ExponentiateNN(int64_t nMantissa,
3801 int64_t nExponent,
3802 int64_t *pnResult,
3803 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003804{
3805 uint64_t uResult;
3806
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003807 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003808 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003809 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3810
3811 // Do the exponentiation of the positive mantissa
3812 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3813 if(uReturn) {
3814 return uReturn;
3815 }
3816
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003817
Laurence Lundblade983500d2020-05-14 11:49:34 -07003818 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3819 of INT64_MIN. This assumes two's compliment representation where
3820 INT64_MIN is one increment farther from 0 than INT64_MAX.
3821 Trying to write -INT64_MIN doesn't work to get this because the
3822 compiler tries to work with an int64_t which can't represent
3823 -INT64_MIN.
3824 */
3825 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3826
3827 // Error out if too large
3828 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003829 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3830 }
3831
3832 // Casts are safe because of checks above
3833 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3834
3835 return QCBOR_SUCCESS;
3836}
3837
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003838
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003839/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003840 Compute value with signed mantissa and unsigned result. Works with
3841 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003842 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003843static inline QCBORError ExponentitateNU(int64_t nMantissa,
3844 int64_t nExponent,
3845 uint64_t *puResult,
3846 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003847{
3848 if(nMantissa < 0) {
3849 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3850 }
3851
3852 // Cast to unsigned is OK because of check for negative
3853 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3854 // Exponentiation is straight forward
3855 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3856}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003857
3858
3859/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003860 Compute value with signed mantissa and unsigned result. Works with
3861 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003862 */
3863static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3864 int64_t nExponent,
3865 uint64_t *puResult,
3866 fExponentiator pfExp)
3867{
3868 return (*pfExp)(uMantissa, nExponent, puResult);
3869}
3870
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003871#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3872
3873
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003874
3875
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003876
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003877static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003878{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003879 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003880
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003881 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003882 const uint8_t *pByte = BigNum.ptr;
3883 size_t uLen = BigNum.len;
3884 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003885 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003886 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003887 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003888 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003889 }
3890
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003891 *pResult = uResult;
3892 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003893}
3894
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003895
Laurence Lundblade887add82020-05-17 05:50:34 -07003896static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003897{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003898 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003899}
3900
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003901
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003902static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003903{
3904 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003905 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3906 if(uError) {
3907 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003908 }
3909 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3910 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003911 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003912}
3913
3914
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003915static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003916{
3917 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003918 /* The negative integer furthest from zero for a C int64_t is
3919 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3920 negative number in CBOR is computed as -n - 1 where n is the
3921 encoded integer, where n is what is in the variable BigNum. When
3922 converting BigNum to a uint64_t, the maximum value is thus
3923 INT64_MAX, so that when it -n - 1 is applied to it the result will
3924 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003925
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003926 -n - 1 <= INT64_MIN.
3927 -n - 1 <= -INT64_MAX - 1
3928 n <= INT64_MAX.
3929 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003930 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003931 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003932 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003933 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003934
3935 /// Now apply -n - 1. The cast is safe because
3936 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3937 // is the largest positive integer that an int64_t can
3938 // represent. */
3939 *pnResult = -(int64_t)uResult - 1;
3940
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003941 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003942}
3943
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003944
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003945
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003946
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003947
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003948/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003949Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003950
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003951\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003952
Laurence Lundblade93d89472020-10-03 22:30:50 -07003953\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
3954 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003955
3956\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
3957
Laurence Lundblade93d89472020-10-03 22:30:50 -07003958\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
3959 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07003960*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07003961static QCBORError
3962ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003963{
3964 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003965 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003966 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003967#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003968 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003969 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
3970 http://www.cplusplus.com/reference/cmath/llround/
3971 */
3972 // Not interested in FE_INEXACT
3973 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003974 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
3975 *pnValue = llround(pItem->val.dfnum);
3976 } else {
3977 *pnValue = lroundf(pItem->val.fnum);
3978 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003979 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
3980 // llround() shouldn't result in divide by zero, but catch
3981 // it here in case it unexpectedly does. Don't try to
3982 // distinguish between the various exceptions because it seems
3983 // they vary by CPU, compiler and OS.
3984 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003985 }
3986 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003987 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003988 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003989#else
3990 return QCBOR_ERR_HW_FLOAT_DISABLED;
3991#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003992 break;
3993
3994 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003995 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003996 *pnValue = pItem->val.int64;
3997 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07003998 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003999 }
4000 break;
4001
4002 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004003 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004004 if(pItem->val.uint64 < INT64_MAX) {
4005 *pnValue = pItem->val.int64;
4006 } else {
4007 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4008 }
4009 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004010 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004011 }
4012 break;
4013
4014 default:
4015 return QCBOR_ERR_UNEXPECTED_TYPE;
4016 }
4017 return QCBOR_SUCCESS;
4018}
4019
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004020
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004021void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004022 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004023 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004024 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004025{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004026 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004027 return;
4028 }
4029
Laurence Lundbladee6430642020-03-14 21:15:44 -07004030 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004031 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4032 if(uError) {
4033 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004034 return;
4035 }
4036
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004037 if(pItem) {
4038 *pItem = Item;
4039 }
4040
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004041 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004042}
4043
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004044
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004045void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4046 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004047 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004048 int64_t *pnValue,
4049 QCBORItem *pItem)
4050{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004051 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004052 if(pMe->uLastError != QCBOR_SUCCESS) {
4053 return;
4054 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004055
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004056 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004057}
4058
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004059
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004060void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4061 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004062 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004063 int64_t *pnValue,
4064 QCBORItem *pItem)
4065{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004066 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004067 if(pMe->uLastError != QCBOR_SUCCESS) {
4068 return;
4069 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004070
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004071 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004072}
4073
4074
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004075/*
4076 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004077
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004078 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004079
Laurence Lundblade93d89472020-10-03 22:30:50 -07004080 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4081 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004082
4083 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4084
Laurence Lundblade93d89472020-10-03 22:30:50 -07004085 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4086 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004087 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004088static QCBORError
4089Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004090{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004091 switch(pItem->uDataType) {
4092
4093 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004094 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004095 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004096 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004097 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004098 }
4099 break;
4100
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004101 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004102 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004103 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004104 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004105 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004106 }
4107 break;
4108
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004109#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4110 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004111 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004112 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004113 pItem->val.expAndMantissa.nExponent,
4114 pnValue,
4115 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004116 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004117 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004118 }
4119 break;
4120
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004121 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004122 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004123 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004124 pItem->val.expAndMantissa.nExponent,
4125 pnValue,
4126 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004127 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004128 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004129 }
4130 break;
4131
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004132 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004133 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004134 int64_t nMantissa;
4135 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004136 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4137 if(uErr) {
4138 return uErr;
4139 }
4140 return ExponentiateNN(nMantissa,
4141 pItem->val.expAndMantissa.nExponent,
4142 pnValue,
4143 Exponentitate10);
4144 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004145 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004146 }
4147 break;
4148
4149 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004150 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004151 int64_t nMantissa;
4152 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004153 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4154 if(uErr) {
4155 return uErr;
4156 }
4157 return ExponentiateNN(nMantissa,
4158 pItem->val.expAndMantissa.nExponent,
4159 pnValue,
4160 Exponentitate10);
4161 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004162 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004163 }
4164 break;
4165
4166 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004167 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004168 int64_t nMantissa;
4169 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004170 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4171 if(uErr) {
4172 return uErr;
4173 }
4174 return ExponentiateNN(nMantissa,
4175 pItem->val.expAndMantissa.nExponent,
4176 pnValue,
4177 Exponentitate2);
4178 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004179 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004180 }
4181 break;
4182
4183 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004184 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004185 int64_t nMantissa;
4186 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004187 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4188 if(uErr) {
4189 return uErr;
4190 }
4191 return ExponentiateNN(nMantissa,
4192 pItem->val.expAndMantissa.nExponent,
4193 pnValue,
4194 Exponentitate2);
4195 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004196 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004197 }
4198 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004199#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4200
Laurence Lundbladee6430642020-03-14 21:15:44 -07004201
Laurence Lundbladec4537442020-04-14 18:53:22 -07004202 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004203 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004204}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004205
4206
Laurence Lundbladec4537442020-04-14 18:53:22 -07004207/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004208 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004209 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004210void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004211{
4212 QCBORItem Item;
4213
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004214 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004215
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004216 if(pMe->uLastError == QCBOR_SUCCESS) {
4217 // The above conversion succeeded
4218 return;
4219 }
4220
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004221 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004222 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004223 return;
4224 }
4225
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004226 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004227}
4228
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004229
4230/*
4231Public function, see header qcbor/qcbor_decode.h file
4232*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004233void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4234 int64_t nLabel,
4235 uint32_t uConvertTypes,
4236 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004237{
4238 QCBORItem Item;
4239
Laurence Lundblade93d89472020-10-03 22:30:50 -07004240 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4241 nLabel,
4242 uConvertTypes,
4243 pnValue,
4244 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004245
4246 if(pMe->uLastError == QCBOR_SUCCESS) {
4247 // The above conversion succeeded
4248 return;
4249 }
4250
4251 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4252 // The above conversion failed in a way that code below can't correct
4253 return;
4254 }
4255
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004256 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004257}
4258
4259
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004260/*
4261Public function, see header qcbor/qcbor_decode.h file
4262*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004263void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4264 const char *szLabel,
4265 uint32_t uConvertTypes,
4266 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004267{
4268 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004269 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4270 szLabel,
4271 uConvertTypes,
4272 pnValue,
4273 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004274
4275 if(pMe->uLastError == QCBOR_SUCCESS) {
4276 // The above conversion succeeded
4277 return;
4278 }
4279
4280 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4281 // The above conversion failed in a way that code below can't correct
4282 return;
4283 }
4284
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004285 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004286}
4287
4288
Laurence Lundblade93d89472020-10-03 22:30:50 -07004289static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004290{
4291 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004292 case QCBOR_TYPE_DOUBLE:
4293 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004294#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004295 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004296 // Can't use llround here because it will not convert values
4297 // greater than INT64_MAX and less than UINT64_MAX that
4298 // need to be converted so it is more complicated.
4299 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4300 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4301 if(isnan(pItem->val.dfnum)) {
4302 return QCBOR_ERR_FLOAT_EXCEPTION;
4303 } else if(pItem->val.dfnum < 0) {
4304 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4305 } else {
4306 double dRounded = round(pItem->val.dfnum);
4307 // See discussion in DecodeDateEpoch() for
4308 // explanation of - 0x7ff
4309 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4310 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4311 }
4312 *puValue = (uint64_t)dRounded;
4313 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004314 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004315 if(isnan(pItem->val.fnum)) {
4316 return QCBOR_ERR_FLOAT_EXCEPTION;
4317 } else if(pItem->val.fnum < 0) {
4318 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4319 } else {
4320 float fRounded = roundf(pItem->val.fnum);
4321 // See discussion in DecodeDateEpoch() for
4322 // explanation of - 0x7ff
4323 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4324 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4325 }
4326 *puValue = (uint64_t)fRounded;
4327 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004328 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004329 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4330 // round() and roundf() shouldn't result in exceptions here, but
4331 // catch them to be robust and thorough. Don't try to
4332 // distinguish between the various exceptions because it seems
4333 // they vary by CPU, compiler and OS.
4334 return QCBOR_ERR_FLOAT_EXCEPTION;
4335 }
4336
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004337 } else {
4338 return QCBOR_ERR_UNEXPECTED_TYPE;
4339 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004340#else
4341 return QCBOR_ERR_HW_FLOAT_DISABLED;
4342#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004343 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004344
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004345 case QCBOR_TYPE_INT64:
4346 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4347 if(pItem->val.int64 >= 0) {
4348 *puValue = (uint64_t)pItem->val.int64;
4349 } else {
4350 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4351 }
4352 } else {
4353 return QCBOR_ERR_UNEXPECTED_TYPE;
4354 }
4355 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004356
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004357 case QCBOR_TYPE_UINT64:
4358 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4359 *puValue = pItem->val.uint64;
4360 } else {
4361 return QCBOR_ERR_UNEXPECTED_TYPE;
4362 }
4363 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004364
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004365 default:
4366 return QCBOR_ERR_UNEXPECTED_TYPE;
4367 }
4368
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004369 return QCBOR_SUCCESS;
4370}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004371
4372
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004373void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004374 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004375 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004376 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004377{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004378 if(pMe->uLastError != QCBOR_SUCCESS) {
4379 return;
4380 }
4381
Laurence Lundbladec4537442020-04-14 18:53:22 -07004382 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004383
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004384 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4385 if(uError) {
4386 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004387 return;
4388 }
4389
Laurence Lundbladea826c502020-05-10 21:07:00 -07004390 if(pItem) {
4391 *pItem = Item;
4392 }
4393
Laurence Lundblade93d89472020-10-03 22:30:50 -07004394 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004395}
4396
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004397
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004398void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004399 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004400 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004401 uint64_t *puValue,
4402 QCBORItem *pItem)
4403{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004404 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004405 if(pMe->uLastError != QCBOR_SUCCESS) {
4406 return;
4407 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004408
Laurence Lundblade93d89472020-10-03 22:30:50 -07004409 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004410}
4411
4412
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004413void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004414 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004415 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004416 uint64_t *puValue,
4417 QCBORItem *pItem)
4418{
4419 if(pMe->uLastError != QCBOR_SUCCESS) {
4420 return;
4421 }
4422
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004423 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004424 if(pMe->uLastError != QCBOR_SUCCESS) {
4425 return;
4426 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004427
Laurence Lundblade93d89472020-10-03 22:30:50 -07004428 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004429}
4430
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004431
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004432
Laurence Lundblade93d89472020-10-03 22:30:50 -07004433static QCBORError
4434UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004435{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004436 switch(pItem->uDataType) {
4437
4438 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004439 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004440 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4441 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004442 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004443 }
4444 break;
4445
4446 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004447 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004448 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4449 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004450 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004451 }
4452 break;
4453
4454#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4455
4456 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004457 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004458 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004459 pItem->val.expAndMantissa.nExponent,
4460 puValue,
4461 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004462 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004463 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004464 }
4465 break;
4466
4467 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004468 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004469 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4470 pItem->val.expAndMantissa.nExponent,
4471 puValue,
4472 Exponentitate2);
4473 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004474 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004475 }
4476 break;
4477
4478 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004479 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004480 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004481 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004482 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004483 if(uErr != QCBOR_SUCCESS) {
4484 return uErr;
4485 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004486 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004487 pItem->val.expAndMantissa.nExponent,
4488 puValue,
4489 Exponentitate10);
4490 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004491 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004492 }
4493 break;
4494
4495 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004496 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004497 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4498 } 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_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004504 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004505 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004506 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004507 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004508 if(uErr != QCBOR_SUCCESS) {
4509 return uErr;
4510 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004511 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004512 pItem->val.expAndMantissa.nExponent,
4513 puValue,
4514 Exponentitate2);
4515 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004516 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004517 }
4518 break;
4519
4520 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004521 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004522 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4523 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004524 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004525 }
4526 break;
4527#endif
4528 default:
4529 return QCBOR_ERR_UNEXPECTED_TYPE;
4530 }
4531}
4532
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004533
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004534/*
4535 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004536 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004537void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004538{
4539 QCBORItem Item;
4540
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004541 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004542
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004543 if(pMe->uLastError == QCBOR_SUCCESS) {
4544 // The above conversion succeeded
4545 return;
4546 }
4547
4548 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4549 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07004550 return;
4551 }
4552
Laurence Lundblade93d89472020-10-03 22:30:50 -07004553 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004554}
4555
Laurence Lundbladec4537442020-04-14 18:53:22 -07004556
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004557/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004558 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004559*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004560void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004561 int64_t nLabel,
4562 uint32_t uConvertTypes,
4563 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004564{
4565 QCBORItem Item;
4566
Laurence Lundblade93d89472020-10-03 22:30:50 -07004567 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4568 nLabel,
4569 uConvertTypes,
4570 puValue,
4571 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004572
4573 if(pMe->uLastError == QCBOR_SUCCESS) {
4574 // The above conversion succeeded
4575 return;
4576 }
4577
4578 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4579 // The above conversion failed in a way that code below can't correct
4580 return;
4581 }
4582
Laurence Lundblade93d89472020-10-03 22:30:50 -07004583 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004584}
4585
4586
4587/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004588 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004589*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004590void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004591 const char *szLabel,
4592 uint32_t uConvertTypes,
4593 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004594{
4595 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004596 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4597 szLabel,
4598 uConvertTypes,
4599 puValue,
4600 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004601
4602 if(pMe->uLastError == QCBOR_SUCCESS) {
4603 // The above conversion succeeded
4604 return;
4605 }
4606
4607 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4608 // The above conversion failed in a way that code below can't correct
4609 return;
4610 }
4611
Laurence Lundblade93d89472020-10-03 22:30:50 -07004612 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004613}
4614
4615
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004616
4617
Laurence Lundblade9b334962020-08-27 10:55:53 -07004618static QCBORError ConvertDouble(const QCBORItem *pItem,
4619 uint32_t uConvertTypes,
4620 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004621{
4622 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004623 case QCBOR_TYPE_FLOAT:
4624#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4625 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4626 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004627 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004628 *pdValue = (double)pItem->val.fnum;
4629 } else {
4630 return QCBOR_ERR_UNEXPECTED_TYPE;
4631 }
4632 }
4633#else
4634 return QCBOR_ERR_HW_FLOAT_DISABLED;
4635#endif
4636 break;
4637
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004638 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004639 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4640 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004641 *pdValue = pItem->val.dfnum;
4642 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004643 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004644 }
4645 }
4646 break;
4647
4648 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004649#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004650 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004651 // A simple cast seems to do the job with no worry of exceptions.
4652 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004653 *pdValue = (double)pItem->val.int64;
4654
4655 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004656 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004657 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004658#else
4659 return QCBOR_ERR_HW_FLOAT_DISABLED;
4660#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004661 break;
4662
4663 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004664#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004665 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004666 // A simple cast seems to do the job with no worry of exceptions.
4667 // There will be precision loss for some values.
4668 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004669 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004670 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004671 }
4672 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004673#else
4674 return QCBOR_ERR_HW_FLOAT_DISABLED;
4675#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004676
4677 default:
4678 return QCBOR_ERR_UNEXPECTED_TYPE;
4679 }
4680
4681 return QCBOR_SUCCESS;
4682}
4683
4684
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004685void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004686 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004687 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004688 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004689{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004690 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004691 return;
4692 }
4693
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004694 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004695
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004696 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004697 if(uError) {
4698 pMe->uLastError = (uint8_t)uError;
4699 return;
4700 }
4701
4702 if(pItem) {
4703 *pItem = Item;
4704 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004705
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004706 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004707}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004708
Laurence Lundbladec4537442020-04-14 18:53:22 -07004709
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004710void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4711 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004712 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004713 double *pdValue,
4714 QCBORItem *pItem)
4715{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004716 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004717 if(pMe->uLastError != QCBOR_SUCCESS) {
4718 return;
4719 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004720
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004721 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004722}
4723
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004724
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004725void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4726 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004727 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004728 double *pdValue,
4729 QCBORItem *pItem)
4730{
4731 if(pMe->uLastError != QCBOR_SUCCESS) {
4732 return;
4733 }
4734
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004735 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004736 if(pMe->uLastError != QCBOR_SUCCESS) {
4737 return;
4738 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004739
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004740 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004741}
4742
4743
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004744#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004745static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4746{
4747 double dResult;
4748
4749 dResult = 0.0;
4750 const uint8_t *pByte = BigNum.ptr;
4751 size_t uLen = BigNum.len;
4752 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004753 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004754 while(uLen--) {
4755 dResult = (dResult * 256.0) + (double)*pByte++;
4756 }
4757
4758 return dResult;
4759}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004760#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4761
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004762
Laurence Lundblade93d89472020-10-03 22:30:50 -07004763static QCBORError
4764DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004765{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004766#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004767 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004768 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4769
4770 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004771 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004772
4773#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004774 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004775 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004776 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004777 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4778 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4779 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004780 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004781 }
4782 break;
4783
4784 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004785 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004786 // Underflow gives 0, overflow gives infinity
4787 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4788 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004789 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004790 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004791 }
4792 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004793#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004794
4795 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004796 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004797 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4798 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004799 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004800 }
4801 break;
4802
4803 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004804 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004805 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004806 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004807 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004808 }
4809 break;
4810
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004811#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004812 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004813 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004814 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4815 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4816 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004817 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004818 }
4819 break;
4820
4821 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004822 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004823 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4824 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4825 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004826 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004827 }
4828 break;
4829
4830 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004831 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004832 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4833 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
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_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004840 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004841 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004842 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4843 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004844 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004845 }
4846 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004847#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4848
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004849 default:
4850 return QCBOR_ERR_UNEXPECTED_TYPE;
4851 }
4852
4853 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004854
4855#else
4856 (void)pItem;
4857 (void)uConvertTypes;
4858 (void)pdValue;
4859 return QCBOR_ERR_HW_FLOAT_DISABLED;
4860#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4861
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004862}
4863
4864
4865/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004866 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004867*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004868void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4869 uint32_t uConvertTypes,
4870 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004871{
4872
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004873 QCBORItem Item;
4874
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004875 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004876
4877 if(pMe->uLastError == QCBOR_SUCCESS) {
4878 // The above conversion succeeded
4879 return;
4880 }
4881
4882 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4883 // The above conversion failed in a way that code below can't correct
4884 return;
4885 }
4886
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004887 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004888}
4889
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004890
4891/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004892 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004893*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004894void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4895 int64_t nLabel,
4896 uint32_t uConvertTypes,
4897 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004898{
4899 QCBORItem Item;
4900
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004901 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004902
4903 if(pMe->uLastError == QCBOR_SUCCESS) {
4904 // The above conversion succeeded
4905 return;
4906 }
4907
4908 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4909 // The above conversion failed in a way that code below can't correct
4910 return;
4911 }
4912
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004913 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004914}
4915
4916
4917/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004918 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004919*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004920void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4921 const char *szLabel,
4922 uint32_t uConvertTypes,
4923 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004924{
4925 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004926 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004927
4928 if(pMe->uLastError == QCBOR_SUCCESS) {
4929 // The above conversion succeeded
4930 return;
4931 }
4932
4933 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4934 // The above conversion failed in a way that code below can't correct
4935 return;
4936 }
4937
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004938 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004939}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004940
4941
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004942
4943
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004944#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004945static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
4946{
4947 while((uInt & 0xff00000000000000UL) == 0) {
4948 uInt = uInt << 8;
4949 };
4950
4951 UsefulOutBuf UOB;
4952
4953 UsefulOutBuf_Init(&UOB, Buffer);
4954
4955 while(uInt) {
4956 const uint64_t xx = uInt & 0xff00000000000000UL;
4957 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
4958 uInt = uInt << 8;
4959 (void)xx;
4960 }
4961
4962 return UsefulOutBuf_OutUBuf(&UOB);
4963}
4964
4965
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004966static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
4967 TagSpecification TagSpec,
4968 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004969{
4970 QCBORError uErr;
4971 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004972 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004973 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004974 if(uErr != QCBOR_SUCCESS) {
4975 goto Done;
4976 }
4977
4978 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
4979 break; // Successful exit. Moving on to finish decoding.
4980 }
4981
4982 // The item is an array, which means an undecoded
4983 // mantissa and exponent, so decode it. It will then
4984 // have a different type and exit the loop if.
4985 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
4986 if(uErr != QCBOR_SUCCESS) {
4987 goto Done;
4988 }
4989
4990 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07004991 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004992 }
4993Done:
4994 return uErr;
4995}
4996
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004997
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07004998static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004999 TagSpecification TagSpec,
5000 QCBORItem *pItem,
5001 int64_t *pnMantissa,
5002 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005003{
5004 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005005
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005006 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005007 if(uErr != QCBOR_SUCCESS) {
5008 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005009 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005010
Laurence Lundblade9b334962020-08-27 10:55:53 -07005011 switch (pItem->uDataType) {
5012
5013 case QCBOR_TYPE_DECIMAL_FRACTION:
5014 case QCBOR_TYPE_BIGFLOAT:
5015 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5016 *pnExponent = pItem->val.expAndMantissa.nExponent;
5017 break;
5018
5019 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5020 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5021 *pnExponent = pItem->val.expAndMantissa.nExponent;
5022 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5023 break;
5024
5025 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5026 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5027 *pnExponent = pItem->val.expAndMantissa.nExponent;
5028 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5029 break;
5030
5031 default:
5032 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5033 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005034
5035 Done:
5036 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005037}
5038
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005039
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005040static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005041 TagSpecification TagSpec,
5042 QCBORItem *pItem,
5043 UsefulBuf BufferForMantissa,
5044 UsefulBufC *pMantissa,
5045 bool *pbIsNegative,
5046 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005047{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005048 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005049
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005050 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005051 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005052 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005053 }
5054
5055 uint64_t uMantissa;
5056
5057 switch (pItem->uDataType) {
5058
5059 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005060 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005061 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5062 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5063 *pbIsNegative = false;
5064 } else {
5065 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5066 *pbIsNegative = true;
5067 }
5068 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5069 *pnExponent = pItem->val.expAndMantissa.nExponent;
5070 break;
5071
5072 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005073 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005074 *pnExponent = pItem->val.expAndMantissa.nExponent;
5075 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5076 *pbIsNegative = false;
5077 break;
5078
5079 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005080 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005081 *pnExponent = pItem->val.expAndMantissa.nExponent;
5082 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5083 *pbIsNegative = true;
5084 break;
5085
5086 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005087 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005088 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005089
5090Done:
5091 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005092}
5093
5094
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005095/*
5096 Public function, see header qcbor/qcbor_decode.h file
5097*/
5098void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5099 uint8_t uTagRequirement,
5100 int64_t *pnMantissa,
5101 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005102{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005103 if(pMe->uLastError != QCBOR_SUCCESS) {
5104 return;
5105 }
5106
5107 QCBORItem Item;
5108 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5109 if(uError) {
5110 pMe->uLastError = (uint8_t)uError;
5111 return;
5112 }
5113
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005114 const TagSpecification TagSpec =
5115 {
5116 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005117 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5118 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5119 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005120 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005121
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005122 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005123}
5124
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005125
5126/*
5127 Public function, see header qcbor/qcbor_decode.h file
5128*/
5129void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005130 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005131 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005132 int64_t *pnMantissa,
5133 int64_t *pnExponent)
5134{
5135 if(pMe->uLastError != QCBOR_SUCCESS) {
5136 return;
5137 }
5138
5139 QCBORItem Item;
5140 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5141
5142 const TagSpecification TagSpec =
5143 {
5144 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005145 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5146 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5147 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005148 };
5149
5150 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5151}
5152
5153
5154/*
5155 Public function, see header qcbor/qcbor_decode.h file
5156*/
5157void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005158 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005159 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005160 int64_t *pnMantissa,
5161 int64_t *pnExponent)
5162{
5163 if(pMe->uLastError != QCBOR_SUCCESS) {
5164 return;
5165 }
5166
5167 QCBORItem Item;
5168 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5169
5170 const TagSpecification TagSpec =
5171 {
5172 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005173 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5174 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5175 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005176 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005177
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005178 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5179}
5180
5181
5182/*
5183 Public function, see header qcbor/qcbor_decode.h file
5184*/
5185void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5186 uint8_t uTagRequirement,
5187 UsefulBuf MantissaBuffer,
5188 UsefulBufC *pMantissa,
5189 bool *pbMantissaIsNegative,
5190 int64_t *pnExponent)
5191{
5192 if(pMe->uLastError != QCBOR_SUCCESS) {
5193 return;
5194 }
5195
5196 QCBORItem Item;
5197 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5198 if(uError) {
5199 pMe->uLastError = (uint8_t)uError;
5200 return;
5201 }
5202
5203 const TagSpecification TagSpec =
5204 {
5205 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005206 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5207 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5208 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005209 };
5210
Laurence Lundblade93d89472020-10-03 22:30:50 -07005211 ProcessMantissaAndExponentBig(pMe,
5212 TagSpec,
5213 &Item,
5214 MantissaBuffer,
5215 pMantissa,
5216 pbMantissaIsNegative,
5217 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005218}
5219
5220
5221/*
5222 Public function, see header qcbor/qcbor_decode.h file
5223*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005224void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005225 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005226 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005227 UsefulBuf BufferForMantissa,
5228 UsefulBufC *pMantissa,
5229 bool *pbIsNegative,
5230 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005231{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005232 if(pMe->uLastError != QCBOR_SUCCESS) {
5233 return;
5234 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005235
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005236 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005237 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005238 if(pMe->uLastError != QCBOR_SUCCESS) {
5239 return;
5240 }
5241
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005242 const TagSpecification TagSpec =
5243 {
5244 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005245 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5246 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5247 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005248 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005249
Laurence Lundblade93d89472020-10-03 22:30:50 -07005250 ProcessMantissaAndExponentBig(pMe,
5251 TagSpec,
5252 &Item,
5253 BufferForMantissa,
5254 pMantissa,
5255 pbIsNegative,
5256 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005257}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005258
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005259
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005260/*
5261 Public function, see header qcbor/qcbor_decode.h file
5262*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005263void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005264 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005265 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005266 UsefulBuf BufferForMantissa,
5267 UsefulBufC *pMantissa,
5268 bool *pbIsNegative,
5269 int64_t *pnExponent)
5270{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005271 if(pMe->uLastError != QCBOR_SUCCESS) {
5272 return;
5273 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005274
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005275 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005276 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5277 if(pMe->uLastError != QCBOR_SUCCESS) {
5278 return;
5279 }
5280
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005281 const TagSpecification TagSpec =
5282 {
5283 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005284 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5285 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5286 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005287 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005288
5289 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5290}
5291
5292
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005293/*
5294 Public function, see header qcbor/qcbor_decode.h file
5295*/
5296void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5297 uint8_t uTagRequirement,
5298 int64_t *pnMantissa,
5299 int64_t *pnExponent)
5300{
5301 if(pMe->uLastError != QCBOR_SUCCESS) {
5302 return;
5303 }
5304
5305 QCBORItem Item;
5306 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5307 if(uError) {
5308 pMe->uLastError = (uint8_t)uError;
5309 return;
5310 }
5311 const TagSpecification TagSpec =
5312 {
5313 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005314 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5315 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5316 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005317 };
5318
5319 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5320}
5321
5322
5323/*
5324 Public function, see header qcbor/qcbor_decode.h file
5325*/
5326void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005327 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005328 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005329 int64_t *pnMantissa,
5330 int64_t *pnExponent)
5331{
5332 if(pMe->uLastError != QCBOR_SUCCESS) {
5333 return;
5334 }
5335
5336 QCBORItem Item;
5337 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5338 if(pMe->uLastError != QCBOR_SUCCESS) {
5339 return;
5340 }
5341
5342 const TagSpecification TagSpec =
5343 {
5344 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005345 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5346 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5347 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005348 };
5349
5350 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5351}
5352
5353
5354/*
5355 Public function, see header qcbor/qcbor_decode.h file
5356*/
5357void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005358 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005359 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005360 int64_t *pnMantissa,
5361 int64_t *pnExponent)
5362{
5363 if(pMe->uLastError != QCBOR_SUCCESS) {
5364 return;
5365 }
5366
5367 QCBORItem Item;
5368 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5369 if(pMe->uLastError != QCBOR_SUCCESS) {
5370 return;
5371 }
5372
5373 const TagSpecification TagSpec =
5374 {
5375 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005376 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5377 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5378 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005379 };
5380
5381 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5382}
5383
5384
5385/*
5386 Public function, see header qcbor/qcbor_decode.h file
5387*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005388void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5389 uint8_t uTagRequirement,
5390 UsefulBuf MantissaBuffer,
5391 UsefulBufC *pMantissa,
5392 bool *pbMantissaIsNegative,
5393 int64_t *pnExponent)
5394{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005395 if(pMe->uLastError != QCBOR_SUCCESS) {
5396 return;
5397 }
5398
5399 QCBORItem Item;
5400 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5401 if(uError) {
5402 pMe->uLastError = (uint8_t)uError;
5403 return;
5404 }
5405
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005406 const TagSpecification TagSpec =
5407 {
5408 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005409 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5410 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5411 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005412 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005413
5414 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005415}
5416
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005417
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005418/*
5419 Public function, see header qcbor/qcbor_decode.h file
5420*/
5421void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005422 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005423 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005424 UsefulBuf BufferForMantissa,
5425 UsefulBufC *pMantissa,
5426 bool *pbIsNegative,
5427 int64_t *pnExponent)
5428{
5429 if(pMe->uLastError != QCBOR_SUCCESS) {
5430 return;
5431 }
5432
5433 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005434 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5435 if(pMe->uLastError != QCBOR_SUCCESS) {
5436 return;
5437 }
5438
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005439 const TagSpecification TagSpec =
5440 {
5441 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005442 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5443 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5444 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005445 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005446
Laurence Lundblade93d89472020-10-03 22:30:50 -07005447 ProcessMantissaAndExponentBig(pMe,
5448 TagSpec,
5449 &Item,
5450 BufferForMantissa,
5451 pMantissa,
5452 pbIsNegative,
5453 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005454}
5455
5456
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005457/*
5458 Public function, see header qcbor/qcbor_decode.h file
5459*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005460void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005461 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005462 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005463 UsefulBuf BufferForMantissa,
5464 UsefulBufC *pMantissa,
5465 bool *pbIsNegative,
5466 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005467{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005468 if(pMe->uLastError != QCBOR_SUCCESS) {
5469 return;
5470 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005471
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005472 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005473 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5474 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005475 return;
5476 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005477
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005478 const TagSpecification TagSpec =
5479 {
5480 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005481 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5482 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5483 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005484 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005485
Laurence Lundblade93d89472020-10-03 22:30:50 -07005486 ProcessMantissaAndExponentBig(pMe,
5487 TagSpec,
5488 &Item,
5489 BufferForMantissa,
5490 pMantissa,
5491 pbIsNegative,
5492 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005493}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005494
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005495#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */