blob: 7ca2b812391ded66f6daf979f61f68502c5ca671 [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 Lundblade3f1318a2021-01-04 18:26:44 -08003 Copyright (c) 2018-2021, Laurence Lundblade.
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02004 Copyright (c) 2021, Arm Limited.
Laurence Lundbladed92a6162018-11-01 11:38:35 +07005 All rights reserved.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08006
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07007Redistribution and use in source and binary forms, with or without
8modification, are permitted provided that the following conditions are
9met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 copyright notice, this list of conditions and the following
14 disclaimer in the documentation and/or other materials provided
15 with the distribution.
16 * Neither the name of The Linux Foundation nor the names of its
17 contributors, nor the name "Laurence Lundblade" may be used to
18 endorse or promote products derived from this software without
19 specific prior written permission.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080020
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070021THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
22WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
24ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080032 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070033
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080034
Laurence Lundblade844bb5c2020-03-01 17:27:25 -080035#include "qcbor/qcbor_decode.h"
Laurence Lundblade67257dc2020-07-27 03:33:37 -070036#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080037#include "ieee754.h" /* Does not use math.h */
Laurence Lundbladec7114722020-08-13 05:11:40 -070038
39#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080040
41#include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
42 * pow(), exp2()
43 */
44#include <fenv.h> /* feclearexcept(), fetestexcept() */
45
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080046#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070047
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070048
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080049
Laurence Lundbladea9489f82020-09-12 13:50:56 -070050#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070051
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070052
Laurence Lundblade3f1318a2021-01-04 18:26:44 -080053
54
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070055static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070056QCBORItem_IsMapOrArray(const QCBORItem *pMe)
57{
58 const uint8_t uDataType = pMe->uDataType;
59 return uDataType == QCBOR_TYPE_MAP ||
60 uDataType == QCBOR_TYPE_ARRAY ||
61 uDataType == QCBOR_TYPE_MAP_AS_ARRAY;
62}
63
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070064static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070065QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem *pMe)
66{
67 if(!QCBORItem_IsMapOrArray(pMe)){
68 return false;
69 }
70
71 if(pMe->val.uCount != 0) {
72 return false;
73 }
74 return true;
75}
76
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -070077static inline bool
Laurence Lundblade02625d42020-06-25 14:41:41 -070078QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem *pMe)
79{
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080080#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade02625d42020-06-25 14:41:41 -070081 if(!QCBORItem_IsMapOrArray(pMe)){
82 return false;
83 }
84
85 if(pMe->val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
86 return false;
87 }
88 return true;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -080089#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
90 (void)pMe;
91 return false;
92#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade02625d42020-06-25 14:41:41 -070093}
94
95
Laurence Lundbladeee851742020-01-08 08:37:05 -080096/*===========================================================================
Laurence Lundbladea8edadb2020-06-27 22:35:37 -070097 DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
Laurence Lundbladeee851742020-01-08 08:37:05 -080098 ===========================================================================*/
99
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700100/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800101 * See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
102 * the data structure all these functions work on.
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700103 */
104
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700105
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700106static inline uint8_t
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700107DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700108{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700109 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800110 /* Limit in DecodeNesting_Descend against more than
111 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700112 */
Laurence Lundblade5e87da62020-06-07 03:24:28 -0700113 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700114}
115
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700116
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700117static inline uint8_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700118DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700119{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700120 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800121 /* Limit in DecodeNesting_Descend against more than
122 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
Laurence Lundblade02625d42020-06-25 14:41:41 -0700123 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700124 return (uint8_t)nLevel;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700125}
126
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700127
Laurence Lundblade5f4e8712020-07-25 11:44:43 -0700128static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700129DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700130{
131 return pNesting->pCurrentBounded->u.ma.uStartOffset;
132}
133
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700134
Laurence Lundblade085d7952020-07-24 10:26:30 -0700135static inline bool
136DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
137{
138 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
139 return true;
140 } else {
141 return false;
142 }
143}
144
145
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700146static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700147DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700148{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700149 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700150 return true;
151 } else {
152 return false;
153 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700154}
155
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700156
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700157static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700158DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700159{
160 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800161 /* Not a map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700162 return false;
163 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800164
165#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700166 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800167 /* Is indefinite */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700168 return false;
169 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800170
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800171#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
172
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800173 /* All checks passed; is a definte length map or array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700174 return true;
175}
176
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700177static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700178DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
Laurence Lundblade642282a2020-06-23 12:00:33 -0700179{
180 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800181 /* is a byte string */
Laurence Lundblade642282a2020-06-23 12:00:33 -0700182 return true;
183 }
184 return false;
185}
186
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700187
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700188static inline bool DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700189{
190 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
191 return true;
192 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700193 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700194 return true;
195 }
196 return false;
197}
198
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700199
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700200static inline void DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700201{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800202 /* Should be only called on maps and arrays */
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700203 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800204 * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
205 * larger than DecodeNesting_EnterBoundedMode which keeps it less than
206 * uin32_t so the cast is safe.
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700207 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700208 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700209
210 if(bIsEmpty) {
211 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
212 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700213}
214
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700215
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700216static inline void DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700217{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700218 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700219}
220
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700221
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700222static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700223DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700224{
225 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800226 /* No bounded map or array set up */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700227 return false;
228 }
229 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800230 /* Not a map or array; end of those is by byte count */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700231 return false;
232 }
Laurence Lundblade6ab01fb2020-10-01 13:04:49 -0700233 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800234 /* In a traveral at a level deeper than the bounded level */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700235 return false;
236 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800237 /* Works for both definite- and indefinitelength maps/arrays */
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800238 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
239 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800240 /* Count is not zero, still unconsumed item */
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700241 return false;
242 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800243 /* All checks passed, got to the end of an array or map*/
Laurence Lundblade2c1faf92020-06-26 22:43:56 -0700244 return true;
245}
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700246
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700247
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700248static inline bool
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700249DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700250{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800251 /* Must only be called on map / array */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700252 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
253 return true;
Laurence Lundblade9c905e82020-04-25 11:31:38 -0700254 } else {
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700255 return false;
256 }
Laurence Lundblade3f9ef042020-04-14 13:15:51 -0700257}
258
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700259
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700260static inline bool
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700261DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700262{
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700263 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
264 return true;
265 } else {
266 return false;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700267 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700268}
269
Laurence Lundblade410c7e02020-06-25 23:35:29 -0700270
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700271static inline bool
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700272DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700273{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700274 if(pNesting->pCurrentBounded == NULL) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700275 return false;
276 }
Laurence Lundblade02625d42020-06-25 14:41:41 -0700277
278 if(pNesting->pCurrentBounded->uLevelType != uType) {
279 return false;
280 }
281
282 return true;
Laurence Lundblade2b843b52020-06-16 20:51:03 -0700283}
284
Laurence Lundblade02625d42020-06-25 14:41:41 -0700285
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700286static inline void
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700287DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700288{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800289 /* Only call on a definite-length array / map */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700290 pNesting->pCurrent->u.ma.uCountCursor--;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -0700291}
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700292
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700293
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700294static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700295DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
296{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800297 /* Only call on a definite-length array / map */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700298 pNesting->pCurrent->u.ma.uCountCursor++;
299}
300
301
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700302static inline void
Laurence Lundblade0a042a92020-06-12 14:09:50 -0700303DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
304{
305 pNesting->pCurrent--;
306}
307
Laurence Lundblade02625d42020-06-25 14:41:41 -0700308
309static QCBORError
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700310DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700311{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800312 /* Error out if nesting is too deep */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700313 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700314 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
Laurence Lundblade02625d42020-06-25 14:41:41 -0700315 }
316
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800317 /* The actual descend */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700318 pNesting->pCurrent++;
319
320 pNesting->pCurrent->uLevelType = uType;
321
322 return QCBOR_SUCCESS;
323}
324
325
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700326static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800327DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
328 bool bIsEmpty,
329 size_t uOffset)
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700330{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700331 /*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800332 * Should only be called on map/array.
333 *
334 * Have descended into this before this is called. The job here is
335 * just to mark it in bounded mode.
336 *
337 * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
338 * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
339 *
340 * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700341 */
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -0800342 if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700343 return QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700344 }
345
Laurence Lundblade0750fc42020-06-20 21:02:34 -0700346 pNesting->pCurrentBounded = pNesting->pCurrent;
Laurence Lundblade085d7952020-07-24 10:26:30 -0700347
348 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -0700349
350 return QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -0700351}
352
Laurence Lundblade64b607e2020-05-13 13:05:57 -0700353
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700354static inline QCBORError
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700355DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
Laurence Lundblade02625d42020-06-25 14:41:41 -0700356 uint8_t uQCBORType,
357 uint64_t uCount)
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700358{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700359 QCBORError uError = QCBOR_SUCCESS;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700360
361 if(uCount == 0) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800362 /* Nothing to do for empty definite-length arrays. They are just are
363 * effectively the same as an item that is not a map or array.
364 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700365 goto Done;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800366 /* Empty indefinite-length maps and arrays are handled elsewhere */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700367 }
368
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800369 /* Error out if arrays is too long to handle */
Laurence Lundblade02625d42020-06-25 14:41:41 -0700370 if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
371 uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -0700372 uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700373 goto Done;
374 }
375
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700376 uError = DecodeNesting_Descend(pNesting, uQCBORType);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700377 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700378 goto Done;
379 }
380
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800381 /* Fill in the new map/array level. Check above makes casts OK. */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -0700382 pNesting->pCurrent->u.ma.uCountCursor = (uint16_t)uCount;
383 pNesting->pCurrent->u.ma.uCountTotal = (uint16_t)uCount;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700384
385 DecodeNesting_ClearBoundedMode(pNesting);
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700386
387Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700388 return uError;;
389}
390
391
392static inline void
393DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
394{
395 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
396}
397
398
399static inline void
400DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
401{
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700402 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
Laurence Lundblade02625d42020-06-25 14:41:41 -0700403 pNesting->pCurrentBounded--;
404 if(DecodeNesting_IsCurrentBounded(pNesting)) {
405 break;
406 }
407 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700408}
409
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800410
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700411static inline void
412DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
413{
414 pNesting->pCurrent = pNesting->pCurrentBounded;
415}
416
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700417
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700418static inline QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -0700419DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700420 uint32_t uEndOffset,
421 uint32_t uStartOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700422{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700423 QCBORError uError;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700424
Laurence Lundbladee6f15112020-07-23 18:44:16 -0700425 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
Laurence Lundblade02625d42020-06-25 14:41:41 -0700426 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700427 goto Done;
428 }
429
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800430 /* Fill in the new byte string level */
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700431 pNesting->pCurrent->u.bs.uSavedEndOffset = uEndOffset;
432 pNesting->pCurrent->u.bs.uBstrStartOffset = uStartOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700433
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800434 /* Bstr wrapped levels are always bounded */
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700435 pNesting->pCurrentBounded = pNesting->pCurrent;
436
437Done:
Laurence Lundblade02625d42020-06-25 14:41:41 -0700438 return uError;;
439}
440
Laurence Lundbladed0304932020-06-27 10:59:38 -0700441
442static inline void
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700443DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
Laurence Lundblade02625d42020-06-25 14:41:41 -0700444{
445 pNesting->pCurrent->u.ma.uCountCursor = 0;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700446}
447
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700448
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700449static inline void
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800450DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
451{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700452 if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
453 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
454 }
Laurence Lundbladeddebabe2020-11-22 11:32:17 -0800455}
456
457
458static inline void
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700459DecodeNesting_Init(QCBORDecodeNesting *pNesting)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700460{
Laurence Lundblade02625d42020-06-25 14:41:41 -0700461 /* Assumes that *pNesting has been zero'd before this call. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700462 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
463 pNesting->pCurrent = &(pNesting->pLevels[0]);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700464}
465
466
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700467static inline void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800468DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
469 QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700470{
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -0700471 *pSave = *pNesting;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700472}
473
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700474
Laurence Lundblade02625d42020-06-25 14:41:41 -0700475static inline void
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800476DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
477 const QCBORDecodeNesting *pSave)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -0700478{
479 *pNesting = *pSave;
480}
481
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700482
Laurence Lundblade02625d42020-06-25 14:41:41 -0700483static inline uint32_t
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700484DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700485{
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700486 return pMe->pCurrentBounded->u.bs.uSavedEndOffset;
Laurence Lundblade1d85d522020-06-22 13:24:59 -0700487}
488
489
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800490
491
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800492#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladeee851742020-01-08 08:37:05 -0800493/*===========================================================================
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800494 QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
495
496 The following four functions are pretty wrappers for invocation of
497 the string allocator supplied by the caller.
498
Laurence Lundbladeee851742020-01-08 08:37:05 -0800499 ===========================================================================*/
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800500
Laurence Lundbladeee851742020-01-08 08:37:05 -0800501static inline void
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800502StringAllocator_Free(const QCBORInternalAllocator *pMe, const void *pMem)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800503{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800504 /* These pragmas allow the "-Wcast-qual" warnings flag to be set for
505 * gcc and clang. This is the one place where the const needs to be
506 * cast away so const can be use in the rest of the code.
507 */
508#pragma GCC diagnostic push
509#pragma GCC diagnostic ignored "-Wcast-qual"
510 (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)pMem, 0);
511#pragma GCC diagnostic pop
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800512}
513
Laurence Lundbladeee851742020-01-08 08:37:05 -0800514// StringAllocator_Reallocate called with pMem NULL is
515// equal to StringAllocator_Allocate()
516static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800517StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800518 const void *pMem,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800519 size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800520{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800521 /* See comment in StringAllocator_Free() */
522#pragma GCC diagnostic push
523#pragma GCC diagnostic ignored "-Wcast-qual"
524 return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)pMem, uSize);
525#pragma GCC diagnostic pop
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800526}
527
Laurence Lundbladeee851742020-01-08 08:37:05 -0800528static inline UsefulBuf
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800529StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800530{
531 return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
532}
533
Laurence Lundbladeee851742020-01-08 08:37:05 -0800534static inline void
Laurence Lundblade3a691a02020-12-28 04:15:16 -0800535StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800536{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800537 /* See comment in StringAllocator_Free() */
538#pragma GCC diagnostic push
539#pragma GCC diagnostic ignored "-Wcast-qual"
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800540 if(pMe->pfAllocator) {
541 (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
542 }
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800543#pragma GCC diagnostic pop
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800544}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800545#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800546
547
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800548
549
Laurence Lundbladeee851742020-01-08 08:37:05 -0800550/*===========================================================================
551 QCBORDecode -- The main implementation of CBOR decoding
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700552
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800553 See qcbor/qcbor_decode.h for definition of the object
554 used here: QCBORDecodeContext
Laurence Lundbladeee851742020-01-08 08:37:05 -0800555 ===========================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700556/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800557 * Public function, see header file
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700558 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800559void QCBORDecode_Init(QCBORDecodeContext *pMe,
560 UsefulBufC EncodedCBOR,
561 QCBORDecodeMode nDecodeMode)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700562{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800563 memset(pMe, 0, sizeof(QCBORDecodeContext));
564 UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
565 /* Don't bother with error check on decode mode. If a bad value is
566 * passed it will just act as if the default normal mode of 0 was set.
567 */
568 pMe->uDecodeMode = (uint8_t)nDecodeMode;
569 DecodeNesting_Init(&(pMe->nesting));
570
571 /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
572 * GetNext_TaggedItem() and MapTagNumber(). */
573 memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700574}
575
576
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800577#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
578
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700579/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800580 * Public function, see header file
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700581 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800582void QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
583 QCBORStringAllocate pfAllocateFunction,
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800584 void *pAllocateContext,
585 bool bAllStrings)
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700586{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800587 pMe->StringAllocator.pfAllocator = pfAllocateFunction;
588 pMe->StringAllocator.pAllocateCxt = pAllocateContext;
589 pMe->bStringAllocateAll = bAllStrings;
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700590}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800591#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700592
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800593
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800594
595
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800596/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800597 * Deprecated public function, see header file
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800598 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800599void QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext *pMe,
Laurence Lundbladeee851742020-01-08 08:37:05 -0800600 const QCBORTagListIn *pTagList)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700601{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800602 /* This does nothing now. It is retained for backwards compatibility */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -0700603 (void)pMe;
604 (void)pTagList;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +0700605}
606
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700607
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800608
609
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700610/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800611 * Decoding items is done in six layers, one calling the next one
612 * down. If a layer has no work to do for a particular item, it
613 * returns quickly.
614 *
615 * 1. QCBORDecode_GetNextTagContent - The top layer processes tagged
616 * data items, turning them into the local C representation. For the
617 * most simple it is just associating a QCBOR_TYPE with the data. For
618 * the complex ones that an aggregate of data items, there is some
619 * further decoding and some limited recursion.
620 *
621 * 2. QCBORDecode_GetNextMapOrArray - This manages the beginnings and
622 * ends of maps and arrays. It tracks descending into and ascending
623 * out of maps/arrays. It processes breaks that terminate
624 * indefinite-length maps and arrays.
625 *
626 * 3. QCBORDecode_GetNextMapEntry - This handles the combining of two
627 * items, the label and the data, that make up a map entry. It only
628 * does work on maps. It combines the label and data items into one
629 * labeled item.
630 *
631 * 4. QCBORDecode_GetNextTagNumber - This decodes type 6 tag
632 * numbers. It turns the tag numbers into bit flags associated with
633 * the data item. No actual decoding of the contents of the tag is
634 * performed here.
635 *
636 * 5. QCBORDecode_GetNextFullString - This assembles the sub-items
637 * that make up an indefinite-length string into one string item. It
638 * uses the string allocator to create contiguous space for the
639 * item. It processes all breaks that are part of indefinite-length
640 * strings.
641 *
642 * 6. DecodeAtomicDataItem - This decodes the atomic data items in
643 * CBOR. Each atomic data item has a "major type", an integer
644 * "argument" and optionally some content. For text and byte strings,
645 * the content is the bytes that make up the string. These are the
646 * smallest data items that are considered to be well-formed. The
647 * content may also be other data items in the case of aggregate
648 * types. They are not handled in this layer.
649 *
650 * Roughly this takes 300 bytes of stack for vars. TODO: evaluate this
651 * more carefully and correctly.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700652 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800653
654
655/*
656 * Note about use of int and unsigned variables.
657 *
658 * See http://www.unix.org/whitepapers/64bit.html for reasons int is
659 * used carefully here, and in particular why it isn't used in the
660 * public interface. Also see
661 * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
662 *
663 * Int is used for values that need less than 16-bits and would be
664 * subject to integer promotion and result in complaining from static
665 * analyzers.
666 */
667
668
669/**
670 * @brief Decode the CBOR head, the type and argument.
671 *
672 * @param[in] pUInBuf The input buffer to read from.
673 * @param[out] pnMajorType The decoded major type.
674 * @param[out] puArgument The decoded argument.
675 * @param[out] pnAdditionalInfo The decoded Lower 5 bits of initial byte.
676 *
677 * @retval QCBOR_ERR_UNSUPPORTED
678 * @retval QCBOR_ERR_HIT_END
679 *
680 * This decodes the CBOR "head" that every CBOR data item has. See
681 * longer explaination of the head in documentation for
682 * QCBOREncode_EncodeHead().
683 *
684 * This does the network->host byte order conversion. The conversion
685 * here also results in the conversion for floats in addition to that
686 * for lengths, tags and integer values.
687 *
688 * The int type is preferred to uint8_t for some variables as this
689 * avoids integer promotions, can reduce code size and makes static
690 * analyzers happier.
691 */
692static inline QCBORError
693DecodeHead(UsefulInputBuf *pUInBuf,
694 int *pnMajorType,
695 uint64_t *puArgument,
696 int *pnAdditionalInfo)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700697{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800698 QCBORError uReturn;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800699
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800700 /* Get the initial byte that every CBOR data item has and break it
701 * down. */
702 const int nInitialByte = (int)UsefulInputBuf_GetByte(pUInBuf);
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800703 const int nTmpMajorType = nInitialByte >> 5;
704 const int nAdditionalInfo = nInitialByte & 0x1f;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800705
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800706 /* Where the argument accumulates */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800707 uint64_t uArgument;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800708
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800709 if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800710 /* Need to get 1,2,4 or 8 additional argument bytes. Map
711 * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
712 */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800713 static const uint8_t aIterate[] = {1,2,4,8};
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800714
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800715 /* Loop getting all the bytes in the argument */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800716 uArgument = 0;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800717 for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800718 /* This shift and add gives the endian conversion. */
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800719 uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
720 }
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800721 } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800722 /* The reserved and thus-far unused additional info values */
723 uReturn = QCBOR_ERR_UNSUPPORTED;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800724 goto Done;
725 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800726 /* Less than 24, additional info is argument or 31, an
727 * indefinite-length. No more bytes to get.
728 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800729 uArgument = (uint64_t)nAdditionalInfo;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700730 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800731
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700732 if(UsefulInputBuf_GetError(pUInBuf)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800733 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700734 goto Done;
735 }
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800736
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800737 /* All successful if arrived here. */
738 uReturn = QCBOR_SUCCESS;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800739 *pnMajorType = nTmpMajorType;
Laurence Lundblade4c0cf842019-01-12 03:25:44 -0800740 *puArgument = uArgument;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800741 *pnAdditionalInfo = nAdditionalInfo;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800742
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700743Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800744 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700745}
746
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800747
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800748/**
749 * @brief Decode integer types, major types 0 and 1.
750 *
751 * @param[in] nMajorType The CBOR major type (0 or 1).
752 * @param[in] uArgument The argument from the head.
753 * @param[out] pDecodedItem The filled in decoded item.
754 *
755 * @retval QCBOR_ERR_INT_OVERFLOW
756 *
757 * Must only be called when major type is 0 or 1.
758 *
759 * CBOR doesn't explicitly specify two's compliment for integers but
760 * all CPUs use it these days and the test vectors in the RFC are
761 * so. All integers in the CBOR structure are positive and the major
762 * type indicates positive or negative. CBOR can express positive
763 * integers up to 2^x - 1 where x is the number of bits and negative
764 * integers down to 2^x. Note that negative numbers can be one more
765 * away from zero than positive. Stdint, as far as I can tell, uses
766 * two's compliment to represent negative integers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700767 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -0700768static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800769DecodeInteger(int nMajorType, uint64_t uArgument, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700770{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800771 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800772
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700773 if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800774 if (uArgument <= INT64_MAX) {
775 pDecodedItem->val.int64 = (int64_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700776 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800777
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700778 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800779 pDecodedItem->val.uint64 = uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700780 pDecodedItem->uDataType = QCBOR_TYPE_UINT64;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700781 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800782
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700783 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800784 if(uArgument <= INT64_MAX) {
785 /* CBOR's representation of negative numbers lines up with
786 * the two-compliment representation. A negative integer has
787 * one more in range than a positive integer. INT64_MIN is
788 * equal to (-INT64_MAX) - 1.
789 */
790 pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700791 pDecodedItem->uDataType = QCBOR_TYPE_INT64;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800792
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700793 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800794 /* C can't represent a negative integer in this range so it
795 * is an error.
796 */
797 uReturn = QCBOR_ERR_INT_OVERFLOW;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700798 }
799 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800800
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800801 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700802}
803
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800804
805/* Make sure #define value line up as DecodeSimple counts on this. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700806#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
807#error QCBOR_TYPE_FALSE macro value wrong
808#endif
809
810#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
811#error QCBOR_TYPE_TRUE macro value wrong
812#endif
813
814#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
815#error QCBOR_TYPE_NULL macro value wrong
816#endif
817
818#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
819#error QCBOR_TYPE_UNDEF macro value wrong
820#endif
821
Laurence Lundblade0f99d692018-09-26 14:39:28 -0700822#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
823#error QCBOR_TYPE_BREAK macro value wrong
824#endif
825
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700826#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
827#error QCBOR_TYPE_DOUBLE macro value wrong
828#endif
829
830#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
831#error QCBOR_TYPE_FLOAT macro value wrong
832#endif
833
Laurence Lundblade9b334962020-08-27 10:55:53 -0700834
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800835/**
836 * @brief Decode major type 7 -- true, false, floating-point, break...
837 *
838 * @param[in] nAdditionalInfo The lower five bits from the initial byte.
839 * @param[in] uArgument The argument from the head.
840 * @param[out] pDecodedItem The filled in decoded item.
841 *
842 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200843 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800844 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700845 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800846
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800847static inline QCBORError
848DecodeType7(int nAdditionalInfo, uint64_t uArgument, QCBORItem *pDecodedItem)
849{
850 QCBORError uReturn = QCBOR_SUCCESS;
851
852 /* uAdditionalInfo is 5 bits from the initial byte. Compile time
853 * checks above make sure uAdditionalInfo values line up with
854 * uDataType values. DecodeHead() never returns an AdditionalInfo
855 * > 0x1f so cast is safe.
856 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800857 pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800858
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800859 switch(nAdditionalInfo) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800860 /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
861 * are caught before this is called.
862 */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800863
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800864 case HALF_PREC_FLOAT: /* 25 */
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700865#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800866 /* Half-precision is returned as a double. The cast to
867 * uint16_t is safe because the encoded value was 16 bits. It
868 * was widened to 64 bits to be passed in here.
869 */
870 pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700871 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800872#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200873 uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700874 break;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800875 case SINGLE_PREC_FLOAT: /* 26 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200876#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800877 /* Single precision is normally returned as a double since
878 * double is widely supported, there is no loss of precision,
879 * it makes it easy for the caller in most cases and it can
880 * be converted back to single with no loss of precision
881 *
882 * The cast to uint32_t is safe because the encoded value was
883 * 32 bits. It was widened to 64 bits to be passed in here.
884 */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700885 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800886 const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700887#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800888 /* In the normal case, use HW to convert float to
889 * double. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700890 pDecodedItem->val.dfnum = (double)f;
891 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800892#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800893 /* Use of float HW is disabled, return as a float. */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700894 pDecodedItem->val.fnum = f;
895 pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
896
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800897 /* IEEE754_FloatToDouble() could be used here to return as
898 * a double, but it adds object code and most likely
899 * anyone disabling FLOAT HW use doesn't care about floats
900 * and wants to save object code.
901 */
Laurence Lundbladee2c893c2020-12-26 17:41:53 -0800902#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700903 }
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200904#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
905 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700906 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -0700907
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800908 case DOUBLE_PREC_FLOAT: /* 27 */
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200909#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800910 pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
Laurence Lundblade67bd5512018-11-02 21:44:06 +0700911 pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200912#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
913 uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
Laurence Lundblade12d32c52018-09-19 11:25:27 -0700914 break;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800915
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800916 case CBOR_SIMPLEV_FALSE: /* 20 */
917 case CBOR_SIMPLEV_TRUE: /* 21 */
918 case CBOR_SIMPLEV_NULL: /* 22 */
919 case CBOR_SIMPLEV_UNDEF: /* 23 */
920 case CBOR_SIMPLE_BREAK: /* 31 */
921 break; /* nothing to do */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800922
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800923 case CBOR_SIMPLEV_ONEBYTE: /* 24 */
924 if(uArgument <= CBOR_SIMPLE_BREAK) {
925 /* This takes out f8 00 ... f8 1f which should be encoded
926 * as e0 … f7
927 */
928 uReturn = QCBOR_ERR_BAD_TYPE_7;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700929 goto Done;
930 }
Laurence Lundblade5e390822019-01-06 12:35:01 -0800931 /* FALLTHROUGH */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800932
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800933 default: /* 0-19 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700934 pDecodedItem->uDataType = QCBOR_TYPE_UKNOWN_SIMPLE;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800935 /* DecodeHead() will make uArgument equal to
936 * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
937 * safe because the 2, 4 and 8 byte lengths of uNumber are in
938 * the double/float cases above
Laurence Lundbladeee851742020-01-08 08:37:05 -0800939 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800940 pDecodedItem->val.uSimple = (uint8_t)uArgument;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700941 break;
942 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800943
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700944Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800945 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700946}
947
948
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800949/**
950 * @brief Decode text and byte strings
951 *
952 * @param[in] pAllocator The string allocator or NULL.
953 * @param[in] uStrLen The length of the string.
954 * @param[in] pUInBuf The surce from which to read the string's bytes.
955 * @param[out] pDecodedItem The filled in decoded item.
956 *
957 * @retval QCBOR_ERR_HIT_END
958 * @retval QCBOR_ERR_STRING_ALLOCATE
959 * @retval QCBOR_ERR_STRING_TOO_LONG
960 *
961 * The reads @c uStrlen bytes from @c pUInBuf and fills in @c
962 * pDecodedItem. If @c pAllocator is not NULL then memory for the
963 * string is allocated.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700964 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800965static inline QCBORError
966DecodeBytes(const QCBORInternalAllocator *pAllocator,
967 uint64_t uStrLen,
968 UsefulInputBuf *pUInBuf,
969 QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700970{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800971 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800972
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800973 /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
974 * CPUs. This check makes the casts to size_t below safe.
975 *
976 * The max is 4 bytes less than the largest sizeof() so this can be
977 * tested by putting a SIZE_MAX length in the CBOR test input (no
978 * one will care the limit on strings is 4 bytes shorter).
979 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800980 if(uStrLen > SIZE_MAX-4) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800981 uReturn = QCBOR_ERR_STRING_TOO_LONG;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800982 goto Done;
983 }
984
985 const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(pUInBuf, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530986 if(UsefulBuf_IsNULLC(Bytes)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800987 /* Failed to get the bytes for this string item */
988 uReturn = QCBOR_ERR_HIT_END;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530989 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700990 }
Laurence Lundblade471a3fd2018-10-18 21:27:45 +0530991
Laurence Lundbladef6da33c2020-11-26 18:15:05 -0800992#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800993 /* Note that this is not where allocation to coalesce
994 * indefinite-length strings is done. This is for when the caller
995 * has requested all strings be allocated. Disabling indefinite
996 * length strings also disables this allocate-all option.
997 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800998 if(pAllocator) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -0800999 /* request to use the string allocator to make a copy */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001000 UsefulBuf NewMem = StringAllocator_Allocate(pAllocator, (size_t)uStrLen);
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301001 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001002 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301003 goto Done;
1004 }
1005 pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001006 pDecodedItem->uDataAlloc = 1;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001007 goto Done;
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301008 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001009#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1010 (void)pAllocator;
1011#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1012
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001013 /* Normal case with no string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001014 pDecodedItem->val.string = Bytes;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001015
Laurence Lundblade471a3fd2018-10-18 21:27:45 +05301016Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001017 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001018}
1019
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001020
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001021/**
1022 * @brief Map the CBOR major types for strings to the QCBOR types.
1023 *
1024 * @param[in] nCBORMajorType The CBOR major type to convert.
1025 * @retturns QCBOR type number.
1026 *
1027 * This only works for the two string types.
1028 */
1029static inline uint8_t ConvertStringMajorTypes(int nCBORMajorType)
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001030{
1031 #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
1032 #error QCBOR_TYPE_BYTE_STRING no lined up with major type
1033 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001034
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001035 #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
1036 #error QCBOR_TYPE_TEXT_STRING no lined up with major type
1037 #endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001038
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001039 return (uint8_t)(nCBORMajorType + 4);
1040}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001041
1042
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001043/**
1044 * @brief Map the CBOR major types for arrays/maps to the QCBOR types.
1045 *
1046 * @param[in] nCBORMajorType The CBOR major type to convert.
1047 * @retturns QCBOR type number.
1048 *
1049 * This only works for the two aggregate types.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001050 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001051static inline uint8_t ConvertArrayOrMapType(int nCBORMajorType)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001052{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001053 #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
1054 #error QCBOR_TYPE_ARRAY value not lined up with major type
1055 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001056
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001057 #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
1058 #error QCBOR_TYPE_MAP value not lined up with major type
1059 #endif
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001060
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001061 return (uint8_t)(nCBORMajorType);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001062}
1063
1064
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001065/**
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001066 * @brief Decode a single primitive data item (decode layer 6).
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001067 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001068 * @param[in] pUInBuf Input buffer to read data item from.
1069 * @param[out] pDecodedItem The filled-in decoded item.
1070 * @param[in] pAllocator The allocator to use for strings or NULL.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001071 *
1072 * @retval QCBOR_ERR_UNSUPPORTED
1073 * @retval QCBOR_ERR_HIT_END
1074 * @retval QCBOR_ERR_INT_OVERFLOW
1075 * @retval QCBOR_ERR_STRING_ALLOCATE
1076 * @retval QCBOR_ERR_STRING_TOO_LONG
1077 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001078 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001079 * @retval QCBOR_ERR_BAD_TYPE_7
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001080 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1081 *
1082 * This decodes the most primitive / atomic data item. It does
1083 * no combing of data items.
1084 */
1085static QCBORError
1086DecodeAtomicDataItem(UsefulInputBuf *pUInBuf,
1087 QCBORItem *pDecodedItem,
1088 const QCBORInternalAllocator *pAllocator)
1089{
1090 QCBORError uReturn;
1091
1092 /* Get the major type and the argument. The argument could be
1093 * length of more bytes or the value depending on the major
1094 * type. nAdditionalInfo is an encoding of the length of the
1095 * uNumber and is needed to decode floats and doubles.
1096 */
1097 int nMajorType = 0;
1098 uint64_t uArgument = 0;
1099 int nAdditionalInfo = 0;
1100
1101 memset(pDecodedItem, 0, sizeof(QCBORItem));
1102
1103 uReturn = DecodeHead(pUInBuf, &nMajorType, &uArgument, &nAdditionalInfo);
1104 if(uReturn) {
1105 goto Done;
1106 }
1107
1108 /* At this point the major type and the argument are valid. We've
1109 * got the type and the argument that starts every CBOR data item.
1110 */
1111 switch (nMajorType) {
1112 case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
1113 case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
1114 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1115 uReturn = QCBOR_ERR_BAD_INT;
1116 } else {
1117 uReturn = DecodeInteger(nMajorType, uArgument, pDecodedItem);
1118 }
1119 break;
1120
1121 case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
1122 case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
1123 pDecodedItem->uDataType = ConvertStringMajorTypes(nMajorType);
1124 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1125 pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
1126 } else {
1127 uReturn = DecodeBytes(pAllocator, uArgument, pUInBuf, pDecodedItem);
1128 }
1129 break;
1130
1131 case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
1132 case CBOR_MAJOR_TYPE_MAP: /* Major type 5 */
1133 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1134 /* Indefinite-length string. */
1135#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
1136 pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
1137#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1138 uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
1139 break;
1140#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1141 } else {
1142 /* Definite-length string. */
1143 if(uArgument > QCBOR_MAX_ITEMS_IN_ARRAY) {
1144 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
1145 goto Done;
1146 }
1147 /* cast OK because of check above */
1148 pDecodedItem->val.uCount = (uint16_t)uArgument;
1149 }
1150 pDecodedItem->uDataType = ConvertArrayOrMapType(nMajorType);
1151 break;
1152
1153 case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
1154 if(nAdditionalInfo == LEN_IS_INDEFINITE) {
1155 uReturn = QCBOR_ERR_BAD_INT;
1156 } else {
1157 pDecodedItem->val.uTagV = uArgument;
1158 pDecodedItem->uDataType = QCBOR_TYPE_TAG;
1159 }
1160 break;
1161
1162 case CBOR_MAJOR_TYPE_SIMPLE:
1163 /* Major type 7: float, double, true, false, null... */
1164 uReturn = DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
1165 break;
1166
1167 default:
1168 /* Never happens because DecodeHead() should never return > 7 */
1169 uReturn = QCBOR_ERR_UNSUPPORTED;
1170 break;
1171 }
1172
1173Done:
1174 return uReturn;
1175}
1176
1177
1178/**
1179 * @brief Process indefinite-length strings (decode layer 5).
1180 *
1181 * @param[in] pMe Decoder context
1182 * @param[out] pDecodedItem The decoded item that work is done on.
1183 *
1184 * @retval QCBOR_ERR_UNSUPPORTED
1185 * @retval QCBOR_ERR_HIT_END
1186 * @retval QCBOR_ERR_INT_OVERFLOW
1187 * @retval QCBOR_ERR_STRING_ALLOCATE
1188 * @retval QCBOR_ERR_STRING_TOO_LONG
1189 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001190 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001191 * @retval QCBOR_ERR_BAD_TYPE_7
1192 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001193 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1194 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001195 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001196 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001197 * If @c pDecodedItem is not an indefinite-length string, this does nothing.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001198 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001199 * If it is, this loops getting the subsequent chunk data items that
1200 * make up the string. The string allocator is used to make a
1201 * contiguous buffer for the chunks. When this completes @c
1202 * pDecodedItem contains the put-together string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001203 *
1204 * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001205 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001206static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001207QCBORDecode_GetNextFullString(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001208{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001209 /* Aproximate stack usage
1210 * 64-bit 32-bit
1211 * local vars 32 16
1212 * 2 UsefulBufs 32 16
1213 * QCBORItem 56 52
1214 * TOTAL 120 74
1215 */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001216
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001217 /* The string allocator is used here for two purposes: 1)
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001218 * coalescing the chunks of an indefinite-length string, 2)
1219 * allocating storage for every string returned when requested.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001220 *
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001221 * The first use is below in this function. Indefinite-length
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001222 * strings cannot be processed at all without a string allocator.
1223 *
1224 * The second used is in DecodeBytes() which is called by
1225 * GetNext_Item() below. This second use unneccessary for most use
1226 * and only happens when requested in the call to
1227 * QCBORDecode_SetMemPool(). If the second use not requested then
1228 * NULL is passed for the string allocator to GetNext_Item().
1229 *
1230 * QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS disables the string
1231 * allocator altogether and thus both of these uses. It reduced the
1232 * decoder object code by about 400 bytes.
1233 */
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001234 const QCBORInternalAllocator *pAllocatorForGetNext = NULL;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001235
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001236#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3a691a02020-12-28 04:15:16 -08001237 const QCBORInternalAllocator *pAllocator = NULL;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001238
1239 if(pMe->StringAllocator.pfAllocator) {
1240 pAllocator = &(pMe->StringAllocator);
1241 if(pMe->bStringAllocateAll) {
1242 pAllocatorForGetNext = pAllocator;
1243 }
1244 }
1245#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1246
1247 QCBORError uReturn;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001248 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), pDecodedItem, pAllocatorForGetNext);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001249 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001250 goto Done;
1251 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001252
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001253 /* Only do indefinite-length processing on strings */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001254 const uint8_t uStringType = pDecodedItem->uDataType;
1255 if(uStringType!= QCBOR_TYPE_BYTE_STRING && uStringType != QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001256 goto Done;
1257 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001258
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001259 /* Is this a string with an indefinite length? */
1260 if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
1261 goto Done;
1262 }
1263
1264#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001265 /* Can't decode indefinite-length strings without a string allocator */
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001266 if(pAllocator == NULL) {
1267 uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
1268 goto Done;
1269 }
1270
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001271 /* Loop getting chunks of the indefinite-length string */
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001272 UsefulBufC FullString = NULLUsefulBufC;
1273
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001274 for(;;) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001275 /* Get QCBORItem for next chunk */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001276 QCBORItem StringChunkItem;
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001277 /* Pass a NULL string allocator to GetNext_Item() because the
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001278 * individual string chunks in an indefinite-length should not
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001279 * be allocated. They are always copied in the the contiguous
1280 * buffer allocated here.
1281 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001282 uReturn = DecodeAtomicDataItem(&(pMe->InBuf), &StringChunkItem, NULL);
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001283 if(uReturn) {
1284 break;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001285 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001286
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001287 /* Is item is the marker for end of the indefinite-length string? */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001288 if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001289 /* String is complete */
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001290 pDecodedItem->val.string = FullString;
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301291 pDecodedItem->uDataAlloc = 1;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001292 break;
1293 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001294
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001295 /* All chunks must be of the same type, the type of the item
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001296 * that introduces the indefinite-length string. This also
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001297 * catches errors where the chunk is not a string at all and an
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001298 * indefinite-length string inside an indefinite-length string.
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001299 */
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001300 if(StringChunkItem.uDataType != uStringType ||
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001301 StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
1302 uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001303 break;
1304 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001305
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001306 /* The first time throurgh FullString.ptr is NULL and this is
1307 * equivalent to StringAllocator_Allocate(). Subsequently it is
1308 * not NULL and a reallocation happens.
1309 */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001310 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001311 FullString.ptr,
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001312 FullString.len + StringChunkItem.val.string.len);
1313
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001314 if(UsefulBuf_IsNULL(NewMem)) {
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001315 uReturn = QCBOR_ERR_STRING_ALLOCATE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001316 break;
1317 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001318
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001319 /* Copy new string chunk to the end of accumulated string */
Laurence Lundblade2a6850e2018-10-28 20:13:44 +07001320 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001321 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001322
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001323 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1324 /* Getting the item failed, clean up the allocated memory */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001325 StringAllocator_Free(pAllocator, FullString.ptr);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001326 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001327#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1328 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1329#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001330
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001331Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001332 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001333}
1334
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001335
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001336/**
1337 * @brief This converts a tag number to a shorter mapped value for storage.
1338 *
1339 * @param[in] pMe The decode context.
1340 * @param[in] uUnMappedTag The tag number to map
1341 * @param[out] puMappedTagNumer The stored tag number.
1342 *
1343 * @return error code.
1344 *
1345 * The main point of mapping tag numbers is make QCBORItem
1346 * smaller. With this mapping storage of 4 tags takes up 8
1347 * bytes. Without, it would take up 32 bytes.
1348 *
1349 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1350 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1351 *
1352 * See also UnMapTagNumber() and @ref QCBORItem.
1353 */
1354static inline QCBORError
1355MapTagNumber(QCBORDecodeContext *pMe, uint64_t uUnMappedTag, uint16_t *puMappedTagNumer)
1356{
1357 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1358 unsigned uTagMapIndex;
1359 /* Is there room in the tag map, or is it in it already? */
1360 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1361 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1362 break;
1363 }
1364 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1365 break;
1366 }
1367 }
1368 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1369 return QCBOR_ERR_TOO_MANY_TAGS;
1370 }
1371
1372 /* Covers the cases where tag is new and were it is already in the map */
1373 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1374 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1375
1376 } else {
1377 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1378 }
1379
1380 return QCBOR_SUCCESS;
1381}
1382
1383
1384/**
1385 * @brief This converts a mapped tag number to the actual tag number.
1386 *
1387 * @param[in] pMe The decode context.
1388 * @param[in] uMappedTagNumber The stored tag number.
1389 *
1390 * @return The actual tag number is returned or
1391 * @ref CBOR_TAG_INVALID64 on error.
1392 *
1393 * This is the reverse of MapTagNumber()
1394 */
1395static uint64_t
1396UnMapTagNumber(const QCBORDecodeContext *pMe, uint16_t uMappedTagNumber)
1397{
1398 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1399 return uMappedTagNumber;
1400 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001401 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001402 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001403 /* This won't be negative because of code below in
1404 * MapTagNumber()
1405 */
1406 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1407 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001408 }
1409}
1410
Laurence Lundblade9b334962020-08-27 10:55:53 -07001411
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001412/**
1413 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1414 *
1415 * @param[in] pMe Decoder context
1416 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001417
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001418 * @retval QCBOR_ERR_UNSUPPORTED
1419 * @retval QCBOR_ERR_HIT_END
1420 * @retval QCBOR_ERR_INT_OVERFLOW
1421 * @retval QCBOR_ERR_STRING_ALLOCATE
1422 * @retval QCBOR_ERR_STRING_TOO_LONG
1423 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001424 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001425 * @retval QCBOR_ERR_BAD_TYPE_7
1426 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1427 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1428 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1429 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1430 * @retval QCBOR_ERR_TOO_MANY_TAGS
1431 *
1432 * This loops getting atomic data items until one is not a tag
1433 * number. Usually this is largely pass-through because most
1434 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001435 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001436static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001437QCBORDecode_GetNextTagNumber(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001438{
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001439 /* Accummulate the tags from multiple items here and then copy them
1440 * into the last item, the non-tag item.
1441 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001442 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1443
1444 /* Initialize to CBOR_TAG_INVALID16 */
1445 #if CBOR_TAG_INVALID16 != 0xffff
1446 /* Be sure the memset does the right thing. */
1447 #err CBOR_TAG_INVALID16 tag not defined as expected
1448 #endif
1449 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001450
Laurence Lundblade9b334962020-08-27 10:55:53 -07001451 QCBORError uReturn = QCBOR_SUCCESS;
1452
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001453 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001454 for(;;) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001455 QCBORError uErr = QCBORDecode_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001456 if(uErr != QCBOR_SUCCESS) {
1457 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001458 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001459 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001460
Laurence Lundblade9b334962020-08-27 10:55:53 -07001461 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001462 /* Successful exit from loop; maybe got some tags, maybe not */
1463 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001464 break;
1465 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001466
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001467 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1468 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001469 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001470 /* Continue on to get all tags wrapping this item even though
1471 * it is erroring out in the end. This allows decoding to
1472 * continue. This is a resource limit error, not a problem
1473 * with being well-formed CBOR.
1474 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001475 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001476 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001477 /* Slide tags over one in the array to make room at index 0.
1478 * Must use memmove because the move source and destination
1479 * overlap.
1480 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001481 memmove(&auItemsTags[1],
1482 auItemsTags,
1483 sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001484
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001485 /* Map the tag */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001486 uint16_t uMappedTagNumber = 0;
1487 uReturn = MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumber);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001488 /* Continue even on error so as to consume all tags wrapping
1489 * this data item so decoding can go on. If MapTagNumber()
1490 * errors once it will continue to error.
1491 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001492 auItemsTags[0] = uMappedTagNumber;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001493 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001494
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001495Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001496 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001497}
1498
1499
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001500/**
1501 * @brief Combine a map entry label and value into one item (decode layer 3).
1502 *
1503 * @param[in] pMe Decoder context
1504 * @param[out] pDecodedItem The decoded item that work is done on.
1505 *
1506 * @retval QCBOR_ERR_UNSUPPORTED
1507 * @retval QCBOR_ERR_HIT_END
1508 * @retval QCBOR_ERR_INT_OVERFLOW
1509 * @retval QCBOR_ERR_STRING_ALLOCATE
1510 * @retval QCBOR_ERR_STRING_TOO_LONG
1511 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001512 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001513 * @retval QCBOR_ERR_BAD_TYPE_7
1514 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1515 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1516 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1517 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1518 * @retval QCBOR_ERR_TOO_MANY_TAGS
1519 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1520 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1521 *
1522 * If a the current nesting level is a map, then this
1523 * combines pairs of items into one data item with a label
1524 * and value.
1525 *
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001526 * This is passthrough if the current nesting leve is
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001527 * not a map.
1528 *
1529 * This also implements maps-as-array mode where a map
1530 * is treated like an array to allow caller to do their
1531 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001532 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001533static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001534QCBORDecode_GetNextMapEntry(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001535{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001536 QCBORError uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1537 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001538 goto Done;
1539 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001540
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001541 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1542 /* Break can't be a map entry */
1543 goto Done;
1544 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001545
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001546 if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1547 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001548
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001549 if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1550 /* Save label in pDecodedItem and get the next which will
1551 * be the real data item.
1552 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001553 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001554 uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1555 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001556 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001557 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001558
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301559 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001560
1561 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001562 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001563 pDecodedItem->label.string = LabelItem.val.string;
1564 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001565 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
1566 /* It's not a string and we only want strings */
1567 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001568 goto Done;
1569 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1570 pDecodedItem->label.int64 = LabelItem.val.int64;
1571 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1572 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1573 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1574 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1575 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1576 pDecodedItem->label.string = LabelItem.val.string;
1577 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1578 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1579 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001580 /* label is not an int or a string. It is an arrray
1581 * or a float or such and this implementation doesn't handle that.
1582 * Also, tags on labels are ignored.
1583 */
1584 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001585 goto Done;
1586 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001587 }
1588 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001589 /* Decoding of maps as arrays to let the caller decide what to do
1590 * about labels, particularly lables that are not integers or
1591 * strings.
1592 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001593 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001594 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001595 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001596 goto Done;
1597 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001598 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001599 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1600 * Cast is needed because of integer promotion.
1601 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001602 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001603 }
1604 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001605
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001606Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001607 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001608}
1609
1610
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001611#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001612/**
1613 * @brief Peek and see if next data item is a break;
1614 *
1615 * @param[in] pUIB UsefulInputBuf to read from.
1616 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1617 *
1618 * @return Any decoding error.
1619 *
1620 * See if next item is a CBOR break. If it is, it is consumed,
1621 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001622*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001623static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001624NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1625{
1626 *pbNextIsBreak = false;
1627 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001628 QCBORItem Peek;
1629 size_t uPeek = UsefulInputBuf_Tell(pUIB);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001630 QCBORError uReturn = DecodeAtomicDataItem(pUIB, &Peek, NULL);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001631 if(uReturn != QCBOR_SUCCESS) {
1632 return uReturn;
1633 }
1634 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001635 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001636 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001637 } else {
1638 *pbNextIsBreak = true;
1639 }
1640 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001641
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001642 return QCBOR_SUCCESS;
1643}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001644#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001645
1646
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001647/**
1648 * @brief Ascend up nesting levels if all items in them have been consumed.
1649 *
1650 * @param[in] pMe The decode context.
1651 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1652 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001653 * An item was just consumed, now figure out if it was the
1654 * end of an array/map map that can be closed out. That
1655 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001656*/
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001657static QCBORError
1658QCBORDecode_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001659{
1660 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001661
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001662 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001663 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1664
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001665 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1666 /* Nesting level is bstr-wrapped CBOR */
1667
1668 /* Ascent for bstr-wrapped CBOR is always by explicit call
1669 * so no further ascending can happen.
1670 */
1671 break;
1672
1673 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1674 /* Level is a definite-length array/map */
1675
1676 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001677 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1678 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001679 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001680 break;
1681 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001682 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001683 * is time to ascend one level. This happens below.
1684 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001685
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001686#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001687 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001688 /* Level is an indefinite-length array/map. */
1689
1690 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001691 bool bIsBreak = false;
1692 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1693 if(uReturn != QCBOR_SUCCESS) {
1694 goto Done;
1695 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001696
1697 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001698 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001699 break;
1700 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001701
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001702 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001703 * it is time to ascend one level.
1704 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001705
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001706#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001707 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001708
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001709
1710 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001711
Laurence Lundblade93d89472020-10-03 22:30:50 -07001712 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001713 * QCBORDecode_ExitBoundedMode().
1714 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001715 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001716 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001717 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001718 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001719 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001720 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001721
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001722 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001723 break;
1724 }
1725
1726 /* Finally, actually ascend one level. */
1727 DecodeNesting_Ascend(&(pMe->nesting));
1728 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001729
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001730 uReturn = QCBOR_SUCCESS;
1731
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001732#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001733Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001734#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1735
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001736 return uReturn;
1737}
1738
1739
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001740/**
1741 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1742 *
1743 * @param[in] pMe Decoder context
1744 * @param[out] pDecodedItem The decoded item that work is done on.
1745 *
1746 * @retval QCBOR_ERR_UNSUPPORTED
1747 * @retval QCBOR_ERR_HIT_END
1748 * @retval QCBOR_ERR_INT_OVERFLOW
1749 * @retval QCBOR_ERR_STRING_ALLOCATE
1750 * @retval QCBOR_ERR_STRING_TOO_LONG
1751 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001752 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001753 * @retval QCBOR_ERR_BAD_TYPE_7
1754 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1755 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1756 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1757 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1758 * @retval QCBOR_ERR_TOO_MANY_TAGS
1759 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1760 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1761 * @retval QCBOR_ERR_NO_MORE_ITEMS
1762 * @retval QCBOR_ERR_BAD_BREAK
1763 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
1764 *
1765 * This handles the traversal descending into and asecnding out of
1766 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
1767 * definite- and indefinte-length maps and arrays by looking at the
1768 * item count or finding CBOR breaks. It detects the ends of the
1769 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001770 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001771static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001772QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001773{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001774 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001775 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001776
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001777 /* If out of bytes to consume, it is either the end of the
1778 * top-level sequence of some bstr-wrapped CBOR that was entered.
1779 *
1780 * In the case of bstr-wrapped CBOR, the length of the
1781 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
1782 * the bstr-wrapped CBOR is exited, the length is set back to the
1783 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001784 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001785 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001786 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001787 goto Done;
1788 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001789
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001790 /* Check to see if at the end of a bounded definite-length map or
1791 * array. The check for a break ending indefinite-length array is
1792 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001793 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001794 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001795 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001796 goto Done;
1797 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001798
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001799 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001800 uReturn = QCBORDecode_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001801 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1802 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001803 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001804 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301805
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001806 /* Breaks ending arrays/maps are processed later in the call to
1807 * QCBORDecode_NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001808 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301809 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001810 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301811 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301812 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001813
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001814 /* Record the nesting level for this data item before processing
1815 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001816 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001817 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001818
Laurence Lundblade642282a2020-06-23 12:00:33 -07001819
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001820 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001821 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001822 /* If the new item is a map or array, descend.
1823 *
1824 * Empty indefinite-length maps and arrays are descended into,
1825 * but then ascended out of in the next chunk of code.
1826 *
1827 * Maps and arrays do count as items in the map/array that
1828 * encloses them so a decrement needs to be done for them too,
1829 * but that is done only when all the items in them have been
1830 * processed, not when they are opened with the exception of an
1831 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001832 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001833 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001834 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001835 pDecodedItem->uDataType,
1836 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001837 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001838 /* This error is probably a traversal error and it overrides
1839 * the non-traversal error.
1840 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001841 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001842 goto Done;
1843 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001844 }
1845
Laurence Lundblade02625d42020-06-25 14:41:41 -07001846 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1847 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1848 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001849 /* The following cases are handled here:
1850 * - A non-aggregate item like an integer or string
1851 * - An empty definite-length map or array
1852 * - An indefinite-length map or array that might be empty or might not.
1853 *
1854 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
1855 * for an definite-length map/array and break detection for an
1856 * indefinite-0length map/array. If the end of the map/array was
1857 * reached, then it ascends nesting levels, possibly all the way
1858 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001859 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001860 QCBORError uAscendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001861 uAscendErr = QCBORDecode_NestLevelAscender(pMe, true);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001862 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001863 /* This error is probably a traversal error and it overrides
1864 * the non-traversal error.
1865 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001866 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001867 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001868 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301869 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001870
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001871 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001872 /* Tell the caller what level is next. This tells them what
1873 * maps/arrays were closed out and makes it possible for them to
1874 * reconstruct the tree with just the information returned in a
1875 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001876 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001877 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001878 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001879 pDecodedItem->uNextNestLevel = 0;
1880 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001881 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001882 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001883
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001884Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001885 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001886}
1887
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001888
1889/**
1890 * @brief Shift 0th tag out of the tag list.
1891 *
1892 * pDecodedItem[in,out] The data item to convert.
1893 *
1894 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
1895 * shifted into empty slot at the end of the tag list.
1896 */
1897static inline void ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07001898{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001899 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
1900 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
1901 }
1902 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001903}
1904
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001905
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001906/**
1907 * @brief Convert different epoch date formats in to the QCBOR epoch date format
1908 *
1909 * pDecodedItem[in,out] The data item to convert.
1910 *
1911 * @retval QCBOR_ERR_DATE_OVERFLOW
1912 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001913 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001914 * @retval QCBOR_ERR_BAD_TAG_CONTENT
1915 *
1916 * The epoch date tag defined in QCBOR allows for floating-point
1917 * dates. It even allows a protocol to flop between date formats when
1918 * ever it wants. Floating-point dates aren't that useful as they are
1919 * only needed for dates beyond the age of the earth.
1920 *
1921 * This converts all the date formats into one format of an unsigned
1922 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001923 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001924static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001925{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001926 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001927
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001928#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade59289e52019-12-30 13:44:37 -08001929 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001930#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001931
1932 switch (pDecodedItem->uDataType) {
1933
1934 case QCBOR_TYPE_INT64:
1935 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1936 break;
1937
1938 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001939 /* This only happens for CBOR type 0 > INT64_MAX so it is
1940 * always an overflow.
1941 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07001942 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1943 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001944 break;
1945
1946 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001947 case QCBOR_TYPE_FLOAT:
1948#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001949 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001950 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001951 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001952 pDecodedItem->val.dfnum :
1953 (double)pDecodedItem->val.fnum;
1954
1955 /* The conversion from float to integer requires overflow
1956 * detection since floats can be much larger than integers.
1957 * This implementation errors out on these large float values
1958 * since they are beyond the age of the earth.
1959 *
1960 * These constants for the overflow check are computed by the
1961 * compiler. They are not computed at run time.
1962 *
1963 * The factor of 0x7ff is added/subtracted to avoid a
1964 * rounding error in the wrong direction when the compiler
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001965 * computes these constants. There is rounding because a
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001966 * 64-bit integer has 63 bits of precision where a double
1967 * only has 53 bits. Without the 0x7ff factor, the compiler
1968 * may round up and produce a double for the bounds check
1969 * that is larger than can be stored in a 64-bit integer. The
1970 * amount of 0x7ff is picked because it has 11 bits set.
1971 *
1972 * Without the 0x7ff there is a ~30 minute range of time
1973 * values 10 billion years in the past and in the future
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001974 * where this code could go wrong. Some compilers
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001975 * generate a warning or error without the 0x7ff.
1976 */
1977 const double dDateMax = (double)(INT64_MAX - 0x7ff);
1978 const double dDateMin = (double)(INT64_MIN + 0x7ff);
1979
1980 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07001981 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001982 goto Done;
1983 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001984
1985 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001986 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001987 pDecodedItem->val.epochDate.fSecondsFraction =
1988 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001989 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001990#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07001991
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001992 uReturn = QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001993 goto Done;
1994
Laurence Lundblade9682a532020-06-06 18:33:04 -07001995#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001996 break;
1997
1998 default:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001999 uReturn = QCBOR_ERR_BAD_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002000 goto Done;
2001 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002002
Laurence Lundblade59289e52019-12-30 13:44:37 -08002003 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
2004
2005Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002006 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002007}
2008
2009
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002010/**
2011 * @brief Convert the days epoch date.
2012 *
2013 * pDecodedItem[in,out] The data item to convert.
2014 *
2015 * @retval QCBOR_ERR_DATE_OVERFLOW
2016 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002017 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002018 * @retval QCBOR_ERR_BAD_TAG_CONTENT
2019 *
2020 * This is much simpler than the other epoch date format because
2021 * floating-porint is not allowed. This is mostly a simple type check.
2022 */
2023static QCBORError DecodeDaysEpoch(QCBORItem *pDecodedItem)
2024{
2025 QCBORError uReturn = QCBOR_SUCCESS;
2026
2027 switch (pDecodedItem->uDataType) {
2028
2029 case QCBOR_TYPE_INT64:
2030 pDecodedItem->val.epochDays = pDecodedItem->val.int64;
2031 break;
2032
2033 case QCBOR_TYPE_UINT64:
2034 /* This only happens for CBOR type 0 > INT64_MAX so it is
2035 * always an overflow.
2036 */
2037 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2038 goto Done;
2039 break;
2040
2041 default:
2042 uReturn = QCBOR_ERR_BAD_TAG_CONTENT;
2043 goto Done;
2044 break;
2045 }
2046
2047 pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
2048
2049Done:
2050 return uReturn;
2051}
2052
2053
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002054#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002055/**
2056 * @brief Decode decimal fractions and big floats.
2057 *
2058 * @param[in] pMe The decode context.
2059 * @param[in,out] pDecodedItem On input the array data item that
2060 * holds the mantissa and exponent. On
2061 * output the decoded mantissa and
2062 * exponent.
2063 *
2064 * @returns Decoding errors from getting primitive data items or
2065 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
2066 *
2067 * When called pDecodedItem must be the array that is tagged as a big
2068 * float or decimal fraction, the array that has the two members, the
2069 * exponent and mantissa.
2070 *
2071 * This will fetch and decode the exponent and mantissa and put the
2072 * result back into pDecodedItem.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002073 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002074static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002075QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002076{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002077 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002078
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002079 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002080 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002081 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002082 goto Done;
2083 }
2084
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002085 /* A check for pDecodedItem->val.uCount == 2 would work for
2086 * definite-length arrays, but not for indefnite. Instead remember
2087 * the nesting level the two integers must be at, which is one
2088 * deeper than that of the array.
2089 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002090 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2091
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002092 /* --- Which is it, decimal fraction or a bigfloat? --- */
2093 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(pMe, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002094 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
2095
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002096 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002097 QCBORItem exponentItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002098 uReturn = QCBORDecode_GetNextMapOrArray(pMe, &exponentItem);
2099 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002100 goto Done;
2101 }
2102 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002103 /* Array is empty or a map/array encountered when expecting an int */
2104 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002105 goto Done;
2106 }
2107 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002108 /* Data arriving as an unsigned int < INT64_MAX has been
2109 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2110 * also means that the only data arriving here of type
2111 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2112 * and thus an error that will get handled in the next else.
2113 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002114 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2115 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002116 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2117 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002118 goto Done;
2119 }
2120
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002121 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002122 QCBORItem mantissaItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002123 uReturn = QCBORDecode_GetNextWithTags(pMe, &mantissaItem, NULL);
2124 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002125 goto Done;
2126 }
2127 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002128 /* Mantissa missing or map/array encountered when expecting number */
2129 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002130 goto Done;
2131 }
2132 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002133 /* Data arriving as an unsigned int < INT64_MAX has been
2134 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2135 * also means that the only data arriving here of type
2136 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2137 * and thus an error that will get handled in an else below.
2138 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002139 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07002140 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2141 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002142 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002143 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002144 /* Depends on numbering of QCBOR_TYPE_XXX */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002145 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
2146 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
2147 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002148 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002149 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2150 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002151 goto Done;
2152 }
2153
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002154 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002155 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002156 /* Extra items in the decimal fraction / big float */
2157 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002158 goto Done;
2159 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002160 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002161
2162Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002163 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002164}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002165#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002166
2167
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002168#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002169/**
2170 * @brief Decode the MIME type tag
2171 *
2172 * @param[in,out] pDecodedItem The item to decode.
2173 *
2174 * Handle the text and binary MIME type tags. Slightly too complicated
2175 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2176 * incorreclty text-only.
2177 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002178static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002179{
2180 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2181 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002182 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002183 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2184 } else {
2185 return QCBOR_ERR_BAD_OPT_TAG;
2186 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002187
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002188 return QCBOR_SUCCESS;
2189}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002190#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002191
2192
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002193/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002194 * Table of CBOR tags whose content is either a text string or a byte
2195 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2196 * of uQCBORtype indicates the content should be a byte string rather
2197 * than a text string
2198 */
2199struct StringTagMapEntry {
2200 uint16_t uTagNumber;
2201 uint8_t uQCBORtype;
2202};
2203
2204#define IS_BYTE_STRING_BIT 0x80
2205#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2206
2207static const struct StringTagMapEntry StringTagMap[] = {
2208 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002209 {CBOR_TAG_DAYS_STRING, QCBOR_TYPE_DAYS_STRING},
Laurence Lundblade99615302020-11-29 11:19:47 -08002210 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2211 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2212 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2213 {CBOR_TAG_URI, QCBOR_TYPE_URI},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002214#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002215 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2216 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2217 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2218 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002219#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002220 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2221 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2222};
2223
2224
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002225/**
2226 * @brief Process standard CBOR tags whose content is a string
2227 *
2228 * @param[in] uTag The tag.
2229 * @param[in,out] pDecodedItem The data item.
2230 *
2231 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2232 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
2233 * \ref QCBOR_ERR_BAD_OPT_TAG if the content type was wrong for the tag.
2234 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002235 * Process the CBOR tags that whose content is a byte string or a text
2236 * string and for which the string is just passed on to the caller.
2237 *
2238 * This maps the CBOR tag to the QCBOR type and checks the content
2239 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002240 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002241 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002242 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002243static inline QCBORError
2244ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002245{
Laurence Lundblade99615302020-11-29 11:19:47 -08002246 /* This only works on tags that were not mapped; no need for other yet */
2247 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2248 return QCBOR_ERR_UNSUPPORTED;
2249 }
2250
2251 unsigned uIndex;
2252 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2253 if(StringTagMap[uIndex].uTagNumber == uTag) {
2254 break;
2255 }
2256 }
2257
2258 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
2259 if(uQCBORType == QCBOR_TYPE_NONE) {
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002260 /* repurpose this error to mean not handled here */
Laurence Lundblade99615302020-11-29 11:19:47 -08002261 return QCBOR_ERR_UNSUPPORTED;
2262 }
2263
2264 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2265 if(uQCBORType & IS_BYTE_STRING_BIT) {
2266 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2267 }
2268
2269 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002270 return QCBOR_ERR_BAD_OPT_TAG;
2271 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002272
Laurence Lundblade99615302020-11-29 11:19:47 -08002273 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002274 return QCBOR_SUCCESS;
2275}
2276
2277
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002278/**
2279 * @brief Decode tag content for select tags (decoding layer 1).
2280 *
2281 * @param[in] pMe The decode context.
2282 * @param[out] pDecodedItem The decoded item.
2283 *
2284 * @return Decoding error code.
2285 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002286 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2287 * but the whole tag was not decoded. Here, the whole tags (tag number
2288 * and tag content) that are supported by QCBOR are decoded. This is a
2289 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002290 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002291static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002292QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002293{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002294 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002295
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002296 uReturn = QCBORDecode_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002297 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002298 goto Done;
2299 }
2300
Laurence Lundblade99615302020-11-29 11:19:47 -08002301 /* When there are no tag numbers for the item, this exits first
2302 * thing and effectively does nothing.
2303 *
2304 * This loops over all the tag numbers accumulated for this item
2305 * trying to decode and interpret them. This stops at the end of
2306 * the list or at the first tag number that can't be interpreted by
2307 * this code. This is effectively a recursive processing of the
2308 * tags number list that handles nested tags.
2309 */
2310 while(1) {
2311 /* Don't bother to unmap tags via QCBORITem.uTags since this
2312 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2313 */
2314 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002315
Laurence Lundblade99615302020-11-29 11:19:47 -08002316 if(uTagToProcess == CBOR_TAG_INVALID16) {
2317 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002318 break;
2319
Laurence Lundblade99615302020-11-29 11:19:47 -08002320 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002321 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002322
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002323 } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
2324 uReturn = DecodeDaysEpoch(pDecodedItem);
2325
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002326#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002327 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2328 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002329 uReturn = QCBORDecode_MantissaAndExponent(pMe, pDecodedItem);
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002330#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002331#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002332 } else if(uTagToProcess == CBOR_TAG_MIME ||
2333 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002334 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002335#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002336
Laurence Lundblade99615302020-11-29 11:19:47 -08002337 } else {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002338 /* See if it is a passthrough byte/text string tag; process if so */
Laurence Lundblade99615302020-11-29 11:19:47 -08002339 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002340
Laurence Lundblade99615302020-11-29 11:19:47 -08002341 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002342 /* It wasn't a passthrough byte/text string tag so it is
Laurence Lundblade99615302020-11-29 11:19:47 -08002343 * an unknown tag. This is the exit from the loop on the
2344 * first unknown tag. It is a successful exit.
2345 */
2346 uReturn = QCBOR_SUCCESS;
2347 break;
2348 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002349 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002350
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002351 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002352 /* Error exit from the loop */
2353 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002354 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002355
2356 /* A tag was successfully processed, shift it out of the list of
2357 * tags returned. This is the loop increment.
2358 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002359 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002360 }
2361
2362Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002363 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002364}
2365
2366
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002367/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002368 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002369 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002370QCBORError
2371QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2372{
2373 QCBORError uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002374 uErr = QCBORDecode_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002375 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002376 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2377 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2378 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002379 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002380}
2381
2382
2383/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002384 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002385 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002386QCBORError
2387QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2388{
2389 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2390 const UsefulInputBuf Save = pMe->InBuf;
2391
2392 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2393
2394 pMe->nesting = SaveNesting;
2395 pMe->InBuf = Save;
2396
2397 return uErr;
2398}
2399
2400
2401/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002402 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002403 */
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002404void
2405QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2406{
2407 if(pMe->uLastError != QCBOR_SUCCESS) {
2408 return;
2409 }
2410
2411 pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
2412}
2413
2414
2415/*
2416 * Public function, see header qcbor/qcbor_decode.h file
2417 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002418void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2419{
2420 if(pMe->uLastError != QCBOR_SUCCESS) {
2421 return;
2422 }
2423
2424 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2425}
2426
2427
2428/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002429 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002430 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002431QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002432QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2433 QCBORItem *pDecodedItem,
2434 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002435{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002436 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002437
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002438 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2439 if(uReturn != QCBOR_SUCCESS) {
2440 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002441 }
2442
2443 if(pTags != NULL) {
2444 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002445 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002446 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2447 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002448 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002449 }
2450 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2451 return QCBOR_ERR_TOO_MANY_TAGS;
2452 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002453 pTags->puTags[pTags->uNumUsed] = UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002454 pTags->uNumUsed++;
2455 }
2456 }
2457
2458 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002459}
2460
2461
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002462/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002463 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302464 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002465bool QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002466 const QCBORItem *pItem,
2467 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002468{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002469 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2470 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002471 break;
2472 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002473 if(UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002474 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002475 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002476 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002477
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002478 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002479}
2480
2481
2482/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002483 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002484 */
Laurence Lundblade87495732021-02-26 10:05:55 -07002485QCBORError QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002486{
Laurence Lundblade87495732021-02-26 10:05:55 -07002487 if(puConsumed != NULL) {
2488 *puConsumed = pMe->InBuf.cursor;
2489 }
2490
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002491 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002492
2493 if(uReturn != QCBOR_SUCCESS) {
2494 goto Done;
2495 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002496
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002497 /* Error out if all the maps/arrays are not closed out */
2498 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002499 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002500 goto Done;
2501 }
2502
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002503 /* Error out if not all the bytes are consumed */
2504 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002505 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002506 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002507
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002508Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002509 return uReturn;
2510}
2511
2512
2513/*
2514 * Public function, see header qcbor/qcbor_decode.h file
2515 */
2516QCBORError QCBORDecode_Finish(QCBORDecodeContext *pMe)
2517{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002518#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002519 /* Call the destructor for the string allocator if there is one.
2520 * Always called, even if there are errors; always have to clean up.
2521 */
2522 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002523#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002524
Laurence Lundblade87495732021-02-26 10:05:55 -07002525 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002526}
2527
2528
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002529/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002530 * Public function, see header qcbor/qcbor_decode.h file
2531 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002532// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002533uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2534 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002535 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002536{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002537 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2538 return CBOR_TAG_INVALID64;
2539 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002540 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2541 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002542 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002543 return UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002544 }
2545}
2546
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002547
Laurence Lundblade9b334962020-08-27 10:55:53 -07002548/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002549 * Public function, see header qcbor/qcbor_decode.h file
2550 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002551uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2552 uint32_t uIndex)
2553{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002554 if(pMe->uLastError != QCBOR_SUCCESS) {
2555 return CBOR_TAG_INVALID64;
2556 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002557 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2558 return CBOR_TAG_INVALID64;
2559 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002560 return UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002561 }
2562}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002563
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002564
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002565
2566
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002567#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002568
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002569/* ===========================================================================
2570 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002571
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002572 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002573 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2574 implements the function type QCBORStringAllocate and allows easy
2575 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002576
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002577 This particular allocator is built-in for convenience. The caller
2578 can implement their own. All of this following code will get
2579 dead-stripped if QCBORDecode_SetMemPool() is not called.
2580
2581 This is a very primitive memory allocator. It does not track
2582 individual allocations, only a high-water mark. A free or
2583 reallocation must be of the last chunk allocated.
2584
2585 The size of the pool and offset to free memory are packed into the
2586 first 8 bytes of the memory pool so we don't have to keep them in
2587 the decode context. Since the address of the pool may not be
2588 aligned, they have to be packed and unpacked as if they were
2589 serialized data of the wire or such.
2590
2591 The sizes packed in are uint32_t to be the same on all CPU types
2592 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002593 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002594
2595
Laurence Lundbladeee851742020-01-08 08:37:05 -08002596static inline int
2597MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002598{
2599 // Use of UsefulInputBuf is overkill, but it is convenient.
2600 UsefulInputBuf UIB;
2601
Laurence Lundbladeee851742020-01-08 08:37:05 -08002602 // Just assume the size here. It was checked during SetUp so
2603 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002604 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002605 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2606 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2607 return UsefulInputBuf_GetError(&UIB);
2608}
2609
2610
Laurence Lundbladeee851742020-01-08 08:37:05 -08002611static inline int
2612MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002613{
2614 // Use of UsefulOutBuf is overkill, but convenient. The
2615 // length check performed here is useful.
2616 UsefulOutBuf UOB;
2617
2618 UsefulOutBuf_Init(&UOB, Pool);
2619 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2620 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2621 return UsefulOutBuf_GetError(&UOB);
2622}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002623
2624
2625/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002626 Internal function for an allocation, reallocation free and destuct.
2627
2628 Having only one function rather than one each per mode saves space in
2629 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002630
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002631 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2632 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002633static UsefulBuf
2634MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002635{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002636 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002637
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002638 uint32_t uPoolSize;
2639 uint32_t uFreeOffset;
2640
2641 if(uNewSize > UINT32_MAX) {
2642 // This allocator is only good up to 4GB. This check should
2643 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2644 goto Done;
2645 }
2646 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2647
2648 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2649 goto Done;
2650 }
2651
2652 if(uNewSize) {
2653 if(pMem) {
2654 // REALLOCATION MODE
2655 // Calculate pointer to the end of the memory pool. It is
2656 // assumed that pPool + uPoolSize won't wrap around by
2657 // assuming the caller won't pass a pool buffer in that is
2658 // not in legitimate memory space.
2659 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2660
2661 // Check that the pointer for reallocation is in the range of the
2662 // pool. This also makes sure that pointer math further down
2663 // doesn't wrap under or over.
2664 if(pMem >= pPool && pMem < pPoolEnd) {
2665 // Offset to start of chunk for reallocation. This won't
2666 // wrap under because of check that pMem >= pPool. Cast
2667 // is safe because the pool is always less than UINT32_MAX
2668 // because of check in QCBORDecode_SetMemPool().
2669 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2670
2671 // Check to see if the allocation will fit. uPoolSize -
2672 // uMemOffset will not wrap under because of check that
2673 // pMem is in the range of the uPoolSize by check above.
2674 if(uNewSize <= uPoolSize - uMemOffset) {
2675 ReturnValue.ptr = pMem;
2676 ReturnValue.len = uNewSize;
2677
2678 // Addition won't wrap around over because uNewSize was
2679 // checked to be sure it is less than the pool size.
2680 uFreeOffset = uMemOffset + uNewSize32;
2681 }
2682 }
2683 } else {
2684 // ALLOCATION MODE
2685 // uPoolSize - uFreeOffset will not underflow because this
2686 // pool implementation makes sure uFreeOffset is always
2687 // smaller than uPoolSize through this check here and
2688 // reallocation case.
2689 if(uNewSize <= uPoolSize - uFreeOffset) {
2690 ReturnValue.len = uNewSize;
2691 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002692 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002693 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002694 }
2695 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002696 if(pMem) {
2697 // FREE MODE
2698 // Cast is safe because of limit on pool size in
2699 // QCBORDecode_SetMemPool()
2700 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2701 } else {
2702 // DESTRUCT MODE
2703 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002704 }
2705 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002706
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002707 UsefulBuf Pool = {pPool, uPoolSize};
2708 MemPool_Pack(Pool, uFreeOffset);
2709
2710Done:
2711 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002712}
2713
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002714
Laurence Lundbladef6531662018-12-04 10:42:22 +09002715/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002716 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002717 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002718QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2719 UsefulBuf Pool,
2720 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002721{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002722 // The pool size and free mem offset are packed into the beginning
2723 // of the pool memory. This compile time check make sure the
2724 // constant in the header is correct. This check should optimize
2725 // down to nothing.
2726 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002727 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002728 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002729
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002730 // The pool size and free offset packed in to the beginning of pool
2731 // memory are only 32-bits. This check will optimize out on 32-bit
2732 // machines.
2733 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002734 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002735 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002736
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002737 // This checks that the pool buffer given is big enough.
2738 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002739 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002740 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002741
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002742 QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002743
Laurence Lundblade30816f22018-11-10 13:40:22 +07002744 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002745}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002746#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002747
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002748
2749
Laurence Lundblade9b334962020-08-27 10:55:53 -07002750static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2751{
2752 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2753}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002754
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002755
2756/*
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002757 Consume an entire map or array (and do next to
2758 nothing for non-aggregate types).
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002759 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002760static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002761ConsumeItem(QCBORDecodeContext *pMe,
2762 const QCBORItem *pItemToConsume,
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02002763 uint8_t *puNextNestLevel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002764{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002765 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002766 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002767
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002768 // If it is a map or array, this will tell if it is empty.
2769 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2770
2771 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2772 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002773
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002774 /* This works for definite- and indefinite- length
Laurence Lundblade1341c592020-04-11 14:19:05 -07002775 * maps and arrays by using the nesting level
2776 */
2777 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002778 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002779 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002780 goto Done;
2781 }
2782 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002783
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002784 *puNextNestLevel = Item.uNextNestLevel;
2785
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002786 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002787
Laurence Lundblade1341c592020-04-11 14:19:05 -07002788 } else {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002789 /* item_to_consume is not a map or array */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002790 /* Just pass the nesting level through */
2791 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2792
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002793 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002794 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002795
2796Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002797 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002798}
2799
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002800
2801void QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2802{
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002803 QCBORDecode_VGetNext(pMe, pDecodedItem);
2804
2805 if(pMe->uLastError == QCBOR_SUCCESS) {
Máté Tóth-Pálc6d59682021-05-26 18:55:30 +02002806 pMe->uLastError = (uint8_t)ConsumeItem(pMe, pDecodedItem,
2807 &pDecodedItem->uNextNestLevel);
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002808 }
2809}
2810
2811
2812
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002813/* Call only on maps and arrays. Rewinds the cursor
2814 * to the start as if it was just entered.
2815 */
2816static void RewindMapOrArray(QCBORDecodeContext *pMe)
2817{
2818 /* Reset nesting tracking to the deepest bounded level */
2819 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2820
2821 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
2822
2823 /* Reposition traversal cursor to the start of the map/array */
2824 UsefulInputBuf_Seek(&(pMe->InBuf),
2825 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
2826}
2827
2828
2829/*
2830 Public function, see header qcbor/qcbor_decode.h file
2831 */
2832void QCBORDecode_Rewind(QCBORDecodeContext *pMe)
2833{
2834 if(pMe->nesting.pCurrentBounded != NULL) {
2835 /* In a bounded map, array or bstr-wrapped CBOR */
2836
2837 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
2838 /* In bstr-wrapped CBOR. */
2839
2840 /* Reposition traversal cursor to start of wrapping byte string */
2841 UsefulInputBuf_Seek(&(pMe->InBuf),
2842 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
2843 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2844
2845 } else {
2846 /* In a map or array */
2847 RewindMapOrArray(pMe);
2848 }
2849
2850 } else {
2851 /* Not in anything bounded */
2852
2853 /* Reposition traversal cursor to the start of input CBOR */
2854 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
2855
2856 /* Reset nesting tracking to beginning of input. */
2857 DecodeNesting_Init(&(pMe->nesting));
2858 }
2859
2860 pMe->uLastError = QCBOR_SUCCESS;
2861}
2862
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002863
Laurence Lundblade1341c592020-04-11 14:19:05 -07002864/* Return true if the labels in Item1 and Item2 are the same.
2865 Works only for integer and string labels. Returns false
2866 for any other type. */
2867static inline bool
2868MatchLabel(QCBORItem Item1, QCBORItem Item2)
2869{
2870 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2871 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2872 return true;
2873 }
2874 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002875 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002876 return true;
2877 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002878 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002879 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2880 return true;
2881 }
2882 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2883 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2884 return true;
2885 }
2886 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002887
Laurence Lundblade1341c592020-04-11 14:19:05 -07002888 /* Other label types are never matched */
2889 return false;
2890}
2891
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002892
2893/*
2894 Returns true if Item1 and Item2 are the same type
2895 or if either are of QCBOR_TYPE_ANY.
2896 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002897static inline bool
2898MatchType(QCBORItem Item1, QCBORItem Item2)
2899{
2900 if(Item1.uDataType == Item2.uDataType) {
2901 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002902 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002903 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002904 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002905 return true;
2906 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002907 return false;
2908}
2909
2910
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002911/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002912 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002913
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002914 @param[in] pMe The decode context to search.
2915 @param[in,out] pItemArray The items to search for and the items found.
2916 @param[out] puOffset Byte offset of last item matched.
2917 @param[in] pCBContext Context for the not-found item call back.
2918 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002919
2920 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2921
Laurence Lundblade93d89472020-10-03 22:30:50 -07002922 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2923 were found for one of the labels being
2924 search for. This duplicate detection is
2925 only performed for items in pItemArray,
2926 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002927
Laurence Lundblade93d89472020-10-03 22:30:50 -07002928 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2929 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002930
2931 @retval Also errors returned by QCBORDecode_GetNext().
2932
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002933 On input pItemArray contains a list of labels and data types
2934 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002935
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002936 On output the fully retrieved items are filled in with
2937 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002938
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002939 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002940
2941 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002942 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002943static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002944MapSearch(QCBORDecodeContext *pMe,
2945 QCBORItem *pItemArray,
2946 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002947 void *pCBContext,
2948 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002949{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002950 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002951 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002952
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002953 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002954 uReturn = pMe->uLastError;
2955 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002956 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002957
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002958 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002959 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2960 /* QCBOR_TYPE_NONE as first item indicates just looking
2961 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002962 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2963 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002964 }
2965
Laurence Lundblade085d7952020-07-24 10:26:30 -07002966 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2967 // It is an empty bounded array or map
2968 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2969 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002970 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002971 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002972 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002973 // Nothing is ever found in an empty array or map. All items
2974 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07002975 uReturn = QCBOR_SUCCESS;
2976 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002977 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002978 }
2979
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002980 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002981 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
2982
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002983 /* Reposition to search from the start of the map / array */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002984 RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07002985
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002986 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002987 Loop over all the items in the map or array. Each item
2988 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002989 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002990 length maps and arrays. The only reason this is ever
2991 called on arrays is to find their end position.
2992
2993 This will always run over all items in order to do
2994 duplicate detection.
2995
2996 This will exit with failure if it encounters an
2997 unrecoverable error, but continue on for recoverable
2998 errors.
2999
3000 If a recoverable error occurs on a matched item, then
3001 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003002 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07003003 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02003004 uint8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003005 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003006 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07003007 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003008
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003009 /* Get the item */
3010 QCBORItem Item;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003011 QCBORError uResult = QCBORDecode_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003012 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003013 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003014 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003015 goto Done;
3016 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003017 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003018 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003019 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003020 goto Done;
3021 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003022
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003023 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003024 bool bMatched = false;
3025 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
3026 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003027 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003028 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
3029 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003030 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003031 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003032 if(uResult != QCBOR_SUCCESS) {
3033 /* The label matches, but the data item is in error */
3034 uReturn = uResult;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003035 goto Done;
3036 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003037 if(!MatchType(Item, pItemArray[nIndex])) {
3038 /* The data item is not of the type(s) requested */
3039 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003040 goto Done;
3041 }
3042
Laurence Lundblade1341c592020-04-11 14:19:05 -07003043 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003044 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003045 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003046 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003047 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003048 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003049 bMatched = true;
3050 }
3051 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003052
3053
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003054 if(!bMatched && pfCallback != NULL) {
3055 /*
3056 Call the callback on unmatched labels.
3057 (It is tempting to do duplicate detection here, but that would
3058 require dynamic memory allocation because the number of labels
3059 that might be encountered is unbounded.)
3060 */
3061 uReturn = (*pfCallback)(pCBContext, &Item);
3062 if(uReturn != QCBOR_SUCCESS) {
3063 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003064 }
3065 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003066
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003067 /*
3068 Consume the item whether matched or not. This
3069 does the work of traversing maps and array and
3070 everything in them. In this loop only the
3071 items at the current nesting level are examined
3072 to match the labels.
3073 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003074 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003075 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003076 goto Done;
3077 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003078
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003079 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003080
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003081 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003082
3083 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003084
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003085 // Check here makes sure that this won't accidentally be
3086 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003087 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003088 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3089 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003090 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3091 goto Done;
3092 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003093 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3094 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003095
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003096 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003097 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3098
3099 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003100 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003101 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003102 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003103 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3104 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003105 }
3106 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003107
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003108 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003109}
3110
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003111
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003112/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003113 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003114*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003115void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3116 int64_t nLabel,
3117 uint8_t uQcborType,
3118 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003119{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003120 if(pMe->uLastError != QCBOR_SUCCESS) {
3121 return;
3122 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003123
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003124 QCBORItem OneItemSeach[2];
3125 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3126 OneItemSeach[0].label.int64 = nLabel;
3127 OneItemSeach[0].uDataType = uQcborType;
3128 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003129
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003130 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003131
3132 *pItem = OneItemSeach[0];
3133
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003134 if(uReturn != QCBOR_SUCCESS) {
3135 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003136 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003137 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003138 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003139 }
3140
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003141 Done:
3142 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003143}
3144
3145
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003146/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003147 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003148*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07003149void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3150 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003151 uint8_t uQcborType,
3152 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003153{
Laurence Lundbladeda095972020-06-06 18:35:33 -07003154 if(pMe->uLastError != QCBOR_SUCCESS) {
3155 return;
3156 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003157
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003158 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003159 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3160 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3161 OneItemSeach[0].uDataType = uQcborType;
3162 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003163
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003164 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
3165 if(uReturn != QCBOR_SUCCESS) {
3166 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003167 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003168 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003169 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003170 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003171 }
3172
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003173 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003174
3175Done:
3176 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003177}
3178
3179
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003180
Laurence Lundblade93d89472020-10-03 22:30:50 -07003181static QCBORError
3182CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003183{
3184 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
3185 if(uDataType == puTypeList[i]) {
3186 return QCBOR_SUCCESS;
3187 }
3188 }
3189 return QCBOR_ERR_UNEXPECTED_TYPE;
3190}
3191
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003192
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003193/**
3194 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003195 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003196
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003197 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3198 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07003199
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003200 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
3201 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003202 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003203static QCBORError
3204CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003205{
3206 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3207 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3208 /* There are tags that QCBOR couldn't process on this item and
3209 the caller has told us there should not be. */
3210 return QCBOR_ERR_UNEXPECTED_TYPE;
3211 }
3212
3213 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3214 const int nItemType = pItem->uDataType;
3215
3216 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3217 // Must match the tag and only the tag
3218 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3219 }
3220
3221 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3222 if(uReturn == QCBOR_SUCCESS) {
3223 return QCBOR_SUCCESS;
3224 }
3225
3226 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3227 /* Must match the content type and only the content type.
3228 There was no match just above so it is a fail. */
3229 return QCBOR_ERR_UNEXPECTED_TYPE;
3230 }
3231
3232 /* If here it can match either the tag or the content
3233 and it hasn't matched the content, so the end
3234 result is whether it matches the tag. This is
3235 also the case that the CBOR standard discourages. */
3236
3237 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3238}
3239
Laurence Lundblade9b334962020-08-27 10:55:53 -07003240
Laurence Lundblade9b334962020-08-27 10:55:53 -07003241
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003242// This could be semi-private if need be
3243static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003244void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3245 int64_t nLabel,
3246 TagSpecification TagSpec,
3247 QCBORItem *pItem)
3248{
3249 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3250 if(pMe->uLastError != QCBOR_SUCCESS) {
3251 return;
3252 }
3253
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003254 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003255}
3256
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003257
3258// This could be semi-private if need be
3259static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003260void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3261 const char *szLabel,
3262 TagSpecification TagSpec,
3263 QCBORItem *pItem)
3264{
3265 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3266 if(pMe->uLastError != QCBOR_SUCCESS) {
3267 return;
3268 }
3269
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003270 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003271}
3272
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003273// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003274void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3275 int64_t nLabel,
3276 TagSpecification TagSpec,
3277 UsefulBufC *pString)
3278{
3279 QCBORItem Item;
3280 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3281 if(pMe->uLastError == QCBOR_SUCCESS) {
3282 *pString = Item.val.string;
3283 }
3284}
3285
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003286// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003287void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3288 const char * szLabel,
3289 TagSpecification TagSpec,
3290 UsefulBufC *pString)
3291{
3292 QCBORItem Item;
3293 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3294 if(pMe->uLastError == QCBOR_SUCCESS) {
3295 *pString = Item.val.string;
3296 }
3297}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003298
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003299/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003300 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003301*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003302void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003303{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003304 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3305 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003306}
3307
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003308/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003309 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003310*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003311void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3312 QCBORItem *pItemList,
3313 void *pCallbackCtx,
3314 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003315{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003316 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3317 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003318}
3319
3320
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003321/**
3322 * @brief Search for a map/array by label and enter it
3323 *
3324 * @param[in] pMe The decode context.
3325 * @param[in] pSearch The map/array to search for.
3326 *
3327 * @c pSearch is expected to contain one item of type map or array
3328 * with the label specified. The current bounded map will be searched for
3329 * this and if found will be entered.
3330 *
3331 * If the label is not found, or the item found is not a map or array,
3332 * the error state is set.
3333 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003334static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003335{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003336 // The first item in pSearch is the one that is to be
3337 // entered. It should be the only one filled in. Any other
3338 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003339 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003340 return;
3341 }
3342
3343 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003344 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003345 if(pMe->uLastError != QCBOR_SUCCESS) {
3346 return;
3347 }
3348
Laurence Lundblade9b334962020-08-27 10:55:53 -07003349 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003350 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003351 return;
3352 }
3353
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003354
3355 /* The map or array was found. Now enter it.
3356 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003357 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3358 * next item for the pre-order traversal cursor to be the map/array
3359 * found by MapSearch(). The next few lines of code force the
3360 * cursor to that.
3361 *
3362 * There is no need to retain the old cursor because
3363 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3364 * beginning of the map/array being entered.
3365 *
3366 * The cursor is forced by: 1) setting the input buffer position to
3367 * the item offset found by MapSearch(), 2) setting the map/array
3368 * counter to the total in the map/array, 3) setting the nesting
3369 * level. Setting the map/array counter to the total is not
3370 * strictly correct, but this is OK because this cursor only needs
3371 * to be used to get one item and MapSearch() has already found it
3372 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003373 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003374 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003375
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003376 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3377
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003378 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003379
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003380 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003381}
3382
3383
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003384/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003385 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003386*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003387void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003388{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003389 QCBORItem OneItemSeach[2];
3390 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3391 OneItemSeach[0].label.int64 = nLabel;
3392 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3393 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003394
Laurence Lundblade9b334962020-08-27 10:55:53 -07003395 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003396 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003397}
3398
3399
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003400/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003401 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003402*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003403void QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003404{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003405 QCBORItem OneItemSeach[2];
3406 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3407 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3408 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3409 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003410
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003411 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003412}
3413
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003414/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003415 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003416*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003417void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003418{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003419 QCBORItem OneItemSeach[2];
3420 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3421 OneItemSeach[0].label.int64 = nLabel;
3422 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3423 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003424
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003425 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003426}
3427
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003428/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003429 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003430*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003431void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3432{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003433 QCBORItem OneItemSeach[2];
3434 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3435 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3436 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3437 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003438
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003439 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003440}
3441
3442
Laurence Lundblade02625d42020-06-25 14:41:41 -07003443// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003444void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003445{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003446 QCBORError uErr;
3447
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003448 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003449 if(pMe->uLastError != QCBOR_SUCCESS) {
3450 // Already in error state; do nothing.
3451 return;
3452 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003453
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003454 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003455 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003456 uErr = QCBORDecode_GetNext(pMe, &Item);
3457 if(uErr != QCBOR_SUCCESS) {
3458 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003459 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003460 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003461 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3462 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003463 }
3464
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003465 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003466
3467
Laurence Lundbladef0499502020-08-01 11:55:57 -07003468 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003469 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003470 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3471 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003472 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003473 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3474 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003475 // Special case to increment nesting level for zero-length maps
3476 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003477 DecodeNesting_Descend(&(pMe->nesting), uType);
3478 }
3479
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003480 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003481
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003482 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3483 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003484
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003485 if(pItem != NULL) {
3486 *pItem = Item;
3487 }
3488
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003489Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003490 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003491}
3492
Laurence Lundblade02625d42020-06-25 14:41:41 -07003493
3494/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003495 This is the common work for exiting a level that is a bounded map,
3496 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003497
3498 One chunk of work is to set up the pre-order traversal so it is at
3499 the item just after the bounded map, array or bstr that is being
3500 exited. This is somewhat complex.
3501
3502 The other work is to level-up the bounded mode to next higest bounded
3503 mode or the top level if there isn't one.
3504 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003505static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003506ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003507{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003508 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003509
Laurence Lundblade02625d42020-06-25 14:41:41 -07003510 /*
3511 First the pre-order-traversal byte offset is positioned to the
3512 item just after the bounded mode item that was just consumed.
3513 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003514 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3515
Laurence Lundblade02625d42020-06-25 14:41:41 -07003516 /*
3517 Next, set the current nesting level to one above the bounded level
3518 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003519
Laurence Lundblade02625d42020-06-25 14:41:41 -07003520 DecodeNesting_CheckBoundedType() is always called before this and
3521 makes sure pCurrentBounded is valid.
3522 */
3523 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3524
3525 /*
3526 This does the complex work of leveling up the pre-order traversal
3527 when the end of a map or array or another bounded level is
3528 reached. It may do nothing, or ascend all the way to the top
3529 level.
3530 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003531 uErr = QCBORDecode_NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003532 if(uErr != QCBOR_SUCCESS) {
3533 goto Done;
3534 }
3535
Laurence Lundblade02625d42020-06-25 14:41:41 -07003536 /*
3537 This makes the next highest bounded level the current bounded
3538 level. If there is no next highest level, then no bounded mode is
3539 in effect.
3540 */
3541 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003542
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003543 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003544
3545Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003546 return uErr;
3547}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003548
Laurence Lundblade02625d42020-06-25 14:41:41 -07003549
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003550// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003551void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003552{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003553 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003554 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003555 return;
3556 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003557
Laurence Lundblade02625d42020-06-25 14:41:41 -07003558 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003559
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003560 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003561 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003562 goto Done;
3563 }
3564
Laurence Lundblade02625d42020-06-25 14:41:41 -07003565 /*
3566 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003567 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003568 from previous map search, then do a dummy search.
3569 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003570 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003571 QCBORItem Dummy;
3572 Dummy.uLabelType = QCBOR_TYPE_NONE;
3573 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3574 if(uErr != QCBOR_SUCCESS) {
3575 goto Done;
3576 }
3577 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003578
Laurence Lundblade02625d42020-06-25 14:41:41 -07003579 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003580
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003581Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003582 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003583}
3584
3585
Laurence Lundblade1341c592020-04-11 14:19:05 -07003586
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003587static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003588 const QCBORItem *pItem,
3589 uint8_t uTagRequirement,
3590 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003591{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003592 if(pBstr) {
3593 *pBstr = NULLUsefulBufC;
3594 }
3595
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003596 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003597 /* Already in error state; do nothing. */
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003598 return pMe->uLastError;
3599 }
3600
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003601 QCBORError uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003602
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003603 const TagSpecification TagSpec =
3604 {
3605 uTagRequirement,
3606 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3607 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3608 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003609
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003610 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003611 if(uError != QCBOR_SUCCESS) {
3612 goto Done;
3613 }
3614
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003615 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003616 /* Reverse the decrement done by GetNext() for the bstr so the
3617 * increment in QCBORDecode_NestLevelAscender() called by
3618 * ExitBoundedLevel() will work right.
3619 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003620 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003621 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003622
3623 if(pBstr) {
3624 *pBstr = pItem->val.string;
3625 }
3626
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003627 /* This saves the current length of the UsefulInputBuf and then
3628 * narrows the UsefulInputBuf to start and length of the wrapped
3629 * CBOR that is being entered.
3630 *
3631 * Most of these calls are simple inline accessors so this doesn't
3632 * amount to much code.
3633 */
3634
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003635 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003636 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
3637 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003638 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003639 goto Done;
3640 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003641
3642 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
3643 pItem->val.string.ptr);
3644 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
3645 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
3646 /* This should never happen because pItem->val.string.ptr should
3647 * always be valid since it was just returned.
3648 */
3649 uError = QCBOR_ERR_INPUT_TOO_LARGE;
3650 goto Done;
3651 }
3652
3653 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
3654
3655 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003656 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003657
Laurence Lundblade02625d42020-06-25 14:41:41 -07003658 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003659 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003660 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003661Done:
3662 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003663}
3664
3665
Laurence Lundblade02625d42020-06-25 14:41:41 -07003666/*
3667 Public function, see header qcbor/qcbor_decode.h file
3668 */
3669void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003670 uint8_t uTagRequirement,
3671 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003672{
3673 if(pMe->uLastError != QCBOR_SUCCESS) {
3674 // Already in error state; do nothing.
3675 return;
3676 }
3677
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003678 /* Get the data item that is the byte string being entered */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003679 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003680 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3681 if(pMe->uLastError != QCBOR_SUCCESS) {
3682 return;
3683 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003684
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003685 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003686 &Item,
3687 uTagRequirement,
3688 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003689}
3690
3691
Laurence Lundblade02625d42020-06-25 14:41:41 -07003692/*
3693 Public function, see header qcbor/qcbor_decode.h file
3694 */
3695void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003696 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003697 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003698 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003699{
3700 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003701 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003702
Laurence Lundblade93d89472020-10-03 22:30:50 -07003703 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3704 &Item,
3705 uTagRequirement,
3706 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003707}
3708
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003709
Laurence Lundblade02625d42020-06-25 14:41:41 -07003710/*
3711 Public function, see header qcbor/qcbor_decode.h file
3712 */
3713void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003714 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003715 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003716 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003717{
3718 QCBORItem Item;
3719 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3720
Laurence Lundblade93d89472020-10-03 22:30:50 -07003721 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3722 &Item,
3723 uTagRequirement,
3724 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003725}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003726
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003727
Laurence Lundblade02625d42020-06-25 14:41:41 -07003728/*
3729 Public function, see header qcbor/qcbor_decode.h file
3730 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003731void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003732{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003733 if(pMe->uLastError != QCBOR_SUCCESS) {
3734 // Already in error state; do nothing.
3735 return;
3736 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003737
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003738 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003739 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003740 return;
3741 }
3742
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003743 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3744
Laurence Lundblade02625d42020-06-25 14:41:41 -07003745 /*
3746 Reset the length of the UsefulInputBuf to what it was before
3747 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003748 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003749 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003750 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003751
3752
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003753 QCBORError uErr = ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003754 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003755}
3756
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003757
Laurence Lundbladee6430642020-03-14 21:15:44 -07003758
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003759
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003760static inline void
3761ProcessBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003762{
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003763 if(pMe->uLastError != QCBOR_SUCCESS) {
3764 /* Already in error state, do nothing */
3765 return;
3766 }
3767
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003768 switch(pItem->uDataType) {
3769 case QCBOR_TYPE_TRUE:
3770 *pBool = true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003771 break;
3772
3773 case QCBOR_TYPE_FALSE:
3774 *pBool = false;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003775 break;
3776
3777 default:
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003778 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003779 break;
3780 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003781 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003782}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003783
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003784
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003785/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003786 * Public function, see header qcbor/qcbor_decode.h file
3787 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003788void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003789{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003790 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003791 /* Already in error state, do nothing */
Laurence Lundbladee6430642020-03-14 21:15:44 -07003792 return;
3793 }
3794
Laurence Lundbladec4537442020-04-14 18:53:22 -07003795 QCBORItem Item;
3796
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003797 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3798
3799 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003800}
3801
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003802
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003803/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003804 * Public function, see header qcbor/qcbor_decode.h file
3805 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003806void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003807{
3808 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003809 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003810
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003811 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003812}
3813
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003814
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003815/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003816 * Public function, see header qcbor/qcbor_decode.h file
3817 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003818void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3819{
3820 QCBORItem Item;
3821 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3822
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003823 ProcessBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003824}
3825
3826
3827
Laurence Lundbladec7114722020-08-13 05:11:40 -07003828
3829static void ProcessEpochDate(QCBORDecodeContext *pMe,
3830 QCBORItem *pItem,
3831 uint8_t uTagRequirement,
3832 int64_t *pnTime)
3833{
3834 if(pMe->uLastError != QCBOR_SUCCESS) {
3835 // Already in error state, do nothing
3836 return;
3837 }
3838
3839 QCBORError uErr;
3840
3841 const TagSpecification TagSpec =
3842 {
3843 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003844 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3845 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003846 };
3847
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003848 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003849 if(uErr != QCBOR_SUCCESS) {
3850 goto Done;
3851 }
3852
3853 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3854 uErr = DecodeDateEpoch(pItem);
3855 if(uErr != QCBOR_SUCCESS) {
3856 goto Done;
3857 }
3858 }
3859
Laurence Lundblade9b334962020-08-27 10:55:53 -07003860 // Save the tags in the last item's tags in the decode context
3861 // for QCBORDecode_GetNthTagOfLast()
3862 CopyTags(pMe, pItem);
3863
Laurence Lundbladec7114722020-08-13 05:11:40 -07003864 *pnTime = pItem->val.epochDate.nSeconds;
3865
3866Done:
3867 pMe->uLastError = (uint8_t)uErr;
3868}
3869
3870
3871void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003872 uint8_t uTagRequirement,
3873 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003874{
3875 if(pMe->uLastError != QCBOR_SUCCESS) {
3876 // Already in error state, do nothing
3877 return;
3878 }
3879
3880 QCBORItem Item;
3881 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3882
3883 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3884}
3885
3886
3887void
3888QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3889 int64_t nLabel,
3890 uint8_t uTagRequirement,
3891 int64_t *pnTime)
3892{
3893 QCBORItem Item;
3894 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3895 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3896}
3897
3898
3899void
3900QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3901 const char *szLabel,
3902 uint8_t uTagRequirement,
3903 int64_t *pnTime)
3904{
3905 QCBORItem Item;
3906 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3907 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3908}
3909
3910
3911
Laurence Lundblade46d63e92021-05-13 11:37:10 -07003912/*
3913 * Common processing for the RFC 8943 day-count tag. Mostly
3914 * make sure the tag content is correct and copy forward any
3915 * further other tag numbers.
3916 */
3917static void ProcessEpochDays(QCBORDecodeContext *pMe,
3918 QCBORItem *pItem,
3919 uint8_t uTagRequirement,
3920 int64_t *pnDays)
3921{
3922 if(pMe->uLastError != QCBOR_SUCCESS) {
3923 /* Already in error state, do nothing */
3924 return;
3925 }
3926
3927 QCBORError uErr;
3928
3929 const TagSpecification TagSpec =
3930 {
3931 uTagRequirement,
3932 {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3933 {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3934 };
3935
3936 uErr = CheckTagRequirement(TagSpec, pItem);
3937 if(uErr != QCBOR_SUCCESS) {
3938 goto Done;
3939 }
3940
3941 if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
3942 uErr = DecodeDaysEpoch(pItem);
3943 if(uErr != QCBOR_SUCCESS) {
3944 goto Done;
3945 }
3946 }
3947
3948 /* Save the tags in the last item's tags in the decode context
3949 * for QCBORDecode_GetNthTagOfLast()
3950 */
3951 CopyTags(pMe, pItem);
3952
3953 *pnDays = pItem->val.epochDays;
3954
3955Done:
3956 pMe->uLastError = (uint8_t)uErr;
3957}
3958
3959
3960/*
3961 * Public function, see header qcbor/qcbor_decode.h
3962 */
3963void QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
3964 uint8_t uTagRequirement,
3965 int64_t *pnDays)
3966{
3967 if(pMe->uLastError != QCBOR_SUCCESS) {
3968 /* Already in error state, do nothing */
3969 return;
3970 }
3971
3972 QCBORItem Item;
3973 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3974
3975 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
3976}
3977
3978
3979/*
3980 * Public function, see header qcbor/qcbor_decode.h
3981 */
3982void
3983QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
3984 int64_t nLabel,
3985 uint8_t uTagRequirement,
3986 int64_t *pnDays)
3987{
3988 QCBORItem Item;
3989 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3990 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
3991}
3992
3993
3994/*
3995 * Public function, see header qcbor/qcbor_decode.h
3996 */
3997void
3998QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
3999 const char *szLabel,
4000 uint8_t uTagRequirement,
4001 int64_t *pnDays)
4002{
4003 QCBORItem Item;
4004 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4005 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4006}
4007
4008
4009
Laurence Lundbladec7114722020-08-13 05:11:40 -07004010
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004011void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
4012 TagSpecification TagSpec,
4013 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004014{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004015 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004016 // Already in error state, do nothing
4017 return;
4018 }
4019
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004020 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004021 QCBORItem Item;
4022
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004023 uError = QCBORDecode_GetNext(pMe, &Item);
4024 if(uError != QCBOR_SUCCESS) {
4025 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004026 return;
4027 }
4028
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004029 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004030
4031 if(pMe->uLastError == QCBOR_SUCCESS) {
4032 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07004033 } else {
4034 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004035 }
4036}
4037
Laurence Lundbladec4537442020-04-14 18:53:22 -07004038
4039
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004040
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004041static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004042 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004043 UsefulBufC *pValue,
4044 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004045{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004046 const TagSpecification TagSpec =
4047 {
4048 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004049 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4050 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004051 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004052
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004053 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004054 if(uErr != QCBOR_SUCCESS) {
4055 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004056 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004057
4058 *pValue = pItem->val.string;
4059
4060 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
4061 *pbIsNegative = false;
4062 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
4063 *pbIsNegative = true;
4064 }
4065
4066 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004067}
4068
4069
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004070/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004071 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004072 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004073void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
4074 uint8_t uTagRequirement,
4075 UsefulBufC *pValue,
4076 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004077{
4078 if(pMe->uLastError != QCBOR_SUCCESS) {
4079 // Already in error state, do nothing
4080 return;
4081 }
4082
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004083 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004084 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4085 if(uError != QCBOR_SUCCESS) {
4086 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004087 return;
4088 }
4089
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004090 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004091}
4092
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004093
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004094/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004095 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004096*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004097void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
4098 int64_t nLabel,
4099 uint8_t uTagRequirement,
4100 UsefulBufC *pValue,
4101 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004102{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004103 QCBORItem Item;
4104 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004105 if(pMe->uLastError != QCBOR_SUCCESS) {
4106 return;
4107 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004108
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004109 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004110}
4111
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004112
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004113/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004114 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004115*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004116void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
4117 const char *szLabel,
4118 uint8_t uTagRequirement,
4119 UsefulBufC *pValue,
4120 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004121{
4122 QCBORItem Item;
4123 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004124 if(pMe->uLastError != QCBOR_SUCCESS) {
4125 return;
4126 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004127
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004128 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004129}
4130
4131
4132
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004133
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004134// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004135QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
4136 const QCBORItem *pItem,
4137 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07004138 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004139{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004140 const TagSpecification TagSpecText =
4141 {
4142 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004143 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4144 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004145 };
4146 const TagSpecification TagSpecBinary =
4147 {
4148 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004149 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4150 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004151 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004152
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004153 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004154
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004155 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004156 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004157 if(pbIsTag257 != NULL) {
4158 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004159 }
4160 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004161 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004162 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004163 if(pbIsTag257 != NULL) {
4164 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004165 }
4166 uReturn = QCBOR_SUCCESS;
4167
4168 } else {
4169 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
4170 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07004171
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004172 return uReturn;
4173}
4174
Laurence Lundblade93d89472020-10-03 22:30:50 -07004175// Improvement: add methods for wrapped CBOR, a simple alternate
4176// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004177
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004178
4179
4180
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004181#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07004182
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004183typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004184
4185
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004186// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07004187static QCBORError
4188Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004189{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004190 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004191
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004192 if(uResult != 0) {
4193 /* This loop will run a maximum of 19 times because
4194 * UINT64_MAX < 10 ^^ 19. More than that will cause
4195 * exit with the overflow error
4196 */
4197 for(; nExponent > 0; nExponent--) {
4198 if(uResult > UINT64_MAX / 10) {
4199 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
4200 }
4201 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004202 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004203
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004204 for(; nExponent < 0; nExponent++) {
4205 uResult = uResult / 10;
4206 if(uResult == 0) {
4207 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
4208 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004209 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004210 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004211 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004212
4213 *puResult = uResult;
4214
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004215 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004216}
4217
4218
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004219// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07004220static QCBORError
4221Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004222{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004223 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004224
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004225 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004226
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004227 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07004228 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004229 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07004230 */
4231 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004232 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004233 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07004234 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004235 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004236 nExponent--;
4237 }
4238
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004239 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004240 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004241 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
4242 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004243 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004244 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004245 }
4246
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004247 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004248
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004249 return QCBOR_SUCCESS;
4250}
4251
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004252
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004253/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004254 Compute value with signed mantissa and signed result. Works with
4255 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004256 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004257static inline QCBORError ExponentiateNN(int64_t nMantissa,
4258 int64_t nExponent,
4259 int64_t *pnResult,
4260 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004261{
4262 uint64_t uResult;
4263
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004264 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004265 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004266 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
4267
4268 // Do the exponentiation of the positive mantissa
4269 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4270 if(uReturn) {
4271 return uReturn;
4272 }
4273
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004274
Laurence Lundblade983500d2020-05-14 11:49:34 -07004275 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4276 of INT64_MIN. This assumes two's compliment representation where
4277 INT64_MIN is one increment farther from 0 than INT64_MAX.
4278 Trying to write -INT64_MIN doesn't work to get this because the
4279 compiler tries to work with an int64_t which can't represent
4280 -INT64_MIN.
4281 */
4282 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
4283
4284 // Error out if too large
4285 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004286 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4287 }
4288
4289 // Casts are safe because of checks above
4290 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
4291
4292 return QCBOR_SUCCESS;
4293}
4294
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004295
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004296/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004297 Compute value with signed mantissa and unsigned result. Works with
4298 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004299 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004300static inline QCBORError ExponentitateNU(int64_t nMantissa,
4301 int64_t nExponent,
4302 uint64_t *puResult,
4303 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004304{
4305 if(nMantissa < 0) {
4306 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4307 }
4308
4309 // Cast to unsigned is OK because of check for negative
4310 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
4311 // Exponentiation is straight forward
4312 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4313}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004314
4315
4316/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004317 Compute value with signed mantissa and unsigned result. Works with
4318 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004319 */
4320static inline QCBORError ExponentitateUU(uint64_t uMantissa,
4321 int64_t nExponent,
4322 uint64_t *puResult,
4323 fExponentiator pfExp)
4324{
4325 return (*pfExp)(uMantissa, nExponent, puResult);
4326}
4327
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004328#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004329
4330
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004331
4332
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004333
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004334static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004335{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004336 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004337
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004338 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004339 const uint8_t *pByte = BigNum.ptr;
4340 size_t uLen = BigNum.len;
4341 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004342 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004343 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004344 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004345 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004346 }
4347
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004348 *pResult = uResult;
4349 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004350}
4351
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004352
Laurence Lundblade887add82020-05-17 05:50:34 -07004353static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004354{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004355 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004356}
4357
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004358
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004359static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004360{
4361 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004362 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
4363 if(uError) {
4364 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004365 }
4366 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
4367 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004368 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004369}
4370
4371
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004372static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004373{
4374 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004375 /* The negative integer furthest from zero for a C int64_t is
4376 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4377 negative number in CBOR is computed as -n - 1 where n is the
4378 encoded integer, where n is what is in the variable BigNum. When
4379 converting BigNum to a uint64_t, the maximum value is thus
4380 INT64_MAX, so that when it -n - 1 is applied to it the result will
4381 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07004382
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004383 -n - 1 <= INT64_MIN.
4384 -n - 1 <= -INT64_MAX - 1
4385 n <= INT64_MAX.
4386 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004387 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004388 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004389 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004390 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004391
4392 /// Now apply -n - 1. The cast is safe because
4393 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4394 // is the largest positive integer that an int64_t can
4395 // represent. */
4396 *pnResult = -(int64_t)uResult - 1;
4397
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004398 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004399}
4400
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004401
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004402
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004403
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004404
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004405/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004406Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004407
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004408\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004409
Laurence Lundblade93d89472020-10-03 22:30:50 -07004410\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4411 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004412
4413\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4414
Laurence Lundblade93d89472020-10-03 22:30:50 -07004415\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4416 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004417*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004418static QCBORError
4419ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004420{
4421 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004422 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004423 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004424#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004425 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004426 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4427 http://www.cplusplus.com/reference/cmath/llround/
4428 */
4429 // Not interested in FE_INEXACT
4430 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004431 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4432 *pnValue = llround(pItem->val.dfnum);
4433 } else {
4434 *pnValue = lroundf(pItem->val.fnum);
4435 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004436 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4437 // llround() shouldn't result in divide by zero, but catch
4438 // it here in case it unexpectedly does. Don't try to
4439 // distinguish between the various exceptions because it seems
4440 // they vary by CPU, compiler and OS.
4441 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004442 }
4443 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004444 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004445 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004446#else
4447 return QCBOR_ERR_HW_FLOAT_DISABLED;
4448#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004449 break;
4450
4451 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004452 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004453 *pnValue = pItem->val.int64;
4454 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004455 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004456 }
4457 break;
4458
4459 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004460 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004461 if(pItem->val.uint64 < INT64_MAX) {
4462 *pnValue = pItem->val.int64;
4463 } else {
4464 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4465 }
4466 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004467 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004468 }
4469 break;
4470
4471 default:
4472 return QCBOR_ERR_UNEXPECTED_TYPE;
4473 }
4474 return QCBOR_SUCCESS;
4475}
4476
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004477
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004478void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004479 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004480 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004481 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004482{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004483 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004484 return;
4485 }
4486
Laurence Lundbladee6430642020-03-14 21:15:44 -07004487 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004488 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4489 if(uError) {
4490 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004491 return;
4492 }
4493
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004494 if(pItem) {
4495 *pItem = Item;
4496 }
4497
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004498 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004499}
4500
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004501
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004502void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4503 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004504 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004505 int64_t *pnValue,
4506 QCBORItem *pItem)
4507{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004508 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004509 if(pMe->uLastError != QCBOR_SUCCESS) {
4510 return;
4511 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004512
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004513 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004514}
4515
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004516
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004517void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4518 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004519 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004520 int64_t *pnValue,
4521 QCBORItem *pItem)
4522{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004523 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004524 if(pMe->uLastError != QCBOR_SUCCESS) {
4525 return;
4526 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004527
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004528 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004529}
4530
4531
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004532/*
4533 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004534
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004535 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004536
Laurence Lundblade93d89472020-10-03 22:30:50 -07004537 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4538 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004539
4540 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4541
Laurence Lundblade93d89472020-10-03 22:30:50 -07004542 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4543 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004544 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004545static QCBORError
4546Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004547{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004548 switch(pItem->uDataType) {
4549
4550 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004551 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004552 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004553 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004554 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004555 }
4556 break;
4557
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004558 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004559 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004560 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004561 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004562 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004563 }
4564 break;
4565
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004566#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004567 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004568 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004569 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004570 pItem->val.expAndMantissa.nExponent,
4571 pnValue,
4572 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004573 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004574 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004575 }
4576 break;
4577
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004578 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004579 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004580 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004581 pItem->val.expAndMantissa.nExponent,
4582 pnValue,
4583 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004584 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004585 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004586 }
4587 break;
4588
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004589 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004590 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004591 int64_t nMantissa;
4592 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004593 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4594 if(uErr) {
4595 return uErr;
4596 }
4597 return ExponentiateNN(nMantissa,
4598 pItem->val.expAndMantissa.nExponent,
4599 pnValue,
4600 Exponentitate10);
4601 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004602 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004603 }
4604 break;
4605
4606 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004607 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004608 int64_t nMantissa;
4609 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004610 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4611 if(uErr) {
4612 return uErr;
4613 }
4614 return ExponentiateNN(nMantissa,
4615 pItem->val.expAndMantissa.nExponent,
4616 pnValue,
4617 Exponentitate10);
4618 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004619 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004620 }
4621 break;
4622
4623 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004624 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004625 int64_t nMantissa;
4626 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004627 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4628 if(uErr) {
4629 return uErr;
4630 }
4631 return ExponentiateNN(nMantissa,
4632 pItem->val.expAndMantissa.nExponent,
4633 pnValue,
4634 Exponentitate2);
4635 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004636 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004637 }
4638 break;
4639
4640 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004641 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004642 int64_t nMantissa;
4643 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004644 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4645 if(uErr) {
4646 return uErr;
4647 }
4648 return ExponentiateNN(nMantissa,
4649 pItem->val.expAndMantissa.nExponent,
4650 pnValue,
4651 Exponentitate2);
4652 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004653 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004654 }
4655 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004656#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004657
Laurence Lundbladee6430642020-03-14 21:15:44 -07004658
Laurence Lundbladec4537442020-04-14 18:53:22 -07004659 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004660 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004661}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004662
4663
Laurence Lundbladec4537442020-04-14 18:53:22 -07004664/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004665 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004666 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004667void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004668{
4669 QCBORItem Item;
4670
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004671 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004672
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004673 if(pMe->uLastError == QCBOR_SUCCESS) {
4674 // The above conversion succeeded
4675 return;
4676 }
4677
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004678 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004679 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004680 return;
4681 }
4682
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004683 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004684}
4685
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004686
4687/*
4688Public function, see header qcbor/qcbor_decode.h file
4689*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004690void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4691 int64_t nLabel,
4692 uint32_t uConvertTypes,
4693 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004694{
4695 QCBORItem Item;
4696
Laurence Lundblade93d89472020-10-03 22:30:50 -07004697 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4698 nLabel,
4699 uConvertTypes,
4700 pnValue,
4701 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004702
4703 if(pMe->uLastError == QCBOR_SUCCESS) {
4704 // The above conversion succeeded
4705 return;
4706 }
4707
4708 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4709 // The above conversion failed in a way that code below can't correct
4710 return;
4711 }
4712
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004713 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004714}
4715
4716
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004717/*
4718Public function, see header qcbor/qcbor_decode.h file
4719*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004720void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4721 const char *szLabel,
4722 uint32_t uConvertTypes,
4723 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004724{
4725 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004726 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4727 szLabel,
4728 uConvertTypes,
4729 pnValue,
4730 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004731
4732 if(pMe->uLastError == QCBOR_SUCCESS) {
4733 // The above conversion succeeded
4734 return;
4735 }
4736
4737 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4738 // The above conversion failed in a way that code below can't correct
4739 return;
4740 }
4741
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004742 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004743}
4744
4745
Laurence Lundblade93d89472020-10-03 22:30:50 -07004746static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004747{
4748 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004749 case QCBOR_TYPE_DOUBLE:
4750 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004751#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004752 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004753 // Can't use llround here because it will not convert values
4754 // greater than INT64_MAX and less than UINT64_MAX that
4755 // need to be converted so it is more complicated.
4756 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4757 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4758 if(isnan(pItem->val.dfnum)) {
4759 return QCBOR_ERR_FLOAT_EXCEPTION;
4760 } else if(pItem->val.dfnum < 0) {
4761 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4762 } else {
4763 double dRounded = round(pItem->val.dfnum);
4764 // See discussion in DecodeDateEpoch() for
4765 // explanation of - 0x7ff
4766 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4767 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4768 }
4769 *puValue = (uint64_t)dRounded;
4770 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004771 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004772 if(isnan(pItem->val.fnum)) {
4773 return QCBOR_ERR_FLOAT_EXCEPTION;
4774 } else if(pItem->val.fnum < 0) {
4775 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4776 } else {
4777 float fRounded = roundf(pItem->val.fnum);
4778 // See discussion in DecodeDateEpoch() for
4779 // explanation of - 0x7ff
4780 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4781 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4782 }
4783 *puValue = (uint64_t)fRounded;
4784 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004785 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004786 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4787 // round() and roundf() shouldn't result in exceptions here, but
4788 // catch them to be robust and thorough. Don't try to
4789 // distinguish between the various exceptions because it seems
4790 // they vary by CPU, compiler and OS.
4791 return QCBOR_ERR_FLOAT_EXCEPTION;
4792 }
4793
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004794 } else {
4795 return QCBOR_ERR_UNEXPECTED_TYPE;
4796 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004797#else
4798 return QCBOR_ERR_HW_FLOAT_DISABLED;
4799#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004800 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004801
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004802 case QCBOR_TYPE_INT64:
4803 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4804 if(pItem->val.int64 >= 0) {
4805 *puValue = (uint64_t)pItem->val.int64;
4806 } else {
4807 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4808 }
4809 } else {
4810 return QCBOR_ERR_UNEXPECTED_TYPE;
4811 }
4812 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004813
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004814 case QCBOR_TYPE_UINT64:
4815 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4816 *puValue = pItem->val.uint64;
4817 } else {
4818 return QCBOR_ERR_UNEXPECTED_TYPE;
4819 }
4820 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004821
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004822 default:
4823 return QCBOR_ERR_UNEXPECTED_TYPE;
4824 }
4825
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004826 return QCBOR_SUCCESS;
4827}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004828
4829
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004830void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004831 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004832 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004833 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004834{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004835 if(pMe->uLastError != QCBOR_SUCCESS) {
4836 return;
4837 }
4838
Laurence Lundbladec4537442020-04-14 18:53:22 -07004839 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004840
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004841 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4842 if(uError) {
4843 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004844 return;
4845 }
4846
Laurence Lundbladea826c502020-05-10 21:07:00 -07004847 if(pItem) {
4848 *pItem = Item;
4849 }
4850
Laurence Lundblade93d89472020-10-03 22:30:50 -07004851 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004852}
4853
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004854
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004855void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004856 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004857 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004858 uint64_t *puValue,
4859 QCBORItem *pItem)
4860{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004861 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004862 if(pMe->uLastError != QCBOR_SUCCESS) {
4863 return;
4864 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004865
Laurence Lundblade93d89472020-10-03 22:30:50 -07004866 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004867}
4868
4869
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004870void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004871 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004872 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004873 uint64_t *puValue,
4874 QCBORItem *pItem)
4875{
4876 if(pMe->uLastError != QCBOR_SUCCESS) {
4877 return;
4878 }
4879
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004880 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004881 if(pMe->uLastError != QCBOR_SUCCESS) {
4882 return;
4883 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004884
Laurence Lundblade93d89472020-10-03 22:30:50 -07004885 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004886}
4887
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004888
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004889
Laurence Lundblade93d89472020-10-03 22:30:50 -07004890static QCBORError
4891UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004892{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004893 switch(pItem->uDataType) {
4894
4895 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004896 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004897 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4898 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004899 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004900 }
4901 break;
4902
4903 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004904 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004905 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4906 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004907 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004908 }
4909 break;
4910
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004911#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004912
4913 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004914 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004915 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004916 pItem->val.expAndMantissa.nExponent,
4917 puValue,
4918 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004919 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004920 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004921 }
4922 break;
4923
4924 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004925 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004926 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4927 pItem->val.expAndMantissa.nExponent,
4928 puValue,
4929 Exponentitate2);
4930 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004931 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004932 }
4933 break;
4934
4935 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004936 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004937 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004938 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004939 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004940 if(uErr != QCBOR_SUCCESS) {
4941 return uErr;
4942 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004943 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004944 pItem->val.expAndMantissa.nExponent,
4945 puValue,
4946 Exponentitate10);
4947 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004948 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004949 }
4950 break;
4951
4952 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004953 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004954 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4955 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004956 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004957 }
4958 break;
4959
4960 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004961 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004962 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004963 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004964 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004965 if(uErr != QCBOR_SUCCESS) {
4966 return uErr;
4967 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004968 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004969 pItem->val.expAndMantissa.nExponent,
4970 puValue,
4971 Exponentitate2);
4972 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004973 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004974 }
4975 break;
4976
4977 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004978 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004979 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4980 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004981 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004982 }
4983 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004984#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004985 default:
4986 return QCBOR_ERR_UNEXPECTED_TYPE;
4987 }
4988}
4989
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004990
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004991/*
4992 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004993 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004994void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004995{
4996 QCBORItem Item;
4997
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004998 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004999
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005000 if(pMe->uLastError == QCBOR_SUCCESS) {
5001 // The above conversion succeeded
5002 return;
5003 }
5004
5005 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5006 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07005007 return;
5008 }
5009
Laurence Lundblade93d89472020-10-03 22:30:50 -07005010 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005011}
5012
Laurence Lundbladec4537442020-04-14 18:53:22 -07005013
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005014/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005015 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005016*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005017void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07005018 int64_t nLabel,
5019 uint32_t uConvertTypes,
5020 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005021{
5022 QCBORItem Item;
5023
Laurence Lundblade93d89472020-10-03 22:30:50 -07005024 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
5025 nLabel,
5026 uConvertTypes,
5027 puValue,
5028 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005029
5030 if(pMe->uLastError == QCBOR_SUCCESS) {
5031 // The above conversion succeeded
5032 return;
5033 }
5034
5035 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5036 // The above conversion failed in a way that code below can't correct
5037 return;
5038 }
5039
Laurence Lundblade93d89472020-10-03 22:30:50 -07005040 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005041}
5042
5043
5044/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005045 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005046*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005047void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07005048 const char *szLabel,
5049 uint32_t uConvertTypes,
5050 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005051{
5052 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07005053 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
5054 szLabel,
5055 uConvertTypes,
5056 puValue,
5057 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005058
5059 if(pMe->uLastError == QCBOR_SUCCESS) {
5060 // The above conversion succeeded
5061 return;
5062 }
5063
5064 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5065 // The above conversion failed in a way that code below can't correct
5066 return;
5067 }
5068
Laurence Lundblade93d89472020-10-03 22:30:50 -07005069 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005070}
5071
5072
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005073
5074
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005075#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade9b334962020-08-27 10:55:53 -07005076static QCBORError ConvertDouble(const QCBORItem *pItem,
5077 uint32_t uConvertTypes,
5078 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005079{
5080 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005081 case QCBOR_TYPE_FLOAT:
5082#ifndef QCBOR_DISABLE_FLOAT_HW_USE
5083 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5084 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005085 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005086 *pdValue = (double)pItem->val.fnum;
5087 } else {
5088 return QCBOR_ERR_UNEXPECTED_TYPE;
5089 }
5090 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005091#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005092 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005093#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005094 break;
5095
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005096 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005097 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5098 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005099 *pdValue = pItem->val.dfnum;
5100 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005101 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005102 }
5103 }
5104 break;
5105
5106 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005107#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005108 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005109 // A simple cast seems to do the job with no worry of exceptions.
5110 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005111 *pdValue = (double)pItem->val.int64;
5112
5113 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005114 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005115 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005116#else
5117 return QCBOR_ERR_HW_FLOAT_DISABLED;
5118#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005119 break;
5120
5121 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005122#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005123 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005124 // A simple cast seems to do the job with no worry of exceptions.
5125 // There will be precision loss for some values.
5126 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005127 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005128 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005129 }
5130 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005131#else
5132 return QCBOR_ERR_HW_FLOAT_DISABLED;
5133#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005134
5135 default:
5136 return QCBOR_ERR_UNEXPECTED_TYPE;
5137 }
5138
5139 return QCBOR_SUCCESS;
5140}
5141
5142
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005143void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005144 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005145 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005146 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005147{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005148 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005149 return;
5150 }
5151
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005152 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005153
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005154 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005155 if(uError) {
5156 pMe->uLastError = (uint8_t)uError;
5157 return;
5158 }
5159
5160 if(pItem) {
5161 *pItem = Item;
5162 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005163
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005164 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005165}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005166
Laurence Lundbladec4537442020-04-14 18:53:22 -07005167
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005168void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
5169 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005170 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005171 double *pdValue,
5172 QCBORItem *pItem)
5173{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005174 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005175 if(pMe->uLastError != QCBOR_SUCCESS) {
5176 return;
5177 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005178
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005179 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005180}
5181
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005182
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005183void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
5184 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005185 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005186 double *pdValue,
5187 QCBORItem *pItem)
5188{
5189 if(pMe->uLastError != QCBOR_SUCCESS) {
5190 return;
5191 }
5192
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005193 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005194 if(pMe->uLastError != QCBOR_SUCCESS) {
5195 return;
5196 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005197
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005198 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005199}
5200
5201
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005202#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005203static double ConvertBigNumToDouble(const UsefulBufC BigNum)
5204{
5205 double dResult;
5206
5207 dResult = 0.0;
5208 const uint8_t *pByte = BigNum.ptr;
5209 size_t uLen = BigNum.len;
5210 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07005211 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005212 while(uLen--) {
5213 dResult = (dResult * 256.0) + (double)*pByte++;
5214 }
5215
5216 return dResult;
5217}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005218#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5219
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005220
Laurence Lundblade93d89472020-10-03 22:30:50 -07005221static QCBORError
5222DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005223{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005224#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005225 /*
Laurence Lundblade16a207a2021-09-18 17:22:46 -07005226 * What Every Computer Scientist Should Know About Floating-Point Arithmetic
5227 * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
5228 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005229 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005230
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005231#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005232 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005233 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005234 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005235 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5236 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
5237 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005238 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005239 }
5240 break;
5241
5242 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005243 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005244 // Underflow gives 0, overflow gives infinity
5245 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5246 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005247 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005248 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005249 }
5250 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005251#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005252
5253 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005254 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005255 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
5256 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005257 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005258 }
5259 break;
5260
5261 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005262 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005263 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005264 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005265 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005266 }
5267 break;
5268
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005269#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005270 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005271 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005272 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5273 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5274 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005275 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005276 }
5277 break;
5278
5279 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005280 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005281 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5282 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5283 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005284 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005285 }
5286 break;
5287
5288 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005289 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005290 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5291 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5292 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005293 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005294 }
5295 break;
5296
5297 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005298 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005299 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005300 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5301 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005302 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005303 }
5304 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005305#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005306
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005307 default:
5308 return QCBOR_ERR_UNEXPECTED_TYPE;
5309 }
5310
5311 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005312
5313#else
5314 (void)pItem;
5315 (void)uConvertTypes;
5316 (void)pdValue;
5317 return QCBOR_ERR_HW_FLOAT_DISABLED;
5318#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5319
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005320}
5321
5322
5323/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005324 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005325*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005326void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
5327 uint32_t uConvertTypes,
5328 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005329{
5330
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005331 QCBORItem Item;
5332
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005333 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005334
5335 if(pMe->uLastError == QCBOR_SUCCESS) {
5336 // The above conversion succeeded
5337 return;
5338 }
5339
5340 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5341 // The above conversion failed in a way that code below can't correct
5342 return;
5343 }
5344
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005345 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005346}
5347
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005348
5349/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005350 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005351*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005352void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5353 int64_t nLabel,
5354 uint32_t uConvertTypes,
5355 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005356{
5357 QCBORItem Item;
5358
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005359 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005360
5361 if(pMe->uLastError == QCBOR_SUCCESS) {
5362 // The above conversion succeeded
5363 return;
5364 }
5365
5366 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5367 // The above conversion failed in a way that code below can't correct
5368 return;
5369 }
5370
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005371 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005372}
5373
5374
5375/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005376 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005377*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005378void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5379 const char *szLabel,
5380 uint32_t uConvertTypes,
5381 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005382{
5383 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005384 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005385
5386 if(pMe->uLastError == QCBOR_SUCCESS) {
5387 // The above conversion succeeded
5388 return;
5389 }
5390
5391 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5392 // The above conversion failed in a way that code below can't correct
5393 return;
5394 }
5395
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005396 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005397}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005398#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005399
5400
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005401
5402
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005403#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005404static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5405{
5406 while((uInt & 0xff00000000000000UL) == 0) {
5407 uInt = uInt << 8;
5408 };
5409
5410 UsefulOutBuf UOB;
5411
5412 UsefulOutBuf_Init(&UOB, Buffer);
5413
5414 while(uInt) {
5415 const uint64_t xx = uInt & 0xff00000000000000UL;
5416 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5417 uInt = uInt << 8;
5418 (void)xx;
5419 }
5420
5421 return UsefulOutBuf_OutUBuf(&UOB);
5422}
5423
5424
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005425static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5426 TagSpecification TagSpec,
5427 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005428{
5429 QCBORError uErr;
5430 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005431 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005432 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005433 if(uErr != QCBOR_SUCCESS) {
5434 goto Done;
5435 }
5436
5437 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5438 break; // Successful exit. Moving on to finish decoding.
5439 }
5440
5441 // The item is an array, which means an undecoded
5442 // mantissa and exponent, so decode it. It will then
5443 // have a different type and exit the loop if.
5444 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5445 if(uErr != QCBOR_SUCCESS) {
5446 goto Done;
5447 }
5448
5449 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005450 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005451 }
5452Done:
5453 return uErr;
5454}
5455
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005456
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005457static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005458 TagSpecification TagSpec,
5459 QCBORItem *pItem,
5460 int64_t *pnMantissa,
5461 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005462{
5463 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005464
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005465 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005466 if(uErr != QCBOR_SUCCESS) {
5467 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005468 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005469
Laurence Lundblade9b334962020-08-27 10:55:53 -07005470 switch (pItem->uDataType) {
5471
5472 case QCBOR_TYPE_DECIMAL_FRACTION:
5473 case QCBOR_TYPE_BIGFLOAT:
5474 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5475 *pnExponent = pItem->val.expAndMantissa.nExponent;
5476 break;
5477
5478 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5479 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5480 *pnExponent = pItem->val.expAndMantissa.nExponent;
5481 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5482 break;
5483
5484 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5485 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5486 *pnExponent = pItem->val.expAndMantissa.nExponent;
5487 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5488 break;
5489
5490 default:
5491 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5492 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005493
5494 Done:
5495 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005496}
5497
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005498
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005499static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005500 TagSpecification TagSpec,
5501 QCBORItem *pItem,
5502 UsefulBuf BufferForMantissa,
5503 UsefulBufC *pMantissa,
5504 bool *pbIsNegative,
5505 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005506{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005507 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005508
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005509 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005510 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005511 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005512 }
5513
5514 uint64_t uMantissa;
5515
5516 switch (pItem->uDataType) {
5517
5518 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005519 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005520 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5521 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5522 *pbIsNegative = false;
5523 } else {
5524 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5525 *pbIsNegative = true;
5526 }
5527 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5528 *pnExponent = pItem->val.expAndMantissa.nExponent;
5529 break;
5530
5531 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005532 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005533 *pnExponent = pItem->val.expAndMantissa.nExponent;
5534 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5535 *pbIsNegative = false;
5536 break;
5537
5538 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005539 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005540 *pnExponent = pItem->val.expAndMantissa.nExponent;
5541 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5542 *pbIsNegative = true;
5543 break;
5544
5545 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005546 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005547 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005548
5549Done:
5550 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005551}
5552
5553
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005554/*
5555 Public function, see header qcbor/qcbor_decode.h file
5556*/
5557void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5558 uint8_t uTagRequirement,
5559 int64_t *pnMantissa,
5560 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005561{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005562 if(pMe->uLastError != QCBOR_SUCCESS) {
5563 return;
5564 }
5565
5566 QCBORItem Item;
5567 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5568 if(uError) {
5569 pMe->uLastError = (uint8_t)uError;
5570 return;
5571 }
5572
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005573 const TagSpecification TagSpec =
5574 {
5575 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005576 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5577 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5578 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005579 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005580
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005581 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005582}
5583
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005584
5585/*
5586 Public function, see header qcbor/qcbor_decode.h file
5587*/
5588void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005589 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005590 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005591 int64_t *pnMantissa,
5592 int64_t *pnExponent)
5593{
5594 if(pMe->uLastError != QCBOR_SUCCESS) {
5595 return;
5596 }
5597
5598 QCBORItem Item;
5599 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5600
5601 const TagSpecification TagSpec =
5602 {
5603 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005604 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5605 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5606 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005607 };
5608
5609 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5610}
5611
5612
5613/*
5614 Public function, see header qcbor/qcbor_decode.h file
5615*/
5616void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005617 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005618 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005619 int64_t *pnMantissa,
5620 int64_t *pnExponent)
5621{
5622 if(pMe->uLastError != QCBOR_SUCCESS) {
5623 return;
5624 }
5625
5626 QCBORItem Item;
5627 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5628
5629 const TagSpecification TagSpec =
5630 {
5631 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005632 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5633 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5634 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005635 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005636
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005637 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5638}
5639
5640
5641/*
5642 Public function, see header qcbor/qcbor_decode.h file
5643*/
5644void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5645 uint8_t uTagRequirement,
5646 UsefulBuf MantissaBuffer,
5647 UsefulBufC *pMantissa,
5648 bool *pbMantissaIsNegative,
5649 int64_t *pnExponent)
5650{
5651 if(pMe->uLastError != QCBOR_SUCCESS) {
5652 return;
5653 }
5654
5655 QCBORItem Item;
5656 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5657 if(uError) {
5658 pMe->uLastError = (uint8_t)uError;
5659 return;
5660 }
5661
5662 const TagSpecification TagSpec =
5663 {
5664 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005665 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5666 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5667 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005668 };
5669
Laurence Lundblade93d89472020-10-03 22:30:50 -07005670 ProcessMantissaAndExponentBig(pMe,
5671 TagSpec,
5672 &Item,
5673 MantissaBuffer,
5674 pMantissa,
5675 pbMantissaIsNegative,
5676 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005677}
5678
5679
5680/*
5681 Public function, see header qcbor/qcbor_decode.h file
5682*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005683void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005684 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005685 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005686 UsefulBuf BufferForMantissa,
5687 UsefulBufC *pMantissa,
5688 bool *pbIsNegative,
5689 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005690{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005691 if(pMe->uLastError != QCBOR_SUCCESS) {
5692 return;
5693 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005694
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005695 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005696 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005697 if(pMe->uLastError != QCBOR_SUCCESS) {
5698 return;
5699 }
5700
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005701 const TagSpecification TagSpec =
5702 {
5703 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005704 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5705 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5706 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005707 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005708
Laurence Lundblade93d89472020-10-03 22:30:50 -07005709 ProcessMantissaAndExponentBig(pMe,
5710 TagSpec,
5711 &Item,
5712 BufferForMantissa,
5713 pMantissa,
5714 pbIsNegative,
5715 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005716}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005717
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005718
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005719/*
5720 Public function, see header qcbor/qcbor_decode.h file
5721*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005722void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005723 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005724 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005725 UsefulBuf BufferForMantissa,
5726 UsefulBufC *pMantissa,
5727 bool *pbIsNegative,
5728 int64_t *pnExponent)
5729{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005730 if(pMe->uLastError != QCBOR_SUCCESS) {
5731 return;
5732 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005733
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005734 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005735 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5736 if(pMe->uLastError != QCBOR_SUCCESS) {
5737 return;
5738 }
5739
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005740 const TagSpecification TagSpec =
5741 {
5742 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005743 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5744 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5745 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005746 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005747
5748 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5749}
5750
5751
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005752/*
5753 Public function, see header qcbor/qcbor_decode.h file
5754*/
5755void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5756 uint8_t uTagRequirement,
5757 int64_t *pnMantissa,
5758 int64_t *pnExponent)
5759{
5760 if(pMe->uLastError != QCBOR_SUCCESS) {
5761 return;
5762 }
5763
5764 QCBORItem Item;
5765 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5766 if(uError) {
5767 pMe->uLastError = (uint8_t)uError;
5768 return;
5769 }
5770 const TagSpecification TagSpec =
5771 {
5772 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005773 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5774 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5775 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005776 };
5777
5778 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5779}
5780
5781
5782/*
5783 Public function, see header qcbor/qcbor_decode.h file
5784*/
5785void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005786 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005787 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005788 int64_t *pnMantissa,
5789 int64_t *pnExponent)
5790{
5791 if(pMe->uLastError != QCBOR_SUCCESS) {
5792 return;
5793 }
5794
5795 QCBORItem Item;
5796 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5797 if(pMe->uLastError != QCBOR_SUCCESS) {
5798 return;
5799 }
5800
5801 const TagSpecification TagSpec =
5802 {
5803 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005804 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5805 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5806 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005807 };
5808
5809 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5810}
5811
5812
5813/*
5814 Public function, see header qcbor/qcbor_decode.h file
5815*/
5816void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005817 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005818 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005819 int64_t *pnMantissa,
5820 int64_t *pnExponent)
5821{
5822 if(pMe->uLastError != QCBOR_SUCCESS) {
5823 return;
5824 }
5825
5826 QCBORItem Item;
5827 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5828 if(pMe->uLastError != QCBOR_SUCCESS) {
5829 return;
5830 }
5831
5832 const TagSpecification TagSpec =
5833 {
5834 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005835 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5836 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5837 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005838 };
5839
5840 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5841}
5842
5843
5844/*
5845 Public function, see header qcbor/qcbor_decode.h file
5846*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005847void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5848 uint8_t uTagRequirement,
5849 UsefulBuf MantissaBuffer,
5850 UsefulBufC *pMantissa,
5851 bool *pbMantissaIsNegative,
5852 int64_t *pnExponent)
5853{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005854 if(pMe->uLastError != QCBOR_SUCCESS) {
5855 return;
5856 }
5857
5858 QCBORItem Item;
5859 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5860 if(uError) {
5861 pMe->uLastError = (uint8_t)uError;
5862 return;
5863 }
5864
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005865 const TagSpecification TagSpec =
5866 {
5867 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005868 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5869 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5870 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005871 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005872
5873 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005874}
5875
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005876
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005877/*
5878 Public function, see header qcbor/qcbor_decode.h file
5879*/
5880void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005881 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005882 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005883 UsefulBuf BufferForMantissa,
5884 UsefulBufC *pMantissa,
5885 bool *pbIsNegative,
5886 int64_t *pnExponent)
5887{
5888 if(pMe->uLastError != QCBOR_SUCCESS) {
5889 return;
5890 }
5891
5892 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005893 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5894 if(pMe->uLastError != QCBOR_SUCCESS) {
5895 return;
5896 }
5897
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005898 const TagSpecification TagSpec =
5899 {
5900 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005901 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5902 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5903 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005904 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005905
Laurence Lundblade93d89472020-10-03 22:30:50 -07005906 ProcessMantissaAndExponentBig(pMe,
5907 TagSpec,
5908 &Item,
5909 BufferForMantissa,
5910 pMantissa,
5911 pbIsNegative,
5912 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005913}
5914
5915
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005916/*
5917 Public function, see header qcbor/qcbor_decode.h file
5918*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005919void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005920 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005921 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005922 UsefulBuf BufferForMantissa,
5923 UsefulBufC *pMantissa,
5924 bool *pbIsNegative,
5925 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005926{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005927 if(pMe->uLastError != QCBOR_SUCCESS) {
5928 return;
5929 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005930
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005931 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005932 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5933 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005934 return;
5935 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005936
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005937 const TagSpecification TagSpec =
5938 {
5939 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005940 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5941 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5942 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005943 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005944
Laurence Lundblade93d89472020-10-03 22:30:50 -07005945 ProcessMantissaAndExponentBig(pMe,
5946 TagSpec,
5947 &Item,
5948 BufferForMantissa,
5949 pMantissa,
5950 pbIsNegative,
5951 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005952}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005953
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005954#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */