blob: 13910d5cc59fa2516b75ee77b3ac78995a0a9e7a [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladeee851742020-01-08 08:37:05 -08003 Copyright (c) 2018-2020, Laurence Lundblade.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07004 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080031 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080034#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070035#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundbladec7114722020-08-13 05:11:40 -070036#include "ieee754.h" // Does not use math.h
37
38#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade323f8a92020-09-06 19:43:09 -070039#include <math.h> // For isnan(), llround(), llroudf(), round(), roundf(),
40 // pow(), exp2()
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -070041#include <fenv.h> // feclearexcept(), fetestexcept()
Laurence Lundbladec7114722020-08-13 05:11:40 -070042#endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070043
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070044
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +053045/*
46 This casts away the const-ness of a pointer, usually so it can be
47 freed or realloced.
48 */
49#define UNCONST_POINTER(ptr) ((void *)(ptr))
50
Laurence Lundbladea9489f82020-09-12 13:50:56 -070051#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070052
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070053
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070054static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070055QCBORItem_IsMapOrArray(const QCBORItem *pMe)
56{
57 const uint8_t uDataType = pMe->uDataType;
58 return uDataType == QCBOR_TYPE_MAP ||
59 uDataType == QCBOR_TYPE_ARRAY ||
60 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
61}
62
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070063static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070064QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
65{
66 if(!QCBORItem_IsMapOrArray(pMe)){
67 return false;
68 }
69
70 if(pMe->val.uCount != 0) {
71 return false;
72 }
73 return true;
74}
75
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070076static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070077QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
78{
79 if(!QCBORItem_IsMapOrArray(pMe)){
80 return false;
81 }
82
83 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
84 return false;
85 }
86 return true;
87}
88
89
Laurence Lundbladeee851742020-01-08 08:37:05 -080090/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070091 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080092 ===========================================================================*/
93
Laurence Lundblade9c905e82020-04-25 11:31:38 -070094/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070095 See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
Laurence Lundblade93d89472020-10-03 22:30:50 -070096 the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -070097 */
98
Laurence Lundblade24d509a2020-06-06 18:43:15 -070099
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700100static inline uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700101DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700102{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700103 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700104 /*
105 Limit in DecodeNesting_Descend against more than
106 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
107 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700108 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700109}
110
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700111
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700112static inline uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700113DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700114{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700115 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700116 /*
117 Limit in DecodeNesting_Descend against more than
118 QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
119 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700120 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700121}
122
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700123
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700124static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700125DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700126{
127 return pNesting->pCurrentBounded->u.ma.uStartOffset;
128}
129
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700130
Laurence Lundblade085d7952020-07-24 10:26:30 -0700131static inline bool
132DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
133{
134 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
135 return true;
136 } else {
137 return false;
138 }
139}
140
141
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700142static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700143DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700144{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700145 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700146 return true;
147 } else {
148 return false;
149 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700150}
151
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700152
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700153static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700154DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700155{
156 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700157 // Not a map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700158 return false;
159 }
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700160 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700161 // Is indefinite
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700162 return false;
163 }
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700164 // All checks passed; is a definte length map or array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700165 return true;
166}
167
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700168
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700169static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700170DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700171{
172 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700173 // is a byte string
Laurence Lundblade642282a2020-06-23 12:00:33 -0700174 return true;
175 }
176 return false;
177}
178
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700179
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700180static inline bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700181{
182 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
183 return true;
184 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700185 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700186 return true;
187 }
188 return false;
189}
190
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700191
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700192static inline void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700193{
194 // Should be only called on maps and arrays
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700195 /*
196 DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
197 larger than DecodeNesting_EnterBoundedMode which keeps it less than
198 uin32_t so the cast is safe.
199 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700200 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700201
202 if(bIsEmpty) {
203 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
204 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700205}
206
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700207
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700208static inline void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700209{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700210 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700211}
212
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700213
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700214static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700215DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700216{
217 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700218 // No bounded map or array set up
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700219 return false;
220 }
221 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700222 // Not a map or array; end of those is by byte count
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700223 return false;
224 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700225 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
226 // In a traveral at a level deeper than the bounded level
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700227 return false;
228 }
Laurence Lundbladed0304932020-06-27 10:59:38 -0700229 // Works for both definite and indefinite length maps/arrays
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800230 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
231 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700232 // Count is not zero, still unconsumed item
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700233 return false;
234 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700235 // All checks passed, got to the end of an array or map
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700236 return true;
237}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700238
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700239
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700240static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700241DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700242{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700243 // Must only be called on map / array
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700244 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
245 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700246 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700247 return false;
248 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700249}
250
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700251
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700252static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700253DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700254{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700255 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
256 return true;
257 } else {
258 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700259 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700260}
261
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700262
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700263static inline bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700264DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700265{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700266 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700267 return false;
268 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700269
270 if(pNesting->pCurrentBounded->uLevelType != uType) {
271 return false;
272 }
273
274 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700275}
276
Laurence Lundblade02625d42020-06-25 14:41:41 -0700277
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700278static inline void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700279DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700280{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700281 // Only call on a defnite length array / map
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700282 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700283}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700284
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700285
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700286static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700287DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
288{
289 // Only call on a defnite length array / map
290 pNesting->pCurrent->u.ma.uCountCursor++;
291}
292
293
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700294static inline void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700295DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
296{
297 pNesting->pCurrent--;
298}
299
Laurence Lundblade02625d42020-06-25 14:41:41 -0700300
301static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700302DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700303{
304 // Error out if nesting is too deep
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700305 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700306 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700307 }
308
309 // The actual descend
310 pNesting->pCurrent++;
311
312 pNesting->pCurrent->uLevelType = uType;
313
314 return QCBOR_SUCCESS;
315}
316
317
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700318static inline QCBORError
Laurence Lundblade085d7952020-07-24 10:26:30 -0700319DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700320{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700321 /*
322 Should only be called on map/array.
323
324 Have descended into this before this is called. The job here is
325 just to mark it in bounded mode.
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700326
327 Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
328 uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700329 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -0700330 if(uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700331 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700332 }
333
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700334 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700335
336 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700337
338 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700339}
340
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700341
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700342static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700343DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700344 uint8_t uQCBORType,
345 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700346{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700347 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700348
349 if(uCount == 0) {
350 // Nothing to do for empty definite lenth arrays. They are just are
351 // effectively the same as an item that is not a map or array
352 goto Done;
353 // Empty indefinite length maps and arrays are handled elsewhere
354 }
355
356 // Error out if arrays is too long to handle
Laurence Lundblade02625d42020-06-25 14:41:41 -0700357 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
358 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700359 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700360 goto Done;
361 }
362
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700363 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700364 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700365 goto Done;
366 }
367
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700368 // Fill in the new map/array level. Check above makes casts OK.
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700369 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
370 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700371
372 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700373
374Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700375 return uError;;
376}
377
378
379static inline void
380DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
381{
382 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
383}
384
385
386static inline void
387DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
388{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700389 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700390 pNesting->pCurrentBounded--;
391 if(DecodeNesting_IsCurrentBounded(pNesting)) {
392 break;
393 }
394 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700395}
396
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700397static inline void
398DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
399{
400 pNesting->pCurrent = pNesting->pCurrentBounded;
401}
402
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700403
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700404static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700405DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700406 uint32_t uEndOffset,
407 uint32_t uEndOfBstr)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700408{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700409 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700410
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700411 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700412 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700413 goto Done;
414 }
415
Laurence Lundblade02625d42020-06-25 14:41:41 -0700416 // Fill in the new byte string level
Laurence Lundbladef76a2622020-08-06 19:51:03 -0700417 pNesting->pCurrent->u.bs.uPreviousEndOffset = uEndOffset;
418 pNesting->pCurrent->u.bs.uEndOfBstr = uEndOfBstr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700419
Laurence Lundblade02625d42020-06-25 14:41:41 -0700420 // Bstr wrapped levels are always bounded
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700421 pNesting->pCurrentBounded = pNesting->pCurrent;
422
423Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700424 return uError;;
425}
426
Laurence Lundbladed0304932020-06-27 10:59:38 -0700427
428static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700429DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700430{
431 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700432}
433
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700434
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700435static inline void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800436DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
437{
438 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
439}
440
441
442static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700443DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700444{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700445 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700446 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
447 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700448}
449
450
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700451static inline void
Laurence Lundblade02625d42020-06-25 14:41:41 -0700452DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting, QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700453{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700454 *pSave = *pNesting;
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700455 pNesting->pCurrent = pNesting->pCurrentBounded;
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800456 DecodeNesting_ResetMapOrArrayCount(pNesting);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700457}
458
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700459
Laurence Lundblade02625d42020-06-25 14:41:41 -0700460static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700461DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting, const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700462{
463 *pNesting = *pSave;
464}
465
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700466
Laurence Lundblade02625d42020-06-25 14:41:41 -0700467static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700468DecodeNesting_GetEndOfBstr(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700469{
470 return pMe->pCurrentBounded->u.bs.uEndOfBstr;
471}
472
473
Laurence Lundblade02625d42020-06-25 14:41:41 -0700474static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700475DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700476{
477 return pMe->pCurrentBounded->u.bs.uPreviousEndOffset;
478}
479
480
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800481#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800482/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800483 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
484
485 The following four functions are pretty wrappers for invocation of
486 the string allocator supplied by the caller.
487
Laurence Lundbladeee851742020-01-08 08:37:05 -0800488 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800489
Laurence Lundbladeee851742020-01-08 08:37:05 -0800490static inline void
491StringAllocator_Free(const QCORInternalAllocator *pMe, void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800492{
493 (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, 0);
494}
495
Laurence Lundbladeee851742020-01-08 08:37:05 -0800496// StringAllocator_Reallocate called with pMem NULL is
497// equal to StringAllocator_Allocate()
498static inline UsefulBuf
499StringAllocator_Reallocate(const QCORInternalAllocator *pMe,
500 void *pMem,
501 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800502{
503 return (pMe->pfAllocator)(pMe->pAllocateCxt, pMem, uSize);
504}
505
Laurence Lundbladeee851742020-01-08 08:37:05 -0800506static inline UsefulBuf
507StringAllocator_Allocate(const QCORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800508{
509 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
510}
511
Laurence Lundbladeee851742020-01-08 08:37:05 -0800512static inline void
513StringAllocator_Destruct(const QCORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800514{
515 if(pMe->pfAllocator) {
516 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
517 }
518}
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800519#endif
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800520
521
Laurence Lundbladeee851742020-01-08 08:37:05 -0800522/*===========================================================================
523 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700524
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800525 See qcbor/qcbor_decode.h for definition of the object
526 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800527 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700528/*
529 Public function, see header file
530 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800531void QCBORDecode_Init(QCBORDecodeContext *me,
532 UsefulBufC EncodedCBOR,
533 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700534{
535 memset(me, 0, sizeof(QCBORDecodeContext));
536 UsefulInputBuf_Init(&(me->InBuf), EncodedCBOR);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800537 // Don't bother with error check on decode mode. If a bad value is
538 // passed it will just act as if the default normal mode of 0 was set.
Laurence Lundbladee6bcef12020-04-01 10:56:27 -0700539 me->uDecodeMode = (uint8_t)nDecodeMode;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700540 DecodeNesting_Init(&(me->nesting));
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700541 for(int i = 0; i < QCBOR_NUM_MAPPED_TAGS; i++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -0700542 me->auMappedTags[i] = CBOR_TAG_INVALID16;
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700543 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700544}
545
546
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800547#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
548
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700549/*
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700550 Public function, see header file
551 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800552void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
553 QCBORStringAllocate pfAllocateFunction,
554 void *pAllocateContext,
555 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700556{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800557 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
558 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
559 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700560}
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800561#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700562
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800563
564/*
565 Public function, see header file
566 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700567void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800568 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700569{
Laurence Lundblade830fbf92020-05-31 17:22:33 -0700570 // This does nothing now. It is retained for backwards compatibility
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700571 (void)pMe;
572 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700573}
574
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700575
576/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800577 This decodes the fundamental part of a CBOR data item, the type and
578 number
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800579
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700580 This is the counterpart to QCBOREncode_EncodeHead().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800581
Laurence Lundbladeee851742020-01-08 08:37:05 -0800582 This does the network->host byte order conversion. The conversion
583 here also results in the conversion for floats in addition to that
584 for lengths, tags and integer values.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800585
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700586 This returns:
587 pnMajorType -- the major type for the item
Laurence Lundbladeee851742020-01-08 08:37:05 -0800588
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800589 puArgument -- the "number" which is used a the value for integers,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800590 tags and floats and length for strings and arrays
591
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800592 pnAdditionalInfo -- Pass this along to know what kind of float or
Laurence Lundbladeee851742020-01-08 08:37:05 -0800593 if length is indefinite
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800594
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800595 The int type is preferred to uint8_t for some variables as this
596 avoids integer promotions, can reduce code size and makes
597 static analyzers happier.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700598
599 @retval QCBOR_ERR_UNSUPPORTED
600
601 @retval QCBOR_ERR_HIT_END
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700602 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700603static inline QCBORError DecodeTypeAndNumber(UsefulInputBuf *pUInBuf,
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800604 int *pnMajorType,
605 uint64_t *puArgument,
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800606 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700607{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700608 QCBORError nReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800609
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700610 // Get the initial byte that every CBOR data item has
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800611 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800612
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700613 // Break down the initial byte
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800614 const int nTmpMajorType = nInitialByte >> 5;
615 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800616
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800617 // Where the number or argument accumulates
618 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800619
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800620 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700621 // Need to get 1,2,4 or 8 additional argument bytes. Map
622 // LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800623 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800624
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800625 // Loop getting all the bytes in the argument
626 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800627 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800628 // This shift and add gives the endian conversion
629 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
630 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800631 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800632 // The reserved and thus-far unused additional info values
633 nReturn = QCBOR_ERR_UNSUPPORTED;
634 goto Done;
635 } else {
636 // Less than 24, additional info is argument or 31, an indefinite length
637 // No more bytes to get
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800638 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700639 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800640
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700641 if(UsefulInputBuf_GetError(pUInBuf)) {
642 nReturn = QCBOR_ERR_HIT_END;
643 goto Done;
644 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800645
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700646 // All successful if we got here.
647 nReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800648 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800649 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800650 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800651
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700652Done:
653 return nReturn;
654}
655
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800656
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700657/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800658 CBOR doesn't explicitly specify two's compliment for integers but all
659 CPUs use it these days and the test vectors in the RFC are so. All
660 integers in the CBOR structure are positive and the major type
661 indicates positive or negative. CBOR can express positive integers
662 up to 2^x - 1 where x is the number of bits and negative integers
663 down to 2^x. Note that negative numbers can be one more away from
664 zero than positive. Stdint, as far as I can tell, uses two's
665 compliment to represent negative integers.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800666
Laurence Lundblade9b334962020-08-27 10:55:53 -0700667 See http://www.unix.org/whitepapers/64bit.html for reasons int is
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800668 used carefully here, and in particular why it isn't used in the interface.
669 Also see
670 https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
671
672 Int is used for values that need less than 16-bits and would be subject
673 to integer promotion and complaining by static analyzers.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700674
675 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700676 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700677static inline QCBORError
Laurence Lundbladeee851742020-01-08 08:37:05 -0800678DecodeInteger(int nMajorType, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700679{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700680 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800681
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700682 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
683 if (uNumber <= INT64_MAX) {
684 pDecodedItem->val.int64 = (int64_t)uNumber;
685 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800686
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700687 } else {
688 pDecodedItem->val.uint64 = uNumber;
689 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800690
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700691 }
692 } else {
693 if(uNumber <= INT64_MAX) {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800694 // CBOR's representation of negative numbers lines up with the
695 // two-compliment representation. A negative integer has one
696 // more in range than a positive integer. INT64_MIN is
697 // equal to (-INT64_MAX) - 1.
698 pDecodedItem->val.int64 = (-(int64_t)uNumber) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700699 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800700
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700701 } else {
702 // C can't represent a negative integer in this range
Laurence Lundblade21d1d812019-09-28 22:47:49 -1000703 // so it is an error.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700704 nReturn = QCBOR_ERR_INT_OVERFLOW;
705 }
706 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800707
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700708 return nReturn;
709}
710
711// Make sure #define value line up as DecodeSimple counts on this.
712#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
713#error QCBOR_TYPE_FALSE macro value wrong
714#endif
715
716#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
717#error QCBOR_TYPE_TRUE macro value wrong
718#endif
719
720#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
721#error QCBOR_TYPE_NULL macro value wrong
722#endif
723
724#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
725#error QCBOR_TYPE_UNDEF macro value wrong
726#endif
727
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700728#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
729#error QCBOR_TYPE_BREAK macro value wrong
730#endif
731
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700732#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
733#error QCBOR_TYPE_DOUBLE macro value wrong
734#endif
735
736#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
737#error QCBOR_TYPE_FLOAT macro value wrong
738#endif
739
740/*
741 Decode true, false, floats, break...
Laurence Lundblade9b334962020-08-27 10:55:53 -0700742
743 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
744
745 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700746 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700747static inline QCBORError
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800748DecodeSimple(int nAdditionalInfo, uint64_t uNumber, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700749{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700750 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800751
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700752 // uAdditionalInfo is 5 bits from the initial byte. Compile time checks
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800753 // above make sure uAdditionalInfo values line up with uDataType values.
Laurence Lundblade93d89472020-10-03 22:30:50 -0700754 // DecodeTypeAndNumber() never returns an AdditionalInfo > 0x1f so cast
755 // is safe
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800756 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800757
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800758 switch(nAdditionalInfo) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800759 // No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they are
760 // caught before this is called.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800761
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700762 case HALF_PREC_FLOAT: // 25
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700763#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700764 // Half-precision is returned as a double.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700765 // The cast to uint16_t is safe because the encoded value
Laurence Lundblade9682a532020-06-06 18:33:04 -0700766 // was 16 bits. It was widened to 64 bits to be passed in here.
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700767 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uNumber);
768 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700769#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700770 nReturn = QCBOR_ERR_HALF_PRECISION_DISABLED;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700771#endif
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700772 break;
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700773 case SINGLE_PREC_FLOAT: // 26
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700774 // Single precision is normally returned as a double
775 // since double is widely supported, there is no loss of
776 // precision, it makes it easy for the caller in
777 // most cases and it can be converted back to single
778 // with no loss of precision
779 //
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -0700780 // The cast to uint32_t is safe because the encoded value
Laurence Lundblade8fa7d5d2020-07-11 16:30:47 -0700781 // was 32 bits. It was widened to 64 bits to be passed in here.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700782 {
783 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uNumber);
784#ifndef QCBOR_DISABLE_FLOAT_HW_USE
785 // In the normal case, use HW to convert float to double.
786 pDecodedItem->val.dfnum = (double)f;
787 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade9682a532020-06-06 18:33:04 -0700788#else
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700789 // Use of float HW is disabled, return as a float.
790 pDecodedItem->val.fnum = f;
791 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
792
793 // IEEE754_FloatToDouble() could be used here to return
794 // as a double, but it adds object code and most likely
795 // anyone disabling FLOAT HW use doesn't care about
796 // floats and wants to save object code.
Laurence Lundblade9682a532020-06-06 18:33:04 -0700797#endif
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700798 }
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700799 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700800
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700801 case DOUBLE_PREC_FLOAT: // 27
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700802 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uNumber);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700803 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700804 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800805
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700806 case CBOR_SIMPLEV_FALSE: // 20
807 case CBOR_SIMPLEV_TRUE: // 21
808 case CBOR_SIMPLEV_NULL: // 22
809 case CBOR_SIMPLEV_UNDEF: // 23
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700810 case CBOR_SIMPLE_BREAK: // 31
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700811 break; // nothing to do
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800812
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700813 case CBOR_SIMPLEV_ONEBYTE: // 24
814 if(uNumber <= CBOR_SIMPLE_BREAK) {
815 // This takes out f8 00 ... f8 1f which should be encoded as e0 … f7
Laurence Lundblade077475f2019-04-26 09:06:33 -0700816 nReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700817 goto Done;
818 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800819 /* FALLTHROUGH */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700820 // fall through intentionally
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800821
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700822 default: // 0-19
823 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800824 /*
825 DecodeTypeAndNumber will make uNumber equal to
826 uAdditionalInfo when uAdditionalInfo is < 24 This cast is
827 safe because the 2, 4 and 8 byte lengths of uNumber are in
828 the double/float cases above
829 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700830 pDecodedItem->val.uSimple = (uint8_t)uNumber;
831 break;
832 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800833
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700834Done:
835 return nReturn;
836}
837
838
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700839/*
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530840 Decode text and byte strings. Call the string allocator if asked to.
Laurence Lundblade9b334962020-08-27 10:55:53 -0700841
842 @retval QCBOR_ERR_HIT_END
843
844 @retval QCBOR_ERR_STRING_ALLOCATE
845
846 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700847 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700848static inline QCBORError DecodeBytes(const QCORInternalAllocator *pAllocator,
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800849 uint64_t uStrLen,
850 UsefulInputBuf *pUInBuf,
851 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700852{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700853 QCBORError nReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800854
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800855 // CBOR lengths can be 64 bits, but size_t is not 64 bits on all CPUs.
856 // This check makes the casts to size_t below safe.
857
858 // 4 bytes less than the largest sizeof() so this can be tested by
859 // putting a SIZE_MAX length in the CBOR test input (no one will
860 // care the limit on strings is 4 bytes shorter).
861 if(uStrLen > SIZE_MAX-4) {
862 nReturn = QCBOR_ERR_STRING_TOO_LONG;
863 goto Done;
864 }
865
866 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530867 if(UsefulBuf_IsNULLC(Bytes)) {
868 // Failed to get the bytes for this string item
869 nReturn = QCBOR_ERR_HIT_END;
870 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700871 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530872
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800873#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800874 if(pAllocator) {
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530875 // We are asked to use string allocator to make a copy
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800876 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530877 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade30816f22018-11-10 13:40:22 +0700878 nReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530879 goto Done;
880 }
881 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800882 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800883 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530884 }
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800885#else
886 (void)pAllocator;
887#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
888
889 // Normal case with no string allocator
890 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800891
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530892Done:
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700893 return nReturn;
894}
895
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700896
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800897/* Map the CBOR major types for strings to the QCBOR types for strngs */
898static inline uint8_t MapStringMajorTypes(int nCBORMajorType)
899{
900 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
901 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
902 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800903
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800904 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
905 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
906 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700907
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800908 return (uint8_t)(nCBORMajorType + 4);
909}
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700910
911
Laurence Lundbladeee851742020-01-08 08:37:05 -0800912// Make sure the constants align as this is assumed by
913// the GetAnItem() implementation
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700914#if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
915#error QCBOR_TYPE_ARRAY value not lined up with major type
916#endif
917#if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
918#error QCBOR_TYPE_MAP value not lined up with major type
919#endif
920
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700921/*
Laurence Lundbladeee851742020-01-08 08:37:05 -0800922 This gets a single data item and decodes it including preceding
923 optional tagging. This does not deal with arrays and maps and nesting
924 except to decode the data item introducing them. Arrays and maps are
925 handled at the next level up in GetNext().
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800926
Laurence Lundbladeee851742020-01-08 08:37:05 -0800927 Errors detected here include: an array that is too long to decode,
928 hit end of buffer unexpectedly, a few forms of invalid encoded CBOR
Laurence Lundblade9b334962020-08-27 10:55:53 -0700929
930 @retval QCBOR_ERR_UNSUPPORTED
931
932 @retval QCBOR_ERR_HIT_END
933
934 @retval QCBOR_ERR_INT_OVERFLOW
935
936 @retval QCBOR_ERR_STRING_ALLOCATE
937
938 @retval QCBOR_ERR_STRING_TOO_LONG
939
940 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
941
942 @retval QCBOR_ERR_BAD_TYPE_7
943
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700944 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800945static QCBORError GetNext_Item(UsefulInputBuf *pUInBuf,
946 QCBORItem *pDecodedItem,
947 const QCORInternalAllocator *pAllocator)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700948{
Laurence Lundblade30816f22018-11-10 13:40:22 +0700949 QCBORError nReturn;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800950
Laurence Lundbladeee851742020-01-08 08:37:05 -0800951 /*
952 Get the major type and the number. Number could be length of more
953 bytes or the value depending on the major type nAdditionalInfo is
954 an encoding of the length of the uNumber and is needed to decode
955 floats and doubles
956 */
Rob Gilton47cc9562020-08-10 12:03:38 +0100957 int nMajorType = 0;
958 uint64_t uNumber = 0;
959 int nAdditionalInfo = 0;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800960
Laurence Lundblade4b09f632019-10-09 14:34:59 -0700961 memset(pDecodedItem, 0, sizeof(QCBORItem));
962
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800963 nReturn = DecodeTypeAndNumber(pUInBuf, &nMajorType, &uNumber, &nAdditionalInfo);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800964
Laurence Lundbladeee851742020-01-08 08:37:05 -0800965 // Error out here if we got into trouble on the type and number. The
966 // code after this will not work if the type and number is not good.
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700967 if(nReturn) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700968 goto Done;
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700969 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800970
Laurence Lundbladeee851742020-01-08 08:37:05 -0800971 // At this point the major type and the value are valid. We've got
972 // the type and the number that starts every CBOR data item.
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800973 switch (nMajorType) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700974 case CBOR_MAJOR_TYPE_POSITIVE_INT: // Major type 0
975 case CBOR_MAJOR_TYPE_NEGATIVE_INT: // Major type 1
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800976 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700977 nReturn = QCBOR_ERR_BAD_INT;
978 } else {
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800979 nReturn = DecodeInteger(nMajorType, uNumber, pDecodedItem);
Laurence Lundblade3a6042e2019-06-28 19:58:04 -0700980 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700981 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800982
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700983 case CBOR_MAJOR_TYPE_BYTE_STRING: // Major type 2
984 case CBOR_MAJOR_TYPE_TEXT_STRING: // Major type 3
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800985 pDecodedItem->uDataType = (uint8_t)MapStringMajorTypes(nMajorType);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800986 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade5697c502020-11-25 19:23:50 -0800987 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700988 } else {
Laurence Lundblade12721ba2020-11-24 22:29:57 -0800989 nReturn = DecodeBytes(pAllocator, uNumber, pUInBuf, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700990 }
991 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800992
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700993 case CBOR_MAJOR_TYPE_ARRAY: // Major type 4
994 case CBOR_MAJOR_TYPE_MAP: // Major type 5
995 // Record the number of items in the array or map
996 if(uNumber > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700997 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700998 goto Done;
999 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001000 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001001 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001002 } else {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001003 // type conversion OK because of check above
1004 pDecodedItem->val.uCount = (uint16_t)uNumber;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001005 }
Laurence Lundbladeee851742020-01-08 08:37:05 -08001006 // C preproc #if above makes sure constants for major types align
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001007 // DecodeTypeAndNumber never returns a major type > 7 so cast is safe
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001008 pDecodedItem->uDataType = (uint8_t)nMajorType;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001009 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001010
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001011 case CBOR_MAJOR_TYPE_OPTIONAL: // Major type 6, optional prepended tags
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001012 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001013 nReturn = QCBOR_ERR_BAD_INT;
1014 } else {
1015 pDecodedItem->val.uTagV = uNumber;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001016 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001017 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001018 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001019
Laurence Lundbladeee851742020-01-08 08:37:05 -08001020 case CBOR_MAJOR_TYPE_SIMPLE:
1021 // Major type 7, float, double, true, false, null...
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001022 nReturn = DecodeSimple(nAdditionalInfo, uNumber, pDecodedItem);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001023 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001024
Laurence Lundbladeee851742020-01-08 08:37:05 -08001025 default:
1026 // Never happens because DecodeTypeAndNumber() should never return > 7
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001027 nReturn = QCBOR_ERR_UNSUPPORTED;
1028 break;
1029 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001030
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001031Done:
1032 return nReturn;
1033}
1034
1035
1036
Laurence Lundblade5697c502020-11-25 19:23:50 -08001037/**
1038 @brief Process indefinite length strings
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001039
Laurence Lundblade5697c502020-11-25 19:23:50 -08001040 @param[in] pMe Decoder context
1041 @param[in,out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001042
1043 @retval QCBOR_ERR_UNSUPPORTED
Laurence Lundblade9b334962020-08-27 10:55:53 -07001044 @retval QCBOR_ERR_HIT_END
Laurence Lundblade9b334962020-08-27 10:55:53 -07001045 @retval QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade9b334962020-08-27 10:55:53 -07001046 @retval QCBOR_ERR_STRING_ALLOCATE
Laurence Lundblade9b334962020-08-27 10:55:53 -07001047 @retval QCBOR_ERR_STRING_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001048 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Laurence Lundblade9b334962020-08-27 10:55:53 -07001049 @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade9b334962020-08-27 10:55:53 -07001050 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
Laurence Lundblade9b334962020-08-27 10:55:53 -07001051 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade5697c502020-11-25 19:23:50 -08001052
1053 If @c pDecodedItem is not an indefinite length string, this does nothing.
1054
1055 If it is, this loops getting the subsequent chunks that make up the
1056 string. The string allocator is used to make a contiguous buffer for
1057 the chunks. When this completes @c pDecodedItem contains the
1058 put-together string.
1059
1060 Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001061 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001062static inline QCBORError
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001063GetNext_FullItem(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001064{
Laurence Lundblade5697c502020-11-25 19:23:50 -08001065 /* Aproximate stack usage
1066 * 64-bit 32-bit
1067 * local vars 32 16
1068 * 2 UsefulBufs 32 16
1069 * QCBORItem 56 52
1070 * TOTAL 120 74
1071 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001072
Laurence Lundblade5697c502020-11-25 19:23:50 -08001073 /* The string allocator is used here for two purposes: 1)
1074 * coalescing the chunks of an indefinite length string, 2)
1075 * allocating storage for every string returned.
1076 *
1077 * The first use is below in this function. Indefinite length
1078 * strings cannot be processed at all without a string allocator.
1079 *
1080 * The second used is in DecodeBytes() which is called by
1081 * GetNext_Item() below. This second use unneccessary for most use
1082 * and only happens when requested in the call to
1083 * QCBORDecode_SetMemPool(). If the second use not requested then
1084 * NULL is passed for the string allocator to GetNext_Item().
1085 *
1086 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1087 * allocator altogether and thus both of these uses. It reduced the
1088 * decoder object code by about 400 bytes.
1089 */
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001090 const QCORInternalAllocator *pAllocatorForGetNext = NULL;
1091
1092#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
1093 const QCORInternalAllocator *pAllocator = NULL;
1094
1095 if(pMe->StringAllocator.pfAllocator) {
1096 pAllocator = &(pMe->StringAllocator);
Laurence Lundblade5697c502020-11-25 19:23:50 -08001097 if(pMe->bStringAllocateAll) {
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001098 pAllocatorForGetNext = pAllocator;
1099 }
1100 }
1101#endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001102
Laurence Lundblade5697c502020-11-25 19:23:50 -08001103 QCBORError uReturn;
1104 uReturn = GetNext_Item(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
1105 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001106 goto Done;
1107 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001108
Laurence Lundblade5697c502020-11-25 19:23:50 -08001109 /* Only do indefinite length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001110 const uint8_t uStringType = pDecodedItem->uDataType;
1111 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade5697c502020-11-25 19:23:50 -08001112 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001113 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001114
Laurence Lundblade5697c502020-11-25 19:23:50 -08001115 /* Is this a string with an indefinite length? */
1116 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1117 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001118 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001119
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001120#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade5697c502020-11-25 19:23:50 -08001121 /* Can't do indefinite length strings without a string allocator */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001122 if(pAllocator == NULL) {
Laurence Lundblade5697c502020-11-25 19:23:50 -08001123 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001124 goto Done;
1125 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001126
Laurence Lundblade5697c502020-11-25 19:23:50 -08001127 /* Loop getting chunks of the indefinite length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001128 UsefulBufC FullString = NULLUsefulBufC;
1129
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001130 for(;;) {
Laurence Lundblade5697c502020-11-25 19:23:50 -08001131 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001132 QCBORItem StringChunkItem;
Laurence Lundblade5697c502020-11-25 19:23:50 -08001133 /* Pass a NULL string allocator to GetNext_Item() because the
1134 * individual string chunks in an indefinite length should not
1135 * be allocated. They are always copied in the the contiguous
1136 * buffer allocated here.
1137 */
1138 uReturn = GetNext_Item(&(pMe->InBuf), &StringChunkItem, NULL);
1139 if(uReturn) {
1140 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001141 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001142
Laurence Lundblade5697c502020-11-25 19:23:50 -08001143 /* Is item is the marker for end of the indefinite length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001144 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade5697c502020-11-25 19:23:50 -08001145 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001146 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301147 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001148 break;
1149 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001150
Laurence Lundblade5697c502020-11-25 19:23:50 -08001151 /* All chunks must be of the same type, the type of the item
1152 * that introduces the indefinite length string. This also
1153 * catches errors where the chunk is not a string at all and an
1154 * indefinite length string inside an indefinite length string.
1155 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001156 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundblade5697c502020-11-25 19:23:50 -08001157 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1158 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001159 break;
1160 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001161
Laurence Lundblade5697c502020-11-25 19:23:50 -08001162 /* The first time throurgh FullString.ptr is NULL and this is
1163 * equivalent to StringAllocator_Allocate(). Subsequently it is
1164 * not NULL and a reallocation happens.
1165 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001166 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1167 UNCONST_POINTER(FullString.ptr),
1168 FullString.len + StringChunkItem.val.string.len);
1169
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001170 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade5697c502020-11-25 19:23:50 -08001171 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001172 break;
1173 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001174
Laurence Lundblade5697c502020-11-25 19:23:50 -08001175 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001176 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001177 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001178
Laurence Lundblade5697c502020-11-25 19:23:50 -08001179 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1180 /* Getting the item failed, clean up the allocated memory */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001181 StringAllocator_Free(pAllocator, UNCONST_POINTER(FullString.ptr));
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001182 }
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001183#else
Laurence Lundblade5697c502020-11-25 19:23:50 -08001184 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001185#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001186
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001187Done:
Laurence Lundblade5697c502020-11-25 19:23:50 -08001188 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001189}
1190
Laurence Lundblade12721ba2020-11-24 22:29:57 -08001191
Laurence Lundblade9b334962020-08-27 10:55:53 -07001192static uint64_t ConvertTag(const QCBORDecodeContext *me, uint16_t uTagVal) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001193 if(uTagVal <= QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001194 return uTagVal;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001195 } else if(uTagVal == CBOR_TAG_INVALID16) {
1196 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001197 } else {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001198 // This won't be negative because of code below in GetNext_TaggedItem()
1199 const unsigned uIndex = uTagVal - (QCBOR_LAST_UNMAPPED_TAG + 1);
1200 return me->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001201 }
1202}
1203
Laurence Lundblade9b334962020-08-27 10:55:53 -07001204
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001205/*
Laurence Lundblade59289e52019-12-30 13:44:37 -08001206 Gets all optional tag data items preceding a data item that is not an
1207 optional tag and records them as bits in the tag map.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001208
1209 @retval QCBOR_ERR_UNSUPPORTED
1210
1211 @retval QCBOR_ERR_HIT_END
1212
1213 @retval QCBOR_ERR_INT_OVERFLOW
1214
1215 @retval QCBOR_ERR_STRING_ALLOCATE
1216
1217 @retval QCBOR_ERR_STRING_TOO_LONG
1218
1219 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1220
1221 @retval QCBOR_ERR_BAD_TYPE_7
1222
1223 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1224
1225 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1226
1227 @retval QCBOR_ERR_TOO_MANY_TAGS
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001228 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001229static QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001230GetNext_TaggedItem(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001231{
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001232 uint16_t auTags[QCBOR_MAX_TAGS_PER_ITEM] = {CBOR_TAG_INVALID16,
1233 CBOR_TAG_INVALID16,
1234 CBOR_TAG_INVALID16,
1235 CBOR_TAG_INVALID16};
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001236
Laurence Lundblade9b334962020-08-27 10:55:53 -07001237 QCBORError uReturn = QCBOR_SUCCESS;
1238
Laurence Lundblade59289e52019-12-30 13:44:37 -08001239 // Loop fetching items until the item fetched is not a tag
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001240 for(;;) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001241 QCBORError uErr = GetNext_FullItem(me, pDecodedItem);
1242 if(uErr != QCBOR_SUCCESS) {
1243 uReturn = uErr;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001244 goto Done; // Error out of the loop
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001245 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001246
Laurence Lundblade9b334962020-08-27 10:55:53 -07001247 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001248 // Successful exit from loop; maybe got some tags, maybe not
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001249 memcpy(pDecodedItem->uTags, auTags, sizeof(auTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001250 break;
1251 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001252
Laurence Lundblade9b334962020-08-27 10:55:53 -07001253 if(auTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1254 // No room in the tag list
1255 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1256 // Continue on to get all tags on this item even though
1257 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001258 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001259 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001260 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001261 // Slide tags over one in the array to make room at index 0
1262 for(size_t uTagIndex = QCBOR_MAX_TAGS_PER_ITEM - 1; uTagIndex > 0; uTagIndex--) {
1263 auTags[uTagIndex] = auTags[uTagIndex-1];
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001264 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001265
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001266 // Is the tag > 16 bits?
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001267 if(pDecodedItem->val.uTagV > QCBOR_LAST_UNMAPPED_TAG) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001268 size_t uTagMapIndex;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001269 // Is there room in the tag map, or is it in it already?
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001270 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07001271 if(me->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001272 break;
1273 }
1274 if(me->auMappedTags[uTagMapIndex] == pDecodedItem->val.uTagV) {
1275 break;
1276 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001277 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001278 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1279 // No room for the tag
Laurence Lundblade9b334962020-08-27 10:55:53 -07001280 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
1281 // Continue on to get all tags on this item even though
1282 // it is erroring out in the end. This is a resource limit
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001283 // error, not a problem with being well-formed CBOR.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001284 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001285 }
1286
Laurence Lundblade410c7e02020-06-25 23:35:29 -07001287 // Covers the cases where tag is new and were it is already in the map
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001288 me->auMappedTags[uTagMapIndex] = pDecodedItem->val.uTagV;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001289 auTags[0] = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001290
1291 } else {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001292 auTags[0] = (uint16_t)pDecodedItem->val.uTagV;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001293 }
1294 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001295
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001296Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001297 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001298}
1299
1300
1301/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001302 This layer takes care of map entries. It combines the label and data
1303 items into one QCBORItem.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001304
1305 @retval QCBOR_ERR_UNSUPPORTED
1306
1307 @retval QCBOR_ERR_HIT_END
1308
1309 @retval QCBOR_ERR_INT_OVERFLOW
1310
1311 @retval QCBOR_ERR_STRING_ALLOCATE
1312
1313 @retval QCBOR_ERR_STRING_TOO_LONG
1314
1315 @retval QCBOR_ERR_HALF_PRECISION_DISABLED
1316
1317 @retval QCBOR_ERR_BAD_TYPE_7
1318
1319 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1320
1321 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1322
1323 @retval QCBOR_ERR_TOO_MANY_TAGS
1324
1325 @retval QCBOR_ERR_MAP_LABEL_TYPE
1326
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001327 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001328 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001329static inline QCBORError
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001330GetNext_MapEntry(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001331{
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001332 // Stack use: int/ptr 1, QCBORItem -- 56
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001333 QCBORError nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001334 if(nReturn)
1335 goto Done;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001336
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001337 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001338 // Break can't be a map entry
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001339 goto Done;
1340 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001341
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001342 if(me->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1343 // In a map and caller wants maps decoded, not treated as arrays
1344
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001345 if(DecodeNesting_IsCurrentTypeMap(&(me->nesting))) {
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001346 // If in a map and the right decoding mode, get the label
1347
Laurence Lundbladeee851742020-01-08 08:37:05 -08001348 // Save label in pDecodedItem and get the next which will
1349 // be the real data
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001350 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001351 nReturn = GetNext_TaggedItem(me, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001352 if(QCBORDecode_IsUnrecoverableError(nReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001353 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001354 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001355
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301356 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001357
1358 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
1359 // strings are always good labels
1360 pDecodedItem->label.string = LabelItem.val.string;
1361 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
1362 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == me->uDecodeMode) {
Laurence Lundbladeee851742020-01-08 08:37:05 -08001363 // It's not a string and we only want strings
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001364 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1365 goto Done;
1366 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1367 pDecodedItem->label.int64 = LabelItem.val.int64;
1368 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1369 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1370 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1371 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1372 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1373 pDecodedItem->label.string = LabelItem.val.string;
1374 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1375 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1376 } else {
1377 // label is not an int or a string. It is an arrray
1378 // or a float or such and this implementation doesn't handle that.
1379 // Also, tags on labels are ignored.
1380 nReturn = QCBOR_ERR_MAP_LABEL_TYPE;
1381 goto Done;
1382 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001383 }
1384 } else {
1385 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001386 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001387 nReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001388 goto Done;
1389 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001390 // Decoding a map as an array
1391 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001392 // Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2
1393 // Cast is needed because of integer promotion
1394 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001395 }
1396 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001397
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001398Done:
1399 return nReturn;
1400}
1401
1402
Laurence Lundblade02625d42020-06-25 14:41:41 -07001403/*
1404 See if next item is a CBOR break. If it is, it is consumed,
1405 if not it is not consumed.
1406*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001407static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001408NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1409{
1410 *pbNextIsBreak = false;
1411 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001412 QCBORItem Peek;
1413 size_t uPeek = UsefulInputBuf_Tell(pUIB);
1414 QCBORError uReturn = GetNext_Item(pUIB, &Peek, NULL);
1415 if(uReturn != QCBOR_SUCCESS) {
1416 return uReturn;
1417 }
1418 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001419 // It is not a break, rewind so it can be processed normally.
1420 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001421 } else {
1422 *pbNextIsBreak = true;
1423 }
1424 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001425
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001426 return QCBOR_SUCCESS;
1427}
1428
1429
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001430/*
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001431 An item was just consumed, now figure out if it was the
1432 end of an array or map that can be closed out. That
1433 may in turn close out another map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001434*/
Laurence Lundbladed0304932020-06-27 10:59:38 -07001435static QCBORError NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001436{
1437 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001438
Laurence Lundblade642282a2020-06-23 12:00:33 -07001439 /* This loops ascending nesting levels as long as there is ascending to do */
1440 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1441
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001442 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001443 /* Decrement count for definite length maps / arrays */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001444 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1445 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001446 /* Didn't close out map or array, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001447 break;
1448 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07001449 /* All of a definite length array was consumed; fall through to
1450 ascend */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001451
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001452 } else {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001453 /* If not definite length, have to check for a CBOR break */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001454 bool bIsBreak = false;
1455 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1456 if(uReturn != QCBOR_SUCCESS) {
1457 goto Done;
1458 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001459
1460 if(!bIsBreak) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001461 /* It's not a break so nothing closes out and all work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001462 break;
1463 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001464
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001465 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001466 /*
1467 Break occurred inside a bstr-wrapped CBOR or
1468 in the top level sequence. This is always an
1469 error because neither are an indefinte length
1470 map/array.
1471 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001472 uReturn = QCBOR_ERR_BAD_BREAK;
1473 goto Done;
1474 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001475
Laurence Lundblade02625d42020-06-25 14:41:41 -07001476 /* It was a break in an indefinite length map / array */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001477 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001478
Laurence Lundblade02625d42020-06-25 14:41:41 -07001479 /* All items in the map/array level have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001480
Laurence Lundblade93d89472020-10-03 22:30:50 -07001481 /* But ascent in bounded mode is only by explicit call to
1482 QCBORDecode_ExitBoundedMode() */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001483 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade93d89472020-10-03 22:30:50 -07001484 /* Set the count to zero for definite length arrays to indicate
1485 cursor is at end of bounded map / array */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001486 if(bMarkEnd) {
1487 // Used for definite and indefinite to signal end
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001488 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001489
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001490 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001491 break;
1492 }
1493
1494 /* Finally, actually ascend one level. */
1495 DecodeNesting_Ascend(&(pMe->nesting));
1496 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001497
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001498 uReturn = QCBOR_SUCCESS;
1499
1500Done:
1501 return uReturn;
1502}
1503
1504
1505/*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001506 This handles the traversal descending into and asecnding out of maps,
Laurence Lundblade642282a2020-06-23 12:00:33 -07001507 arrays and bstr-wrapped CBOR. It figures out the ends of definite and
1508 indefinte length maps and arrays by looking at the item count or
1509 finding CBOR breaks. It detects the ends of the top-level sequence
1510 and of bstr-wrapped CBOR by byte count.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001511
1512 @retval QCBOR_ERR_UNSUPPORTED X
1513
1514 @retval QCBOR_ERR_HIT_END
1515
1516 @retval QCBOR_ERR_INT_OVERFLOW X
1517
1518 @retval QCBOR_ERR_STRING_ALLOCATE
1519
1520 @retval QCBOR_ERR_STRING_TOO_LONG
1521
1522 @retval QCBOR_ERR_HALF_PRECISION_DISABLED X
1523
1524 @retval QCBOR_ERR_BAD_TYPE_7 X
1525
1526 @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1527
1528 @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1529
1530 @retval QCBOR_ERR_TOO_MANY_TAGS
1531
1532 @retval QCBOR_ERR_MAP_LABEL_TYPE X
1533
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001534 @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade9b334962020-08-27 10:55:53 -07001535
1536 @retval QCBOR_ERR_NO_MORE_ITEMS
1537
1538 @retval QCBOR_ERR_BAD_BREAK
1539
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001540 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001541static QCBORError
1542QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001543{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001544 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001545 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001546
Laurence Lundblade642282a2020-06-23 12:00:33 -07001547 /*
1548 If out of bytes to consume, it is either the end of the top-level
1549 sequence of some bstr-wrapped CBOR that was entered.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001550
Laurence Lundblade642282a2020-06-23 12:00:33 -07001551 In the case of bstr-wrapped CBOR, the length of the UsefulInputBuf
1552 was set to that of the bstr-wrapped CBOR. When the bstr-wrapped
1553 CBOR is exited, the length is set back to the top-level's length
1554 or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001555 */
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001556 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001557 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001558 goto Done;
1559 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001560
Laurence Lundblade642282a2020-06-23 12:00:33 -07001561 /*
1562 Check to see if at the end of a bounded definite length map or
Laurence Lundblade02625d42020-06-25 14:41:41 -07001563 array. The check for the end of an indefinite length array is
1564 later.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001565 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001566 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001567 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001568 goto Done;
1569 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001570
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001571 /* ==== Next: not at the end so get another item ==== */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001572 uReturn = GetNext_MapEntry(me, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001573 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1574 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001575 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001576 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301577
Laurence Lundblade642282a2020-06-23 12:00:33 -07001578 /*
1579 Breaks ending arrays/maps are always processed at the end of this
1580 function. They should never show up here.
1581 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301582 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001583 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301584 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301585 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001586
Laurence Lundblade642282a2020-06-23 12:00:33 -07001587 /*
1588 Record the nesting level for this data item before processing any
1589 of decrementing and descending.
1590 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001591 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001592
Laurence Lundblade642282a2020-06-23 12:00:33 -07001593
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001594 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001595 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001596 /*
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001597 If the new item is a map or array, descend.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001598
Laurence Lundblade93d89472020-10-03 22:30:50 -07001599 Empty indefinite length maps and arrays are descended into, but
1600 then ascended out of in the next chunk of code.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001601
1602 Maps and arrays do count as items in the map/array that
Laurence Lundblade642282a2020-06-23 12:00:33 -07001603 encloses them so a decrement needs to be done for them too, but
1604 that is done only when all the items in them have been
1605 processed, not when they are opened with the exception of an
1606 empty map or array.
1607 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001608 QCBORError uDescendErr;
1609 uDescendErr = DecodeNesting_DescendMapOrArray(&(me->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001610 pDecodedItem->uDataType,
1611 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001612 if(uDescendErr != QCBOR_SUCCESS) {
1613 /* This error is probably a traversal error and it
1614 overrides the non-traversal error. */
1615 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001616 goto Done;
1617 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001618 }
1619
Laurence Lundblade02625d42020-06-25 14:41:41 -07001620 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1621 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1622 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade642282a2020-06-23 12:00:33 -07001623 /*
1624 The following cases are handled here:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001625 - A non-aggregate like an integer or string
1626 - An empty definite length map or array
1627 - An indefinite length map or array that might be empty or might not.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001628
Laurence Lundbladee6f15112020-07-23 18:44:16 -07001629 NestLevelAscender() does the work of decrementing the count for an
Laurence Lundblade02625d42020-06-25 14:41:41 -07001630 definite length map/array and break detection for an indefinite
1631 length map/array. If the end of the map/array was reached, then
1632 it ascends nesting levels, possibly all the way to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001633 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001634 QCBORError uAscendErr;
1635 uAscendErr = NestLevelAscender(me, true);
1636 if(uAscendErr != QCBOR_SUCCESS) {
1637 /* This error is probably a traversal error and it
1638 overrides the non-traversal error. */
1639 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001640 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001641 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301642 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001643
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001644 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001645 /*
Laurence Lundblade02625d42020-06-25 14:41:41 -07001646 Tell the caller what level is next. This tells them what
1647 maps/arrays were closed out and makes it possible for them to
1648 reconstruct the tree with just the information returned in
1649 a QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001650 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001651 if(DecodeNesting_IsAtEndOfBoundedLevel(&(me->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001652 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001653 pDecodedItem->uNextNestLevel = 0;
1654 } else {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001655 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(me->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001656 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001657
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001658Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001659 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001660}
1661
Laurence Lundblade9b334962020-08-27 10:55:53 -07001662static void ShiftTags(QCBORItem *pDecodedItem)
1663{
1664 pDecodedItem->uTags[0] = pDecodedItem->uTags[1];
1665 pDecodedItem->uTags[1] = pDecodedItem->uTags[2];
1666 pDecodedItem->uTags[2] = pDecodedItem->uTags[3];
1667 pDecodedItem->uTags[2] = CBOR_TAG_INVALID16;
1668}
1669
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001670
Laurence Lundblade59289e52019-12-30 13:44:37 -08001671/*
1672 Mostly just assign the right data type for the date string.
1673 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001674static inline QCBORError DecodeDateString(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001675{
Laurence Lundblade59289e52019-12-30 13:44:37 -08001676 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1677 return QCBOR_ERR_BAD_OPT_TAG;
1678 }
1679
1680 const UsefulBufC Temp = pDecodedItem->val.string;
1681 pDecodedItem->val.dateString = Temp;
1682 pDecodedItem->uDataType = QCBOR_TYPE_DATE_STRING;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001683 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001684 return QCBOR_SUCCESS;
1685}
1686
1687
Laurence Lundblade9b334962020-08-27 10:55:53 -07001688
Laurence Lundblade59289e52019-12-30 13:44:37 -08001689/*
Laurence Lundbladeee851742020-01-08 08:37:05 -08001690 The epoch formatted date. Turns lots of different forms of encoding
1691 date into uniform one
Laurence Lundblade59289e52019-12-30 13:44:37 -08001692 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001693static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001694{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001695 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001696
1697 pDecodedItem->val.epochDate.fSecondsFraction = 0;
1698
1699 switch (pDecodedItem->uDataType) {
1700
1701 case QCBOR_TYPE_INT64:
1702 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1703 break;
1704
1705 case QCBOR_TYPE_UINT64:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001706 // This only happens for CBOR type 0 > INT64_MAX so it is
1707 // always an overflow.
1708 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1709 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001710 break;
1711
1712 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001713 case QCBOR_TYPE_FLOAT:
1714#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001715 {
1716 // This comparison needs to be done as a float before
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001717 // conversion to an int64_t to be able to detect doubles that
1718 // are too large to fit into an int64_t. A double has 52
1719 // bits of preceision. An int64_t has 63. Casting INT64_MAX
1720 // to a double actually causes a round up which is bad and
1721 // wrong for the comparison because it will allow conversion
1722 // of doubles that can't fit into a uint64_t. To remedy this
1723 // INT64_MAX - 0x7ff is used as the cutoff point because if
1724 // that value rounds up in conversion to double it will still
1725 // be less than INT64_MAX. 0x7ff is picked because it has 11
1726 // bits set.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001727 //
Laurence Lundblade7b5a3b62020-07-22 10:17:16 -07001728 // INT64_MAX seconds is on the order of 10 billion years, and
1729 // the earth is less than 5 billion years old, so for most
1730 // uses this conversion error won't occur even though doubles
1731 // can go much larger.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001732 //
1733 // Without the 0x7ff there is a ~30 minute range of time
1734 // values 10 billion years in the past and in the future
Laurence Lundbladec7114722020-08-13 05:11:40 -07001735 // where this code would go wrong. Some compilers
1736 // will generate warnings or errors without the 0x7ff
1737 // because of the precision issue.
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001738 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
1739 pDecodedItem->val.dfnum :
1740 (double)pDecodedItem->val.fnum;
Laurence Lundbladec7114722020-08-13 05:11:40 -07001741 if(isnan(d) ||
1742 d > (double)(INT64_MAX - 0x7ff) ||
1743 d < (double)(INT64_MIN + 0x7ff)) {
1744 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001745 goto Done;
1746 }
1747 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001748 pDecodedItem->val.epochDate.fSecondsFraction =
1749 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001750 }
Laurence Lundblade9682a532020-06-06 18:33:04 -07001751#else
Laurence Lundblade4b270642020-08-14 12:53:07 -07001752
Laurence Lundbladec7114722020-08-13 05:11:40 -07001753 uReturn = QCBOR_ERR_FLOAT_DATE_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001754 goto Done;
1755
Laurence Lundblade9682a532020-06-06 18:33:04 -07001756#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001757 break;
1758
1759 default:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001760 uReturn = QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001761 goto Done;
1762 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001763
Laurence Lundblade59289e52019-12-30 13:44:37 -08001764 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
1765
1766Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07001767 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001768}
1769
1770
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001771/*
1772 Mostly just assign the right data type for the bignum.
1773 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001774static inline QCBORError DecodeBigNum(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001775{
1776 // Stack Use: UsefulBuf 1 -- 16
1777 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1778 return QCBOR_ERR_BAD_OPT_TAG;
1779 }
1780 const UsefulBufC Temp = pDecodedItem->val.string;
1781 pDecodedItem->val.bigNum = Temp;
1782 const bool bIsPosBigNum = (bool)(pDecodedItem->uTags[0] == CBOR_TAG_POS_BIGNUM);
1783 pDecodedItem->uDataType = (uint8_t)(bIsPosBigNum ? QCBOR_TYPE_POSBIGNUM
1784 : QCBOR_TYPE_NEGBIGNUM);
1785 return QCBOR_SUCCESS;
1786}
1787
1788
Laurence Lundblade59289e52019-12-30 13:44:37 -08001789#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
1790/*
1791 Decode decimal fractions and big floats.
1792
1793 When called pDecodedItem must be the array that is tagged as a big
1794 float or decimal fraction, the array that has the two members, the
1795 exponent and mantissa.
1796
1797 This will fetch and decode the exponent and mantissa and put the
1798 result back into pDecodedItem.
1799 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001800static inline QCBORError
Laurence Lundblade59289e52019-12-30 13:44:37 -08001801QCBORDecode_MantissaAndExponent(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
1802{
1803 QCBORError nReturn;
1804
1805 // --- Make sure it is an array; track nesting level of members ---
1806 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
1807 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1808 goto Done;
1809 }
1810
1811 // A check for pDecodedItem->val.uCount == 2 would work for
Laurence Lundbladeee851742020-01-08 08:37:05 -08001812 // definite length arrays, but not for indefnite. Instead remember
1813 // the nesting level the two integers must be at, which is one
1814 // deeper than that of the array.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001815 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
1816
1817 // --- Is it a decimal fraction or a bigfloat? ---
1818 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(me, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
1819 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
1820
1821 // --- Get the exponent ---
1822 QCBORItem exponentItem;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001823 nReturn = QCBORDecode_GetNextMapOrArray(me, &exponentItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001824 if(nReturn != QCBOR_SUCCESS) {
1825 goto Done;
1826 }
1827 if(exponentItem.uNestingLevel != nNestLevel) {
1828 // Array is empty or a map/array encountered when expecting an int
1829 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1830 goto Done;
1831 }
1832 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
1833 // Data arriving as an unsigned int < INT64_MAX has been converted
1834 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1835 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1836 // will be too large for this to handle and thus an error that will
1837 // get handled in the next else.
1838 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
1839 } else {
1840 // Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX
1841 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1842 goto Done;
1843 }
1844
1845 // --- Get the mantissa ---
1846 QCBORItem mantissaItem;
1847 nReturn = QCBORDecode_GetNextWithTags(me, &mantissaItem, NULL);
1848 if(nReturn != QCBOR_SUCCESS) {
1849 goto Done;
1850 }
1851 if(mantissaItem.uNestingLevel != nNestLevel) {
1852 // Mantissa missing or map/array encountered when expecting number
1853 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1854 goto Done;
1855 }
1856 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
1857 // Data arriving as an unsigned int < INT64_MAX has been converted
1858 // to QCBOR_TYPE_INT64 and thus handled here. This is also means
1859 // that the only data arriving here of type QCBOR_TYPE_UINT64 data
1860 // will be too large for this to handle and thus an error that
1861 // will get handled in an else below.
1862 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07001863 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
1864 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001865 // Got a good big num mantissa
1866 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
1867 // Depends on numbering of QCBOR_TYPE_XXX
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001868 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
1869 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
1870 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08001871 } else {
1872 // Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX
1873 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1874 goto Done;
1875 }
1876
1877 // --- Check that array only has the two numbers ---
1878 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07001879 // Extra items in the decimal fraction / big float
Laurence Lundblade59289e52019-12-30 13:44:37 -08001880 nReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
1881 goto Done;
1882 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07001883 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001884
1885Done:
Laurence Lundblade59289e52019-12-30 13:44:37 -08001886 return nReturn;
1887}
1888#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
1889
1890
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001891static inline QCBORError DecodeURI(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001892{
1893 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1894 return QCBOR_ERR_BAD_OPT_TAG;
1895 }
1896 pDecodedItem->uDataType = QCBOR_TYPE_URI;
1897 return QCBOR_SUCCESS;
1898}
1899
1900
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001901static inline QCBORError DecodeB64URL(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001902{
1903 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1904 return QCBOR_ERR_BAD_OPT_TAG;
1905 }
1906 pDecodedItem->uDataType = QCBOR_TYPE_BASE64URL;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001907
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001908 return QCBOR_SUCCESS;
1909}
1910
1911
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001912static inline QCBORError DecodeB64(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001913{
1914 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1915 return QCBOR_ERR_BAD_OPT_TAG;
1916 }
1917 pDecodedItem->uDataType = QCBOR_TYPE_BASE64;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001918
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001919 return QCBOR_SUCCESS;
1920}
1921
1922
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001923static inline QCBORError DecodeRegex(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001924{
1925 if(pDecodedItem->uDataType != QCBOR_TYPE_TEXT_STRING) {
1926 return QCBOR_ERR_BAD_OPT_TAG;
1927 }
1928 pDecodedItem->uDataType = QCBOR_TYPE_REGEX;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001929
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001930 return QCBOR_SUCCESS;
1931}
1932
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001933
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001934static inline QCBORError DecodeWrappedCBOR(QCBORItem *pDecodedItem)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001935{
1936 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1937 return QCBOR_ERR_BAD_OPT_TAG;
1938 }
1939 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001940
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07001941 return QCBOR_SUCCESS;
1942}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001943
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001944
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001945static inline QCBORError DecodeWrappedCBORSequence(QCBORItem *pDecodedItem)
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001946{
1947 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1948 return QCBOR_ERR_BAD_OPT_TAG;
1949 }
1950 pDecodedItem->uDataType = QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001951
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07001952 return QCBOR_SUCCESS;
1953}
1954
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001955
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001956static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001957{
1958 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
1959 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07001960 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001961 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
1962 } else {
1963 return QCBOR_ERR_BAD_OPT_TAG;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001964
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001965 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001966
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001967 return QCBOR_SUCCESS;
1968}
1969
1970
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001971static inline QCBORError DecodeUUID(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001972{
1973 if(pDecodedItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
1974 return QCBOR_ERR_BAD_OPT_TAG;
1975 }
1976 pDecodedItem->uDataType = QCBOR_TYPE_UUID;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001977
Laurence Lundblade91853ae2020-06-15 19:35:58 -07001978 return QCBOR_SUCCESS;
1979}
1980
1981
Laurence Lundblade59289e52019-12-30 13:44:37 -08001982/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08001983 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08001984 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001985static QCBORError
1986QCBORDecode_GetNextTag(QCBORDecodeContext *me, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001987{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001988 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001989
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001990 uReturn = QCBORDecode_GetNextMapOrArray(me, pDecodedItem);
1991 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001992 goto Done;
1993 }
1994
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07001995 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
1996 switch(pDecodedItem->uTags[uTagIndex]) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08001997
Laurence Lundblade4a21be12020-08-05 12:48:33 -07001998 // Many of the functions here only just map a CBOR tag to
1999 // a QCBOR_TYPE for a string and could probably be
2000 // implemented with less object code. This implementation
2001 // of string types takes about 120 bytes of object code
2002 // (that is always linked and not removed by dead stripping).
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002003 case CBOR_TAG_DATE_STRING:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002004 uReturn = DecodeDateString(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002005 break;
2006
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002007 case CBOR_TAG_DATE_EPOCH:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002008 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002009 break;
2010
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002011 case CBOR_TAG_POS_BIGNUM:
2012 case CBOR_TAG_NEG_BIGNUM:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002013 uReturn = DecodeBigNum(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002014 break;
2015
Laurence Lundblade93d89472020-10-03 22:30:50 -07002016#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002017 case CBOR_TAG_DECIMAL_FRACTION:
2018 case CBOR_TAG_BIGFLOAT:
Laurence Lundblade59289e52019-12-30 13:44:37 -08002019 // For aggregate tagged types, what goes into pTags is only collected
2020 // from the surrounding data item, not the contents, so pTags is not
2021 // passed on here.
2022
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002023 uReturn = QCBORDecode_MantissaAndExponent(me, pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002024 break;
Laurence Lundblade93d89472020-10-03 22:30:50 -07002025#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002026
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002027 case CBOR_TAG_CBOR:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002028 uReturn = DecodeWrappedCBOR(pDecodedItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07002029 break;
2030
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002031 case CBOR_TAG_CBOR_SEQUENCE:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002032 uReturn = DecodeWrappedCBORSequence(pDecodedItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002033 break;
2034
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002035 case CBOR_TAG_URI:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002036 uReturn = DecodeURI(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002037 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002038
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002039 case CBOR_TAG_B64URL:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002040 uReturn = DecodeB64URL(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002041 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002042
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002043 case CBOR_TAG_B64:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002044 uReturn = DecodeB64(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002045 break;
2046
2047 case CBOR_TAG_MIME:
2048 case CBOR_TAG_BINARY_MIME:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002049 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002050 break;
2051
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002052 case CBOR_TAG_REGEX:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002053 uReturn = DecodeRegex(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002054 break;
2055
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002056 case CBOR_TAG_BIN_UUID:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002057 uReturn = DecodeUUID(pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002058 break;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002059
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002060 case CBOR_TAG_INVALID16:
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002061 // The end of the tag list or no tags
2062 // Successful exit from the loop.
2063 goto Done;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002064
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002065 default:
2066 // A tag that is not understood
2067 // A successful exit from the loop
2068 goto Done;
2069
2070 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002071 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002072 goto Done;
2073 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002074 // A tag was successfully processed, shift it
2075 // out of the list of tags returned.
2076 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002077 }
2078
2079Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002080 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002081}
2082
2083
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002084/*
2085 Public function, see header qcbor/qcbor_decode.h file
2086 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002087QCBORError
2088QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2089{
2090 QCBORError uErr;
2091 uErr = QCBORDecode_GetNextTag(pMe, pDecodedItem);
2092 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002093 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2094 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2095 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002096 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002097}
2098
2099
2100/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002101 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002102 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002103QCBORError
2104QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2105{
2106 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2107 const UsefulInputBuf Save = pMe->InBuf;
2108
2109 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2110
2111 pMe->nesting = SaveNesting;
2112 pMe->InBuf = Save;
2113
2114 return uErr;
2115}
2116
2117
2118/*
2119 Public function, see header qcbor/qcbor_decode.h file
2120 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002121void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2122{
2123 if(pMe->uLastError != QCBOR_SUCCESS) {
2124 return;
2125 }
2126
2127 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2128}
2129
2130
2131/*
2132 Public function, see header qcbor/qcbor_decode.h file
2133 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002134QCBORError
2135QCBORDecode_GetNextWithTags(QCBORDecodeContext *me,
2136 QCBORItem *pDecodedItem,
2137 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002138{
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002139 QCBORError nReturn;
2140
2141 nReturn = QCBORDecode_GetNext(me, pDecodedItem);
2142 if(nReturn != QCBOR_SUCCESS) {
2143 return nReturn;
2144 }
2145
2146 if(pTags != NULL) {
2147 pTags->uNumUsed = 0;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002148 // Reverse the order because pTags is reverse of
2149 // QCBORItem.uTags.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002150 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2151 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002152 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002153 }
2154 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2155 return QCBOR_ERR_TOO_MANY_TAGS;
2156 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002157 pTags->puTags[pTags->uNumUsed] = ConvertTag(me,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002158 pTags->uNumUsed++;
2159 }
2160 }
2161
2162 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002163}
2164
2165
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002166/*
Laurence Lundblade6de37062018-10-15 12:22:42 +05302167 Decoding items is done in 5 layered functions, one calling the
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302168 next one down. If a layer has no work to do for a particular item
2169 it returns quickly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002170
Laurence Lundblade59289e52019-12-30 13:44:37 -08002171 - QCBORDecode_GetNext, GetNextWithTags -- The top layer processes
2172 tagged data items, turning them into the local C representation.
2173 For the most simple it is just associating a QCBOR_TYPE with the data. For
2174 the complex ones that an aggregate of data items, there is some further
2175 decoding and a little bit of recursion.
2176
2177 - QCBORDecode_GetNextMapOrArray - This manages the beginnings and
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302178 ends of maps and arrays. It tracks descending into and ascending
Laurence Lundblade6de37062018-10-15 12:22:42 +05302179 out of maps/arrays. It processes all breaks that terminate
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002180 indefinite length maps and arrays.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002181
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302182 - GetNext_MapEntry -- This handles the combining of two
2183 items, the label and the data, that make up a map entry.
2184 It only does work on maps. It combines the label and data
2185 items into one labeled item.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002186
Laurence Lundblade59289e52019-12-30 13:44:37 -08002187 - GetNext_TaggedItem -- This decodes type 6 tagging. It turns the
2188 tags into bit flags associated with the data item. No actual decoding
2189 of the contents of the tagged item is performed here.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002190
Laurence Lundblade59289e52019-12-30 13:44:37 -08002191 - GetNext_FullItem -- This assembles the sub-items that make up
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302192 an indefinte length string into one string item. It uses the
Laurence Lundblade6de37062018-10-15 12:22:42 +05302193 string allocater to create contiguous space for the item. It
2194 processes all breaks that are part of indefinite length strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002195
Laurence Lundblade59289e52019-12-30 13:44:37 -08002196 - GetNext_Item -- This decodes the atomic data items in CBOR. Each
2197 atomic data item has a "major type", an integer "argument" and optionally
2198 some content. For text and byte strings, the content is the bytes
2199 that make up the string. These are the smallest data items that are
2200 considered to be well-formed. The content may also be other data items in
2201 the case of aggregate types. They are not handled in this layer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002202
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002203 Roughly this takes 300 bytes of stack for vars. Need to
2204 evaluate this more carefully and correctly.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002205
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302206 */
2207
2208
2209/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002210 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002211 */
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002212bool QCBORDecode_IsTagged(QCBORDecodeContext *me,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002213 const QCBORItem *pItem,
2214 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002215{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002216 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2217 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002218 break;
2219 }
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002220 if(ConvertTag(me, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002221 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002222 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002223 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002224
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002225 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002226}
2227
2228
2229/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002230 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002231 */
Laurence Lundblade30816f22018-11-10 13:40:22 +07002232QCBORError QCBORDecode_Finish(QCBORDecodeContext *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002233{
Laurence Lundblade085d7952020-07-24 10:26:30 -07002234 QCBORError uReturn = me->uLastError;
2235
2236 if(uReturn != QCBOR_SUCCESS) {
2237 goto Done;
2238 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002239
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002240 // Error out if all the maps/arrays are not closed out
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002241 if(!DecodeNesting_IsCurrentAtTop(&(me->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002242 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002243 goto Done;
2244 }
2245
2246 // Error out if not all the bytes are consumed
2247 if(UsefulInputBuf_BytesUnconsumed(&(me->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002248 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002249 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002250
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002251Done:
Laurence Lundblade12721ba2020-11-24 22:29:57 -08002252#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade6de37062018-10-15 12:22:42 +05302253 // Call the destructor for the string allocator if there is one.
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002254 // Always called, even if there are errors; always have to clean up
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002255 StringAllocator_Destruct(&(me->StringAllocator));
Laurence Lundblade12721ba2020-11-24 22:29:57 -08002256#endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002257
Laurence Lundblade085d7952020-07-24 10:26:30 -07002258 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002259}
2260
2261
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002262/*
Laurence Lundblade9b334962020-08-27 10:55:53 -07002263 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002264*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07002265// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002266uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2267 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002268 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002269{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002270 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2271 return CBOR_TAG_INVALID64;
2272 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002273 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2274 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002275 } else {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07002276 return ConvertTag(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002277 }
2278}
2279
Laurence Lundblade9b334962020-08-27 10:55:53 -07002280/*
2281 Public function, see header qcbor/qcbor_decode.h file
2282*/
2283uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2284 uint32_t uIndex)
2285{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002286 if(pMe->uLastError != QCBOR_SUCCESS) {
2287 return CBOR_TAG_INVALID64;
2288 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002289 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2290 return CBOR_TAG_INVALID64;
2291 } else {
2292 return ConvertTag(pMe, pMe->uLastTags[uIndex]);
2293 }
2294}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002295
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002296/*
2297
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002298Decoder errors handled in this file
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002299
Laurence Lundbladeee851742020-01-08 08:37:05 -08002300 - Hit end of input before it was expected while decoding type and
2301 number QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002302
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002303 - negative integer that is too large for C QCBOR_ERR_INT_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002304
Laurence Lundbladeee851742020-01-08 08:37:05 -08002305 - Hit end of input while decoding a text or byte string
2306 QCBOR_ERR_HIT_END
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002307
Laurence Lundbladeee851742020-01-08 08:37:05 -08002308 - Encountered conflicting tags -- e.g., an item is tagged both a date
2309 string and an epoch date QCBOR_ERR_UNSUPPORTED
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002310
Laurence Lundbladeee851742020-01-08 08:37:05 -08002311 - Encontered an array or mapp that has too many items
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002312 QCBOR_ERR_ARRAY_DECODE_TOO_LONG
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002313
Laurence Lundbladeee851742020-01-08 08:37:05 -08002314 - Encountered array/map nesting that is too deep
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002315 QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002316
Laurence Lundbladeee851742020-01-08 08:37:05 -08002317 - An epoch date > INT64_MAX or < INT64_MIN was encountered
2318 QCBOR_ERR_DATE_OVERFLOW
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002319
Laurence Lundbladeee851742020-01-08 08:37:05 -08002320 - The type of a map label is not a string or int
2321 QCBOR_ERR_MAP_LABEL_TYPE
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002322
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002323 - Hit end with arrays or maps still open -- QCBOR_ERR_EXTRA_BYTES
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002324
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002325 */
2326
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002327
2328
Laurence Lundblade12721ba2020-11-24 22:29:57 -08002329#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002330
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002331/* ===========================================================================
2332 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002333
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002334 This implements a simple sting allocator for indefinite length
2335 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2336 implements the function type QCBORStringAllocate and allows easy
2337 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002338
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002339 This particular allocator is built-in for convenience. The caller
2340 can implement their own. All of this following code will get
2341 dead-stripped if QCBORDecode_SetMemPool() is not called.
2342
2343 This is a very primitive memory allocator. It does not track
2344 individual allocations, only a high-water mark. A free or
2345 reallocation must be of the last chunk allocated.
2346
2347 The size of the pool and offset to free memory are packed into the
2348 first 8 bytes of the memory pool so we don't have to keep them in
2349 the decode context. Since the address of the pool may not be
2350 aligned, they have to be packed and unpacked as if they were
2351 serialized data of the wire or such.
2352
2353 The sizes packed in are uint32_t to be the same on all CPU types
2354 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002355 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002356
2357
Laurence Lundbladeee851742020-01-08 08:37:05 -08002358static inline int
2359MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002360{
2361 // Use of UsefulInputBuf is overkill, but it is convenient.
2362 UsefulInputBuf UIB;
2363
Laurence Lundbladeee851742020-01-08 08:37:05 -08002364 // Just assume the size here. It was checked during SetUp so
2365 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002366 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002367 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2368 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2369 return UsefulInputBuf_GetError(&UIB);
2370}
2371
2372
Laurence Lundbladeee851742020-01-08 08:37:05 -08002373static inline int
2374MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002375{
2376 // Use of UsefulOutBuf is overkill, but convenient. The
2377 // length check performed here is useful.
2378 UsefulOutBuf UOB;
2379
2380 UsefulOutBuf_Init(&UOB, Pool);
2381 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2382 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2383 return UsefulOutBuf_GetError(&UOB);
2384}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002385
2386
2387/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002388 Internal function for an allocation, reallocation free and destuct.
2389
2390 Having only one function rather than one each per mode saves space in
2391 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002392
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002393 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2394 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002395static UsefulBuf
2396MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002397{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002398 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002399
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002400 uint32_t uPoolSize;
2401 uint32_t uFreeOffset;
2402
2403 if(uNewSize > UINT32_MAX) {
2404 // This allocator is only good up to 4GB. This check should
2405 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2406 goto Done;
2407 }
2408 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2409
2410 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2411 goto Done;
2412 }
2413
2414 if(uNewSize) {
2415 if(pMem) {
2416 // REALLOCATION MODE
2417 // Calculate pointer to the end of the memory pool. It is
2418 // assumed that pPool + uPoolSize won't wrap around by
2419 // assuming the caller won't pass a pool buffer in that is
2420 // not in legitimate memory space.
2421 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2422
2423 // Check that the pointer for reallocation is in the range of the
2424 // pool. This also makes sure that pointer math further down
2425 // doesn't wrap under or over.
2426 if(pMem >= pPool && pMem < pPoolEnd) {
2427 // Offset to start of chunk for reallocation. This won't
2428 // wrap under because of check that pMem >= pPool. Cast
2429 // is safe because the pool is always less than UINT32_MAX
2430 // because of check in QCBORDecode_SetMemPool().
2431 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2432
2433 // Check to see if the allocation will fit. uPoolSize -
2434 // uMemOffset will not wrap under because of check that
2435 // pMem is in the range of the uPoolSize by check above.
2436 if(uNewSize <= uPoolSize - uMemOffset) {
2437 ReturnValue.ptr = pMem;
2438 ReturnValue.len = uNewSize;
2439
2440 // Addition won't wrap around over because uNewSize was
2441 // checked to be sure it is less than the pool size.
2442 uFreeOffset = uMemOffset + uNewSize32;
2443 }
2444 }
2445 } else {
2446 // ALLOCATION MODE
2447 // uPoolSize - uFreeOffset will not underflow because this
2448 // pool implementation makes sure uFreeOffset is always
2449 // smaller than uPoolSize through this check here and
2450 // reallocation case.
2451 if(uNewSize <= uPoolSize - uFreeOffset) {
2452 ReturnValue.len = uNewSize;
2453 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002454 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002455 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002456 }
2457 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002458 if(pMem) {
2459 // FREE MODE
2460 // Cast is safe because of limit on pool size in
2461 // QCBORDecode_SetMemPool()
2462 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2463 } else {
2464 // DESTRUCT MODE
2465 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002466 }
2467 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002468
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002469 UsefulBuf Pool = {pPool, uPoolSize};
2470 MemPool_Pack(Pool, uFreeOffset);
2471
2472Done:
2473 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002474}
2475
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002476
Laurence Lundbladef6531662018-12-04 10:42:22 +09002477/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002478 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002479 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002480QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2481 UsefulBuf Pool,
2482 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002483{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002484 // The pool size and free mem offset are packed into the beginning
2485 // of the pool memory. This compile time check make sure the
2486 // constant in the header is correct. This check should optimize
2487 // down to nothing.
2488 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002489 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002490 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002491
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002492 // The pool size and free offset packed in to the beginning of pool
2493 // memory are only 32-bits. This check will optimize out on 32-bit
2494 // machines.
2495 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002496 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002497 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002498
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002499 // This checks that the pool buffer given is big enough.
2500 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002501 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002502 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002503
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002504 pMe->StringAllocator.pfAllocator = MemPool_Function;
2505 pMe->StringAllocator.pAllocateCxt = Pool.ptr;
2506 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002507
Laurence Lundblade30816f22018-11-10 13:40:22 +07002508 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002509}
Laurence Lundblade12721ba2020-11-24 22:29:57 -08002510#endif
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002511
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002512
2513
Laurence Lundblade9b334962020-08-27 10:55:53 -07002514static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2515{
2516 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2517}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002518
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002519
2520/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002521 Consume an entire map or array (and do next to
2522 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002523 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002524static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002525ConsumeItem(QCBORDecodeContext *pMe,
2526 const QCBORItem *pItemToConsume,
2527 uint_fast8_t *puNextNestLevel)
2528{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002529 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002530 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002531
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002532 // If it is a map or array, this will tell if it is empty.
2533 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2534
2535 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2536 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002537
Laurence Lundblade1341c592020-04-11 14:19:05 -07002538 /* This works for definite and indefinite length
2539 * maps and arrays by using the nesting level
2540 */
2541 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002542 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002543 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002544 goto Done;
2545 }
2546 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002547
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002548 *puNextNestLevel = Item.uNextNestLevel;
2549
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002550 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002551
Laurence Lundblade1341c592020-04-11 14:19:05 -07002552 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002553 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002554 /* Just pass the nesting level through */
2555 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2556
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002557 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002558 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002559
2560Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002561 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002562}
2563
2564
Laurence Lundblade1341c592020-04-11 14:19:05 -07002565/* Return true if the labels in Item1 and Item2 are the same.
2566 Works only for integer and string labels. Returns false
2567 for any other type. */
2568static inline bool
2569MatchLabel(QCBORItem Item1, QCBORItem Item2)
2570{
2571 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2572 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2573 return true;
2574 }
2575 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002576 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002577 return true;
2578 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002579 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002580 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2581 return true;
2582 }
2583 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2584 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2585 return true;
2586 }
2587 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002588
Laurence Lundblade1341c592020-04-11 14:19:05 -07002589 /* Other label types are never matched */
2590 return false;
2591}
2592
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002593
2594/*
2595 Returns true if Item1 and Item2 are the same type
2596 or if either are of QCBOR_TYPE_ANY.
2597 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002598static inline bool
2599MatchType(QCBORItem Item1, QCBORItem Item2)
2600{
2601 if(Item1.uDataType == Item2.uDataType) {
2602 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002603 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002604 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002605 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002606 return true;
2607 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002608 return false;
2609}
2610
2611
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002612/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002613 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002614
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002615 @param[in] pMe The decode context to search.
2616 @param[in,out] pItemArray The items to search for and the items found.
2617 @param[out] puOffset Byte offset of last item matched.
2618 @param[in] pCBContext Context for the not-found item call back.
2619 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002620
2621 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2622
Laurence Lundblade93d89472020-10-03 22:30:50 -07002623 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2624 were found for one of the labels being
2625 search for. This duplicate detection is
2626 only performed for items in pItemArray,
2627 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002628
Laurence Lundblade93d89472020-10-03 22:30:50 -07002629 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2630 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002631
2632 @retval Also errors returned by QCBORDecode_GetNext().
2633
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002634 On input pItemArray contains a list of labels and data types
2635 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002636
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002637 On output the fully retrieved items are filled in with
2638 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002639
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002640 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002641
2642 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002643 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002644static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002645MapSearch(QCBORDecodeContext *pMe,
2646 QCBORItem *pItemArray,
2647 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002648 void *pCBContext,
2649 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002650{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002651 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002652 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002653
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002654 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002655 uReturn = pMe->uLastError;
2656 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002657 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002658
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002659 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002660 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2661 /* QCBOR_TYPE_NONE as first item indicates just looking
2662 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002663 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2664 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002665 }
2666
Laurence Lundblade085d7952020-07-24 10:26:30 -07002667 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2668 // It is an empty bounded array or map
2669 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2670 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002671 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002672 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002673 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002674 // Nothing is ever found in an empty array or map. All items
2675 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002676 uReturn = QCBOR_SUCCESS;
2677 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002678 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002679 }
2680
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002681 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002682 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2683
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002684 /* Reposition to search from the start of the map / array */
Laurence Lundblade02625d42020-06-25 14:41:41 -07002685 UsefulInputBuf_Seek(&(pMe->InBuf),
2686 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
Laurence Lundblade1341c592020-04-11 14:19:05 -07002687
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002688 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002689 Loop over all the items in the map or array. Each item
2690 could be a map or array, but label matching is only at
2691 the main level. This handles definite and indefinite
2692 length maps and arrays. The only reason this is ever
2693 called on arrays is to find their end position.
2694
2695 This will always run over all items in order to do
2696 duplicate detection.
2697
2698 This will exit with failure if it encounters an
2699 unrecoverable error, but continue on for recoverable
2700 errors.
2701
2702 If a recoverable error occurs on a matched item, then
2703 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002704 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002705 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002706 uint_fast8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002707 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002708 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07002709 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002710
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002711 /* Get the item */
2712 QCBORItem Item;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002713 QCBORError uResult = QCBORDecode_GetNextTag(pMe, &Item);
2714 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002715 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002716 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002717 goto Done;
2718 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002719 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002720 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002721 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002722 goto Done;
2723 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002724
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002725 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002726 bool bMatched = false;
2727 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
2728 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002729 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002730 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
2731 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002732 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002733 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002734 /* Also try to match its type */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002735 if(!MatchType(Item, pItemArray[nIndex])) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002736 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002737 goto Done;
2738 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002739
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002740 if(uResult != QCBOR_SUCCESS) {
2741 uReturn = uResult;
2742 goto Done;
2743 }
2744
Laurence Lundblade1341c592020-04-11 14:19:05 -07002745 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002746 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002747 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002748 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002749 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002750 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002751 bMatched = true;
2752 }
2753 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002754
2755
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002756 if(!bMatched && pfCallback != NULL) {
2757 /*
2758 Call the callback on unmatched labels.
2759 (It is tempting to do duplicate detection here, but that would
2760 require dynamic memory allocation because the number of labels
2761 that might be encountered is unbounded.)
2762 */
2763 uReturn = (*pfCallback)(pCBContext, &Item);
2764 if(uReturn != QCBOR_SUCCESS) {
2765 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002766 }
2767 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002768
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002769 /*
2770 Consume the item whether matched or not. This
2771 does the work of traversing maps and array and
2772 everything in them. In this loop only the
2773 items at the current nesting level are examined
2774 to match the labels.
2775 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002776 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07002777 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002778 goto Done;
2779 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002780
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002781 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002782
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002783 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002784
2785 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002786
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002787 // Check here makes sure that this won't accidentally be
2788 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07002789 // QCBOR_MAX_DECODE_INPUT_SIZE.
2790 if(uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
2791 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
2792 goto Done;
2793 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002794 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
2795 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002796
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002797 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002798 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
2799
2800 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002801 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07002802 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002803 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002804 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
2805 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002806 }
2807 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002808
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002809 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002810}
2811
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002812
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002813/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002814 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002815*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002816void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
2817 int64_t nLabel,
2818 uint8_t uQcborType,
2819 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002820{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002821 if(pMe->uLastError != QCBOR_SUCCESS) {
2822 return;
2823 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002824
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002825 QCBORItem OneItemSeach[2];
2826 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
2827 OneItemSeach[0].label.int64 = nLabel;
2828 OneItemSeach[0].uDataType = uQcborType;
2829 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002830
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002831 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002832
2833 *pItem = OneItemSeach[0];
2834
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002835 if(uReturn != QCBOR_SUCCESS) {
2836 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002837 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002838 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002839 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002840 }
2841
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002842 Done:
2843 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002844}
2845
2846
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002847/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002848 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002849*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07002850void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
2851 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07002852 uint8_t uQcborType,
2853 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002854{
Laurence Lundbladeda095972020-06-06 18:35:33 -07002855 if(pMe->uLastError != QCBOR_SUCCESS) {
2856 return;
2857 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002858
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002859 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002860 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
2861 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
2862 OneItemSeach[0].uDataType = uQcborType;
2863 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07002864
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002865 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
2866 if(uReturn != QCBOR_SUCCESS) {
2867 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002868 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002869 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002870 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002871 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002872 }
2873
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07002874 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002875
2876Done:
2877 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002878}
2879
2880
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002881
Laurence Lundblade93d89472020-10-03 22:30:50 -07002882static QCBORError
2883CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07002884{
2885 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
2886 if(uDataType == puTypeList[i]) {
2887 return QCBOR_SUCCESS;
2888 }
2889 }
2890 return QCBOR_ERR_UNEXPECTED_TYPE;
2891}
2892
Laurence Lundblade67257dc2020-07-27 03:33:37 -07002893
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002894/**
2895 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002896 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002897
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002898 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
2899 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07002900
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002901 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
2902 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002903 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07002904static QCBORError
2905CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07002906{
2907 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
2908 pItem->uTags[0] != CBOR_TAG_INVALID16) {
2909 /* There are tags that QCBOR couldn't process on this item and
2910 the caller has told us there should not be. */
2911 return QCBOR_ERR_UNEXPECTED_TYPE;
2912 }
2913
2914 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
2915 const int nItemType = pItem->uDataType;
2916
2917 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
2918 // Must match the tag and only the tag
2919 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2920 }
2921
2922 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
2923 if(uReturn == QCBOR_SUCCESS) {
2924 return QCBOR_SUCCESS;
2925 }
2926
2927 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
2928 /* Must match the content type and only the content type.
2929 There was no match just above so it is a fail. */
2930 return QCBOR_ERR_UNEXPECTED_TYPE;
2931 }
2932
2933 /* If here it can match either the tag or the content
2934 and it hasn't matched the content, so the end
2935 result is whether it matches the tag. This is
2936 also the case that the CBOR standard discourages. */
2937
2938 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
2939}
2940
Laurence Lundblade9b334962020-08-27 10:55:53 -07002941
Laurence Lundblade9b334962020-08-27 10:55:53 -07002942
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002943// This could be semi-private if need be
2944static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002945void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
2946 int64_t nLabel,
2947 TagSpecification TagSpec,
2948 QCBORItem *pItem)
2949{
2950 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
2951 if(pMe->uLastError != QCBOR_SUCCESS) {
2952 return;
2953 }
2954
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002955 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002956}
2957
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07002958
2959// This could be semi-private if need be
2960static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002961void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
2962 const char *szLabel,
2963 TagSpecification TagSpec,
2964 QCBORItem *pItem)
2965{
2966 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
2967 if(pMe->uLastError != QCBOR_SUCCESS) {
2968 return;
2969 }
2970
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002971 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002972}
2973
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002974// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002975void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
2976 int64_t nLabel,
2977 TagSpecification TagSpec,
2978 UsefulBufC *pString)
2979{
2980 QCBORItem Item;
2981 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
2982 if(pMe->uLastError == QCBOR_SUCCESS) {
2983 *pString = Item.val.string;
2984 }
2985}
2986
Laurence Lundblade4e2da002020-06-13 23:08:31 -07002987// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002988void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
2989 const char * szLabel,
2990 TagSpecification TagSpec,
2991 UsefulBufC *pString)
2992{
2993 QCBORItem Item;
2994 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
2995 if(pMe->uLastError == QCBOR_SUCCESS) {
2996 *pString = Item.val.string;
2997 }
2998}
Laurence Lundblade1341c592020-04-11 14:19:05 -07002999
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003000/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003001 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003002*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003003void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003004{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003005 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3006 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003007}
3008
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003009/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003010 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003011*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003012void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3013 QCBORItem *pItemList,
3014 void *pCallbackCtx,
3015 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003016{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003017 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3018 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003019}
3020
3021
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003022/**
3023 * @brief Search for a map/array by label and enter it
3024 *
3025 * @param[in] pMe The decode context.
3026 * @param[in] pSearch The map/array to search for.
3027 *
3028 * @c pSearch is expected to contain one item of type map or array
3029 * with the label specified. The current bounded map will be searched for
3030 * this and if found will be entered.
3031 *
3032 * If the label is not found, or the item found is not a map or array,
3033 * the error state is set.
3034 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003035static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003036{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003037 // The first item in pSearch is the one that is to be
3038 // entered. It should be the only one filled in. Any other
3039 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003040 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003041 return;
3042 }
3043
3044 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003045 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003046 if(pMe->uLastError != QCBOR_SUCCESS) {
3047 return;
3048 }
3049
Laurence Lundblade9b334962020-08-27 10:55:53 -07003050 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003051 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003052 return;
3053 }
3054
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003055 /*
3056 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3057 * next item for the pre-order traversal cursor to be the map/array
3058 * found by MapSearch(). The next few lines of code force the
3059 * cursor to that.
3060 *
3061 * There is no need to retain the old cursor because
3062 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3063 * beginning of the map/array being entered.
3064 *
3065 * The cursor is forced by: 1) setting the input buffer position to
3066 * the item offset found by MapSearch(), 2) setting the map/array
3067 * counter to the total in the map/array, 3) setting the nesting
3068 * level. Setting the map/array counter to the total is not
3069 * strictly correct, but this is OK because this cursor only needs
3070 * to be used to get one item and MapSearch() has already found it
3071 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003072 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003073 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003074
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003075 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3076
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003077 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003078
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003079 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003080}
3081
3082
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003083/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003084 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003085*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003086void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003087{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003088 QCBORItem OneItemSeach[2];
3089 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3090 OneItemSeach[0].label.int64 = nLabel;
3091 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3092 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003093
Laurence Lundblade9b334962020-08-27 10:55:53 -07003094 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003095 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003096}
3097
3098
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003099/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003100 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003101*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003102void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003103{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003104 QCBORItem OneItemSeach[2];
3105 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3106 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3107 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3108 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003109
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003110 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003111}
3112
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003113/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003114 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003115*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003116void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003117{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003118 QCBORItem OneItemSeach[2];
3119 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3120 OneItemSeach[0].label.int64 = nLabel;
3121 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3122 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003123
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003124 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003125}
3126
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003127/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003128 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003129*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003130void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3131{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003132 QCBORItem OneItemSeach[2];
3133 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3134 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3135 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3136 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003137
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003138 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003139}
3140
3141
Laurence Lundblade02625d42020-06-25 14:41:41 -07003142// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003143void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003144{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003145 QCBORError uErr;
3146
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003147 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003148 if(pMe->uLastError != QCBOR_SUCCESS) {
3149 // Already in error state; do nothing.
3150 return;
3151 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003152
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003153 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003154 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003155 uErr = QCBORDecode_GetNext(pMe, &Item);
3156 if(uErr != QCBOR_SUCCESS) {
3157 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003158 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003159 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003160 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3161 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003162 }
3163
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003164 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003165
3166
Laurence Lundbladef0499502020-08-01 11:55:57 -07003167 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003168 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003169 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3170 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003171 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003172 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3173 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003174 // Special case to increment nesting level for zero-length maps
3175 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003176 DecodeNesting_Descend(&(pMe->nesting), uType);
3177 }
3178
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003179 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003180
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003181 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3182 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003183
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003184 if(pItem != NULL) {
3185 *pItem = Item;
3186 }
3187
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003188Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003189 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003190}
3191
Laurence Lundblade02625d42020-06-25 14:41:41 -07003192
3193/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003194 This is the common work for exiting a level that is a bounded map,
3195 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003196
3197 One chunk of work is to set up the pre-order traversal so it is at
3198 the item just after the bounded map, array or bstr that is being
3199 exited. This is somewhat complex.
3200
3201 The other work is to level-up the bounded mode to next higest bounded
3202 mode or the top level if there isn't one.
3203 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003204static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003205ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003206{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003207 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003208
Laurence Lundblade02625d42020-06-25 14:41:41 -07003209 /*
3210 First the pre-order-traversal byte offset is positioned to the
3211 item just after the bounded mode item that was just consumed.
3212 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003213 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3214
Laurence Lundblade02625d42020-06-25 14:41:41 -07003215 /*
3216 Next, set the current nesting level to one above the bounded level
3217 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003218
Laurence Lundblade02625d42020-06-25 14:41:41 -07003219 DecodeNesting_CheckBoundedType() is always called before this and
3220 makes sure pCurrentBounded is valid.
3221 */
3222 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3223
3224 /*
3225 This does the complex work of leveling up the pre-order traversal
3226 when the end of a map or array or another bounded level is
3227 reached. It may do nothing, or ascend all the way to the top
3228 level.
3229 */
Laurence Lundbladed0304932020-06-27 10:59:38 -07003230 uErr = NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003231 if(uErr != QCBOR_SUCCESS) {
3232 goto Done;
3233 }
3234
Laurence Lundblade02625d42020-06-25 14:41:41 -07003235 /*
3236 This makes the next highest bounded level the current bounded
3237 level. If there is no next highest level, then no bounded mode is
3238 in effect.
3239 */
3240 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003241
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003242 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003243
3244Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003245 return uErr;
3246}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003247
Laurence Lundblade02625d42020-06-25 14:41:41 -07003248
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003249// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003250void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003251{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003252 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003253 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003254 return;
3255 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003256
Laurence Lundblade02625d42020-06-25 14:41:41 -07003257 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003258
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003259 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003260 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003261 goto Done;
3262 }
3263
Laurence Lundblade02625d42020-06-25 14:41:41 -07003264 /*
3265 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003266 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003267 from previous map search, then do a dummy search.
3268 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003269 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003270 QCBORItem Dummy;
3271 Dummy.uLabelType = QCBOR_TYPE_NONE;
3272 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3273 if(uErr != QCBOR_SUCCESS) {
3274 goto Done;
3275 }
3276 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003277
Laurence Lundblade02625d42020-06-25 14:41:41 -07003278 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003279
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003280Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003281 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003282}
3283
3284
Laurence Lundblade1341c592020-04-11 14:19:05 -07003285
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003286static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003287 const QCBORItem *pItem,
3288 uint8_t uTagRequirement,
3289 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003290{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003291 if(pBstr) {
3292 *pBstr = NULLUsefulBufC;
3293 }
3294
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003295 if(pMe->uLastError != QCBOR_SUCCESS) {
3296 // Already in error state; do nothing.
3297 return pMe->uLastError;
3298 }
3299
3300 QCBORError uError = QCBOR_SUCCESS;
3301
3302 if(pItem->uDataType != QCBOR_TYPE_BYTE_STRING) {
3303 uError = QCBOR_ERR_UNEXPECTED_TYPE;
3304 goto Done;;
3305 }
3306
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003307 const TagSpecification TagSpec =
3308 {
3309 uTagRequirement,
3310 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3311 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3312 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003313
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003314 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003315 if(uError != QCBOR_SUCCESS) {
3316 goto Done;
3317 }
3318
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003319 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003320 // Reverse the decrement done by GetNext() for the bstr so the
3321 // increment in NestLevelAscender() called by ExitBoundedLevel()
3322 // will work right.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003323 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003324 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003325
3326 if(pBstr) {
3327 *pBstr = pItem->val.string;
3328 }
3329
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003330 // This saves the current length of the UsefulInputBuf and then
3331 // narrows the UsefulInputBuf to start and length of the wrapped
3332 // CBOR that is being entered.
3333 //
3334 // This makes sure the length is less than
3335 // QCBOR_MAX_DECODE_INPUT_SIZE which is slighly less than
3336 // UINT32_MAX. The value UINT32_MAX is used as a special indicator
3337 // value. The checks against QCBOR_MAX_DECODE_INPUT_SIZE also make
3338 // the casts safe. uEndOfBstr will always be less than
3339 // uPreviousLength because of the way UsefulInputBuf works so there
3340 // is no need to check it. There is also a range check in the
3341 // seek.
3342 //
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003343 // Most of these calls are simple inline accessors so this doesn't
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003344 // amount to much code.
3345 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3346 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003347 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003348 goto Done;
3349 }
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003350 const size_t uEndOfBstr = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003351 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOfBstr - pItem->val.string.len);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003352 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003353
Laurence Lundblade02625d42020-06-25 14:41:41 -07003354 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003355 (uint32_t)uPreviousLength,
3356 (uint32_t)uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003357Done:
3358 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003359}
3360
3361
Laurence Lundblade02625d42020-06-25 14:41:41 -07003362/*
3363 Public function, see header qcbor/qcbor_decode.h file
3364 */
3365void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003366 uint8_t uTagRequirement,
3367 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003368{
3369 if(pMe->uLastError != QCBOR_SUCCESS) {
3370 // Already in error state; do nothing.
3371 return;
3372 }
3373
3374 /* Get the data item that is the map that is being searched */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003375 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003376 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3377 if(pMe->uLastError != QCBOR_SUCCESS) {
3378 return;
3379 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003380
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003381 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003382 &Item,
3383 uTagRequirement,
3384 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003385}
3386
3387
Laurence Lundblade02625d42020-06-25 14:41:41 -07003388/*
3389 Public function, see header qcbor/qcbor_decode.h file
3390 */
3391void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003392 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003393 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003394 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003395{
3396 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003397 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003398
Laurence Lundblade93d89472020-10-03 22:30:50 -07003399 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3400 &Item,
3401 uTagRequirement,
3402 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003403}
3404
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003405
Laurence Lundblade02625d42020-06-25 14:41:41 -07003406/*
3407 Public function, see header qcbor/qcbor_decode.h file
3408 */
3409void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003410 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003411 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003412 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003413{
3414 QCBORItem Item;
3415 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3416
Laurence Lundblade93d89472020-10-03 22:30:50 -07003417 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3418 &Item,
3419 uTagRequirement,
3420 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003421}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003422
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003423
Laurence Lundblade02625d42020-06-25 14:41:41 -07003424/*
3425 Public function, see header qcbor/qcbor_decode.h file
3426 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003427void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003428{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003429 if(pMe->uLastError != QCBOR_SUCCESS) {
3430 // Already in error state; do nothing.
3431 return;
3432 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003433
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003434 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003435 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003436 return;
3437 }
3438
3439 /*
3440 Reset the length of the UsefulInputBuf to what it was before
3441 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003442 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003443 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003444 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003445
3446
Laurence Lundblade02625d42020-06-25 14:41:41 -07003447 QCBORError uErr = ExitBoundedLevel(pMe, DecodeNesting_GetEndOfBstr(&(pMe->nesting)));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003448 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003449}
3450
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003451
Laurence Lundbladee6430642020-03-14 21:15:44 -07003452
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003453
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003454
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003455
Laurence Lundblade11a064e2020-05-07 13:13:42 -07003456
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003457
Laurence Lundblade93d89472020-10-03 22:30:50 -07003458static QCBORError
3459InterpretBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003460{
3461 switch(pItem->uDataType) {
3462 case QCBOR_TYPE_TRUE:
3463 *pBool = true;
3464 return QCBOR_SUCCESS;
3465 break;
3466
3467 case QCBOR_TYPE_FALSE:
3468 *pBool = false;
3469 return QCBOR_SUCCESS;
3470 break;
3471
3472 default:
3473 return QCBOR_ERR_UNEXPECTED_TYPE;
3474 break;
3475 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003476 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003477}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003478
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003479
Laurence Lundblade9b334962020-08-27 10:55:53 -07003480
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003481/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003482 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003483*/
Laurence Lundbladec4537442020-04-14 18:53:22 -07003484void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003485{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003486 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003487 // Already in error state, do nothing
Laurence Lundbladee6430642020-03-14 21:15:44 -07003488 return;
3489 }
3490
Laurence Lundbladec4537442020-04-14 18:53:22 -07003491 QCBORError nError;
3492 QCBORItem Item;
3493
3494 nError = QCBORDecode_GetNext(pMe, &Item);
3495 if(nError != QCBOR_SUCCESS) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003496 pMe->uLastError = (uint8_t)nError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003497 return;
3498 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003499 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003500}
3501
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003502
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003503/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003504 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003505*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003506void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003507{
3508 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003509 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003510
Laurence Lundblade9b334962020-08-27 10:55:53 -07003511 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003512}
3513
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003514
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003515/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003516 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003517*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003518void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3519{
3520 QCBORItem Item;
3521 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3522
Laurence Lundblade9b334962020-08-27 10:55:53 -07003523 pMe->uLastError = (uint8_t)InterpretBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003524}
3525
3526
3527
Laurence Lundbladec7114722020-08-13 05:11:40 -07003528
3529static void ProcessEpochDate(QCBORDecodeContext *pMe,
3530 QCBORItem *pItem,
3531 uint8_t uTagRequirement,
3532 int64_t *pnTime)
3533{
3534 if(pMe->uLastError != QCBOR_SUCCESS) {
3535 // Already in error state, do nothing
3536 return;
3537 }
3538
3539 QCBORError uErr;
3540
3541 const TagSpecification TagSpec =
3542 {
3543 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003544 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3545 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003546 };
3547
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003548 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003549 if(uErr != QCBOR_SUCCESS) {
3550 goto Done;
3551 }
3552
3553 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3554 uErr = DecodeDateEpoch(pItem);
3555 if(uErr != QCBOR_SUCCESS) {
3556 goto Done;
3557 }
3558 }
3559
Laurence Lundblade9b334962020-08-27 10:55:53 -07003560 // Save the tags in the last item's tags in the decode context
3561 // for QCBORDecode_GetNthTagOfLast()
3562 CopyTags(pMe, pItem);
3563
Laurence Lundbladec7114722020-08-13 05:11:40 -07003564 *pnTime = pItem->val.epochDate.nSeconds;
3565
3566Done:
3567 pMe->uLastError = (uint8_t)uErr;
3568}
3569
3570
3571void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003572 uint8_t uTagRequirement,
3573 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003574{
3575 if(pMe->uLastError != QCBOR_SUCCESS) {
3576 // Already in error state, do nothing
3577 return;
3578 }
3579
3580 QCBORItem Item;
3581 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3582
3583 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3584}
3585
3586
3587void
3588QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3589 int64_t nLabel,
3590 uint8_t uTagRequirement,
3591 int64_t *pnTime)
3592{
3593 QCBORItem Item;
3594 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3595 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3596}
3597
3598
3599void
3600QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3601 const char *szLabel,
3602 uint8_t uTagRequirement,
3603 int64_t *pnTime)
3604{
3605 QCBORItem Item;
3606 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3607 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3608}
3609
3610
3611
3612
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003613void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
3614 TagSpecification TagSpec,
3615 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003616{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003617 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003618 // Already in error state, do nothing
3619 return;
3620 }
3621
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003622 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003623 QCBORItem Item;
3624
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003625 uError = QCBORDecode_GetNext(pMe, &Item);
3626 if(uError != QCBOR_SUCCESS) {
3627 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003628 return;
3629 }
3630
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003631 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003632
3633 if(pMe->uLastError == QCBOR_SUCCESS) {
3634 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07003635 } else {
3636 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003637 }
3638}
3639
Laurence Lundbladec4537442020-04-14 18:53:22 -07003640
3641
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003642
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003643static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003644 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003645 UsefulBufC *pValue,
3646 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003647{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003648 const TagSpecification TagSpec =
3649 {
3650 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003651 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3652 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003653 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003654
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003655 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003656 if(uErr != QCBOR_SUCCESS) {
3657 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003658 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003659
3660 *pValue = pItem->val.string;
3661
3662 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
3663 *pbIsNegative = false;
3664 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
3665 *pbIsNegative = true;
3666 }
3667
3668 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003669}
3670
3671
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003672/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003673 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003674 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003675void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
3676 uint8_t uTagRequirement,
3677 UsefulBufC *pValue,
3678 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003679{
3680 if(pMe->uLastError != QCBOR_SUCCESS) {
3681 // Already in error state, do nothing
3682 return;
3683 }
3684
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003685 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003686 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
3687 if(uError != QCBOR_SUCCESS) {
3688 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003689 return;
3690 }
3691
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003692 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003693}
3694
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003695
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003696/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003697 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003698*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003699void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
3700 int64_t nLabel,
3701 uint8_t uTagRequirement,
3702 UsefulBufC *pValue,
3703 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003704{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003705 QCBORItem Item;
3706 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003707 if(pMe->uLastError != QCBOR_SUCCESS) {
3708 return;
3709 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003710
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003711 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07003712}
3713
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003714
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003715/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003716 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003717*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003718void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
3719 const char *szLabel,
3720 uint8_t uTagRequirement,
3721 UsefulBufC *pValue,
3722 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003723{
3724 QCBORItem Item;
3725 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003726 if(pMe->uLastError != QCBOR_SUCCESS) {
3727 return;
3728 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003729
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003730 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003731}
3732
3733
3734
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003735
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003736// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003737QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
3738 const QCBORItem *pItem,
3739 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07003740 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003741{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003742 const TagSpecification TagSpecText =
3743 {
3744 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003745 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3746 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003747 };
3748 const TagSpecification TagSpecBinary =
3749 {
3750 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003751 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3752 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003753 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003754
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003755 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003756
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003757 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003758 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003759 if(pbIsTag257 != NULL) {
3760 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003761 }
3762 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003763 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003764 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07003765 if(pbIsTag257 != NULL) {
3766 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003767 }
3768 uReturn = QCBOR_SUCCESS;
3769
3770 } else {
3771 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
3772 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003773
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003774 return uReturn;
3775}
3776
Laurence Lundblade93d89472020-10-03 22:30:50 -07003777// Improvement: add methods for wrapped CBOR, a simple alternate
3778// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003779
Laurence Lundblade91853ae2020-06-15 19:35:58 -07003780
3781
3782
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003783#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07003784
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003785typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003786
3787
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003788// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003789static QCBORError
3790Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07003791{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003792 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003793
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003794 if(uResult != 0) {
3795 /* This loop will run a maximum of 19 times because
3796 * UINT64_MAX < 10 ^^ 19. More than that will cause
3797 * exit with the overflow error
3798 */
3799 for(; nExponent > 0; nExponent--) {
3800 if(uResult > UINT64_MAX / 10) {
3801 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
3802 }
3803 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003804 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003805
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003806 for(; nExponent < 0; nExponent++) {
3807 uResult = uResult / 10;
3808 if(uResult == 0) {
3809 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3810 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003811 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07003812 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003813 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003814
3815 *puResult = uResult;
3816
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003817 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07003818}
3819
3820
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003821// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07003822static QCBORError
3823Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003824{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003825 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003826
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003827 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003828
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003829 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07003830 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003831 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07003832 */
3833 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003834 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003835 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07003836 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003837 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003838 nExponent--;
3839 }
3840
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003841 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003842 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003843 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
3844 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003845 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003846 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003847 }
3848
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003849 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003850
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003851 return QCBOR_SUCCESS;
3852}
3853
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003854
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003855/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003856 Compute value with signed mantissa and signed result. Works with
3857 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003858 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003859static inline QCBORError ExponentiateNN(int64_t nMantissa,
3860 int64_t nExponent,
3861 int64_t *pnResult,
3862 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003863{
3864 uint64_t uResult;
3865
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003866 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07003867 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003868 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
3869
3870 // Do the exponentiation of the positive mantissa
3871 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
3872 if(uReturn) {
3873 return uReturn;
3874 }
3875
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003876
Laurence Lundblade983500d2020-05-14 11:49:34 -07003877 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
3878 of INT64_MIN. This assumes two's compliment representation where
3879 INT64_MIN is one increment farther from 0 than INT64_MAX.
3880 Trying to write -INT64_MIN doesn't work to get this because the
3881 compiler tries to work with an int64_t which can't represent
3882 -INT64_MIN.
3883 */
3884 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
3885
3886 // Error out if too large
3887 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003888 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
3889 }
3890
3891 // Casts are safe because of checks above
3892 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
3893
3894 return QCBOR_SUCCESS;
3895}
3896
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003897
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003898/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003899 Compute value with signed mantissa and unsigned result. Works with
3900 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003901 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003902static inline QCBORError ExponentitateNU(int64_t nMantissa,
3903 int64_t nExponent,
3904 uint64_t *puResult,
3905 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003906{
3907 if(nMantissa < 0) {
3908 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
3909 }
3910
3911 // Cast to unsigned is OK because of check for negative
3912 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
3913 // Exponentiation is straight forward
3914 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
3915}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003916
3917
3918/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003919 Compute value with signed mantissa and unsigned result. Works with
3920 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003921 */
3922static inline QCBORError ExponentitateUU(uint64_t uMantissa,
3923 int64_t nExponent,
3924 uint64_t *puResult,
3925 fExponentiator pfExp)
3926{
3927 return (*pfExp)(uMantissa, nExponent, puResult);
3928}
3929
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07003930#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
3931
3932
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003933
3934
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003935
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07003936static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003937{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003938 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003939
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003940 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003941 const uint8_t *pByte = BigNum.ptr;
3942 size_t uLen = BigNum.len;
3943 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07003944 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07003945 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003946 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07003947 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003948 }
3949
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003950 *pResult = uResult;
3951 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003952}
3953
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003954
Laurence Lundblade887add82020-05-17 05:50:34 -07003955static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003956{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003957 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003958}
3959
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003960
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003961static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003962{
3963 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003964 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
3965 if(uError) {
3966 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003967 }
3968 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
3969 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07003970 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003971}
3972
3973
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003974static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003975{
3976 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003977 /* The negative integer furthest from zero for a C int64_t is
3978 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
3979 negative number in CBOR is computed as -n - 1 where n is the
3980 encoded integer, where n is what is in the variable BigNum. When
3981 converting BigNum to a uint64_t, the maximum value is thus
3982 INT64_MAX, so that when it -n - 1 is applied to it the result will
3983 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07003984
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003985 -n - 1 <= INT64_MIN.
3986 -n - 1 <= -INT64_MAX - 1
3987 n <= INT64_MAX.
3988 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07003989 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003990 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07003991 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07003992 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07003993
3994 /// Now apply -n - 1. The cast is safe because
3995 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
3996 // is the largest positive integer that an int64_t can
3997 // represent. */
3998 *pnResult = -(int64_t)uResult - 1;
3999
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004000 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004001}
4002
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004003
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004004
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004005
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004006
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004007/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004008Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004009
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004010\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004011
Laurence Lundblade93d89472020-10-03 22:30:50 -07004012\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4013 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004014
4015\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4016
Laurence Lundblade93d89472020-10-03 22:30:50 -07004017\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4018 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004019*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004020static QCBORError
4021ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004022{
4023 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004024 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004025 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004026#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004027 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004028 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4029 http://www.cplusplus.com/reference/cmath/llround/
4030 */
4031 // Not interested in FE_INEXACT
4032 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004033 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4034 *pnValue = llround(pItem->val.dfnum);
4035 } else {
4036 *pnValue = lroundf(pItem->val.fnum);
4037 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004038 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4039 // llround() shouldn't result in divide by zero, but catch
4040 // it here in case it unexpectedly does. Don't try to
4041 // distinguish between the various exceptions because it seems
4042 // they vary by CPU, compiler and OS.
4043 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004044 }
4045 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004046 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004047 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004048#else
4049 return QCBOR_ERR_HW_FLOAT_DISABLED;
4050#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004051 break;
4052
4053 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004054 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004055 *pnValue = pItem->val.int64;
4056 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004057 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004058 }
4059 break;
4060
4061 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004062 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004063 if(pItem->val.uint64 < INT64_MAX) {
4064 *pnValue = pItem->val.int64;
4065 } else {
4066 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4067 }
4068 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004069 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004070 }
4071 break;
4072
4073 default:
4074 return QCBOR_ERR_UNEXPECTED_TYPE;
4075 }
4076 return QCBOR_SUCCESS;
4077}
4078
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004079
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004080void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004081 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004082 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004083 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004084{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004085 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004086 return;
4087 }
4088
Laurence Lundbladee6430642020-03-14 21:15:44 -07004089 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004090 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4091 if(uError) {
4092 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004093 return;
4094 }
4095
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004096 if(pItem) {
4097 *pItem = Item;
4098 }
4099
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004100 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004101}
4102
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004103
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004104void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4105 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004106 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004107 int64_t *pnValue,
4108 QCBORItem *pItem)
4109{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004110 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004111 if(pMe->uLastError != QCBOR_SUCCESS) {
4112 return;
4113 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004114
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004115 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004116}
4117
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004118
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004119void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4120 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004121 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004122 int64_t *pnValue,
4123 QCBORItem *pItem)
4124{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004125 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004126 if(pMe->uLastError != QCBOR_SUCCESS) {
4127 return;
4128 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004129
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004130 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004131}
4132
4133
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004134/*
4135 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004136
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004137 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004138
Laurence Lundblade93d89472020-10-03 22:30:50 -07004139 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4140 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004141
4142 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4143
Laurence Lundblade93d89472020-10-03 22:30:50 -07004144 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4145 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004146 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004147static QCBORError
4148Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004149{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004150 switch(pItem->uDataType) {
4151
4152 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004153 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004154 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004155 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004156 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004157 }
4158 break;
4159
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004160 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004161 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004162 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004163 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004164 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004165 }
4166 break;
4167
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004168#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4169 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004170 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004171 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004172 pItem->val.expAndMantissa.nExponent,
4173 pnValue,
4174 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004175 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004176 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004177 }
4178 break;
4179
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004180 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004181 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004182 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004183 pItem->val.expAndMantissa.nExponent,
4184 pnValue,
4185 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004186 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004187 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004188 }
4189 break;
4190
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004191 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004192 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004193 int64_t nMantissa;
4194 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004195 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4196 if(uErr) {
4197 return uErr;
4198 }
4199 return ExponentiateNN(nMantissa,
4200 pItem->val.expAndMantissa.nExponent,
4201 pnValue,
4202 Exponentitate10);
4203 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004204 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004205 }
4206 break;
4207
4208 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004209 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004210 int64_t nMantissa;
4211 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004212 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4213 if(uErr) {
4214 return uErr;
4215 }
4216 return ExponentiateNN(nMantissa,
4217 pItem->val.expAndMantissa.nExponent,
4218 pnValue,
4219 Exponentitate10);
4220 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004221 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004222 }
4223 break;
4224
4225 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004226 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004227 int64_t nMantissa;
4228 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004229 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4230 if(uErr) {
4231 return uErr;
4232 }
4233 return ExponentiateNN(nMantissa,
4234 pItem->val.expAndMantissa.nExponent,
4235 pnValue,
4236 Exponentitate2);
4237 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004238 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004239 }
4240 break;
4241
4242 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004243 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004244 int64_t nMantissa;
4245 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004246 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4247 if(uErr) {
4248 return uErr;
4249 }
4250 return ExponentiateNN(nMantissa,
4251 pItem->val.expAndMantissa.nExponent,
4252 pnValue,
4253 Exponentitate2);
4254 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004255 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004256 }
4257 break;
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004258#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4259
Laurence Lundbladee6430642020-03-14 21:15:44 -07004260
Laurence Lundbladec4537442020-04-14 18:53:22 -07004261 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004262 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004263}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004264
4265
Laurence Lundbladec4537442020-04-14 18:53:22 -07004266/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004267 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004268 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004269void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004270{
4271 QCBORItem Item;
4272
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004273 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004274
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004275 if(pMe->uLastError == QCBOR_SUCCESS) {
4276 // The above conversion succeeded
4277 return;
4278 }
4279
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004280 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004281 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004282 return;
4283 }
4284
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004285 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004286}
4287
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004288
4289/*
4290Public function, see header qcbor/qcbor_decode.h file
4291*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004292void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4293 int64_t nLabel,
4294 uint32_t uConvertTypes,
4295 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004296{
4297 QCBORItem Item;
4298
Laurence Lundblade93d89472020-10-03 22:30:50 -07004299 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4300 nLabel,
4301 uConvertTypes,
4302 pnValue,
4303 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004304
4305 if(pMe->uLastError == QCBOR_SUCCESS) {
4306 // The above conversion succeeded
4307 return;
4308 }
4309
4310 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4311 // The above conversion failed in a way that code below can't correct
4312 return;
4313 }
4314
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004315 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004316}
4317
4318
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004319/*
4320Public function, see header qcbor/qcbor_decode.h file
4321*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004322void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4323 const char *szLabel,
4324 uint32_t uConvertTypes,
4325 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004326{
4327 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004328 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4329 szLabel,
4330 uConvertTypes,
4331 pnValue,
4332 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004333
4334 if(pMe->uLastError == QCBOR_SUCCESS) {
4335 // The above conversion succeeded
4336 return;
4337 }
4338
4339 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4340 // The above conversion failed in a way that code below can't correct
4341 return;
4342 }
4343
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004344 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004345}
4346
4347
Laurence Lundblade93d89472020-10-03 22:30:50 -07004348static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004349{
4350 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004351 case QCBOR_TYPE_DOUBLE:
4352 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004353#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004354 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004355 // Can't use llround here because it will not convert values
4356 // greater than INT64_MAX and less than UINT64_MAX that
4357 // need to be converted so it is more complicated.
4358 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4359 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4360 if(isnan(pItem->val.dfnum)) {
4361 return QCBOR_ERR_FLOAT_EXCEPTION;
4362 } else if(pItem->val.dfnum < 0) {
4363 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4364 } else {
4365 double dRounded = round(pItem->val.dfnum);
4366 // See discussion in DecodeDateEpoch() for
4367 // explanation of - 0x7ff
4368 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4369 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4370 }
4371 *puValue = (uint64_t)dRounded;
4372 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004373 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004374 if(isnan(pItem->val.fnum)) {
4375 return QCBOR_ERR_FLOAT_EXCEPTION;
4376 } else if(pItem->val.fnum < 0) {
4377 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4378 } else {
4379 float fRounded = roundf(pItem->val.fnum);
4380 // See discussion in DecodeDateEpoch() for
4381 // explanation of - 0x7ff
4382 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4383 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4384 }
4385 *puValue = (uint64_t)fRounded;
4386 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004387 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004388 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4389 // round() and roundf() shouldn't result in exceptions here, but
4390 // catch them to be robust and thorough. Don't try to
4391 // distinguish between the various exceptions because it seems
4392 // they vary by CPU, compiler and OS.
4393 return QCBOR_ERR_FLOAT_EXCEPTION;
4394 }
4395
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004396 } else {
4397 return QCBOR_ERR_UNEXPECTED_TYPE;
4398 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004399#else
4400 return QCBOR_ERR_HW_FLOAT_DISABLED;
4401#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004402 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004403
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004404 case QCBOR_TYPE_INT64:
4405 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4406 if(pItem->val.int64 >= 0) {
4407 *puValue = (uint64_t)pItem->val.int64;
4408 } else {
4409 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4410 }
4411 } else {
4412 return QCBOR_ERR_UNEXPECTED_TYPE;
4413 }
4414 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004415
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004416 case QCBOR_TYPE_UINT64:
4417 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4418 *puValue = pItem->val.uint64;
4419 } else {
4420 return QCBOR_ERR_UNEXPECTED_TYPE;
4421 }
4422 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004423
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004424 default:
4425 return QCBOR_ERR_UNEXPECTED_TYPE;
4426 }
4427
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004428 return QCBOR_SUCCESS;
4429}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004430
4431
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004432void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004433 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004434 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004435 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004436{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004437 if(pMe->uLastError != QCBOR_SUCCESS) {
4438 return;
4439 }
4440
Laurence Lundbladec4537442020-04-14 18:53:22 -07004441 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004442
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004443 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4444 if(uError) {
4445 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004446 return;
4447 }
4448
Laurence Lundbladea826c502020-05-10 21:07:00 -07004449 if(pItem) {
4450 *pItem = Item;
4451 }
4452
Laurence Lundblade93d89472020-10-03 22:30:50 -07004453 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004454}
4455
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004456
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004457void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004458 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004459 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004460 uint64_t *puValue,
4461 QCBORItem *pItem)
4462{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004463 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004464 if(pMe->uLastError != QCBOR_SUCCESS) {
4465 return;
4466 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004467
Laurence Lundblade93d89472020-10-03 22:30:50 -07004468 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004469}
4470
4471
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004472void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004473 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004474 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004475 uint64_t *puValue,
4476 QCBORItem *pItem)
4477{
4478 if(pMe->uLastError != QCBOR_SUCCESS) {
4479 return;
4480 }
4481
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004482 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004483 if(pMe->uLastError != QCBOR_SUCCESS) {
4484 return;
4485 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004486
Laurence Lundblade93d89472020-10-03 22:30:50 -07004487 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004488}
4489
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004490
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004491
Laurence Lundblade93d89472020-10-03 22:30:50 -07004492static QCBORError
4493UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004494{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004495 switch(pItem->uDataType) {
4496
4497 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004498 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004499 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4500 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004501 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004502 }
4503 break;
4504
4505 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004506 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004507 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4508 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004509 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004510 }
4511 break;
4512
4513#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
4514
4515 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004516 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004517 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004518 pItem->val.expAndMantissa.nExponent,
4519 puValue,
4520 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004521 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004522 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004523 }
4524 break;
4525
4526 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004527 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004528 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4529 pItem->val.expAndMantissa.nExponent,
4530 puValue,
4531 Exponentitate2);
4532 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004533 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004534 }
4535 break;
4536
4537 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004538 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004539 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004540 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004541 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004542 if(uErr != QCBOR_SUCCESS) {
4543 return uErr;
4544 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004545 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004546 pItem->val.expAndMantissa.nExponent,
4547 puValue,
4548 Exponentitate10);
4549 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004550 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004551 }
4552 break;
4553
4554 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004555 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004556 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4557 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004558 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004559 }
4560 break;
4561
4562 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004563 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004564 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004565 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004566 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004567 if(uErr != QCBOR_SUCCESS) {
4568 return uErr;
4569 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004570 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004571 pItem->val.expAndMantissa.nExponent,
4572 puValue,
4573 Exponentitate2);
4574 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004575 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004576 }
4577 break;
4578
4579 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004580 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004581 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4582 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004583 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004584 }
4585 break;
4586#endif
4587 default:
4588 return QCBOR_ERR_UNEXPECTED_TYPE;
4589 }
4590}
4591
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004592
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004593/*
4594 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004595 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004596void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004597{
4598 QCBORItem Item;
4599
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004600 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004601
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004602 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
Laurence Lundbladee6430642020-03-14 21:15:44 -07004609 return;
4610 }
4611
Laurence Lundblade93d89472020-10-03 22:30:50 -07004612 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004613}
4614
Laurence Lundbladec4537442020-04-14 18:53:22 -07004615
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004616/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004617 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004618*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004619void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004620 int64_t nLabel,
4621 uint32_t uConvertTypes,
4622 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004623{
4624 QCBORItem Item;
4625
Laurence Lundblade93d89472020-10-03 22:30:50 -07004626 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
4627 nLabel,
4628 uConvertTypes,
4629 puValue,
4630 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004631
4632 if(pMe->uLastError == QCBOR_SUCCESS) {
4633 // The above conversion succeeded
4634 return;
4635 }
4636
4637 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4638 // The above conversion failed in a way that code below can't correct
4639 return;
4640 }
4641
Laurence Lundblade93d89472020-10-03 22:30:50 -07004642 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004643}
4644
4645
4646/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004647 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004648*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004649void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07004650 const char *szLabel,
4651 uint32_t uConvertTypes,
4652 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004653{
4654 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004655 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
4656 szLabel,
4657 uConvertTypes,
4658 puValue,
4659 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004660
4661 if(pMe->uLastError == QCBOR_SUCCESS) {
4662 // The above conversion succeeded
4663 return;
4664 }
4665
4666 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4667 // The above conversion failed in a way that code below can't correct
4668 return;
4669 }
4670
Laurence Lundblade93d89472020-10-03 22:30:50 -07004671 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004672}
4673
4674
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004675
4676
Laurence Lundblade9b334962020-08-27 10:55:53 -07004677static QCBORError ConvertDouble(const QCBORItem *pItem,
4678 uint32_t uConvertTypes,
4679 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004680{
4681 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004682 case QCBOR_TYPE_FLOAT:
4683#ifndef QCBOR_DISABLE_FLOAT_HW_USE
4684 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4685 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004686 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004687 *pdValue = (double)pItem->val.fnum;
4688 } else {
4689 return QCBOR_ERR_UNEXPECTED_TYPE;
4690 }
4691 }
4692#else
4693 return QCBOR_ERR_HW_FLOAT_DISABLED;
4694#endif
4695 break;
4696
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004697 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004698 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
4699 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004700 *pdValue = pItem->val.dfnum;
4701 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004702 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004703 }
4704 }
4705 break;
4706
4707 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004708#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004709 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004710 // A simple cast seems to do the job with no worry of exceptions.
4711 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004712 *pdValue = (double)pItem->val.int64;
4713
4714 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004715 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004716 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004717#else
4718 return QCBOR_ERR_HW_FLOAT_DISABLED;
4719#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004720 break;
4721
4722 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004723#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004724 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004725 // A simple cast seems to do the job with no worry of exceptions.
4726 // There will be precision loss for some values.
4727 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004728 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004729 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004730 }
4731 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004732#else
4733 return QCBOR_ERR_HW_FLOAT_DISABLED;
4734#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004735
4736 default:
4737 return QCBOR_ERR_UNEXPECTED_TYPE;
4738 }
4739
4740 return QCBOR_SUCCESS;
4741}
4742
4743
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004744void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004745 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004746 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004747 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004748{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004749 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004750 return;
4751 }
4752
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004753 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004754
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004755 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004756 if(uError) {
4757 pMe->uLastError = (uint8_t)uError;
4758 return;
4759 }
4760
4761 if(pItem) {
4762 *pItem = Item;
4763 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004764
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004765 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004766}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004767
Laurence Lundbladec4537442020-04-14 18:53:22 -07004768
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004769void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
4770 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004771 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004772 double *pdValue,
4773 QCBORItem *pItem)
4774{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004775 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004776 if(pMe->uLastError != QCBOR_SUCCESS) {
4777 return;
4778 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004779
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004780 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004781}
4782
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004783
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004784void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4785 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004786 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004787 double *pdValue,
4788 QCBORItem *pItem)
4789{
4790 if(pMe->uLastError != QCBOR_SUCCESS) {
4791 return;
4792 }
4793
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004794 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004795 if(pMe->uLastError != QCBOR_SUCCESS) {
4796 return;
4797 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004798
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004799 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004800}
4801
4802
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004803#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004804static double ConvertBigNumToDouble(const UsefulBufC BigNum)
4805{
4806 double dResult;
4807
4808 dResult = 0.0;
4809 const uint8_t *pByte = BigNum.ptr;
4810 size_t uLen = BigNum.len;
4811 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07004812 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004813 while(uLen--) {
4814 dResult = (dResult * 256.0) + (double)*pByte++;
4815 }
4816
4817 return dResult;
4818}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004819#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4820
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004821
Laurence Lundblade93d89472020-10-03 22:30:50 -07004822static QCBORError
4823DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004824{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004825#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004826 /*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004827 https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
4828
4829 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004830 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004831
4832#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004833 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004834 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004835 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004836 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4837 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
4838 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004839 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004840 }
4841 break;
4842
4843 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004844 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07004845 // Underflow gives 0, overflow gives infinity
4846 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
4847 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004848 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004849 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004850 }
4851 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004852#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004853
4854 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004855 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004856 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
4857 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004858 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004859 }
4860 break;
4861
4862 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004863 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004864 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004865 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004866 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004867 }
4868 break;
4869
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004870#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004871 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004872 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004873 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4874 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4875 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004876 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004877 }
4878 break;
4879
4880 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004881 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004882 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4883 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
4884 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004885 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004886 }
4887 break;
4888
4889 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004890 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004891 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
4892 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4893 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004894 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004895 }
4896 break;
4897
4898 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004899 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07004900 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004901 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
4902 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004903 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004904 }
4905 break;
Laurence Lundblade410c7e02020-06-25 23:35:29 -07004906#endif /* ndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
4907
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004908 default:
4909 return QCBOR_ERR_UNEXPECTED_TYPE;
4910 }
4911
4912 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004913
4914#else
4915 (void)pItem;
4916 (void)uConvertTypes;
4917 (void)pdValue;
4918 return QCBOR_ERR_HW_FLOAT_DISABLED;
4919#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
4920
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004921}
4922
4923
4924/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004925 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004926*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004927void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
4928 uint32_t uConvertTypes,
4929 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004930{
4931
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004932 QCBORItem Item;
4933
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004934 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07004935
4936 if(pMe->uLastError == QCBOR_SUCCESS) {
4937 // The above conversion succeeded
4938 return;
4939 }
4940
4941 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4942 // The above conversion failed in a way that code below can't correct
4943 return;
4944 }
4945
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004946 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004947}
4948
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004949
4950/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004951 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004952*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004953void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
4954 int64_t nLabel,
4955 uint32_t uConvertTypes,
4956 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004957{
4958 QCBORItem Item;
4959
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004960 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004961
4962 if(pMe->uLastError == QCBOR_SUCCESS) {
4963 // The above conversion succeeded
4964 return;
4965 }
4966
4967 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4968 // The above conversion failed in a way that code below can't correct
4969 return;
4970 }
4971
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004972 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004973}
4974
4975
4976/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004977 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004978*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07004979void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
4980 const char *szLabel,
4981 uint32_t uConvertTypes,
4982 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004983{
4984 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004985 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004986
4987 if(pMe->uLastError == QCBOR_SUCCESS) {
4988 // The above conversion succeeded
4989 return;
4990 }
4991
4992 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4993 // The above conversion failed in a way that code below can't correct
4994 return;
4995 }
4996
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004997 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004998}
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004999
5000
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005001
5002
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005003#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005004static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5005{
5006 while((uInt & 0xff00000000000000UL) == 0) {
5007 uInt = uInt << 8;
5008 };
5009
5010 UsefulOutBuf UOB;
5011
5012 UsefulOutBuf_Init(&UOB, Buffer);
5013
5014 while(uInt) {
5015 const uint64_t xx = uInt & 0xff00000000000000UL;
5016 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5017 uInt = uInt << 8;
5018 (void)xx;
5019 }
5020
5021 return UsefulOutBuf_OutUBuf(&UOB);
5022}
5023
5024
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005025static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5026 TagSpecification TagSpec,
5027 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005028{
5029 QCBORError uErr;
5030 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005031 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005032 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005033 if(uErr != QCBOR_SUCCESS) {
5034 goto Done;
5035 }
5036
5037 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5038 break; // Successful exit. Moving on to finish decoding.
5039 }
5040
5041 // The item is an array, which means an undecoded
5042 // mantissa and exponent, so decode it. It will then
5043 // have a different type and exit the loop if.
5044 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5045 if(uErr != QCBOR_SUCCESS) {
5046 goto Done;
5047 }
5048
5049 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005050 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005051 }
5052Done:
5053 return uErr;
5054}
5055
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005056
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005057static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005058 TagSpecification TagSpec,
5059 QCBORItem *pItem,
5060 int64_t *pnMantissa,
5061 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005062{
5063 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005064
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005065 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005066 if(uErr != QCBOR_SUCCESS) {
5067 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005068 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005069
Laurence Lundblade9b334962020-08-27 10:55:53 -07005070 switch (pItem->uDataType) {
5071
5072 case QCBOR_TYPE_DECIMAL_FRACTION:
5073 case QCBOR_TYPE_BIGFLOAT:
5074 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5075 *pnExponent = pItem->val.expAndMantissa.nExponent;
5076 break;
5077
5078 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5079 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5080 *pnExponent = pItem->val.expAndMantissa.nExponent;
5081 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5082 break;
5083
5084 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5085 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5086 *pnExponent = pItem->val.expAndMantissa.nExponent;
5087 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5088 break;
5089
5090 default:
5091 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5092 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005093
5094 Done:
5095 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005096}
5097
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005098
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005099static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005100 TagSpecification TagSpec,
5101 QCBORItem *pItem,
5102 UsefulBuf BufferForMantissa,
5103 UsefulBufC *pMantissa,
5104 bool *pbIsNegative,
5105 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005106{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005107 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005108
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005109 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005110 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005111 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005112 }
5113
5114 uint64_t uMantissa;
5115
5116 switch (pItem->uDataType) {
5117
5118 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005119 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005120 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5121 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5122 *pbIsNegative = false;
5123 } else {
5124 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5125 *pbIsNegative = true;
5126 }
5127 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5128 *pnExponent = pItem->val.expAndMantissa.nExponent;
5129 break;
5130
5131 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005132 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005133 *pnExponent = pItem->val.expAndMantissa.nExponent;
5134 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5135 *pbIsNegative = false;
5136 break;
5137
5138 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005139 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005140 *pnExponent = pItem->val.expAndMantissa.nExponent;
5141 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5142 *pbIsNegative = true;
5143 break;
5144
5145 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005146 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005147 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005148
5149Done:
5150 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005151}
5152
5153
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005154/*
5155 Public function, see header qcbor/qcbor_decode.h file
5156*/
5157void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5158 uint8_t uTagRequirement,
5159 int64_t *pnMantissa,
5160 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005161{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005162 if(pMe->uLastError != QCBOR_SUCCESS) {
5163 return;
5164 }
5165
5166 QCBORItem Item;
5167 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5168 if(uError) {
5169 pMe->uLastError = (uint8_t)uError;
5170 return;
5171 }
5172
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005173 const TagSpecification TagSpec =
5174 {
5175 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005176 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5177 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5178 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005179 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005180
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005181 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005182}
5183
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005184
5185/*
5186 Public function, see header qcbor/qcbor_decode.h file
5187*/
5188void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005189 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005190 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005191 int64_t *pnMantissa,
5192 int64_t *pnExponent)
5193{
5194 if(pMe->uLastError != QCBOR_SUCCESS) {
5195 return;
5196 }
5197
5198 QCBORItem Item;
5199 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5200
5201 const TagSpecification TagSpec =
5202 {
5203 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005204 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5205 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5206 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005207 };
5208
5209 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5210}
5211
5212
5213/*
5214 Public function, see header qcbor/qcbor_decode.h file
5215*/
5216void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005217 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005218 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005219 int64_t *pnMantissa,
5220 int64_t *pnExponent)
5221{
5222 if(pMe->uLastError != QCBOR_SUCCESS) {
5223 return;
5224 }
5225
5226 QCBORItem Item;
5227 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5228
5229 const TagSpecification TagSpec =
5230 {
5231 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005232 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5233 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5234 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005235 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005236
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005237 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5238}
5239
5240
5241/*
5242 Public function, see header qcbor/qcbor_decode.h file
5243*/
5244void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5245 uint8_t uTagRequirement,
5246 UsefulBuf MantissaBuffer,
5247 UsefulBufC *pMantissa,
5248 bool *pbMantissaIsNegative,
5249 int64_t *pnExponent)
5250{
5251 if(pMe->uLastError != QCBOR_SUCCESS) {
5252 return;
5253 }
5254
5255 QCBORItem Item;
5256 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5257 if(uError) {
5258 pMe->uLastError = (uint8_t)uError;
5259 return;
5260 }
5261
5262 const TagSpecification TagSpec =
5263 {
5264 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005265 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5266 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5267 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005268 };
5269
Laurence Lundblade93d89472020-10-03 22:30:50 -07005270 ProcessMantissaAndExponentBig(pMe,
5271 TagSpec,
5272 &Item,
5273 MantissaBuffer,
5274 pMantissa,
5275 pbMantissaIsNegative,
5276 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005277}
5278
5279
5280/*
5281 Public function, see header qcbor/qcbor_decode.h file
5282*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005283void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005284 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005285 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005286 UsefulBuf BufferForMantissa,
5287 UsefulBufC *pMantissa,
5288 bool *pbIsNegative,
5289 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005290{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005291 if(pMe->uLastError != QCBOR_SUCCESS) {
5292 return;
5293 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005294
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005295 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005296 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005297 if(pMe->uLastError != QCBOR_SUCCESS) {
5298 return;
5299 }
5300
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005301 const TagSpecification TagSpec =
5302 {
5303 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005304 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5305 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5306 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005307 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005308
Laurence Lundblade93d89472020-10-03 22:30:50 -07005309 ProcessMantissaAndExponentBig(pMe,
5310 TagSpec,
5311 &Item,
5312 BufferForMantissa,
5313 pMantissa,
5314 pbIsNegative,
5315 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005316}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005317
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005318
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005319/*
5320 Public function, see header qcbor/qcbor_decode.h file
5321*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005322void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005323 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005324 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005325 UsefulBuf BufferForMantissa,
5326 UsefulBufC *pMantissa,
5327 bool *pbIsNegative,
5328 int64_t *pnExponent)
5329{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005330 if(pMe->uLastError != QCBOR_SUCCESS) {
5331 return;
5332 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005333
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005334 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005335 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5336 if(pMe->uLastError != QCBOR_SUCCESS) {
5337 return;
5338 }
5339
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005340 const TagSpecification TagSpec =
5341 {
5342 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005343 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5344 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5345 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005346 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005347
5348 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5349}
5350
5351
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005352/*
5353 Public function, see header qcbor/qcbor_decode.h file
5354*/
5355void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5356 uint8_t uTagRequirement,
5357 int64_t *pnMantissa,
5358 int64_t *pnExponent)
5359{
5360 if(pMe->uLastError != QCBOR_SUCCESS) {
5361 return;
5362 }
5363
5364 QCBORItem Item;
5365 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5366 if(uError) {
5367 pMe->uLastError = (uint8_t)uError;
5368 return;
5369 }
5370 const TagSpecification TagSpec =
5371 {
5372 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005373 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5374 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5375 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005376 };
5377
5378 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5379}
5380
5381
5382/*
5383 Public function, see header qcbor/qcbor_decode.h file
5384*/
5385void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005386 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005387 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005388 int64_t *pnMantissa,
5389 int64_t *pnExponent)
5390{
5391 if(pMe->uLastError != QCBOR_SUCCESS) {
5392 return;
5393 }
5394
5395 QCBORItem Item;
5396 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5397 if(pMe->uLastError != QCBOR_SUCCESS) {
5398 return;
5399 }
5400
5401 const TagSpecification TagSpec =
5402 {
5403 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005404 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5405 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5406 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005407 };
5408
5409 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5410}
5411
5412
5413/*
5414 Public function, see header qcbor/qcbor_decode.h file
5415*/
5416void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005417 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005418 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005419 int64_t *pnMantissa,
5420 int64_t *pnExponent)
5421{
5422 if(pMe->uLastError != QCBOR_SUCCESS) {
5423 return;
5424 }
5425
5426 QCBORItem Item;
5427 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5428 if(pMe->uLastError != QCBOR_SUCCESS) {
5429 return;
5430 }
5431
5432 const TagSpecification TagSpec =
5433 {
5434 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005435 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5436 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5437 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005438 };
5439
5440 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5441}
5442
5443
5444/*
5445 Public function, see header qcbor/qcbor_decode.h file
5446*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005447void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5448 uint8_t uTagRequirement,
5449 UsefulBuf MantissaBuffer,
5450 UsefulBufC *pMantissa,
5451 bool *pbMantissaIsNegative,
5452 int64_t *pnExponent)
5453{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005454 if(pMe->uLastError != QCBOR_SUCCESS) {
5455 return;
5456 }
5457
5458 QCBORItem Item;
5459 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5460 if(uError) {
5461 pMe->uLastError = (uint8_t)uError;
5462 return;
5463 }
5464
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005465 const TagSpecification TagSpec =
5466 {
5467 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005468 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5469 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5470 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005471 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005472
5473 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005474}
5475
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005476
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005477/*
5478 Public function, see header qcbor/qcbor_decode.h file
5479*/
5480void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005481 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005482 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005483 UsefulBuf BufferForMantissa,
5484 UsefulBufC *pMantissa,
5485 bool *pbIsNegative,
5486 int64_t *pnExponent)
5487{
5488 if(pMe->uLastError != QCBOR_SUCCESS) {
5489 return;
5490 }
5491
5492 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005493 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5494 if(pMe->uLastError != QCBOR_SUCCESS) {
5495 return;
5496 }
5497
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005498 const TagSpecification TagSpec =
5499 {
5500 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005501 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5502 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5503 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005504 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005505
Laurence Lundblade93d89472020-10-03 22:30:50 -07005506 ProcessMantissaAndExponentBig(pMe,
5507 TagSpec,
5508 &Item,
5509 BufferForMantissa,
5510 pMantissa,
5511 pbIsNegative,
5512 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005513}
5514
5515
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005516/*
5517 Public function, see header qcbor/qcbor_decode.h file
5518*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005519void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005520 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005521 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005522 UsefulBuf BufferForMantissa,
5523 UsefulBufC *pMantissa,
5524 bool *pbIsNegative,
5525 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005526{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005527 if(pMe->uLastError != QCBOR_SUCCESS) {
5528 return;
5529 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005530
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005531 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005532 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5533 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005534 return;
5535 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005536
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005537 const TagSpecification TagSpec =
5538 {
5539 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005540 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5541 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5542 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005543 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005544
Laurence Lundblade93d89472020-10-03 22:30:50 -07005545 ProcessMantissaAndExponentBig(pMe,
5546 TagSpec,
5547 &Item,
5548 BufferForMantissa,
5549 pMantissa,
5550 pbIsNegative,
5551 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005552}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005553
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005554#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */