blob: faa0218bcb76d51f6779e834a2d347c3fa5f4d10 [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 Lundbladeaf5921e2022-07-15 09:06:30 -07003 Copyright (c) 2018-2022, 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
David Navarro9123e5b2022-03-28 16:04:03 +02001306 if (StringChunkItem.val.string.len > 0) {
1307 /* The first time throurgh FullString.ptr is NULL and this is
1308 * equivalent to StringAllocator_Allocate(). Subsequently it is
1309 * not NULL and a reallocation happens.
1310 */
1311 UsefulBuf NewMem = StringAllocator_Reallocate(pAllocator,
1312 FullString.ptr,
1313 FullString.len + StringChunkItem.val.string.len);
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08001314
David Navarro9123e5b2022-03-28 16:04:03 +02001315 if(UsefulBuf_IsNULL(NewMem)) {
1316 uReturn = QCBOR_ERR_STRING_ALLOCATE;
1317 break;
1318 }
1319
1320 /* Copy new string chunk to the end of accumulated string */
1321 FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001322 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001323 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001324
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001325 if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
1326 /* Getting the item failed, clean up the allocated memory */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001327 StringAllocator_Free(pAllocator, FullString.ptr);
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001328 }
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001329#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
1330 uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
1331#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001332
Laurence Lundbladed6dfe6d2020-04-09 10:21:36 -07001333Done:
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001334 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001335}
1336
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08001337
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001338/**
1339 * @brief This converts a tag number to a shorter mapped value for storage.
1340 *
1341 * @param[in] pMe The decode context.
1342 * @param[in] uUnMappedTag The tag number to map
1343 * @param[out] puMappedTagNumer The stored tag number.
1344 *
1345 * @return error code.
1346 *
1347 * The main point of mapping tag numbers is make QCBORItem
1348 * smaller. With this mapping storage of 4 tags takes up 8
1349 * bytes. Without, it would take up 32 bytes.
1350 *
1351 * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
1352 * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
1353 *
1354 * See also UnMapTagNumber() and @ref QCBORItem.
1355 */
1356static inline QCBORError
1357MapTagNumber(QCBORDecodeContext *pMe, uint64_t uUnMappedTag, uint16_t *puMappedTagNumer)
1358{
1359 if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
1360 unsigned uTagMapIndex;
1361 /* Is there room in the tag map, or is it in it already? */
1362 for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
1363 if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
1364 break;
1365 }
1366 if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
1367 break;
1368 }
1369 }
1370 if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
1371 return QCBOR_ERR_TOO_MANY_TAGS;
1372 }
1373
1374 /* Covers the cases where tag is new and were it is already in the map */
1375 pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
1376 *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
1377
1378 } else {
1379 *puMappedTagNumer = (uint16_t)uUnMappedTag;
1380 }
1381
1382 return QCBOR_SUCCESS;
1383}
1384
1385
1386/**
1387 * @brief This converts a mapped tag number to the actual tag number.
1388 *
1389 * @param[in] pMe The decode context.
1390 * @param[in] uMappedTagNumber The stored tag number.
1391 *
1392 * @return The actual tag number is returned or
1393 * @ref CBOR_TAG_INVALID64 on error.
1394 *
1395 * This is the reverse of MapTagNumber()
1396 */
1397static uint64_t
1398UnMapTagNumber(const QCBORDecodeContext *pMe, uint16_t uMappedTagNumber)
1399{
1400 if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
1401 return uMappedTagNumber;
1402 } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07001403 return CBOR_TAG_INVALID64;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001404 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001405 /* This won't be negative because of code below in
1406 * MapTagNumber()
1407 */
1408 const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
1409 return pMe->auMappedTags[uIndex];
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001410 }
1411}
1412
Laurence Lundblade9b334962020-08-27 10:55:53 -07001413
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001414/**
1415 * @brief Aggregate all tags wrapping a data item (decode layer 4).
1416 *
1417 * @param[in] pMe Decoder context
1418 * @param[out] pDecodedItem The decoded item that work is done on.
Laurence Lundblade9b334962020-08-27 10:55:53 -07001419
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001420 * @retval QCBOR_ERR_UNSUPPORTED
1421 * @retval QCBOR_ERR_HIT_END
1422 * @retval QCBOR_ERR_INT_OVERFLOW
1423 * @retval QCBOR_ERR_STRING_ALLOCATE
1424 * @retval QCBOR_ERR_STRING_TOO_LONG
1425 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001426 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001427 * @retval QCBOR_ERR_BAD_TYPE_7
1428 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1429 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1430 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1431 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1432 * @retval QCBOR_ERR_TOO_MANY_TAGS
1433 *
1434 * This loops getting atomic data items until one is not a tag
1435 * number. Usually this is largely pass-through because most
1436 * item are not tag numbers.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001437 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001438static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001439QCBORDecode_GetNextTagNumber(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001440{
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001441 /* Accummulate the tags from multiple items here and then copy them
1442 * into the last item, the non-tag item.
1443 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001444 uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
1445
1446 /* Initialize to CBOR_TAG_INVALID16 */
1447 #if CBOR_TAG_INVALID16 != 0xffff
1448 /* Be sure the memset does the right thing. */
1449 #err CBOR_TAG_INVALID16 tag not defined as expected
1450 #endif
1451 memset(auItemsTags, 0xff, sizeof(auItemsTags));
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001452
Laurence Lundblade9b334962020-08-27 10:55:53 -07001453 QCBORError uReturn = QCBOR_SUCCESS;
1454
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001455 /* Loop fetching data items until the item fetched is not a tag */
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001456 for(;;) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001457 QCBORError uErr = QCBORDecode_GetNextFullString(pMe, pDecodedItem);
Laurence Lundblade9b334962020-08-27 10:55:53 -07001458 if(uErr != QCBOR_SUCCESS) {
1459 uReturn = uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001460 goto Done;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001461 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001462
Laurence Lundblade9b334962020-08-27 10:55:53 -07001463 if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001464 /* Successful exit from loop; maybe got some tags, maybe not */
1465 memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001466 break;
1467 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001468
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001469 if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
1470 /* No room in the tag list */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001471 uReturn = QCBOR_ERR_TOO_MANY_TAGS;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001472 /* Continue on to get all tags wrapping this item even though
1473 * it is erroring out in the end. This allows decoding to
1474 * continue. This is a resource limit error, not a problem
1475 * with being well-formed CBOR.
1476 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001477 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001478 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001479 /* Slide tags over one in the array to make room at index 0.
1480 * Must use memmove because the move source and destination
1481 * overlap.
1482 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001483 memmove(&auItemsTags[1],
1484 auItemsTags,
1485 sizeof(auItemsTags) - sizeof(auItemsTags[0]));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001486
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001487 /* Map the tag */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001488 uint16_t uMappedTagNumber = 0;
1489 uReturn = MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumber);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001490 /* Continue even on error so as to consume all tags wrapping
1491 * this data item so decoding can go on. If MapTagNumber()
1492 * errors once it will continue to error.
1493 */
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01001494 auItemsTags[0] = uMappedTagNumber;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07001495 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001496
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001497Done:
Laurence Lundblade9b334962020-08-27 10:55:53 -07001498 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001499}
1500
1501
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001502/**
1503 * @brief Combine a map entry label and value into one item (decode layer 3).
1504 *
1505 * @param[in] pMe Decoder context
1506 * @param[out] pDecodedItem The decoded item that work is done on.
1507 *
1508 * @retval QCBOR_ERR_UNSUPPORTED
1509 * @retval QCBOR_ERR_HIT_END
1510 * @retval QCBOR_ERR_INT_OVERFLOW
1511 * @retval QCBOR_ERR_STRING_ALLOCATE
1512 * @retval QCBOR_ERR_STRING_TOO_LONG
1513 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001514 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001515 * @retval QCBOR_ERR_BAD_TYPE_7
1516 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1517 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1518 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1519 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1520 * @retval QCBOR_ERR_TOO_MANY_TAGS
1521 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1522 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1523 *
1524 * If a the current nesting level is a map, then this
1525 * combines pairs of items into one data item with a label
1526 * and value.
1527 *
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07001528 * This is passthrough if the current nesting level is
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001529 * not a map.
1530 *
1531 * This also implements maps-as-array mode where a map
1532 * is treated like an array to allow caller to do their
1533 * own label processing.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001534 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08001535static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001536QCBORDecode_GetNextMapEntry(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001537{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001538 QCBORError uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1539 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade742df4a2018-10-13 20:07:17 +08001540 goto Done;
1541 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001542
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001543 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
1544 /* Break can't be a map entry */
1545 goto Done;
1546 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001547
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001548 if(pMe->uDecodeMode != QCBOR_DECODE_MODE_MAP_AS_ARRAY) {
1549 /* Normal decoding of maps -- combine label and value into one item. */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001550
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001551 if(DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
1552 /* Save label in pDecodedItem and get the next which will
1553 * be the real data item.
1554 */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001555 QCBORItem LabelItem = *pDecodedItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001556 uReturn = QCBORDecode_GetNextTagNumber(pMe, pDecodedItem);
1557 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001558 goto Done;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07001559 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001560
Laurence Lundblade57dd1442018-10-15 20:26:28 +05301561 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001562
1563 if(LabelItem.uDataType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001564 /* strings are always good labels */
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001565 pDecodedItem->label.string = LabelItem.val.string;
1566 pDecodedItem->uLabelType = QCBOR_TYPE_TEXT_STRING;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001567 } else if (QCBOR_DECODE_MODE_MAP_STRINGS_ONLY == pMe->uDecodeMode) {
1568 /* It's not a string and we only want strings */
1569 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001570 goto Done;
1571 } else if(LabelItem.uDataType == QCBOR_TYPE_INT64) {
1572 pDecodedItem->label.int64 = LabelItem.val.int64;
1573 pDecodedItem->uLabelType = QCBOR_TYPE_INT64;
1574 } else if(LabelItem.uDataType == QCBOR_TYPE_UINT64) {
1575 pDecodedItem->label.uint64 = LabelItem.val.uint64;
1576 pDecodedItem->uLabelType = QCBOR_TYPE_UINT64;
1577 } else if(LabelItem.uDataType == QCBOR_TYPE_BYTE_STRING) {
1578 pDecodedItem->label.string = LabelItem.val.string;
1579 pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
1580 pDecodedItem->uLabelType = QCBOR_TYPE_BYTE_STRING;
1581 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001582 /* label is not an int or a string. It is an arrray
1583 * or a float or such and this implementation doesn't handle that.
1584 * Also, tags on labels are ignored.
1585 */
1586 uReturn = QCBOR_ERR_MAP_LABEL_TYPE;
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +09001587 goto Done;
1588 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001589 }
1590 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001591 /* Decoding of maps as arrays to let the caller decide what to do
1592 * about labels, particularly lables that are not integers or
1593 * strings.
1594 */
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001595 if(pDecodedItem->uDataType == QCBOR_TYPE_MAP) {
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001596 if(pDecodedItem->val.uCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001597 uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001598 goto Done;
1599 }
Laurence Lundbladed61cbf32018-12-09 11:42:21 -08001600 pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001601 /* Cast is safe because of check against QCBOR_MAX_ITEMS_IN_ARRAY/2.
1602 * Cast is needed because of integer promotion.
1603 */
Laurence Lundbladee6bcef12020-04-01 10:56:27 -07001604 pDecodedItem->val.uCount = (uint16_t)(pDecodedItem->val.uCount * 2);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001605 }
1606 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001607
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001608Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001609 return uReturn;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001610}
1611
1612
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001613#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001614/**
1615 * @brief Peek and see if next data item is a break;
1616 *
1617 * @param[in] pUIB UsefulInputBuf to read from.
1618 * @param[out] pbNextIsBreak Indicate if next was a break or not.
1619 *
1620 * @return Any decoding error.
1621 *
1622 * See if next item is a CBOR break. If it is, it is consumed,
1623 * if not it is not consumed.
Laurence Lundblade02625d42020-06-25 14:41:41 -07001624*/
Laurence Lundblade642282a2020-06-23 12:00:33 -07001625static inline QCBORError
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001626NextIsBreak(UsefulInputBuf *pUIB, bool *pbNextIsBreak)
1627{
1628 *pbNextIsBreak = false;
1629 if(UsefulInputBuf_BytesUnconsumed(pUIB) != 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001630 QCBORItem Peek;
1631 size_t uPeek = UsefulInputBuf_Tell(pUIB);
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001632 QCBORError uReturn = DecodeAtomicDataItem(pUIB, &Peek, NULL);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001633 if(uReturn != QCBOR_SUCCESS) {
1634 return uReturn;
1635 }
1636 if(Peek.uDataType != QCBOR_TYPE_BREAK) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001637 /* It is not a break, rewind so it can be processed normally. */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001638 UsefulInputBuf_Seek(pUIB, uPeek);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001639 } else {
1640 *pbNextIsBreak = true;
1641 }
1642 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07001643
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001644 return QCBOR_SUCCESS;
1645}
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001646#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001647
1648
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001649/**
1650 * @brief Ascend up nesting levels if all items in them have been consumed.
1651 *
1652 * @param[in] pMe The decode context.
1653 * @param[in] bMarkEnd If true mark end of maps/arrays with count of zero.
1654 *
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001655 * An item was just consumed, now figure out if it was the
1656 * end of an array/map map that can be closed out. That
1657 * may in turn close out the above array/map...
Laurence Lundblade642282a2020-06-23 12:00:33 -07001658*/
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001659static QCBORError
1660QCBORDecode_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001661{
1662 QCBORError uReturn;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07001663
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001664 /* Loop ascending nesting levels as long as there is ascending to do */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001665 while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
1666
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001667 if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
1668 /* Nesting level is bstr-wrapped CBOR */
1669
1670 /* Ascent for bstr-wrapped CBOR is always by explicit call
1671 * so no further ascending can happen.
1672 */
1673 break;
1674
1675 } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
1676 /* Level is a definite-length array/map */
1677
1678 /* Decrement the item count the definite-length array/map */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001679 DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
1680 if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001681 /* Didn't close out array/map, so all work here is done */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001682 break;
1683 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001684 /* All items in a definite-length array were consumed so it
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001685 * is time to ascend one level. This happens below.
1686 */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001687
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001688#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001689 } else {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001690 /* Level is an indefinite-length array/map. */
1691
1692 /* Check for a break which is what ends indefinite-length arrays/maps */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001693 bool bIsBreak = false;
1694 uReturn = NextIsBreak(&(pMe->InBuf), &bIsBreak);
1695 if(uReturn != QCBOR_SUCCESS) {
1696 goto Done;
1697 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001698
1699 if(!bIsBreak) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001700 /* Not a break so array/map does not close out. All work is done */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001701 break;
1702 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001703
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001704 /* It was a break in an indefinitelength map / array so
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001705 * it is time to ascend one level.
1706 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07001707
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001708#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001709 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001710
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001711
1712 /* All items in the array/map have been consumed. */
Laurence Lundblade642282a2020-06-23 12:00:33 -07001713
Laurence Lundblade93d89472020-10-03 22:30:50 -07001714 /* But ascent in bounded mode is only by explicit call to
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001715 * QCBORDecode_ExitBoundedMode().
1716 */
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07001717 if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001718 /* Set the count to zero for definite-length arrays to indicate
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001719 * cursor is at end of bounded array/map */
Laurence Lundbladed0304932020-06-27 10:59:38 -07001720 if(bMarkEnd) {
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001721 /* Used for definite and indefinite to signal end */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07001722 DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
Laurence Lundbladed0304932020-06-27 10:59:38 -07001723
Laurence Lundblade2c1faf92020-06-26 22:43:56 -07001724 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001725 break;
1726 }
1727
1728 /* Finally, actually ascend one level. */
1729 DecodeNesting_Ascend(&(pMe->nesting));
1730 }
Laurence Lundblade642282a2020-06-23 12:00:33 -07001731
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001732 uReturn = QCBOR_SUCCESS;
1733
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001734#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001735Done:
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001736#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
1737
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001738 return uReturn;
1739}
1740
1741
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001742/**
1743 * @brief Ascending & Descending out of nesting levels (decode layer 2).
1744 *
1745 * @param[in] pMe Decoder context
1746 * @param[out] pDecodedItem The decoded item that work is done on.
1747 *
1748 * @retval QCBOR_ERR_UNSUPPORTED
1749 * @retval QCBOR_ERR_HIT_END
1750 * @retval QCBOR_ERR_INT_OVERFLOW
1751 * @retval QCBOR_ERR_STRING_ALLOCATE
1752 * @retval QCBOR_ERR_STRING_TOO_LONG
1753 * @retval QCBOR_ERR_HALF_PRECISION_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001754 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001755 * @retval QCBOR_ERR_BAD_TYPE_7
1756 * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED
1757 * @retval QCBOR_ERR_NO_STRING_ALLOCATOR
1758 * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK
1759 * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED
1760 * @retval QCBOR_ERR_TOO_MANY_TAGS
1761 * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG
1762 * @retval QCBOR_ERR_MAP_LABEL_TYPE
1763 * @retval QCBOR_ERR_NO_MORE_ITEMS
1764 * @retval QCBOR_ERR_BAD_BREAK
1765 * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP
1766 *
1767 * This handles the traversal descending into and asecnding out of
1768 * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
1769 * definite- and indefinte-length maps and arrays by looking at the
1770 * item count or finding CBOR breaks. It detects the ends of the
1771 * top-level sequence and of bstr-wrapped CBOR by byte count.
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001772 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07001773static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001774QCBORDecode_GetNextMapOrArray(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001775{
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001776 QCBORError uReturn;
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001777 /* ==== First: figure out if at the end of a traversal ==== */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001778
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001779 /* If out of bytes to consume, it is either the end of the
1780 * top-level sequence of some bstr-wrapped CBOR that was entered.
1781 *
1782 * In the case of bstr-wrapped CBOR, the length of the
1783 * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
1784 * the bstr-wrapped CBOR is exited, the length is set back to the
1785 * top-level's length or to the next highest bstr-wrapped CBOR.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001786 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001787 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001788 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001789 goto Done;
1790 }
Laurence Lundblade937ea812020-05-08 11:38:23 -07001791
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001792 /* Check to see if at the end of a bounded definite-length map or
1793 * array. The check for a break ending indefinite-length array is
1794 * later in QCBORDecode_NestLevelAscender().
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001795 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001796 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001797 uReturn = QCBOR_ERR_NO_MORE_ITEMS;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07001798 goto Done;
1799 }
Laurence Lundbladebb1062e2019-08-12 23:28:54 -07001800
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08001801 /* ==== Next: not at the end, so get another item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001802 uReturn = QCBORDecode_GetNextMapEntry(pMe, pDecodedItem);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001803 if(QCBORDecode_IsUnrecoverableError(uReturn)) {
1804 /* Error is so bad that traversal is not possible. */
Laurence Lundblade20b533d2018-10-08 20:44:53 +08001805 goto Done;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07001806 }
Laurence Lundblade7e0d13b2018-10-16 19:54:13 +05301807
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001808 /* Breaks ending arrays/maps are processed later in the call to
1809 * QCBORDecode_NestLevelAscender(). They should never show up here.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001810 */
Laurence Lundblade6de37062018-10-15 12:22:42 +05301811 if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001812 uReturn = QCBOR_ERR_BAD_BREAK;
Laurence Lundblade6de37062018-10-15 12:22:42 +05301813 goto Done;
Laurence Lundblade5b8c5852018-10-14 21:11:42 +05301814 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001815
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001816 /* Record the nesting level for this data item before processing
1817 * any of decrementing and descending.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001818 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001819 pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001820
Laurence Lundblade642282a2020-06-23 12:00:33 -07001821
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001822 /* ==== Next: Process the item for descent, ascent, decrement... ==== */
Laurence Lundblade02625d42020-06-25 14:41:41 -07001823 if(QCBORItem_IsMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001824 /* If the new item is a map or array, descend.
1825 *
1826 * Empty indefinite-length maps and arrays are descended into,
1827 * but then ascended out of in the next chunk of code.
1828 *
1829 * Maps and arrays do count as items in the map/array that
1830 * encloses them so a decrement needs to be done for them too,
1831 * but that is done only when all the items in them have been
1832 * processed, not when they are opened with the exception of an
1833 * empty map or array.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001834 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001835 QCBORError uDescendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001836 uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
Laurence Lundblade642282a2020-06-23 12:00:33 -07001837 pDecodedItem->uDataType,
1838 pDecodedItem->val.uCount);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001839 if(uDescendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001840 /* This error is probably a traversal error and it overrides
1841 * the non-traversal error.
1842 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001843 uReturn = uDescendErr;
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001844 goto Done;
1845 }
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001846 }
1847
Laurence Lundblade02625d42020-06-25 14:41:41 -07001848 if(!QCBORItem_IsMapOrArray(pDecodedItem) ||
1849 QCBORItem_IsEmptyDefiniteLengthMapOrArray(pDecodedItem) ||
1850 QCBORItem_IsIndefiniteLengthMapOrArray(pDecodedItem)) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001851 /* The following cases are handled here:
1852 * - A non-aggregate item like an integer or string
1853 * - An empty definite-length map or array
1854 * - An indefinite-length map or array that might be empty or might not.
1855 *
1856 * QCBORDecode_NestLevelAscender() does the work of decrementing the count
1857 * for an definite-length map/array and break detection for an
1858 * indefinite-0length map/array. If the end of the map/array was
1859 * reached, then it ascends nesting levels, possibly all the way
1860 * to the top level.
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001861 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001862 QCBORError uAscendErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001863 uAscendErr = QCBORDecode_NestLevelAscender(pMe, true);
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001864 if(uAscendErr != QCBOR_SUCCESS) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001865 /* This error is probably a traversal error and it overrides
1866 * the non-traversal error.
1867 */
Laurence Lundbladea9489f82020-09-12 13:50:56 -07001868 uReturn = uAscendErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07001869 goto Done;
Laurence Lundblade5e87da62020-06-07 03:24:28 -07001870 }
Laurence Lundblade6de37062018-10-15 12:22:42 +05301871 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001872
Laurence Lundbladeeaa75a52020-07-09 18:13:23 -07001873 /* ==== Last: tell the caller the nest level of the next item ==== */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001874 /* Tell the caller what level is next. This tells them what
1875 * maps/arrays were closed out and makes it possible for them to
1876 * reconstruct the tree with just the information returned in a
1877 * QCBORItem.
Laurence Lundblade642282a2020-06-23 12:00:33 -07001878 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001879 if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07001880 /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001881 pDecodedItem->uNextNestLevel = 0;
1882 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001883 pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
Laurence Lundblade9c905e82020-04-25 11:31:38 -07001884 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001885
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001886Done:
Laurence Lundblade0a042a92020-06-12 14:09:50 -07001887 return uReturn;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001888}
1889
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001890
1891/**
1892 * @brief Shift 0th tag out of the tag list.
1893 *
1894 * pDecodedItem[in,out] The data item to convert.
1895 *
1896 * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
1897 * shifted into empty slot at the end of the tag list.
1898 */
1899static inline void ShiftTags(QCBORItem *pDecodedItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07001900{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001901 for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
1902 pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
1903 }
1904 pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
Laurence Lundblade9b334962020-08-27 10:55:53 -07001905}
1906
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001907
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001908/**
1909 * @brief Convert different epoch date formats in to the QCBOR epoch date format
1910 *
1911 * pDecodedItem[in,out] The data item to convert.
1912 *
1913 * @retval QCBOR_ERR_DATE_OVERFLOW
1914 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001915 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07001916 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001917 *
1918 * The epoch date tag defined in QCBOR allows for floating-point
1919 * dates. It even allows a protocol to flop between date formats when
1920 * ever it wants. Floating-point dates aren't that useful as they are
1921 * only needed for dates beyond the age of the earth.
1922 *
1923 * This converts all the date formats into one format of an unsigned
1924 * integer plus a floating-point fraction.
Laurence Lundblade59289e52019-12-30 13:44:37 -08001925 */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08001926static QCBORError DecodeDateEpoch(QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08001927{
Laurence Lundbladec7114722020-08-13 05:11:40 -07001928 QCBORError uReturn = QCBOR_SUCCESS;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001929
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001930#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade59289e52019-12-30 13:44:37 -08001931 pDecodedItem->val.epochDate.fSecondsFraction = 0;
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001932#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001933
1934 switch (pDecodedItem->uDataType) {
1935
1936 case QCBOR_TYPE_INT64:
1937 pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
1938 break;
1939
1940 case QCBOR_TYPE_UINT64:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001941 /* This only happens for CBOR type 0 > INT64_MAX so it is
1942 * always an overflow.
1943 */
Laurence Lundbladec7114722020-08-13 05:11:40 -07001944 uReturn = QCBOR_ERR_DATE_OVERFLOW;
1945 goto Done;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001946 break;
1947
1948 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade9682a532020-06-06 18:33:04 -07001949 case QCBOR_TYPE_FLOAT:
1950#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade59289e52019-12-30 13:44:37 -08001951 {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001952 /* Convert working value to double if input was a float */
Laurence Lundblade3ed0bca2020-07-14 22:50:10 -07001953 const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001954 pDecodedItem->val.dfnum :
1955 (double)pDecodedItem->val.fnum;
1956
1957 /* The conversion from float to integer requires overflow
1958 * detection since floats can be much larger than integers.
1959 * This implementation errors out on these large float values
1960 * since they are beyond the age of the earth.
1961 *
1962 * These constants for the overflow check are computed by the
1963 * compiler. They are not computed at run time.
1964 *
1965 * The factor of 0x7ff is added/subtracted to avoid a
1966 * rounding error in the wrong direction when the compiler
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001967 * computes these constants. There is rounding because a
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001968 * 64-bit integer has 63 bits of precision where a double
1969 * only has 53 bits. Without the 0x7ff factor, the compiler
1970 * may round up and produce a double for the bounds check
1971 * that is larger than can be stored in a 64-bit integer. The
1972 * amount of 0x7ff is picked because it has 11 bits set.
1973 *
1974 * Without the 0x7ff there is a ~30 minute range of time
1975 * values 10 billion years in the past and in the future
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001976 * where this code could go wrong. Some compilers
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001977 * generate a warning or error without the 0x7ff.
1978 */
1979 const double dDateMax = (double)(INT64_MAX - 0x7ff);
1980 const double dDateMin = (double)(INT64_MIN + 0x7ff);
1981
1982 if(isnan(d) || d > dDateMax || d < dDateMin) {
Laurence Lundbladec7114722020-08-13 05:11:40 -07001983 uReturn = QCBOR_ERR_DATE_OVERFLOW;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001984 goto Done;
1985 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001986
1987 /* The actual conversion */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001988 pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
Laurence Lundblade2feb1e12020-07-15 03:50:45 -07001989 pDecodedItem->val.epochDate.fSecondsFraction =
1990 d - (double)pDecodedItem->val.epochDate.nSeconds;
Laurence Lundblade59289e52019-12-30 13:44:37 -08001991 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08001992#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade4b270642020-08-14 12:53:07 -07001993
Laurence Lundblade16a207a2021-09-18 17:22:46 -07001994 uReturn = QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundblade4b270642020-08-14 12:53:07 -07001995 goto Done;
1996
Laurence Lundblade9682a532020-06-06 18:33:04 -07001997#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade59289e52019-12-30 13:44:37 -08001998 break;
1999
2000 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002001 /* It's the arrays and maps that are unrecoverable because
2002 * they are not consumed here. Since this is just an error
2003 * condition, no extra code is added here to make the error
2004 * recoverable for non-arrays and maps like strings. */
2005 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002006 goto Done;
2007 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002008
Laurence Lundblade59289e52019-12-30 13:44:37 -08002009 pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
2010
2011Done:
Laurence Lundbladec7114722020-08-13 05:11:40 -07002012 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002013}
2014
2015
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002016/**
2017 * @brief Convert the days epoch date.
2018 *
2019 * pDecodedItem[in,out] The data item to convert.
2020 *
2021 * @retval QCBOR_ERR_DATE_OVERFLOW
2022 * @retval QCBOR_ERR_FLOAT_DATE_DISABLED
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002023 * @retval QCBOR_ERR_ALL_FLOAT_DISABLED
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002024 * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002025 *
2026 * This is much simpler than the other epoch date format because
2027 * floating-porint is not allowed. This is mostly a simple type check.
2028 */
2029static QCBORError DecodeDaysEpoch(QCBORItem *pDecodedItem)
2030{
2031 QCBORError uReturn = QCBOR_SUCCESS;
2032
2033 switch (pDecodedItem->uDataType) {
2034
2035 case QCBOR_TYPE_INT64:
2036 pDecodedItem->val.epochDays = pDecodedItem->val.int64;
2037 break;
2038
2039 case QCBOR_TYPE_UINT64:
2040 /* This only happens for CBOR type 0 > INT64_MAX so it is
2041 * always an overflow.
2042 */
2043 uReturn = QCBOR_ERR_DATE_OVERFLOW;
2044 goto Done;
2045 break;
2046
2047 default:
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002048 /* It's the arrays and maps that are unrecoverable because
2049 * they are not consumed here. Since this is just an error
2050 * condition, no extra code is added here to make the error
2051 * recoverable for non-arrays and maps like strings. */
2052 uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002053 goto Done;
2054 break;
2055 }
2056
2057 pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
2058
2059Done:
2060 return uReturn;
2061}
2062
2063
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002064#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002065/**
2066 * @brief Decode decimal fractions and big floats.
2067 *
2068 * @param[in] pMe The decode context.
2069 * @param[in,out] pDecodedItem On input the array data item that
2070 * holds the mantissa and exponent. On
2071 * output the decoded mantissa and
2072 * exponent.
2073 *
2074 * @returns Decoding errors from getting primitive data items or
2075 * \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
2076 *
2077 * When called pDecodedItem must be the array that is tagged as a big
2078 * float or decimal fraction, the array that has the two members, the
2079 * exponent and mantissa.
2080 *
2081 * This will fetch and decode the exponent and mantissa and put the
2082 * result back into pDecodedItem.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002083 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002084static inline QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002085QCBORDecode_MantissaAndExponent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002086{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002087 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002088
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002089 /* --- Make sure it is an array; track nesting level of members --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002090 if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002091 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002092 goto Done;
2093 }
2094
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002095 /* A check for pDecodedItem->val.uCount == 2 would work for
2096 * definite-length arrays, but not for indefnite. Instead remember
2097 * the nesting level the two integers must be at, which is one
2098 * deeper than that of the array.
2099 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002100 const int nNestLevel = pDecodedItem->uNestingLevel + 1;
2101
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002102 /* --- Which is it, decimal fraction or a bigfloat? --- */
2103 const bool bIsTaggedDecimalFraction = QCBORDecode_IsTagged(pMe, pDecodedItem, CBOR_TAG_DECIMAL_FRACTION);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002104 pDecodedItem->uDataType = bIsTaggedDecimalFraction ? QCBOR_TYPE_DECIMAL_FRACTION : QCBOR_TYPE_BIGFLOAT;
2105
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002106 /* --- Get the exponent --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002107 QCBORItem exponentItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002108 uReturn = QCBORDecode_GetNextMapOrArray(pMe, &exponentItem);
2109 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002110 goto Done;
2111 }
2112 if(exponentItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002113 /* Array is empty or a map/array encountered when expecting an int */
2114 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002115 goto Done;
2116 }
2117 if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002118 /* Data arriving as an unsigned int < INT64_MAX has been
2119 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2120 * also means that the only data arriving here of type
2121 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2122 * and thus an error that will get handled in the next else.
2123 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002124 pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
2125 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002126 /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
2127 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002128 goto Done;
2129 }
2130
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002131 /* --- Get the mantissa --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002132 QCBORItem mantissaItem;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002133 uReturn = QCBORDecode_GetNextWithTags(pMe, &mantissaItem, NULL);
2134 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002135 goto Done;
2136 }
2137 if(mantissaItem.uNestingLevel != nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002138 /* Mantissa missing or map/array encountered when expecting number */
2139 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002140 goto Done;
2141 }
2142 if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002143 /* Data arriving as an unsigned int < INT64_MAX has been
2144 * converted to QCBOR_TYPE_INT64 and thus handled here. This is
2145 * also means that the only data arriving here of type
2146 * QCBOR_TYPE_UINT64 data will be too large for this to handle
2147 * and thus an error that will get handled in an else below.
2148 */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002149 pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
Laurence Lundblade93d89472020-10-03 22:30:50 -07002150 } else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
2151 mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002152 /* Got a good big num mantissa */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002153 pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002154 /* Depends on numbering of QCBOR_TYPE_XXX */
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002155 pDecodedItem->uDataType = (uint8_t)(pDecodedItem->uDataType +
2156 mantissaItem.uDataType - QCBOR_TYPE_POSBIGNUM +
2157 1);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002158 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002159 /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
2160 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002161 goto Done;
2162 }
2163
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002164 /* --- Check that array only has the two numbers --- */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002165 if(mantissaItem.uNextNestLevel == nNestLevel) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002166 /* Extra items in the decimal fraction / big float */
2167 uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002168 goto Done;
2169 }
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002170 pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002171
2172Done:
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002173 return uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002174}
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002175#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002176
2177
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002178#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002179/**
2180 * @brief Decode the MIME type tag
2181 *
2182 * @param[in,out] pDecodedItem The item to decode.
2183 *
2184 * Handle the text and binary MIME type tags. Slightly too complicated
2185 * f or ProcessTaggedString() because the RFC 7049 MIME type was
2186 * incorreclty text-only.
2187 */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002188static inline QCBORError DecodeMIME(QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002189{
2190 if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
2191 pDecodedItem->uDataType = QCBOR_TYPE_MIME;
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07002192 } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002193 pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
2194 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002195 /* It's the arrays and maps that are unrecoverable because
2196 * they are not consumed here. Since this is just an error
2197 * condition, no extra code is added here to make the error
2198 * recoverable for non-arrays and maps like strings. */
2199 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002200 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002201
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002202 return QCBOR_SUCCESS;
2203}
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002204#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002205
2206
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002207/**
Laurence Lundblade99615302020-11-29 11:19:47 -08002208 * Table of CBOR tags whose content is either a text string or a byte
2209 * string. The table maps the CBOR tag to the QCBOR type. The high-bit
2210 * of uQCBORtype indicates the content should be a byte string rather
2211 * than a text string
2212 */
2213struct StringTagMapEntry {
2214 uint16_t uTagNumber;
2215 uint8_t uQCBORtype;
2216};
2217
2218#define IS_BYTE_STRING_BIT 0x80
2219#define QCBOR_TYPE_MASK ~IS_BYTE_STRING_BIT
2220
2221static const struct StringTagMapEntry StringTagMap[] = {
2222 {CBOR_TAG_DATE_STRING, QCBOR_TYPE_DATE_STRING},
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002223 {CBOR_TAG_DAYS_STRING, QCBOR_TYPE_DAYS_STRING},
Laurence Lundblade99615302020-11-29 11:19:47 -08002224 {CBOR_TAG_POS_BIGNUM, QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
2225 {CBOR_TAG_NEG_BIGNUM, QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
2226 {CBOR_TAG_CBOR, QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
2227 {CBOR_TAG_URI, QCBOR_TYPE_URI},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002228#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002229 {CBOR_TAG_B64URL, QCBOR_TYPE_BASE64URL},
2230 {CBOR_TAG_B64, QCBOR_TYPE_BASE64},
2231 {CBOR_TAG_REGEX, QCBOR_TYPE_REGEX},
2232 {CBOR_TAG_BIN_UUID, QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002233#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade99615302020-11-29 11:19:47 -08002234 {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
2235 {CBOR_TAG_INVALID16, QCBOR_TYPE_NONE}
2236};
2237
2238
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002239/**
2240 * @brief Process standard CBOR tags whose content is a string
2241 *
2242 * @param[in] uTag The tag.
2243 * @param[in,out] pDecodedItem The data item.
2244 *
2245 * @returns This returns QCBOR_SUCCESS if the tag was procssed,
2246 * \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002247 * \ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT if the content type was wrong for the tag.
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002248 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002249 * Process the CBOR tags that whose content is a byte string or a text
2250 * string and for which the string is just passed on to the caller.
2251 *
2252 * This maps the CBOR tag to the QCBOR type and checks the content
2253 * type. Nothing more. It may not be the most important
Laurence Lundbladec02e13e2020-12-06 05:45:41 -08002254 * functionality, but it part of implementing as much of RFC 8949 as
Laurence Lundblade99615302020-11-29 11:19:47 -08002255 * possible.
Laurence Lundblade99615302020-11-29 11:19:47 -08002256 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002257static inline QCBORError
2258ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002259{
Laurence Lundblade99615302020-11-29 11:19:47 -08002260 /* This only works on tags that were not mapped; no need for other yet */
2261 if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
2262 return QCBOR_ERR_UNSUPPORTED;
2263 }
2264
2265 unsigned uIndex;
2266 for(uIndex = 0; StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
2267 if(StringTagMap[uIndex].uTagNumber == uTag) {
2268 break;
2269 }
2270 }
2271
2272 const uint8_t uQCBORType = StringTagMap[uIndex].uQCBORtype;
2273 if(uQCBORType == QCBOR_TYPE_NONE) {
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002274 /* repurpose this error to mean not handled here */
Laurence Lundblade99615302020-11-29 11:19:47 -08002275 return QCBOR_ERR_UNSUPPORTED;
2276 }
2277
2278 uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
2279 if(uQCBORType & IS_BYTE_STRING_BIT) {
2280 uExpectedType = QCBOR_TYPE_BYTE_STRING;
2281 }
2282
2283 if(pDecodedItem->uDataType != uExpectedType) {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002284 /* It's the arrays and maps that are unrecoverable because
2285 * they are not consumed here. Since this is just an error
2286 * condition, no extra code is added here to make the error
2287 * recoverable for non-arrays and maps like strings. */
2288 return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002289 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002290
Laurence Lundblade99615302020-11-29 11:19:47 -08002291 pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002292 return QCBOR_SUCCESS;
2293}
2294
2295
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002296/**
2297 * @brief Decode tag content for select tags (decoding layer 1).
2298 *
2299 * @param[in] pMe The decode context.
2300 * @param[out] pDecodedItem The decoded item.
2301 *
2302 * @return Decoding error code.
2303 *
Laurence Lundblade99615302020-11-29 11:19:47 -08002304 * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
2305 * but the whole tag was not decoded. Here, the whole tags (tag number
2306 * and tag content) that are supported by QCBOR are decoded. This is a
2307 * quick pass through for items that are not tags.
Laurence Lundblade59289e52019-12-30 13:44:37 -08002308 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002309static QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002310QCBORDecode_GetNextTagContent(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
Laurence Lundblade59289e52019-12-30 13:44:37 -08002311{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002312 QCBORError uReturn;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002313
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002314 uReturn = QCBORDecode_GetNextMapOrArray(pMe, pDecodedItem);
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002315 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002316 goto Done;
2317 }
2318
Laurence Lundblade99615302020-11-29 11:19:47 -08002319 /* When there are no tag numbers for the item, this exits first
2320 * thing and effectively does nothing.
2321 *
2322 * This loops over all the tag numbers accumulated for this item
2323 * trying to decode and interpret them. This stops at the end of
2324 * the list or at the first tag number that can't be interpreted by
2325 * this code. This is effectively a recursive processing of the
2326 * tags number list that handles nested tags.
2327 */
2328 while(1) {
2329 /* Don't bother to unmap tags via QCBORITem.uTags since this
2330 * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
2331 */
2332 const uint16_t uTagToProcess = pDecodedItem->uTags[0];
Laurence Lundblade59289e52019-12-30 13:44:37 -08002333
Laurence Lundblade99615302020-11-29 11:19:47 -08002334 if(uTagToProcess == CBOR_TAG_INVALID16) {
2335 /* Hit the end of the tag list. A successful exit. */
Laurence Lundblade59289e52019-12-30 13:44:37 -08002336 break;
2337
Laurence Lundblade99615302020-11-29 11:19:47 -08002338 } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002339 uReturn = DecodeDateEpoch(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002340
Laurence Lundblade46d63e92021-05-13 11:37:10 -07002341 } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
2342 uReturn = DecodeDaysEpoch(pDecodedItem);
2343
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002344#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade99615302020-11-29 11:19:47 -08002345 } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
2346 uTagToProcess == CBOR_TAG_BIGFLOAT) {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002347 uReturn = QCBORDecode_MantissaAndExponent(pMe, pDecodedItem);
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07002348#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002349#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
Laurence Lundblade99615302020-11-29 11:19:47 -08002350 } else if(uTagToProcess == CBOR_TAG_MIME ||
2351 uTagToProcess == CBOR_TAG_BINARY_MIME) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002352 uReturn = DecodeMIME(pDecodedItem);
Laurence Lundblade24bd7e12021-01-09 00:05:11 -08002353#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07002354
Laurence Lundblade99615302020-11-29 11:19:47 -08002355 } else {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002356 /* See if it is a passthrough byte/text string tag; process if so */
Laurence Lundblade99615302020-11-29 11:19:47 -08002357 uReturn = ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
Laurence Lundblade0a042a92020-06-12 14:09:50 -07002358
Laurence Lundblade99615302020-11-29 11:19:47 -08002359 if(uReturn == QCBOR_ERR_UNSUPPORTED) {
Laurence Lundbladea9e7ab92022-03-23 10:28:48 +01002360 /* It wasn't a passthrough byte/text string tag so it is
Laurence Lundblade99615302020-11-29 11:19:47 -08002361 * an unknown tag. This is the exit from the loop on the
2362 * first unknown tag. It is a successful exit.
2363 */
2364 uReturn = QCBOR_SUCCESS;
2365 break;
2366 }
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002367 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002368
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002369 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade99615302020-11-29 11:19:47 -08002370 /* Error exit from the loop */
2371 break;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002372 }
Laurence Lundblade99615302020-11-29 11:19:47 -08002373
2374 /* A tag was successfully processed, shift it out of the list of
2375 * tags returned. This is the loop increment.
2376 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002377 ShiftTags(pDecodedItem);
Laurence Lundblade59289e52019-12-30 13:44:37 -08002378 }
2379
2380Done:
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002381 return uReturn;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002382}
2383
2384
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002385/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002386 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002387 */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002388QCBORError
2389QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2390{
2391 QCBORError uErr;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002392 uErr = QCBORDecode_GetNextTagContent(pMe, pDecodedItem);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002393 if(uErr != QCBOR_SUCCESS) {
Laurence Lundblade59289e52019-12-30 13:44:37 -08002394 pDecodedItem->uDataType = QCBOR_TYPE_NONE;
2395 pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
2396 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07002397 return uErr;
Laurence Lundblade59289e52019-12-30 13:44:37 -08002398}
2399
2400
2401/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002402 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade59289e52019-12-30 13:44:37 -08002403 */
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002404QCBORError
2405QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2406{
2407 const QCBORDecodeNesting SaveNesting = pMe->nesting;
2408 const UsefulInputBuf Save = pMe->InBuf;
2409
2410 QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
2411
2412 pMe->nesting = SaveNesting;
2413 pMe->InBuf = Save;
2414
2415 return uErr;
2416}
2417
2418
2419/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002420 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade2a26abb2020-11-05 19:06:54 -08002421 */
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002422void
2423QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2424{
2425 if(pMe->uLastError != QCBOR_SUCCESS) {
2426 return;
2427 }
2428
2429 pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
2430}
2431
2432
2433/*
2434 * Public function, see header qcbor/qcbor_decode.h file
2435 */
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002436void QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2437{
2438 if(pMe->uLastError != QCBOR_SUCCESS) {
2439 return;
2440 }
2441
2442 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
2443}
2444
2445
2446/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002447 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07002448 */
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002449QCBORError
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002450QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
2451 QCBORItem *pDecodedItem,
2452 QCBORTagListOut *pTags)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002453{
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002454 QCBORError uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002455
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002456 uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
2457 if(uReturn != QCBOR_SUCCESS) {
2458 return uReturn;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002459 }
2460
2461 if(pTags != NULL) {
2462 pTags->uNumUsed = 0;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002463 /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002464 for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
2465 if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade9b334962020-08-27 10:55:53 -07002466 continue;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002467 }
2468 if(pTags->uNumUsed >= pTags->uNumAllocated) {
2469 return QCBOR_ERR_TOO_MANY_TAGS;
2470 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002471 pTags->puTags[pTags->uNumUsed] = UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002472 pTags->uNumUsed++;
2473 }
2474 }
2475
2476 return QCBOR_SUCCESS;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002477}
2478
2479
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002480/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002481 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade0fb2f642018-10-11 19:33:35 +05302482 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002483bool QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002484 const QCBORItem *pItem,
2485 uint64_t uTag)
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002486{
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002487 for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
2488 if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002489 break;
2490 }
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002491 if(UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002492 return true;
Laurence Lundblade830fbf92020-05-31 17:22:33 -07002493 }
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002494 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002495
Laurence Lundbladef71e1622020-08-06 18:52:13 -07002496 return false;
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002497}
2498
2499
2500/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002501 * Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladedbe6f212018-10-28 11:37:53 +07002502 */
Laurence Lundblade87495732021-02-26 10:05:55 -07002503QCBORError QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002504{
Laurence Lundblade87495732021-02-26 10:05:55 -07002505 if(puConsumed != NULL) {
2506 *puConsumed = pMe->InBuf.cursor;
2507 }
2508
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002509 QCBORError uReturn = pMe->uLastError;
Laurence Lundblade085d7952020-07-24 10:26:30 -07002510
2511 if(uReturn != QCBOR_SUCCESS) {
2512 goto Done;
2513 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002514
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002515 /* Error out if all the maps/arrays are not closed out */
2516 if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002517 uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002518 goto Done;
2519 }
2520
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002521 /* Error out if not all the bytes are consumed */
2522 if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
Laurence Lundblade085d7952020-07-24 10:26:30 -07002523 uReturn = QCBOR_ERR_EXTRA_BYTES;
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002524 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002525
Laurence Lundblade20b533d2018-10-08 20:44:53 +08002526Done:
Laurence Lundblade87495732021-02-26 10:05:55 -07002527 return uReturn;
2528}
2529
2530
2531/*
2532 * Public function, see header qcbor/qcbor_decode.h file
2533 */
2534QCBORError QCBORDecode_Finish(QCBORDecodeContext *pMe)
2535{
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002536#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002537 /* Call the destructor for the string allocator if there is one.
2538 * Always called, even if there are errors; always have to clean up.
2539 */
2540 StringAllocator_Destruct(&(pMe->StringAllocator));
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002541#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002542
Laurence Lundblade87495732021-02-26 10:05:55 -07002543 return QCBORDecode_PartialFinish(pMe, NULL);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002544}
2545
2546
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002547/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002548 * Public function, see header qcbor/qcbor_decode.h file
2549 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002550// Improvement: make these inline?
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002551uint64_t QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
2552 const QCBORItem *pItem,
Laurence Lundblade9b334962020-08-27 10:55:53 -07002553 uint32_t uIndex)
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002554{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002555 if(pItem->uDataType == QCBOR_TYPE_NONE) {
2556 return CBOR_TAG_INVALID64;
2557 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002558 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2559 return CBOR_TAG_INVALID64;
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002560 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002561 return UnMapTagNumber(pMe, pItem->uTags[uIndex]);
Laurence Lundbladec75e68b2020-06-15 20:34:46 -07002562 }
2563}
2564
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002565
Laurence Lundblade9b334962020-08-27 10:55:53 -07002566/*
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002567 * Public function, see header qcbor/qcbor_decode.h file
2568 */
Laurence Lundblade9b334962020-08-27 10:55:53 -07002569uint64_t QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
2570 uint32_t uIndex)
2571{
Laurence Lundblade88e9db22020-11-02 03:56:33 -08002572 if(pMe->uLastError != QCBOR_SUCCESS) {
2573 return CBOR_TAG_INVALID64;
2574 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002575 if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
2576 return CBOR_TAG_INVALID64;
2577 } else {
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002578 return UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
Laurence Lundblade9b334962020-08-27 10:55:53 -07002579 }
2580}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002581
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002582
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002583
2584
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002585#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
Laurence Lundbladef6531662018-12-04 10:42:22 +09002586
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002587/* ===========================================================================
2588 MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002589
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08002590 This implements a simple sting allocator for indefinite-length
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002591 strings that can be enabled by calling QCBORDecode_SetMemPool(). It
2592 implements the function type QCBORStringAllocate and allows easy
2593 use of it.
Laurence Lundbladef6531662018-12-04 10:42:22 +09002594
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002595 This particular allocator is built-in for convenience. The caller
2596 can implement their own. All of this following code will get
2597 dead-stripped if QCBORDecode_SetMemPool() is not called.
2598
2599 This is a very primitive memory allocator. It does not track
2600 individual allocations, only a high-water mark. A free or
2601 reallocation must be of the last chunk allocated.
2602
2603 The size of the pool and offset to free memory are packed into the
2604 first 8 bytes of the memory pool so we don't have to keep them in
2605 the decode context. Since the address of the pool may not be
2606 aligned, they have to be packed and unpacked as if they were
2607 serialized data of the wire or such.
2608
2609 The sizes packed in are uint32_t to be the same on all CPU types
2610 and simplify the code.
Laurence Lundbladeee851742020-01-08 08:37:05 -08002611 ========================================================================== */
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002612
2613
Laurence Lundbladeee851742020-01-08 08:37:05 -08002614static inline int
2615MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002616{
2617 // Use of UsefulInputBuf is overkill, but it is convenient.
2618 UsefulInputBuf UIB;
2619
Laurence Lundbladeee851742020-01-08 08:37:05 -08002620 // Just assume the size here. It was checked during SetUp so
2621 // the assumption is safe.
Laurence Lundblade93d89472020-10-03 22:30:50 -07002622 UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002623 *puPoolSize = UsefulInputBuf_GetUint32(&UIB);
2624 *puFreeOffset = UsefulInputBuf_GetUint32(&UIB);
2625 return UsefulInputBuf_GetError(&UIB);
2626}
2627
2628
Laurence Lundbladeee851742020-01-08 08:37:05 -08002629static inline int
2630MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002631{
2632 // Use of UsefulOutBuf is overkill, but convenient. The
2633 // length check performed here is useful.
2634 UsefulOutBuf UOB;
2635
2636 UsefulOutBuf_Init(&UOB, Pool);
2637 UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
2638 UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
2639 return UsefulOutBuf_GetError(&UOB);
2640}
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002641
2642
2643/*
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002644 Internal function for an allocation, reallocation free and destuct.
2645
2646 Having only one function rather than one each per mode saves space in
2647 QCBORDecodeContext.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002648
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002649 Code Reviewers: THIS FUNCTION DOES POINTER MATH
2650 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002651static UsefulBuf
2652MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002653{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002654 UsefulBuf ReturnValue = NULLUsefulBuf;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002655
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002656 uint32_t uPoolSize;
2657 uint32_t uFreeOffset;
2658
2659 if(uNewSize > UINT32_MAX) {
2660 // This allocator is only good up to 4GB. This check should
2661 // optimize out if sizeof(size_t) == sizeof(uint32_t)
2662 goto Done;
2663 }
2664 const uint32_t uNewSize32 = (uint32_t)uNewSize;
2665
2666 if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
2667 goto Done;
2668 }
2669
2670 if(uNewSize) {
2671 if(pMem) {
2672 // REALLOCATION MODE
2673 // Calculate pointer to the end of the memory pool. It is
2674 // assumed that pPool + uPoolSize won't wrap around by
2675 // assuming the caller won't pass a pool buffer in that is
2676 // not in legitimate memory space.
2677 const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
2678
2679 // Check that the pointer for reallocation is in the range of the
2680 // pool. This also makes sure that pointer math further down
2681 // doesn't wrap under or over.
2682 if(pMem >= pPool && pMem < pPoolEnd) {
2683 // Offset to start of chunk for reallocation. This won't
2684 // wrap under because of check that pMem >= pPool. Cast
2685 // is safe because the pool is always less than UINT32_MAX
2686 // because of check in QCBORDecode_SetMemPool().
2687 const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2688
2689 // Check to see if the allocation will fit. uPoolSize -
2690 // uMemOffset will not wrap under because of check that
2691 // pMem is in the range of the uPoolSize by check above.
2692 if(uNewSize <= uPoolSize - uMemOffset) {
2693 ReturnValue.ptr = pMem;
2694 ReturnValue.len = uNewSize;
2695
2696 // Addition won't wrap around over because uNewSize was
2697 // checked to be sure it is less than the pool size.
2698 uFreeOffset = uMemOffset + uNewSize32;
2699 }
2700 }
2701 } else {
2702 // ALLOCATION MODE
2703 // uPoolSize - uFreeOffset will not underflow because this
2704 // pool implementation makes sure uFreeOffset is always
2705 // smaller than uPoolSize through this check here and
2706 // reallocation case.
2707 if(uNewSize <= uPoolSize - uFreeOffset) {
2708 ReturnValue.len = uNewSize;
2709 ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
Laurence Lundblade06350ea2020-01-27 19:32:40 -08002710 uFreeOffset += (uint32_t)uNewSize;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002711 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002712 }
2713 } else {
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002714 if(pMem) {
2715 // FREE MODE
2716 // Cast is safe because of limit on pool size in
2717 // QCBORDecode_SetMemPool()
2718 uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
2719 } else {
2720 // DESTRUCT MODE
2721 // Nothing to do for this allocator
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002722 }
2723 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002724
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002725 UsefulBuf Pool = {pPool, uPoolSize};
2726 MemPool_Pack(Pool, uFreeOffset);
2727
2728Done:
2729 return ReturnValue;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002730}
2731
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002732
Laurence Lundbladef6531662018-12-04 10:42:22 +09002733/*
Laurence Lundblade844bb5c2020-03-01 17:27:25 -08002734 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef6531662018-12-04 10:42:22 +09002735 */
Laurence Lundbladeee851742020-01-08 08:37:05 -08002736QCBORError QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
2737 UsefulBuf Pool,
2738 bool bAllStrings)
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002739{
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002740 // The pool size and free mem offset are packed into the beginning
2741 // of the pool memory. This compile time check make sure the
2742 // constant in the header is correct. This check should optimize
2743 // down to nothing.
2744 if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002745 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002746 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002747
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002748 // The pool size and free offset packed in to the beginning of pool
2749 // memory are only 32-bits. This check will optimize out on 32-bit
2750 // machines.
2751 if(Pool.len > UINT32_MAX) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002752 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002753 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002754
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002755 // This checks that the pool buffer given is big enough.
2756 if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07002757 return QCBOR_ERR_MEM_POOL_SIZE;
Laurence Lundblade1d7eb632019-02-17 17:23:38 -08002758 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002759
Laurence Lundblade3427dee2021-06-20 11:11:24 -07002760 QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002761
Laurence Lundblade30816f22018-11-10 13:40:22 +07002762 return QCBOR_SUCCESS;
Laurence Lundblade041ffa52018-10-07 11:43:51 +07002763}
Laurence Lundbladef6da33c2020-11-26 18:15:05 -08002764#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002765
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002766
2767
Laurence Lundblade9b334962020-08-27 10:55:53 -07002768static inline void CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
2769{
2770 memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
2771}
Laurence Lundblade1d85d522020-06-22 13:24:59 -07002772
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002773
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002774/**
2775 * @brief Consume an entire map or array including its contents.
2776 *
2777 * @param[in] pMe The decoder context.
2778 * @param[in] pItemToConsume The array/map whose contents are to be
2779 * consumed.
2780 * @param[out] puNextNestLevel The next nesting level after the item was
2781 * fully consumed.
2782 *
2783 * This may be called when @c pItemToConsume is not an array or
2784 * map. In that case, this is just a pass through for @c puNextNestLevel
2785 * since there is nothing to do.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002786 */
Laurence Lundblade9c905e82020-04-25 11:31:38 -07002787static inline QCBORError
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002788ConsumeItem(QCBORDecodeContext *pMe,
2789 const QCBORItem *pItemToConsume,
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02002790 uint8_t *puNextNestLevel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002791{
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002792 QCBORError uReturn;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002793 QCBORItem Item;
Laurence Lundblade9b334962020-08-27 10:55:53 -07002794
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002795 /* If it is a map or array, this will tell if it is empty. */
Laurence Lundbladed40951e2020-08-28 11:11:14 -07002796 const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
2797
2798 if(QCBORItem_IsMapOrArray(pItemToConsume) && !bIsEmpty) {
2799 /* There is only real work to do for non-empty maps and arrays */
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002800
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002801 /* This works for definite- and indefinite-length maps and
2802 * arrays by using the nesting level
Laurence Lundblade1341c592020-04-11 14:19:05 -07002803 */
2804 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002805 uReturn = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002806 if(QCBORDecode_IsUnrecoverableError(uReturn) ||
2807 uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002808 goto Done;
2809 }
2810 } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002811
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002812 *puNextNestLevel = Item.uNextNestLevel;
2813
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002814 uReturn = QCBOR_SUCCESS;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002815
Laurence Lundblade1341c592020-04-11 14:19:05 -07002816 } else {
Laurence Lundbladeaf5921e2022-07-15 09:06:30 -07002817 /* pItemToConsume is not a map or array. Just pass the nesting
2818 * level through. */
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002819 *puNextNestLevel = pItemToConsume->uNextNestLevel;
2820
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002821 uReturn = QCBOR_SUCCESS;
Laurence Lundblade1341c592020-04-11 14:19:05 -07002822 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002823
2824Done:
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07002825 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002826}
2827
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002828
2829void QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
2830{
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002831 QCBORDecode_VGetNext(pMe, pDecodedItem);
2832
2833 if(pMe->uLastError == QCBOR_SUCCESS) {
Máté Tóth-Pálc6d59682021-05-26 18:55:30 +02002834 pMe->uLastError = (uint8_t)ConsumeItem(pMe, pDecodedItem,
2835 &pDecodedItem->uNextNestLevel);
Laurence Lundblade732e52d2021-02-22 20:11:01 -07002836 }
2837}
2838
2839
2840
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002841/* Call only on maps and arrays. Rewinds the cursor
2842 * to the start as if it was just entered.
2843 */
2844static void RewindMapOrArray(QCBORDecodeContext *pMe)
2845{
2846 /* Reset nesting tracking to the deepest bounded level */
2847 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2848
2849 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
2850
2851 /* Reposition traversal cursor to the start of the map/array */
2852 UsefulInputBuf_Seek(&(pMe->InBuf),
2853 DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
2854}
2855
2856
2857/*
2858 Public function, see header qcbor/qcbor_decode.h file
2859 */
2860void QCBORDecode_Rewind(QCBORDecodeContext *pMe)
2861{
2862 if(pMe->nesting.pCurrentBounded != NULL) {
2863 /* In a bounded map, array or bstr-wrapped CBOR */
2864
2865 if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
2866 /* In bstr-wrapped CBOR. */
2867
2868 /* Reposition traversal cursor to start of wrapping byte string */
2869 UsefulInputBuf_Seek(&(pMe->InBuf),
2870 pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
2871 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
2872
2873 } else {
2874 /* In a map or array */
2875 RewindMapOrArray(pMe);
2876 }
2877
2878 } else {
2879 /* Not in anything bounded */
2880
2881 /* Reposition traversal cursor to the start of input CBOR */
2882 UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
2883
2884 /* Reset nesting tracking to beginning of input. */
2885 DecodeNesting_Init(&(pMe->nesting));
2886 }
2887
2888 pMe->uLastError = QCBOR_SUCCESS;
2889}
2890
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002891
Laurence Lundblade1341c592020-04-11 14:19:05 -07002892/* Return true if the labels in Item1 and Item2 are the same.
2893 Works only for integer and string labels. Returns false
2894 for any other type. */
2895static inline bool
2896MatchLabel(QCBORItem Item1, QCBORItem Item2)
2897{
2898 if(Item1.uLabelType == QCBOR_TYPE_INT64) {
2899 if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
2900 return true;
2901 }
2902 } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002903 if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07002904 return true;
2905 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002906 } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002907 if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
2908 return true;
2909 }
2910 } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
2911 if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
2912 return true;
2913 }
2914 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07002915
Laurence Lundblade1341c592020-04-11 14:19:05 -07002916 /* Other label types are never matched */
2917 return false;
2918}
2919
Laurence Lundblade2b843b52020-06-16 20:51:03 -07002920
2921/*
2922 Returns true if Item1 and Item2 are the same type
2923 or if either are of QCBOR_TYPE_ANY.
2924 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002925static inline bool
2926MatchType(QCBORItem Item1, QCBORItem Item2)
2927{
2928 if(Item1.uDataType == Item2.uDataType) {
2929 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002930 } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002931 return true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07002932 } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002933 return true;
2934 }
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002935 return false;
2936}
2937
2938
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002939/**
Laurence Lundblade5f53f832020-09-03 12:00:14 -07002940 @brief Search a map for a set of items.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002941
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002942 @param[in] pMe The decode context to search.
2943 @param[in,out] pItemArray The items to search for and the items found.
2944 @param[out] puOffset Byte offset of last item matched.
2945 @param[in] pCBContext Context for the not-found item call back.
2946 @param[in] pfCallback Function to call on items not matched in pItemArray.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002947
2948 @retval QCBOR_ERR_NOT_ENTERED Trying to search without having entered a map
2949
Laurence Lundblade93d89472020-10-03 22:30:50 -07002950 @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
2951 were found for one of the labels being
2952 search for. This duplicate detection is
2953 only performed for items in pItemArray,
2954 not every item in the map.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002955
Laurence Lundblade93d89472020-10-03 22:30:50 -07002956 @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
2957 wrong for the matchd label.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002958
2959 @retval Also errors returned by QCBORDecode_GetNext().
2960
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002961 On input pItemArray contains a list of labels and data types
2962 of items to be found.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002963
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07002964 On output the fully retrieved items are filled in with
2965 values and such. The label was matched, so it never changes.
Laurence Lundblade9b334962020-08-27 10:55:53 -07002966
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002967 If an item was not found, its data type is set to QCBOR_TYPE_NONE.
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07002968
2969 This also finds the ends of maps and arrays when they are exited.
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002970 */
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07002971static QCBORError
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002972MapSearch(QCBORDecodeContext *pMe,
2973 QCBORItem *pItemArray,
2974 size_t *puOffset,
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002975 void *pCBContext,
2976 QCBORItemCallback pfCallback)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07002977{
Laurence Lundbladee6f15112020-07-23 18:44:16 -07002978 QCBORError uReturn;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002979 uint64_t uFoundItemBitMap = 0;
Laurence Lundbladefb492ea2020-05-02 11:14:07 -07002980
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002981 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002982 uReturn = pMe->uLastError;
2983 goto Done2;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07002984 }
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002985
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002986 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002987 pItemArray->uLabelType != QCBOR_TYPE_NONE) {
2988 /* QCBOR_TYPE_NONE as first item indicates just looking
2989 for the end of an array, so don't give error. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07002990 uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
2991 goto Done2;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07002992 }
2993
Laurence Lundblade085d7952020-07-24 10:26:30 -07002994 if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
2995 // It is an empty bounded array or map
2996 if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
2997 // Just trying to find the end of the map or array
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07002998 pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
Laurence Lundblade085d7952020-07-24 10:26:30 -07002999 uReturn = QCBOR_SUCCESS;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003000 } else {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003001 // Nothing is ever found in an empty array or map. All items
3002 // are marked as not found below.
Laurence Lundblade085d7952020-07-24 10:26:30 -07003003 uReturn = QCBOR_SUCCESS;
3004 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003005 goto Done2;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003006 }
3007
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003008 QCBORDecodeNesting SaveNesting;
Laurence Lundblade085d7952020-07-24 10:26:30 -07003009 DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
3010
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003011 /* Reposition to search from the start of the map / array */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003012 RewindMapOrArray(pMe);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003013
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003014 /*
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003015 Loop over all the items in the map or array. Each item
3016 could be a map or array, but label matching is only at
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003017 the main level. This handles definite- and indefinite-
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003018 length maps and arrays. The only reason this is ever
3019 called on arrays is to find their end position.
3020
3021 This will always run over all items in order to do
3022 duplicate detection.
3023
3024 This will exit with failure if it encounters an
3025 unrecoverable error, but continue on for recoverable
3026 errors.
3027
3028 If a recoverable error occurs on a matched item, then
3029 that error code is returned.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003030 */
Laurence Lundblade0a042a92020-06-12 14:09:50 -07003031 const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
Máté Tóth-Pál2f2aa5f2021-05-17 21:35:09 +02003032 uint8_t uNextNestLevel;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003033 do {
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003034 /* Remember offset of the item because sometimes it has to be returned */
Laurence Lundblade1341c592020-04-11 14:19:05 -07003035 const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003036
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003037 /* Get the item */
3038 QCBORItem Item;
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003039 QCBORError uResult = QCBORDecode_GetNextTagContent(pMe, &Item);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003040 if(QCBORDecode_IsUnrecoverableError(uResult)) {
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003041 /* Unrecoverable error so map can't even be decoded. */
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003042 uReturn = uResult;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003043 goto Done;
3044 }
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003045 if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003046 // Unexpected end of map or array.
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003047 uReturn = uResult;
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003048 goto Done;
3049 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003050
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003051 /* See if item has one of the labels that are of interest */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003052 bool bMatched = false;
3053 for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
3054 if(MatchLabel(Item, pItemArray[nIndex])) {
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003055 /* A label match has been found */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003056 if(uFoundItemBitMap & (0x01ULL << nIndex)) {
3057 uReturn = QCBOR_ERR_DUPLICATE_LABEL;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003058 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003059 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003060 if(uResult != QCBOR_SUCCESS) {
3061 /* The label matches, but the data item is in error */
3062 uReturn = uResult;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003063 goto Done;
3064 }
Laurence Lundblade63926052021-03-29 16:05:51 -07003065 if(!MatchType(Item, pItemArray[nIndex])) {
3066 /* The data item is not of the type(s) requested */
3067 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003068 goto Done;
3069 }
3070
Laurence Lundblade1341c592020-04-11 14:19:05 -07003071 /* Successful match. Return the item. */
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003072 pItemArray[nIndex] = Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003073 uFoundItemBitMap |= 0x01ULL << nIndex;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003074 if(puOffset) {
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003075 *puOffset = uOffset;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003076 }
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003077 bMatched = true;
3078 }
3079 }
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003080
3081
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003082 if(!bMatched && pfCallback != NULL) {
3083 /*
3084 Call the callback on unmatched labels.
3085 (It is tempting to do duplicate detection here, but that would
3086 require dynamic memory allocation because the number of labels
3087 that might be encountered is unbounded.)
3088 */
3089 uReturn = (*pfCallback)(pCBContext, &Item);
3090 if(uReturn != QCBOR_SUCCESS) {
3091 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003092 }
3093 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003094
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003095 /*
3096 Consume the item whether matched or not. This
3097 does the work of traversing maps and array and
3098 everything in them. In this loop only the
3099 items at the current nesting level are examined
3100 to match the labels.
3101 */
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003102 uReturn = ConsumeItem(pMe, &Item, &uNextNestLevel);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003103 if(uReturn != QCBOR_SUCCESS) {
Laurence Lundblade1341c592020-04-11 14:19:05 -07003104 goto Done;
3105 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003106
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003107 } while (uNextNestLevel >= uMapNestLevel);
Laurence Lundblade9b334962020-08-27 10:55:53 -07003108
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003109 uReturn = QCBOR_SUCCESS;
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003110
3111 const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003112
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003113 // Check here makes sure that this won't accidentally be
3114 // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003115 // QCBOR_MAX_DECODE_INPUT_SIZE.
Laurence Lundblade9c1b7b42020-12-12 11:44:16 -08003116 // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
3117 if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003118 uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
3119 goto Done;
3120 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003121 /* Cast OK because encoded CBOR is limited to UINT32_MAX */
3122 pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003123
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003124 Done:
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003125 DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
3126
3127 Done2:
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003128 /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
Laurence Lundbladec7114722020-08-13 05:11:40 -07003129 for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003130 if(!(uFoundItemBitMap & (0x01ULL << i))) {
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003131 pItemArray[i].uDataType = QCBOR_TYPE_NONE;
3132 pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003133 }
3134 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003135
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003136 return uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003137}
3138
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003139
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003140/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003141 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003142*/
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003143void QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
3144 int64_t nLabel,
3145 uint8_t uQcborType,
3146 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003147{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003148 if(pMe->uLastError != QCBOR_SUCCESS) {
3149 return;
3150 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003151
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003152 QCBORItem OneItemSeach[2];
3153 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3154 OneItemSeach[0].label.int64 = nLabel;
3155 OneItemSeach[0].uDataType = uQcborType;
3156 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003157
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003158 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
Laurence Lundblade93d3f532020-09-28 21:09:12 -07003159
3160 *pItem = OneItemSeach[0];
3161
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003162 if(uReturn != QCBOR_SUCCESS) {
3163 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003164 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003165 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003166 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003167 }
3168
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003169 Done:
3170 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003171}
3172
3173
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003174/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003175 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003176*/
Laurence Lundbladeda095972020-06-06 18:35:33 -07003177void QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
3178 const char *szLabel,
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003179 uint8_t uQcborType,
3180 QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003181{
Laurence Lundbladeda095972020-06-06 18:35:33 -07003182 if(pMe->uLastError != QCBOR_SUCCESS) {
3183 return;
3184 }
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003185
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003186 QCBORItem OneItemSeach[2];
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003187 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3188 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3189 OneItemSeach[0].uDataType = uQcborType;
3190 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE; // Indicates end of array
Laurence Lundblade1341c592020-04-11 14:19:05 -07003191
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003192 QCBORError uReturn = MapSearch(pMe, OneItemSeach, NULL, NULL, NULL);
3193 if(uReturn != QCBOR_SUCCESS) {
3194 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003195 }
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003196 if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003197 uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003198 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003199 }
3200
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003201 *pItem = OneItemSeach[0];
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003202
3203Done:
3204 pMe->uLastError = (uint8_t)uReturn;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003205}
3206
3207
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003208
Laurence Lundblade93d89472020-10-03 22:30:50 -07003209static QCBORError
3210CheckTypeList(int uDataType, const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07003211{
3212 for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
3213 if(uDataType == puTypeList[i]) {
3214 return QCBOR_SUCCESS;
3215 }
3216 }
3217 return QCBOR_ERR_UNEXPECTED_TYPE;
3218}
3219
Laurence Lundblade67257dc2020-07-27 03:33:37 -07003220
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003221/**
3222 @param[in] TagSpec Specification for matching tags.
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003223 @param[in] pItem The item to check.
Laurence Lundblade9b334962020-08-27 10:55:53 -07003224
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003225 @retval QCBOR_SUCCESS \c uDataType is allowed by @c TagSpec
3226 @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
Laurence Lundblade9b334962020-08-27 10:55:53 -07003227
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003228 The data type must be one of the QCBOR_TYPEs, not the IETF CBOR Registered
3229 tag value.
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003230 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07003231static QCBORError
3232CheckTagRequirement(const TagSpecification TagSpec, const QCBORItem *pItem)
Laurence Lundblade9b334962020-08-27 10:55:53 -07003233{
3234 if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
3235 pItem->uTags[0] != CBOR_TAG_INVALID16) {
3236 /* There are tags that QCBOR couldn't process on this item and
3237 the caller has told us there should not be. */
3238 return QCBOR_ERR_UNEXPECTED_TYPE;
3239 }
3240
3241 const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
3242 const int nItemType = pItem->uDataType;
3243
3244 if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
3245 // Must match the tag and only the tag
3246 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3247 }
3248
3249 QCBORError uReturn = CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
3250 if(uReturn == QCBOR_SUCCESS) {
3251 return QCBOR_SUCCESS;
3252 }
3253
3254 if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
3255 /* Must match the content type and only the content type.
3256 There was no match just above so it is a fail. */
3257 return QCBOR_ERR_UNEXPECTED_TYPE;
3258 }
3259
3260 /* If here it can match either the tag or the content
3261 and it hasn't matched the content, so the end
3262 result is whether it matches the tag. This is
3263 also the case that the CBOR standard discourages. */
3264
3265 return CheckTypeList(nItemType, TagSpec.uTaggedTypes);
3266}
3267
Laurence Lundblade9b334962020-08-27 10:55:53 -07003268
Laurence Lundblade9b334962020-08-27 10:55:53 -07003269
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003270// This could be semi-private if need be
3271static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003272void QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext *pMe,
3273 int64_t nLabel,
3274 TagSpecification TagSpec,
3275 QCBORItem *pItem)
3276{
3277 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
3278 if(pMe->uLastError != QCBOR_SUCCESS) {
3279 return;
3280 }
3281
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003282 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003283}
3284
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07003285
3286// This could be semi-private if need be
3287static inline
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003288void QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext *pMe,
3289 const char *szLabel,
3290 TagSpecification TagSpec,
3291 QCBORItem *pItem)
3292{
3293 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
3294 if(pMe->uLastError != QCBOR_SUCCESS) {
3295 return;
3296 }
3297
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003298 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003299}
3300
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003301// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003302void QCBORDecode_GetTaggedStringInMapN(QCBORDecodeContext *pMe,
3303 int64_t nLabel,
3304 TagSpecification TagSpec,
3305 UsefulBufC *pString)
3306{
3307 QCBORItem Item;
3308 QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
3309 if(pMe->uLastError == QCBOR_SUCCESS) {
3310 *pString = Item.val.string;
3311 }
3312}
3313
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003314// Semi-private
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003315void QCBORDecode_GetTaggedStringInMapSZ(QCBORDecodeContext *pMe,
3316 const char * szLabel,
3317 TagSpecification TagSpec,
3318 UsefulBufC *pString)
3319{
3320 QCBORItem Item;
3321 QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
3322 if(pMe->uLastError == QCBOR_SUCCESS) {
3323 *pString = Item.val.string;
3324 }
3325}
Laurence Lundblade1341c592020-04-11 14:19:05 -07003326
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003327/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003328 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003329*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003330void QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003331{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003332 QCBORError uErr = MapSearch(pMe, pItemList, NULL, NULL, NULL);
3333 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003334}
3335
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003336/*
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003337 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003338*/
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003339void QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
3340 QCBORItem *pItemList,
3341 void *pCallbackCtx,
3342 QCBORItemCallback pfCB)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003343{
Laurence Lundblade5f53f832020-09-03 12:00:14 -07003344 QCBORError uErr = MapSearch(pMe, pItemList, NULL, pCallbackCtx, pfCB);
3345 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003346}
3347
3348
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003349/**
3350 * @brief Search for a map/array by label and enter it
3351 *
3352 * @param[in] pMe The decode context.
3353 * @param[in] pSearch The map/array to search for.
3354 *
3355 * @c pSearch is expected to contain one item of type map or array
3356 * with the label specified. The current bounded map will be searched for
3357 * this and if found will be entered.
3358 *
3359 * If the label is not found, or the item found is not a map or array,
3360 * the error state is set.
3361 */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003362static void SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
Laurence Lundblade1341c592020-04-11 14:19:05 -07003363{
Laurence Lundblade323f8a92020-09-06 19:43:09 -07003364 // The first item in pSearch is the one that is to be
3365 // entered. It should be the only one filled in. Any other
3366 // will be ignored unless it causes an error.
Laurence Lundblade34691b92020-05-18 22:25:25 -07003367 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade34691b92020-05-18 22:25:25 -07003368 return;
3369 }
3370
3371 size_t uOffset;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003372 pMe->uLastError = (uint8_t)MapSearch(pMe, pSearch, &uOffset, NULL, NULL);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003373 if(pMe->uLastError != QCBOR_SUCCESS) {
3374 return;
3375 }
3376
Laurence Lundblade9b334962020-08-27 10:55:53 -07003377 if(pSearch->uDataType == QCBOR_TYPE_NONE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003378 pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003379 return;
3380 }
3381
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003382
3383 /* The map or array was found. Now enter it.
3384 *
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003385 * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
3386 * next item for the pre-order traversal cursor to be the map/array
3387 * found by MapSearch(). The next few lines of code force the
3388 * cursor to that.
3389 *
3390 * There is no need to retain the old cursor because
3391 * QCBORDecode_EnterBoundedMapOrArray() will set it to the
3392 * beginning of the map/array being entered.
3393 *
3394 * The cursor is forced by: 1) setting the input buffer position to
3395 * the item offset found by MapSearch(), 2) setting the map/array
3396 * counter to the total in the map/array, 3) setting the nesting
3397 * level. Setting the map/array counter to the total is not
3398 * strictly correct, but this is OK because this cursor only needs
3399 * to be used to get one item and MapSearch() has already found it
3400 * confirming it exists.
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003401 */
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003402 UsefulInputBuf_Seek(&(pMe->InBuf), uOffset);
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003403
Laurence Lundbladeddebabe2020-11-22 11:32:17 -08003404 DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
3405
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003406 DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003407
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003408 QCBORDecode_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003409}
3410
3411
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003412/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003413 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003414*/
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003415void QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003416{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003417 QCBORItem OneItemSeach[2];
3418 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3419 OneItemSeach[0].label.int64 = nLabel;
3420 OneItemSeach[0].uDataType = QCBOR_TYPE_MAP;
3421 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003422
Laurence Lundblade9b334962020-08-27 10:55:53 -07003423 /* The map to enter was found, now finish off entering it. */
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003424 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003425}
3426
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_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003432{
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_MAP;
3437 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade9b334962020-08-27 10:55:53 -07003438
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003439 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003440}
3441
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003442/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003443 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003444*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003445void QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
Laurence Lundblade1341c592020-04-11 14:19:05 -07003446{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003447 QCBORItem OneItemSeach[2];
3448 OneItemSeach[0].uLabelType = QCBOR_TYPE_INT64;
3449 OneItemSeach[0].label.int64 = nLabel;
3450 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3451 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003452
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003453 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade34691b92020-05-18 22:25:25 -07003454}
3455
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003456/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003457 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003458*/
Laurence Lundblade34691b92020-05-18 22:25:25 -07003459void QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel)
3460{
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003461 QCBORItem OneItemSeach[2];
3462 OneItemSeach[0].uLabelType = QCBOR_TYPE_TEXT_STRING;
3463 OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
3464 OneItemSeach[0].uDataType = QCBOR_TYPE_ARRAY;
3465 OneItemSeach[1].uLabelType = QCBOR_TYPE_NONE;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003466
Laurence Lundbladeb90f5362020-05-25 12:17:40 -07003467 SearchAndEnter(pMe, OneItemSeach);
Laurence Lundblade1341c592020-04-11 14:19:05 -07003468}
3469
3470
Laurence Lundblade02625d42020-06-25 14:41:41 -07003471// Semi-private function
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003472void QCBORDecode_EnterBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType, QCBORItem *pItem)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003473{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003474 QCBORError uErr;
3475
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003476 /* Must only be called on maps and arrays. */
Laurence Lundblade34691b92020-05-18 22:25:25 -07003477 if(pMe->uLastError != QCBOR_SUCCESS) {
3478 // Already in error state; do nothing.
3479 return;
3480 }
Laurence Lundblade1341c592020-04-11 14:19:05 -07003481
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003482 /* Get the data item that is the map or array being entered. */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003483 QCBORItem Item;
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003484 uErr = QCBORDecode_GetNext(pMe, &Item);
3485 if(uErr != QCBOR_SUCCESS) {
3486 goto Done;
Laurence Lundblade3f9ef042020-04-14 13:15:51 -07003487 }
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07003488 if(Item.uDataType != uType) {
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003489 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
3490 goto Done;
Laurence Lundblade1341c592020-04-11 14:19:05 -07003491 }
3492
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003493 CopyTags(pMe, &Item);
Laurence Lundbladed40951e2020-08-28 11:11:14 -07003494
3495
Laurence Lundbladef0499502020-08-01 11:55:57 -07003496 const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
Laurence Lundblade085d7952020-07-24 10:26:30 -07003497 if(bIsEmpty) {
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003498 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
3499 // Undo decrement done by QCBORDecode_GetNext() so the the
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003500 // the decrement when exiting the map/array works correctly
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07003501 pMe->nesting.pCurrent->u.ma.uCountCursor++;
3502 }
Laurence Lundblade93d89472020-10-03 22:30:50 -07003503 // Special case to increment nesting level for zero-length maps
3504 // and arrays entered in bounded mode.
Laurence Lundbladee6f15112020-07-23 18:44:16 -07003505 DecodeNesting_Descend(&(pMe->nesting), uType);
3506 }
3507
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003508 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003509
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003510 uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
3511 UsefulInputBuf_Tell(&(pMe->InBuf)));
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003512
Laurence Lundblade6545d1b2020-10-14 11:13:13 -07003513 if(pItem != NULL) {
3514 *pItem = Item;
3515 }
3516
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003517Done:
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003518 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003519}
3520
Laurence Lundblade02625d42020-06-25 14:41:41 -07003521
3522/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07003523 This is the common work for exiting a level that is a bounded map,
3524 array or bstr wrapped CBOR.
Laurence Lundblade02625d42020-06-25 14:41:41 -07003525
3526 One chunk of work is to set up the pre-order traversal so it is at
3527 the item just after the bounded map, array or bstr that is being
3528 exited. This is somewhat complex.
3529
3530 The other work is to level-up the bounded mode to next higest bounded
3531 mode or the top level if there isn't one.
3532 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003533static QCBORError
Laurence Lundblade02625d42020-06-25 14:41:41 -07003534ExitBoundedLevel(QCBORDecodeContext *pMe, uint32_t uEndOffset)
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003535{
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003536 QCBORError uErr;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003537
Laurence Lundblade02625d42020-06-25 14:41:41 -07003538 /*
3539 First the pre-order-traversal byte offset is positioned to the
3540 item just after the bounded mode item that was just consumed.
3541 */
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003542 UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
3543
Laurence Lundblade02625d42020-06-25 14:41:41 -07003544 /*
3545 Next, set the current nesting level to one above the bounded level
3546 that was just exited.
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003547
Laurence Lundblade02625d42020-06-25 14:41:41 -07003548 DecodeNesting_CheckBoundedType() is always called before this and
3549 makes sure pCurrentBounded is valid.
3550 */
3551 DecodeNesting_LevelUpCurrent(&(pMe->nesting));
3552
3553 /*
3554 This does the complex work of leveling up the pre-order traversal
3555 when the end of a map or array or another bounded level is
3556 reached. It may do nothing, or ascend all the way to the top
3557 level.
3558 */
Laurence Lundblade3f1318a2021-01-04 18:26:44 -08003559 uErr = QCBORDecode_NestLevelAscender(pMe, false);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003560 if(uErr != QCBOR_SUCCESS) {
3561 goto Done;
3562 }
3563
Laurence Lundblade02625d42020-06-25 14:41:41 -07003564 /*
3565 This makes the next highest bounded level the current bounded
3566 level. If there is no next highest level, then no bounded mode is
3567 in effect.
3568 */
3569 DecodeNesting_LevelUpBounded(&(pMe->nesting));
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003570
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003571 pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003572
3573Done:
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003574 return uErr;
3575}
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003576
Laurence Lundblade02625d42020-06-25 14:41:41 -07003577
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003578// Semi-private function
Laurence Lundblade02625d42020-06-25 14:41:41 -07003579void QCBORDecode_ExitBoundedMapOrArray(QCBORDecodeContext *pMe, uint8_t uType)
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003580{
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003581 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade02625d42020-06-25 14:41:41 -07003582 /* Already in error state; do nothing. */
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003583 return;
3584 }
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003585
Laurence Lundblade02625d42020-06-25 14:41:41 -07003586 QCBORError uErr;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003587
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003588 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003589 uErr = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003590 goto Done;
3591 }
3592
Laurence Lundblade02625d42020-06-25 14:41:41 -07003593 /*
3594 Have to set the offset to the end of the map/array
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003595 that is being exited. If there is no cached value,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003596 from previous map search, then do a dummy search.
3597 */
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07003598 if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003599 QCBORItem Dummy;
3600 Dummy.uLabelType = QCBOR_TYPE_NONE;
3601 uErr = MapSearch(pMe, &Dummy, NULL, NULL, NULL);
3602 if(uErr != QCBOR_SUCCESS) {
3603 goto Done;
3604 }
3605 }
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003606
Laurence Lundblade02625d42020-06-25 14:41:41 -07003607 uErr = ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003608
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003609Done:
Laurence Lundblade2b843b52020-06-16 20:51:03 -07003610 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladebb87be22020-04-09 19:15:32 -07003611}
3612
3613
Laurence Lundblade1341c592020-04-11 14:19:05 -07003614
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003615static QCBORError InternalEnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003616 const QCBORItem *pItem,
3617 uint8_t uTagRequirement,
3618 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003619{
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003620 if(pBstr) {
3621 *pBstr = NULLUsefulBufC;
3622 }
3623
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003624 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003625 /* Already in error state; do nothing. */
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003626 return pMe->uLastError;
3627 }
3628
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003629 QCBORError uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003630
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003631 const TagSpecification TagSpec =
3632 {
3633 uTagRequirement,
3634 {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
3635 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3636 };
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003637
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003638 uError = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003639 if(uError != QCBOR_SUCCESS) {
3640 goto Done;
3641 }
3642
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003643 if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003644 /* Reverse the decrement done by GetNext() for the bstr so the
3645 * increment in QCBORDecode_NestLevelAscender() called by
3646 * ExitBoundedLevel() will work right.
3647 */
Laurence Lundbladea8edadb2020-06-27 22:35:37 -07003648 DecodeNesting_ReverseDecrement(&(pMe->nesting));
Laurence Lundblade6c8a4442020-06-22 22:16:11 -07003649 }
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003650
3651 if(pBstr) {
3652 *pBstr = pItem->val.string;
3653 }
3654
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003655 /* This saves the current length of the UsefulInputBuf and then
3656 * narrows the UsefulInputBuf to start and length of the wrapped
3657 * CBOR that is being entered.
3658 *
3659 * Most of these calls are simple inline accessors so this doesn't
3660 * amount to much code.
3661 */
3662
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003663 const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003664 /* This check makes the cast of uPreviousLength to uint32_t below safe. */
3665 if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003666 uError = QCBOR_ERR_INPUT_TOO_LARGE;
Laurence Lundbladef76a2622020-08-06 19:51:03 -07003667 goto Done;
3668 }
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003669
3670 const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
3671 pItem->val.string.ptr);
3672 /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
3673 if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
3674 /* This should never happen because pItem->val.string.ptr should
3675 * always be valid since it was just returned.
3676 */
3677 uError = QCBOR_ERR_INPUT_TOO_LARGE;
3678 goto Done;
3679 }
3680
3681 const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
3682
3683 UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003684 UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003685
Laurence Lundblade02625d42020-06-25 14:41:41 -07003686 uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
Laurence Lundbladea4308a82020-10-03 18:08:57 -07003687 (uint32_t)uPreviousLength,
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003688 (uint32_t)uStartOfBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003689Done:
3690 return uError;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003691}
3692
3693
Laurence Lundblade02625d42020-06-25 14:41:41 -07003694/*
3695 Public function, see header qcbor/qcbor_decode.h file
3696 */
3697void QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
Laurence Lundbladec45b5672020-07-25 23:16:36 -07003698 uint8_t uTagRequirement,
3699 UsefulBufC *pBstr)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003700{
3701 if(pMe->uLastError != QCBOR_SUCCESS) {
3702 // Already in error state; do nothing.
3703 return;
3704 }
3705
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003706 /* Get the data item that is the byte string being entered */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003707 QCBORItem Item;
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003708 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3709 if(pMe->uLastError != QCBOR_SUCCESS) {
3710 return;
3711 }
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003712
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07003713 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003714 &Item,
3715 uTagRequirement,
3716 pBstr);
Laurence Lundblade24d509a2020-06-06 18:43:15 -07003717}
3718
3719
Laurence Lundblade02625d42020-06-25 14:41:41 -07003720/*
3721 Public function, see header qcbor/qcbor_decode.h file
3722 */
3723void QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003724 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003725 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003726 UsefulBufC *pBstr)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003727{
3728 QCBORItem Item;
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003729 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003730
Laurence Lundblade93d89472020-10-03 22:30:50 -07003731 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3732 &Item,
3733 uTagRequirement,
3734 pBstr);
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003735}
3736
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003737
Laurence Lundblade02625d42020-06-25 14:41:41 -07003738/*
3739 Public function, see header qcbor/qcbor_decode.h file
3740 */
3741void QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003742 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07003743 uint8_t uTagRequirement,
Laurence Lundblade02625d42020-06-25 14:41:41 -07003744 UsefulBufC *pBstr)
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003745{
3746 QCBORItem Item;
3747 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3748
Laurence Lundblade93d89472020-10-03 22:30:50 -07003749 pMe->uLastError = (uint8_t)InternalEnterBstrWrapped(pMe,
3750 &Item,
3751 uTagRequirement,
3752 pBstr);
Laurence Lundbladeaa965d72020-06-17 22:29:22 -07003753}
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003754
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003755
Laurence Lundblade02625d42020-06-25 14:41:41 -07003756/*
3757 Public function, see header qcbor/qcbor_decode.h file
3758 */
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003759void QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003760{
Laurence Lundblade02625d42020-06-25 14:41:41 -07003761 if(pMe->uLastError != QCBOR_SUCCESS) {
3762 // Already in error state; do nothing.
3763 return;
3764 }
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003765
Laurence Lundblade2cd4b0d2020-07-31 08:29:07 -07003766 if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
Laurence Lundbladea9489f82020-09-12 13:50:56 -07003767 pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
Laurence Lundblade02625d42020-06-25 14:41:41 -07003768 return;
3769 }
3770
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003771 const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
3772
Laurence Lundblade02625d42020-06-25 14:41:41 -07003773 /*
3774 Reset the length of the UsefulInputBuf to what it was before
3775 the bstr wrapped CBOR was entered.
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003776 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07003777 UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003778 DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
Laurence Lundblade0750fc42020-06-20 21:02:34 -07003779
3780
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003781 QCBORError uErr = ExitBoundedLevel(pMe, uEndOfBstr);
Laurence Lundblade1d85d522020-06-22 13:24:59 -07003782 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed8c82c52020-06-12 22:15:52 -07003783}
3784
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003785
Laurence Lundbladee6430642020-03-14 21:15:44 -07003786
Laurence Lundblade82c2a8f2020-04-29 12:40:19 -07003787
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003788static inline void
3789ProcessBool(QCBORDecodeContext *pMe, const QCBORItem *pItem, bool *pBool)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003790{
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003791 if(pMe->uLastError != QCBOR_SUCCESS) {
3792 /* Already in error state, do nothing */
3793 return;
3794 }
3795
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003796 switch(pItem->uDataType) {
3797 case QCBOR_TYPE_TRUE:
3798 *pBool = true;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003799 break;
3800
3801 case QCBOR_TYPE_FALSE:
3802 *pBool = false;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003803 break;
3804
3805 default:
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003806 pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003807 break;
3808 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07003809 CopyTags(pMe, pItem);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003810}
Laurence Lundbladee6430642020-03-14 21:15:44 -07003811
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003812
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003813/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003814 * Public function, see header qcbor/qcbor_decode.h file
3815 */
Laurence Lundbladec4537442020-04-14 18:53:22 -07003816void QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003817{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07003818 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003819 /* Already in error state, do nothing */
Laurence Lundbladee6430642020-03-14 21:15:44 -07003820 return;
3821 }
3822
Laurence Lundbladec4537442020-04-14 18:53:22 -07003823 QCBORItem Item;
3824
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003825 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3826
3827 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003828}
3829
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003830
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003831/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003832 * Public function, see header qcbor/qcbor_decode.h file
3833 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003834void QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe, int64_t nLabel, bool *pValue)
Laurence Lundbladee6430642020-03-14 21:15:44 -07003835{
3836 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003837 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003838
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003839 ProcessBool(pMe, &Item, pValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07003840}
3841
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07003842
Laurence Lundblade4e2da002020-06-13 23:08:31 -07003843/*
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003844 * Public function, see header qcbor/qcbor_decode.h file
3845 */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003846void QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe, const char *szLabel, bool *pValue)
3847{
3848 QCBORItem Item;
3849 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3850
Laurence Lundblade9f9c3732021-03-23 09:38:46 -07003851 ProcessBool(pMe, &Item, pValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07003852}
3853
3854
3855
Laurence Lundbladec7114722020-08-13 05:11:40 -07003856
3857static void ProcessEpochDate(QCBORDecodeContext *pMe,
3858 QCBORItem *pItem,
3859 uint8_t uTagRequirement,
3860 int64_t *pnTime)
3861{
3862 if(pMe->uLastError != QCBOR_SUCCESS) {
3863 // Already in error state, do nothing
3864 return;
3865 }
3866
3867 QCBORError uErr;
3868
3869 const TagSpecification TagSpec =
3870 {
3871 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07003872 {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3873 {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
Laurence Lundbladec7114722020-08-13 05:11:40 -07003874 };
3875
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07003876 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladec7114722020-08-13 05:11:40 -07003877 if(uErr != QCBOR_SUCCESS) {
3878 goto Done;
3879 }
3880
3881 if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
3882 uErr = DecodeDateEpoch(pItem);
3883 if(uErr != QCBOR_SUCCESS) {
3884 goto Done;
3885 }
3886 }
3887
Laurence Lundblade9b334962020-08-27 10:55:53 -07003888 // Save the tags in the last item's tags in the decode context
3889 // for QCBORDecode_GetNthTagOfLast()
3890 CopyTags(pMe, pItem);
3891
Laurence Lundbladec7114722020-08-13 05:11:40 -07003892 *pnTime = pItem->val.epochDate.nSeconds;
3893
3894Done:
3895 pMe->uLastError = (uint8_t)uErr;
3896}
3897
3898
3899void QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07003900 uint8_t uTagRequirement,
3901 int64_t *pnTime)
Laurence Lundbladec7114722020-08-13 05:11:40 -07003902{
3903 if(pMe->uLastError != QCBOR_SUCCESS) {
3904 // Already in error state, do nothing
3905 return;
3906 }
3907
3908 QCBORItem Item;
3909 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
3910
3911 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3912}
3913
3914
3915void
3916QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
3917 int64_t nLabel,
3918 uint8_t uTagRequirement,
3919 int64_t *pnTime)
3920{
3921 QCBORItem Item;
3922 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
3923 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3924}
3925
3926
3927void
3928QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
3929 const char *szLabel,
3930 uint8_t uTagRequirement,
3931 int64_t *pnTime)
3932{
3933 QCBORItem Item;
3934 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
3935 ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
3936}
3937
3938
3939
Laurence Lundblade46d63e92021-05-13 11:37:10 -07003940/*
3941 * Common processing for the RFC 8943 day-count tag. Mostly
3942 * make sure the tag content is correct and copy forward any
3943 * further other tag numbers.
3944 */
3945static void ProcessEpochDays(QCBORDecodeContext *pMe,
3946 QCBORItem *pItem,
3947 uint8_t uTagRequirement,
3948 int64_t *pnDays)
3949{
3950 if(pMe->uLastError != QCBOR_SUCCESS) {
3951 /* Already in error state, do nothing */
3952 return;
3953 }
3954
3955 QCBORError uErr;
3956
3957 const TagSpecification TagSpec =
3958 {
3959 uTagRequirement,
3960 {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
3961 {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
3962 };
3963
3964 uErr = CheckTagRequirement(TagSpec, pItem);
3965 if(uErr != QCBOR_SUCCESS) {
3966 goto Done;
3967 }
3968
3969 if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
3970 uErr = DecodeDaysEpoch(pItem);
3971 if(uErr != QCBOR_SUCCESS) {
3972 goto Done;
3973 }
3974 }
3975
3976 /* Save the tags in the last item's tags in the decode context
3977 * for QCBORDecode_GetNthTagOfLast()
3978 */
3979 CopyTags(pMe, pItem);
3980
3981 *pnDays = pItem->val.epochDays;
3982
3983Done:
3984 pMe->uLastError = (uint8_t)uErr;
3985}
3986
3987
3988/*
3989 * Public function, see header qcbor/qcbor_decode.h
3990 */
3991void QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
3992 uint8_t uTagRequirement,
3993 int64_t *pnDays)
3994{
3995 if(pMe->uLastError != QCBOR_SUCCESS) {
3996 /* Already in error state, do nothing */
3997 return;
3998 }
3999
4000 QCBORItem Item;
4001 pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
4002
4003 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4004}
4005
4006
4007/*
4008 * Public function, see header qcbor/qcbor_decode.h
4009 */
4010void
4011QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
4012 int64_t nLabel,
4013 uint8_t uTagRequirement,
4014 int64_t *pnDays)
4015{
4016 QCBORItem Item;
4017 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
4018 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4019}
4020
4021
4022/*
4023 * Public function, see header qcbor/qcbor_decode.h
4024 */
4025void
4026QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
4027 const char *szLabel,
4028 uint8_t uTagRequirement,
4029 int64_t *pnDays)
4030{
4031 QCBORItem Item;
4032 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
4033 ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
4034}
4035
4036
4037
Laurence Lundbladec7114722020-08-13 05:11:40 -07004038
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004039void QCBORDecode_GetTaggedStringInternal(QCBORDecodeContext *pMe,
4040 TagSpecification TagSpec,
4041 UsefulBufC *pBstr)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004042{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004043 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004044 // Already in error state, do nothing
4045 return;
4046 }
4047
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004048 QCBORError uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004049 QCBORItem Item;
4050
Laurence Lundblade5f4e8712020-07-25 11:44:43 -07004051 uError = QCBORDecode_GetNext(pMe, &Item);
4052 if(uError != QCBOR_SUCCESS) {
4053 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004054 return;
4055 }
4056
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004057 pMe->uLastError = (uint8_t)CheckTagRequirement(TagSpec, &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004058
4059 if(pMe->uLastError == QCBOR_SUCCESS) {
4060 *pBstr = Item.val.string;
Laurence Lundbladeab40c6f2020-08-28 11:24:58 -07004061 } else {
4062 *pBstr = NULLUsefulBufC;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004063 }
4064}
4065
Laurence Lundbladec4537442020-04-14 18:53:22 -07004066
4067
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004068
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004069static QCBORError ProcessBigNum(uint8_t uTagRequirement,
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004070 const QCBORItem *pItem,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004071 UsefulBufC *pValue,
4072 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004073{
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004074 const TagSpecification TagSpec =
4075 {
4076 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004077 {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4078 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004079 };
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004080
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004081 QCBORError uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004082 if(uErr != QCBOR_SUCCESS) {
4083 return uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004084 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004085
4086 *pValue = pItem->val.string;
4087
4088 if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
4089 *pbIsNegative = false;
4090 } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
4091 *pbIsNegative = true;
4092 }
4093
4094 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004095}
4096
4097
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004098/*
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004099 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004100 */
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004101void QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
4102 uint8_t uTagRequirement,
4103 UsefulBufC *pValue,
4104 bool *pbIsNegative)
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004105{
4106 if(pMe->uLastError != QCBOR_SUCCESS) {
4107 // Already in error state, do nothing
4108 return;
4109 }
4110
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004111 QCBORItem Item;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004112 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4113 if(uError != QCBOR_SUCCESS) {
4114 pMe->uLastError = (uint8_t)uError;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004115 return;
4116 }
4117
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004118 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004119}
4120
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004121
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004122/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004123 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade4e2da002020-06-13 23:08:31 -07004124*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004125void QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
4126 int64_t nLabel,
4127 uint8_t uTagRequirement,
4128 UsefulBufC *pValue,
4129 bool *pbIsNegative)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004130{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004131 QCBORItem Item;
4132 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004133 if(pMe->uLastError != QCBOR_SUCCESS) {
4134 return;
4135 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004136
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004137 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004138}
4139
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004140
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004141/*
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004142 Public function, see header qcbor/qcbor_decode.h
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004143*/
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004144void QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
4145 const char *szLabel,
4146 uint8_t uTagRequirement,
4147 UsefulBufC *pValue,
4148 bool *pbIsNegative)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004149{
4150 QCBORItem Item;
4151 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004152 if(pMe->uLastError != QCBOR_SUCCESS) {
4153 return;
4154 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004155
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07004156 pMe->uLastError = (uint8_t)ProcessBigNum(uTagRequirement, &Item, pValue, pbIsNegative);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004157}
4158
4159
4160
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004161
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004162// Semi private
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004163QCBORError QCBORDecode_GetMIMEInternal(uint8_t uTagRequirement,
4164 const QCBORItem *pItem,
4165 UsefulBufC *pMessage,
Laurence Lundblade4982f412020-09-18 23:02:18 -07004166 bool *pbIsTag257)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004167{
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004168 const TagSpecification TagSpecText =
4169 {
4170 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004171 {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4172 {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004173 };
4174 const TagSpecification TagSpecBinary =
4175 {
4176 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07004177 {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
4178 {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004179 };
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004180
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004181 QCBORError uReturn;
Laurence Lundblade9b334962020-08-27 10:55:53 -07004182
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004183 if(CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004184 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004185 if(pbIsTag257 != NULL) {
4186 *pbIsTag257 = false;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004187 }
4188 uReturn = QCBOR_SUCCESS;
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07004189 } else if(CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004190 *pMessage = pItem->val.string;
Laurence Lundblade4982f412020-09-18 23:02:18 -07004191 if(pbIsTag257 != NULL) {
4192 *pbIsTag257 = true;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004193 }
4194 uReturn = QCBOR_SUCCESS;
4195
4196 } else {
4197 uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
4198 }
Laurence Lundblade9b334962020-08-27 10:55:53 -07004199
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004200 return uReturn;
4201}
4202
Laurence Lundblade93d89472020-10-03 22:30:50 -07004203// Improvement: add methods for wrapped CBOR, a simple alternate
4204// to EnterBstrWrapped
Laurence Lundblade9bb039a2020-08-05 12:25:15 -07004205
Laurence Lundblade91853ae2020-06-15 19:35:58 -07004206
4207
4208
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004209#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladee6430642020-03-14 21:15:44 -07004210
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004211typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004212
4213
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004214// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07004215static QCBORError
4216Exponentitate10(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004217{
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004218 uint64_t uResult = uMantissa;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004219
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004220 if(uResult != 0) {
4221 /* This loop will run a maximum of 19 times because
4222 * UINT64_MAX < 10 ^^ 19. More than that will cause
4223 * exit with the overflow error
4224 */
4225 for(; nExponent > 0; nExponent--) {
4226 if(uResult > UINT64_MAX / 10) {
4227 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
4228 }
4229 uResult = uResult * 10;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004230 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004231
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004232 for(; nExponent < 0; nExponent++) {
4233 uResult = uResult / 10;
4234 if(uResult == 0) {
4235 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
4236 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004237 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004238 }
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004239 /* else, mantissa is zero so this returns zero */
Laurence Lundbladec4537442020-04-14 18:53:22 -07004240
4241 *puResult = uResult;
4242
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004243 return QCBOR_SUCCESS;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004244}
4245
4246
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004247// The exponentiator that works on only positive numbers
Laurence Lundblade93d89472020-10-03 22:30:50 -07004248static QCBORError
4249Exponentitate2(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004250{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004251 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004252
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004253 uResult = uMantissa;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004254
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004255 /* This loop will run a maximum of 64 times because
Laurence Lundbladee6430642020-03-14 21:15:44 -07004256 * INT64_MAX < 2^31. More than that will cause
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004257 * exit with the overflow error
Laurence Lundbladee6430642020-03-14 21:15:44 -07004258 */
4259 while(nExponent > 0) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004260 if(uResult > UINT64_MAX >> 1) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004261 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Error overflow
Laurence Lundbladee6430642020-03-14 21:15:44 -07004262 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004263 uResult = uResult << 1;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004264 nExponent--;
4265 }
4266
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004267 while(nExponent < 0 ) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004268 if(uResult == 0) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004269 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW; // Underflow error
4270 }
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004271 uResult = uResult >> 1;
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004272 nExponent++;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004273 }
4274
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004275 *puResult = uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004276
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004277 return QCBOR_SUCCESS;
4278}
4279
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004280
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004281/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004282 Compute value with signed mantissa and signed result. Works with
4283 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004284 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004285static inline QCBORError ExponentiateNN(int64_t nMantissa,
4286 int64_t nExponent,
4287 int64_t *pnResult,
4288 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004289{
4290 uint64_t uResult;
4291
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004292 // Take the absolute value of the mantissa and convert to unsigned.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004293 // Improvement: this should be possible in one instruction
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004294 uint64_t uMantissa = nMantissa > 0 ? (uint64_t)nMantissa : (uint64_t)-nMantissa;
4295
4296 // Do the exponentiation of the positive mantissa
4297 QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
4298 if(uReturn) {
4299 return uReturn;
4300 }
4301
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004302
Laurence Lundblade983500d2020-05-14 11:49:34 -07004303 /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
4304 of INT64_MIN. This assumes two's compliment representation where
4305 INT64_MIN is one increment farther from 0 than INT64_MAX.
4306 Trying to write -INT64_MIN doesn't work to get this because the
4307 compiler tries to work with an int64_t which can't represent
4308 -INT64_MIN.
4309 */
4310 uint64_t uMax = nMantissa > 0 ? INT64_MAX : (uint64_t)INT64_MAX+1;
4311
4312 // Error out if too large
4313 if(uResult > uMax) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004314 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4315 }
4316
4317 // Casts are safe because of checks above
4318 *pnResult = nMantissa > 0 ? (int64_t)uResult : -(int64_t)uResult;
4319
4320 return QCBOR_SUCCESS;
4321}
4322
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004323
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004324/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004325 Compute value with signed mantissa and unsigned result. Works with
4326 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004327 */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004328static inline QCBORError ExponentitateNU(int64_t nMantissa,
4329 int64_t nExponent,
4330 uint64_t *puResult,
4331 fExponentiator pfExp)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004332{
4333 if(nMantissa < 0) {
4334 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4335 }
4336
4337 // Cast to unsigned is OK because of check for negative
4338 // Cast to unsigned is OK because UINT64_MAX > INT64_MAX
4339 // Exponentiation is straight forward
4340 return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
4341}
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004342
4343
4344/*
Laurence Lundblade93d89472020-10-03 22:30:50 -07004345 Compute value with signed mantissa and unsigned result. Works with
4346 exponent of 2 or 10 based on exponentiator.
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004347 */
4348static inline QCBORError ExponentitateUU(uint64_t uMantissa,
4349 int64_t nExponent,
4350 uint64_t *puResult,
4351 fExponentiator pfExp)
4352{
4353 return (*pfExp)(uMantissa, nExponent, puResult);
4354}
4355
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004356#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004357
4358
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004359
4360
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004361
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07004362static QCBORError ConvertBigNumToUnsigned(const UsefulBufC BigNum, uint64_t uMax, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004363{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004364 uint64_t uResult;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004365
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004366 uResult = 0;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004367 const uint8_t *pByte = BigNum.ptr;
4368 size_t uLen = BigNum.len;
4369 while(uLen--) {
Laurence Lundblade313b2862020-05-16 01:23:06 -07004370 if(uResult > (uMax >> 8)) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004371 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004372 }
Laurence Lundblade313b2862020-05-16 01:23:06 -07004373 uResult = (uResult << 8) + *pByte++;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004374 }
4375
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004376 *pResult = uResult;
4377 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004378}
4379
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004380
Laurence Lundblade887add82020-05-17 05:50:34 -07004381static inline QCBORError ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum, uint64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004382{
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004383 return ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004384}
4385
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004386
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004387static inline QCBORError ConvertPositiveBigNumToSigned(const UsefulBufC BigNum, int64_t *pResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004388{
4389 uint64_t uResult;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004390 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
4391 if(uError) {
4392 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004393 }
4394 /* Cast is safe because ConvertBigNum is told to limit to INT64_MAX */
4395 *pResult = (int64_t)uResult;
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004396 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004397}
4398
4399
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004400static inline QCBORError ConvertNegativeBigNumToSigned(const UsefulBufC BigNum, int64_t *pnResult)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004401{
4402 uint64_t uResult;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004403 /* The negative integer furthest from zero for a C int64_t is
4404 INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
4405 negative number in CBOR is computed as -n - 1 where n is the
4406 encoded integer, where n is what is in the variable BigNum. When
4407 converting BigNum to a uint64_t, the maximum value is thus
4408 INT64_MAX, so that when it -n - 1 is applied to it the result will
4409 never be further from 0 than INT64_MIN.
Laurence Lundbladeda095972020-06-06 18:35:33 -07004410
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004411 -n - 1 <= INT64_MIN.
4412 -n - 1 <= -INT64_MAX - 1
4413 n <= INT64_MAX.
4414 */
Laurence Lundbladeda095972020-06-06 18:35:33 -07004415 QCBORError uError = ConvertBigNumToUnsigned(BigNum, INT64_MAX, &uResult);
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004416 if(uError != QCBOR_SUCCESS) {
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004417 return uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004418 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004419
4420 /// Now apply -n - 1. The cast is safe because
4421 // ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
4422 // is the largest positive integer that an int64_t can
4423 // represent. */
4424 *pnResult = -(int64_t)uResult - 1;
4425
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004426 return QCBOR_SUCCESS;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004427}
4428
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004429
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004430
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004431
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004432
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004433/*
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004434Convert integers and floats to an int64_t.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004435
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004436\param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004437
Laurence Lundblade93d89472020-10-03 22:30:50 -07004438\retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4439 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004440
4441\retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4442
Laurence Lundblade93d89472020-10-03 22:30:50 -07004443\retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4444 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004445*/
Laurence Lundblade93d89472020-10-03 22:30:50 -07004446static QCBORError
4447ConvertInt64(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004448{
4449 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004450 case QCBOR_TYPE_FLOAT:
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004451 case QCBOR_TYPE_DOUBLE:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004452#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004453 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004454 /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
4455 http://www.cplusplus.com/reference/cmath/llround/
4456 */
4457 // Not interested in FE_INEXACT
4458 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004459 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4460 *pnValue = llround(pItem->val.dfnum);
4461 } else {
4462 *pnValue = lroundf(pItem->val.fnum);
4463 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004464 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4465 // llround() shouldn't result in divide by zero, but catch
4466 // it here in case it unexpectedly does. Don't try to
4467 // distinguish between the various exceptions because it seems
4468 // they vary by CPU, compiler and OS.
4469 return QCBOR_ERR_FLOAT_EXCEPTION;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004470 }
4471 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004472 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004473 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004474#else
4475 return QCBOR_ERR_HW_FLOAT_DISABLED;
4476#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004477 break;
4478
4479 case QCBOR_TYPE_INT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004480 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004481 *pnValue = pItem->val.int64;
4482 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004483 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004484 }
4485 break;
4486
4487 case QCBOR_TYPE_UINT64:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004488 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004489 if(pItem->val.uint64 < INT64_MAX) {
4490 *pnValue = pItem->val.int64;
4491 } else {
4492 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4493 }
4494 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004495 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004496 }
4497 break;
4498
4499 default:
4500 return QCBOR_ERR_UNEXPECTED_TYPE;
4501 }
4502 return QCBOR_SUCCESS;
4503}
4504
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004505
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004506void QCBORDecode_GetInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004507 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004508 int64_t *pnValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004509 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07004510{
Laurence Lundbladebf3c42d2020-04-14 19:08:51 -07004511 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07004512 return;
4513 }
4514
Laurence Lundbladee6430642020-03-14 21:15:44 -07004515 QCBORItem Item;
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004516 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4517 if(uError) {
4518 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004519 return;
4520 }
4521
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004522 if(pItem) {
4523 *pItem = Item;
4524 }
4525
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004526 pMe->uLastError = (uint8_t)ConvertInt64(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004527}
4528
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004529
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004530void QCBORDecode_GetInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
4531 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004532 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004533 int64_t *pnValue,
4534 QCBORItem *pItem)
4535{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004536 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004537 if(pMe->uLastError != QCBOR_SUCCESS) {
4538 return;
4539 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004540
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004541 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004542}
4543
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004544
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004545void QCBORDecode_GetInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
4546 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004547 uint32_t uConvertTypes,
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004548 int64_t *pnValue,
4549 QCBORItem *pItem)
4550{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004551 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004552 if(pMe->uLastError != QCBOR_SUCCESS) {
4553 return;
4554 }
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004555
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004556 pMe->uLastError = (uint8_t)ConvertInt64(pItem, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004557}
4558
4559
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004560/*
4561 Convert a large variety of integer types to an int64_t.
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004562
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004563 \param[in] uConvertTypes Bit mask list of conversion options.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004564
Laurence Lundblade93d89472020-10-03 22:30:50 -07004565 \retval QCBOR_ERR_UNEXPECTED_TYPE Conversion, possible, but not requested
4566 in uConvertTypes.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004567
4568 \retval QCBOR_ERR_UNEXPECTED_TYPE Of a type that can't be converted
4569
Laurence Lundblade93d89472020-10-03 22:30:50 -07004570 \retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW Conversion result is too large
4571 or too small.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004572 */
Laurence Lundblade93d89472020-10-03 22:30:50 -07004573static QCBORError
4574Int64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004575{
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004576 switch(pItem->uDataType) {
4577
4578 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004579 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004580 return ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004581 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004582 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004583 }
4584 break;
4585
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004586 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004587 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004588 return ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004589 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004590 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004591 }
4592 break;
4593
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004594#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004595 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004596 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004597 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004598 pItem->val.expAndMantissa.nExponent,
4599 pnValue,
4600 &Exponentitate10);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004601 } 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
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004606 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004607 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004608 return ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004609 pItem->val.expAndMantissa.nExponent,
4610 pnValue,
4611 Exponentitate2);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004612 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004613 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004614 }
4615 break;
4616
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004617 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004618 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004619 int64_t nMantissa;
4620 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004621 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4622 if(uErr) {
4623 return uErr;
4624 }
4625 return ExponentiateNN(nMantissa,
4626 pItem->val.expAndMantissa.nExponent,
4627 pnValue,
4628 Exponentitate10);
4629 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004630 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004631 }
4632 break;
4633
4634 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004635 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004636 int64_t nMantissa;
4637 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004638 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4639 if(uErr) {
4640 return uErr;
4641 }
4642 return ExponentiateNN(nMantissa,
4643 pItem->val.expAndMantissa.nExponent,
4644 pnValue,
4645 Exponentitate10);
4646 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004647 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004648 }
4649 break;
4650
4651 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004652 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004653 int64_t nMantissa;
4654 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004655 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4656 if(uErr) {
4657 return uErr;
4658 }
4659 return ExponentiateNN(nMantissa,
4660 pItem->val.expAndMantissa.nExponent,
4661 pnValue,
4662 Exponentitate2);
4663 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004664 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004665 }
4666 break;
4667
4668 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004669 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004670 int64_t nMantissa;
4671 QCBORError uErr;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004672 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
4673 if(uErr) {
4674 return uErr;
4675 }
4676 return ExponentiateNN(nMantissa,
4677 pItem->val.expAndMantissa.nExponent,
4678 pnValue,
4679 Exponentitate2);
4680 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004681 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladee6430642020-03-14 21:15:44 -07004682 }
4683 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004684#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004685
Laurence Lundbladee6430642020-03-14 21:15:44 -07004686
Laurence Lundbladec4537442020-04-14 18:53:22 -07004687 default:
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07004688 return QCBOR_ERR_UNEXPECTED_TYPE; }
Laurence Lundbladec4537442020-04-14 18:53:22 -07004689}
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004690
4691
Laurence Lundbladec4537442020-04-14 18:53:22 -07004692/*
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004693 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004694 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004695void QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, int64_t *pnValue)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004696{
4697 QCBORItem Item;
4698
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004699 QCBORDecode_GetInt64ConvertInternal(pMe, uConvertTypes, pnValue, &Item);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004700
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004701 if(pMe->uLastError == QCBOR_SUCCESS) {
4702 // The above conversion succeeded
4703 return;
4704 }
4705
Laurence Lundbladef6c86662020-05-12 02:08:00 -07004706 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004707 // The above conversion failed in a way that code below can't correct
Laurence Lundbladec4537442020-04-14 18:53:22 -07004708 return;
4709 }
4710
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004711 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07004712}
4713
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004714
4715/*
4716Public function, see header qcbor/qcbor_decode.h file
4717*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004718void QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
4719 int64_t nLabel,
4720 uint32_t uConvertTypes,
4721 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004722{
4723 QCBORItem Item;
4724
Laurence Lundblade93d89472020-10-03 22:30:50 -07004725 QCBORDecode_GetInt64ConvertInternalInMapN(pMe,
4726 nLabel,
4727 uConvertTypes,
4728 pnValue,
4729 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004730
4731 if(pMe->uLastError == QCBOR_SUCCESS) {
4732 // The above conversion succeeded
4733 return;
4734 }
4735
4736 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4737 // The above conversion failed in a way that code below can't correct
4738 return;
4739 }
4740
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004741 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004742}
4743
4744
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004745/*
4746Public function, see header qcbor/qcbor_decode.h file
4747*/
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004748void QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
4749 const char *szLabel,
4750 uint32_t uConvertTypes,
4751 int64_t *pnValue)
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004752{
4753 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07004754 QCBORDecode_GetInt64ConvertInternalInMapSZ(pMe,
4755 szLabel,
4756 uConvertTypes,
4757 pnValue,
4758 &Item);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004759
4760 if(pMe->uLastError == QCBOR_SUCCESS) {
4761 // The above conversion succeeded
4762 return;
4763 }
4764
4765 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
4766 // The above conversion failed in a way that code below can't correct
4767 return;
4768 }
4769
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004770 pMe->uLastError = (uint8_t)Int64ConvertAll(&Item, uConvertTypes, pnValue);
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004771}
4772
4773
Laurence Lundblade93d89472020-10-03 22:30:50 -07004774static QCBORError ConvertUInt64(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004775{
4776 switch(pItem->uDataType) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004777 case QCBOR_TYPE_DOUBLE:
4778 case QCBOR_TYPE_FLOAT:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004779#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004780 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004781 // Can't use llround here because it will not convert values
4782 // greater than INT64_MAX and less than UINT64_MAX that
4783 // need to be converted so it is more complicated.
4784 feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
4785 if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
4786 if(isnan(pItem->val.dfnum)) {
4787 return QCBOR_ERR_FLOAT_EXCEPTION;
4788 } else if(pItem->val.dfnum < 0) {
4789 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4790 } else {
4791 double dRounded = round(pItem->val.dfnum);
4792 // See discussion in DecodeDateEpoch() for
4793 // explanation of - 0x7ff
4794 if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
4795 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4796 }
4797 *puValue = (uint64_t)dRounded;
4798 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004799 } else {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004800 if(isnan(pItem->val.fnum)) {
4801 return QCBOR_ERR_FLOAT_EXCEPTION;
4802 } else if(pItem->val.fnum < 0) {
4803 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4804 } else {
4805 float fRounded = roundf(pItem->val.fnum);
4806 // See discussion in DecodeDateEpoch() for
4807 // explanation of - 0x7ff
4808 if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
4809 return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
4810 }
4811 *puValue = (uint64_t)fRounded;
4812 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004813 }
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07004814 if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
4815 // round() and roundf() shouldn't result in exceptions here, but
4816 // catch them to be robust and thorough. Don't try to
4817 // distinguish between the various exceptions because it seems
4818 // they vary by CPU, compiler and OS.
4819 return QCBOR_ERR_FLOAT_EXCEPTION;
4820 }
4821
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004822 } else {
4823 return QCBOR_ERR_UNEXPECTED_TYPE;
4824 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004825#else
4826 return QCBOR_ERR_HW_FLOAT_DISABLED;
4827#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004828 break;
Laurence Lundblade843a10c2020-05-23 13:57:00 -07004829
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004830 case QCBOR_TYPE_INT64:
4831 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4832 if(pItem->val.int64 >= 0) {
4833 *puValue = (uint64_t)pItem->val.int64;
4834 } else {
4835 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4836 }
4837 } else {
4838 return QCBOR_ERR_UNEXPECTED_TYPE;
4839 }
4840 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004841
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004842 case QCBOR_TYPE_UINT64:
4843 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
4844 *puValue = pItem->val.uint64;
4845 } else {
4846 return QCBOR_ERR_UNEXPECTED_TYPE;
4847 }
4848 break;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004849
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004850 default:
4851 return QCBOR_ERR_UNEXPECTED_TYPE;
4852 }
4853
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004854 return QCBOR_SUCCESS;
4855}
Laurence Lundbladec4537442020-04-14 18:53:22 -07004856
4857
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004858void QCBORDecode_GetUInt64ConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004859 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004860 uint64_t *puValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004861 QCBORItem *pItem)
Laurence Lundbladec4537442020-04-14 18:53:22 -07004862{
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004863 if(pMe->uLastError != QCBOR_SUCCESS) {
4864 return;
4865 }
4866
Laurence Lundbladec4537442020-04-14 18:53:22 -07004867 QCBORItem Item;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004868
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07004869 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
4870 if(uError) {
4871 pMe->uLastError = (uint8_t)uError;
Laurence Lundbladec4537442020-04-14 18:53:22 -07004872 return;
4873 }
4874
Laurence Lundbladea826c502020-05-10 21:07:00 -07004875 if(pItem) {
4876 *pItem = Item;
4877 }
4878
Laurence Lundblade93d89472020-10-03 22:30:50 -07004879 pMe->uLastError = (uint8_t)ConvertUInt64(&Item, uConvertTypes, puValue);
Laurence Lundbladec4537442020-04-14 18:53:22 -07004880}
4881
Laurence Lundblade9c905e82020-04-25 11:31:38 -07004882
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07004883void QCBORDecode_GetUInt64ConvertInternalInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004884 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004885 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004886 uint64_t *puValue,
4887 QCBORItem *pItem)
4888{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004889 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004890 if(pMe->uLastError != QCBOR_SUCCESS) {
4891 return;
4892 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004893
Laurence Lundblade93d89472020-10-03 22:30:50 -07004894 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004895}
4896
4897
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07004898void QCBORDecode_GetUInt64ConvertInternalInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004899 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004900 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004901 uint64_t *puValue,
4902 QCBORItem *pItem)
4903{
4904 if(pMe->uLastError != QCBOR_SUCCESS) {
4905 return;
4906 }
4907
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07004908 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07004909 if(pMe->uLastError != QCBOR_SUCCESS) {
4910 return;
4911 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004912
Laurence Lundblade93d89472020-10-03 22:30:50 -07004913 pMe->uLastError = (uint8_t)ConvertUInt64(pItem, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004914}
4915
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004916
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07004917
Laurence Lundblade93d89472020-10-03 22:30:50 -07004918static QCBORError
4919UInt64ConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004920{
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004921 switch(pItem->uDataType) {
4922
4923 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004924 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004925 return ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
4926 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004927 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004928 }
4929 break;
4930
4931 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004932 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004933 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4934 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004935 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004936 }
4937 break;
4938
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07004939#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004940
4941 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004942 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004943 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004944 pItem->val.expAndMantissa.nExponent,
4945 puValue,
4946 Exponentitate10);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004947 } 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_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004953 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004954 return ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
4955 pItem->val.expAndMantissa.nExponent,
4956 puValue,
4957 Exponentitate2);
4958 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004959 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004960 }
4961 break;
4962
4963 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004964 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004965 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004966 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004967 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004968 if(uErr != QCBOR_SUCCESS) {
4969 return uErr;
4970 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004971 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004972 pItem->val.expAndMantissa.nExponent,
4973 puValue,
4974 Exponentitate10);
4975 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004976 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004977 }
4978 break;
4979
4980 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004981 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004982 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
4983 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004984 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004985 }
4986 break;
4987
4988 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07004989 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004990 uint64_t uMantissa;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07004991 QCBORError uErr;
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004992 uErr = ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004993 if(uErr != QCBOR_SUCCESS) {
4994 return uErr;
4995 }
Laurence Lundblade784b54b2020-08-10 01:24:52 -07004996 return ExponentitateUU(uMantissa,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07004997 pItem->val.expAndMantissa.nExponent,
4998 puValue,
4999 Exponentitate2);
5000 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005001 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005002 }
5003 break;
5004
5005 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005006 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005007 return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
5008 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005009 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005010 }
5011 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005012#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005013 default:
5014 return QCBOR_ERR_UNEXPECTED_TYPE;
5015 }
5016}
5017
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005018
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005019/*
5020 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005021 */
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005022void QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe, uint32_t uConvertTypes, uint64_t *puValue)
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005023{
5024 QCBORItem Item;
5025
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005026 QCBORDecode_GetUInt64ConvertInternal(pMe, uConvertTypes, puValue, &Item);
Laurence Lundblade9c905e82020-04-25 11:31:38 -07005027
Laurence Lundbladef6c86662020-05-12 02:08:00 -07005028 if(pMe->uLastError == QCBOR_SUCCESS) {
5029 // The above conversion succeeded
5030 return;
5031 }
5032
5033 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5034 // The above conversion failed in a way that code below can't correct
Laurence Lundbladee6430642020-03-14 21:15:44 -07005035 return;
5036 }
5037
Laurence Lundblade93d89472020-10-03 22:30:50 -07005038 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005039}
5040
Laurence Lundbladec4537442020-04-14 18:53:22 -07005041
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005042/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005043 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005044*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005045void QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07005046 int64_t nLabel,
5047 uint32_t uConvertTypes,
5048 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005049{
5050 QCBORItem Item;
5051
Laurence Lundblade93d89472020-10-03 22:30:50 -07005052 QCBORDecode_GetUInt64ConvertInternalInMapN(pMe,
5053 nLabel,
5054 uConvertTypes,
5055 puValue,
5056 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005057
5058 if(pMe->uLastError == QCBOR_SUCCESS) {
5059 // The above conversion succeeded
5060 return;
5061 }
5062
5063 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5064 // The above conversion failed in a way that code below can't correct
5065 return;
5066 }
5067
Laurence Lundblade93d89472020-10-03 22:30:50 -07005068 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005069}
5070
5071
5072/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005073 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005074*/
Laurence Lundblade95b64bb2020-08-30 00:17:38 -07005075void QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundblade9b334962020-08-27 10:55:53 -07005076 const char *szLabel,
5077 uint32_t uConvertTypes,
5078 uint64_t *puValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005079{
5080 QCBORItem Item;
Laurence Lundblade93d89472020-10-03 22:30:50 -07005081 QCBORDecode_GetUInt64ConvertInternalInMapSZ(pMe,
5082 szLabel,
5083 uConvertTypes,
5084 puValue,
5085 &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005086
5087 if(pMe->uLastError == QCBOR_SUCCESS) {
5088 // The above conversion succeeded
5089 return;
5090 }
5091
5092 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5093 // The above conversion failed in a way that code below can't correct
5094 return;
5095 }
5096
Laurence Lundblade93d89472020-10-03 22:30:50 -07005097 pMe->uLastError = (uint8_t)UInt64ConvertAll(&Item, uConvertTypes, puValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005098}
5099
5100
Laurence Lundbladef7a70bc2020-10-24 12:23:25 -07005101
5102
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005103#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Laurence Lundblade9b334962020-08-27 10:55:53 -07005104static QCBORError ConvertDouble(const QCBORItem *pItem,
5105 uint32_t uConvertTypes,
5106 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005107{
5108 switch(pItem->uDataType) {
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005109 case QCBOR_TYPE_FLOAT:
5110#ifndef QCBOR_DISABLE_FLOAT_HW_USE
5111 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5112 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005113 // Simple cast does the job.
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005114 *pdValue = (double)pItem->val.fnum;
5115 } else {
5116 return QCBOR_ERR_UNEXPECTED_TYPE;
5117 }
5118 }
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005119#else /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005120 return QCBOR_ERR_HW_FLOAT_DISABLED;
Laurence Lundbladee2c893c2020-12-26 17:41:53 -08005121#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005122 break;
5123
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005124 case QCBOR_TYPE_DOUBLE:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005125 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
5126 if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005127 *pdValue = pItem->val.dfnum;
5128 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005129 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005130 }
5131 }
5132 break;
5133
5134 case QCBOR_TYPE_INT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005135#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005136 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005137 // A simple cast seems to do the job with no worry of exceptions.
5138 // There will be precision loss for some values.
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005139 *pdValue = (double)pItem->val.int64;
5140
5141 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005142 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005143 }
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005144#else
5145 return QCBOR_ERR_HW_FLOAT_DISABLED;
5146#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005147 break;
5148
5149 case QCBOR_TYPE_UINT64:
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005150#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005151 if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
Laurence Lundbladedfd49fc2020-09-01 14:17:16 -07005152 // A simple cast seems to do the job with no worry of exceptions.
5153 // There will be precision loss for some values.
5154 *pdValue = (double)pItem->val.uint64;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005155 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005156 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005157 }
5158 break;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005159#else
5160 return QCBOR_ERR_HW_FLOAT_DISABLED;
5161#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005162
5163 default:
5164 return QCBOR_ERR_UNEXPECTED_TYPE;
5165 }
5166
5167 return QCBOR_SUCCESS;
5168}
5169
5170
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005171void QCBORDecode_GetDoubleConvertInternal(QCBORDecodeContext *pMe,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005172 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005173 double *pdValue,
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005174 QCBORItem *pItem)
Laurence Lundbladee6430642020-03-14 21:15:44 -07005175{
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005176 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundbladec4537442020-04-14 18:53:22 -07005177 return;
5178 }
5179
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005180 QCBORItem Item;
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005181
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005182 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005183 if(uError) {
5184 pMe->uLastError = (uint8_t)uError;
5185 return;
5186 }
5187
5188 if(pItem) {
5189 *pItem = Item;
5190 }
Laurence Lundbladec4537442020-04-14 18:53:22 -07005191
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005192 pMe->uLastError = (uint8_t)ConvertDouble(&Item, uConvertTypes, pdValue);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005193}
Laurence Lundbladec4537442020-04-14 18:53:22 -07005194
Laurence Lundbladec4537442020-04-14 18:53:22 -07005195
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005196void QCBORDecode_GetDoubleConvertInternalInMapN(QCBORDecodeContext *pMe,
5197 int64_t nLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005198 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005199 double *pdValue,
5200 QCBORItem *pItem)
5201{
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005202 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005203 if(pMe->uLastError != QCBOR_SUCCESS) {
5204 return;
5205 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005206
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005207 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005208}
5209
Laurence Lundblade784b54b2020-08-10 01:24:52 -07005210
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005211void QCBORDecode_GetDoubleConvertInternalInMapSZ(QCBORDecodeContext *pMe,
5212 const char * szLabel,
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005213 uint32_t uConvertTypes,
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005214 double *pdValue,
5215 QCBORItem *pItem)
5216{
5217 if(pMe->uLastError != QCBOR_SUCCESS) {
5218 return;
5219 }
5220
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005221 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
Laurence Lundbladeabf5c572020-06-29 21:21:29 -07005222 if(pMe->uLastError != QCBOR_SUCCESS) {
5223 return;
5224 }
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005225
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005226 pMe->uLastError = (uint8_t)ConvertDouble(pItem, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005227}
5228
5229
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005230#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005231static double ConvertBigNumToDouble(const UsefulBufC BigNum)
5232{
5233 double dResult;
5234
5235 dResult = 0.0;
5236 const uint8_t *pByte = BigNum.ptr;
5237 size_t uLen = BigNum.len;
5238 /* This will overflow and become the float value INFINITY if the number
Laurence Lundblade11fd78b2020-09-01 22:13:27 -07005239 is too large to fit. */
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005240 while(uLen--) {
5241 dResult = (dResult * 256.0) + (double)*pByte++;
5242 }
5243
5244 return dResult;
5245}
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005246#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5247
Laurence Lundblade9ab5abb2020-05-20 12:10:45 -07005248
Laurence Lundblade93d89472020-10-03 22:30:50 -07005249static QCBORError
5250DoubleConvertAll(const QCBORItem *pItem, uint32_t uConvertTypes, double *pdValue)
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005251{
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005252#ifndef QCBOR_DISABLE_FLOAT_HW_USE
Laurence Lundblade54cd99c2020-05-15 02:25:32 -07005253 /*
Laurence Lundblade16a207a2021-09-18 17:22:46 -07005254 * What Every Computer Scientist Should Know About Floating-Point Arithmetic
5255 * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
5256 */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005257 switch(pItem->uDataType) {
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005258
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005259#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005260 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005261 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005262 // Underflow gives 0, overflow gives infinity
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005263 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5264 pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
5265 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005266 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005267 }
5268 break;
5269
5270 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005271 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
Laurence Lundblade51722fd2020-09-02 13:01:33 -07005272 // Underflow gives 0, overflow gives infinity
5273 *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
5274 exp2((double)pItem->val.expAndMantissa.nExponent);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005275 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005276 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005277 }
5278 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005279#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005280
5281 case QCBOR_TYPE_POSBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005282 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005283 *pdValue = ConvertBigNumToDouble(pItem->val.bigNum);
5284 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005285 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005286 }
5287 break;
5288
5289 case QCBOR_TYPE_NEGBIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005290 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005291 *pdValue = -1-ConvertBigNumToDouble(pItem->val.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005292 } 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
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005297#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005298 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005299 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005300 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5301 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5302 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005303 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005304 }
5305 break;
5306
5307 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005308 if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005309 double dMantissa = -ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5310 *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
5311 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005312 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005313 }
5314 break;
5315
5316 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005317 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005318 double dMantissa = ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
5319 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5320 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005321 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005322 }
5323 break;
5324
5325 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005326 if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
Laurence Lundbladeda095972020-06-06 18:35:33 -07005327 double dMantissa = -1-ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005328 *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
5329 } else {
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005330 return QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005331 }
5332 break;
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005333#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
Laurence Lundblade410c7e02020-06-25 23:35:29 -07005334
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005335 default:
5336 return QCBOR_ERR_UNEXPECTED_TYPE;
5337 }
5338
5339 return QCBOR_SUCCESS;
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005340
5341#else
5342 (void)pItem;
5343 (void)uConvertTypes;
5344 (void)pdValue;
5345 return QCBOR_ERR_HW_FLOAT_DISABLED;
5346#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
5347
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005348}
5349
5350
5351/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005352 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005353*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005354void QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
5355 uint32_t uConvertTypes,
5356 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005357{
5358
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005359 QCBORItem Item;
5360
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005361 QCBORDecode_GetDoubleConvertInternal(pMe, uConvertTypes, pdValue, &Item);
Laurence Lundbladeb340ba72020-05-14 11:41:10 -07005362
5363 if(pMe->uLastError == QCBOR_SUCCESS) {
5364 // The above conversion succeeded
5365 return;
5366 }
5367
5368 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5369 // The above conversion failed in a way that code below can't correct
5370 return;
5371 }
5372
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005373 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundbladee6430642020-03-14 21:15:44 -07005374}
5375
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005376
5377/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005378 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005379*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005380void QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
5381 int64_t nLabel,
5382 uint32_t uConvertTypes,
5383 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005384{
5385 QCBORItem Item;
5386
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005387 QCBORDecode_GetDoubleConvertInternalInMapN(pMe, nLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005388
5389 if(pMe->uLastError == QCBOR_SUCCESS) {
5390 // The above conversion succeeded
5391 return;
5392 }
5393
5394 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5395 // The above conversion failed in a way that code below can't correct
5396 return;
5397 }
5398
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005399 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005400}
5401
5402
5403/*
Laurence Lundblade4e2da002020-06-13 23:08:31 -07005404 Public function, see header qcbor/qcbor_decode.h file
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005405*/
Laurence Lundblade9b334962020-08-27 10:55:53 -07005406void QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
5407 const char *szLabel,
5408 uint32_t uConvertTypes,
5409 double *pdValue)
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005410{
5411 QCBORItem Item;
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005412 QCBORDecode_GetDoubleConvertInternalInMapSZ(pMe, szLabel, uConvertTypes, pdValue, &Item);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005413
5414 if(pMe->uLastError == QCBOR_SUCCESS) {
5415 // The above conversion succeeded
5416 return;
5417 }
5418
5419 if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
5420 // The above conversion failed in a way that code below can't correct
5421 return;
5422 }
5423
Laurence Lundblade78f7b932020-07-28 20:02:25 -07005424 pMe->uLastError = (uint8_t)DoubleConvertAll(&Item, uConvertTypes, pdValue);
Laurence Lundblade7e5be1d2020-05-24 21:17:28 -07005425}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02005426#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005427
5428
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005429
5430
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005431#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
Laurence Lundbladef7c0adb2020-08-08 20:20:58 -07005432static inline UsefulBufC ConvertIntToBigNum(uint64_t uInt, UsefulBuf Buffer)
5433{
5434 while((uInt & 0xff00000000000000UL) == 0) {
5435 uInt = uInt << 8;
5436 };
5437
5438 UsefulOutBuf UOB;
5439
5440 UsefulOutBuf_Init(&UOB, Buffer);
5441
5442 while(uInt) {
5443 const uint64_t xx = uInt & 0xff00000000000000UL;
5444 UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
5445 uInt = uInt << 8;
5446 (void)xx;
5447 }
5448
5449 return UsefulOutBuf_OutUBuf(&UOB);
5450}
5451
5452
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005453static QCBORError MantissaAndExponentTypeHandler(QCBORDecodeContext *pMe,
5454 TagSpecification TagSpec,
5455 QCBORItem *pItem)
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005456{
5457 QCBORError uErr;
5458 // Loops runs at most 1.5 times. Making it a loop saves object code.
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005459 while(1) {
Laurence Lundblade6f3f78e2020-08-31 13:09:14 -07005460 uErr = CheckTagRequirement(TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005461 if(uErr != QCBOR_SUCCESS) {
5462 goto Done;
5463 }
5464
5465 if(pItem->uDataType != QCBOR_TYPE_ARRAY) {
5466 break; // Successful exit. Moving on to finish decoding.
5467 }
5468
5469 // The item is an array, which means an undecoded
5470 // mantissa and exponent, so decode it. It will then
5471 // have a different type and exit the loop if.
5472 uErr = QCBORDecode_MantissaAndExponent(pMe, pItem);
5473 if(uErr != QCBOR_SUCCESS) {
5474 goto Done;
5475 }
5476
5477 // Second time around, the type must match.
Laurence Lundblade9b334962020-08-27 10:55:53 -07005478 TagSpec.uTagRequirement = QCBOR_TAG_REQUIREMENT_TAG;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005479 }
5480Done:
5481 return uErr;
5482}
5483
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005484
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005485static void ProcessMantissaAndExponent(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005486 TagSpecification TagSpec,
5487 QCBORItem *pItem,
5488 int64_t *pnMantissa,
5489 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005490{
5491 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005492
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005493 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005494 if(uErr != QCBOR_SUCCESS) {
5495 goto Done;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005496 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005497
Laurence Lundblade9b334962020-08-27 10:55:53 -07005498 switch (pItem->uDataType) {
5499
5500 case QCBOR_TYPE_DECIMAL_FRACTION:
5501 case QCBOR_TYPE_BIGFLOAT:
5502 *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
5503 *pnExponent = pItem->val.expAndMantissa.nExponent;
5504 break;
5505
5506 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
5507 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
5508 *pnExponent = pItem->val.expAndMantissa.nExponent;
5509 uErr = ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5510 break;
5511
5512 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
5513 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
5514 *pnExponent = pItem->val.expAndMantissa.nExponent;
5515 uErr = ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
5516 break;
5517
5518 default:
5519 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
5520 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005521
5522 Done:
5523 pMe->uLastError = (uint8_t)uErr;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005524}
5525
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005526
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005527static void ProcessMantissaAndExponentBig(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005528 TagSpecification TagSpec,
5529 QCBORItem *pItem,
5530 UsefulBuf BufferForMantissa,
5531 UsefulBufC *pMantissa,
5532 bool *pbIsNegative,
5533 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005534{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005535 QCBORError uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005536
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005537 uErr = MantissaAndExponentTypeHandler(pMe, TagSpec, pItem);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005538 if(uErr != QCBOR_SUCCESS) {
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005539 goto Done;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005540 }
5541
5542 uint64_t uMantissa;
5543
5544 switch (pItem->uDataType) {
5545
5546 case QCBOR_TYPE_DECIMAL_FRACTION:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005547 case QCBOR_TYPE_BIGFLOAT:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005548 if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
5549 uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
5550 *pbIsNegative = false;
5551 } else {
5552 uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
5553 *pbIsNegative = true;
5554 }
5555 *pMantissa = ConvertIntToBigNum(uMantissa, BufferForMantissa);
5556 *pnExponent = pItem->val.expAndMantissa.nExponent;
5557 break;
5558
5559 case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005560 case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005561 *pnExponent = pItem->val.expAndMantissa.nExponent;
5562 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5563 *pbIsNegative = false;
5564 break;
5565
5566 case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005567 case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005568 *pnExponent = pItem->val.expAndMantissa.nExponent;
5569 *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
5570 *pbIsNegative = true;
5571 break;
5572
5573 default:
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005574 uErr = QCBOR_ERR_UNEXPECTED_TYPE;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005575 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005576
5577Done:
5578 pMe->uLastError = (uint8_t)uErr;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005579}
5580
5581
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005582/*
5583 Public function, see header qcbor/qcbor_decode.h file
5584*/
5585void QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
5586 uint8_t uTagRequirement,
5587 int64_t *pnMantissa,
5588 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005589{
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005590 if(pMe->uLastError != QCBOR_SUCCESS) {
5591 return;
5592 }
5593
5594 QCBORItem Item;
5595 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5596 if(uError) {
5597 pMe->uLastError = (uint8_t)uError;
5598 return;
5599 }
5600
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005601 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 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005608
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005609 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005610}
5611
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005612
5613/*
5614 Public function, see header qcbor/qcbor_decode.h file
5615*/
5616void QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005617 int64_t nLabel,
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_GetItemInMapN(pMe, nLabel, 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 };
5636
5637 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5638}
5639
5640
5641/*
5642 Public function, see header qcbor/qcbor_decode.h file
5643*/
5644void QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005645 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005646 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005647 int64_t *pnMantissa,
5648 int64_t *pnExponent)
5649{
5650 if(pMe->uLastError != QCBOR_SUCCESS) {
5651 return;
5652 }
5653
5654 QCBORItem Item;
5655 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5656
5657 const TagSpecification TagSpec =
5658 {
5659 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005660 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5661 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5662 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005663 };
Laurence Lundblade9b334962020-08-27 10:55:53 -07005664
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005665 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5666}
5667
5668
5669/*
5670 Public function, see header qcbor/qcbor_decode.h file
5671*/
5672void QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
5673 uint8_t uTagRequirement,
5674 UsefulBuf MantissaBuffer,
5675 UsefulBufC *pMantissa,
5676 bool *pbMantissaIsNegative,
5677 int64_t *pnExponent)
5678{
5679 if(pMe->uLastError != QCBOR_SUCCESS) {
5680 return;
5681 }
5682
5683 QCBORItem Item;
5684 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5685 if(uError) {
5686 pMe->uLastError = (uint8_t)uError;
5687 return;
5688 }
5689
5690 const TagSpecification TagSpec =
5691 {
5692 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005693 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5694 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5695 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005696 };
5697
Laurence Lundblade93d89472020-10-03 22:30:50 -07005698 ProcessMantissaAndExponentBig(pMe,
5699 TagSpec,
5700 &Item,
5701 MantissaBuffer,
5702 pMantissa,
5703 pbMantissaIsNegative,
5704 pnExponent);
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005705}
5706
5707
5708/*
5709 Public function, see header qcbor/qcbor_decode.h file
5710*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005711void QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005712 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005713 uint8_t uTagRequirement,
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005714 UsefulBuf BufferForMantissa,
5715 UsefulBufC *pMantissa,
5716 bool *pbIsNegative,
5717 int64_t *pnExponent)
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005718{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005719 if(pMe->uLastError != QCBOR_SUCCESS) {
5720 return;
5721 }
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005722
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005723 QCBORItem Item;
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005724 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005725 if(pMe->uLastError != QCBOR_SUCCESS) {
5726 return;
5727 }
5728
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005729 const TagSpecification TagSpec =
5730 {
5731 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005732 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5733 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5734 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005735 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005736
Laurence Lundblade93d89472020-10-03 22:30:50 -07005737 ProcessMantissaAndExponentBig(pMe,
5738 TagSpec,
5739 &Item,
5740 BufferForMantissa,
5741 pMantissa,
5742 pbIsNegative,
5743 pnExponent);
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005744}
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005745
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005746
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005747/*
5748 Public function, see header qcbor/qcbor_decode.h file
5749*/
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005750void QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005751 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005752 uint8_t uTagRequirement,
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005753 UsefulBuf BufferForMantissa,
5754 UsefulBufC *pMantissa,
5755 bool *pbIsNegative,
5756 int64_t *pnExponent)
5757{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005758 if(pMe->uLastError != QCBOR_SUCCESS) {
5759 return;
5760 }
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005761
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005762 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005763 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5764 if(pMe->uLastError != QCBOR_SUCCESS) {
5765 return;
5766 }
5767
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005768 const TagSpecification TagSpec =
5769 {
5770 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005771 {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
5772 QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
5773 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005774 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005775
5776 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, BufferForMantissa, pMantissa, pbIsNegative, pnExponent);
5777}
5778
5779
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005780/*
5781 Public function, see header qcbor/qcbor_decode.h file
5782*/
5783void QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
5784 uint8_t uTagRequirement,
5785 int64_t *pnMantissa,
5786 int64_t *pnExponent)
5787{
5788 if(pMe->uLastError != QCBOR_SUCCESS) {
5789 return;
5790 }
5791
5792 QCBORItem Item;
5793 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5794 if(uError) {
5795 pMe->uLastError = (uint8_t)uError;
5796 return;
5797 }
5798 const TagSpecification TagSpec =
5799 {
5800 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005801 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5802 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5803 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005804 };
5805
5806 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5807}
5808
5809
5810/*
5811 Public function, see header qcbor/qcbor_decode.h file
5812*/
5813void QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005814 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005815 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005816 int64_t *pnMantissa,
5817 int64_t *pnExponent)
5818{
5819 if(pMe->uLastError != QCBOR_SUCCESS) {
5820 return;
5821 }
5822
5823 QCBORItem Item;
5824 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5825 if(pMe->uLastError != QCBOR_SUCCESS) {
5826 return;
5827 }
5828
5829 const TagSpecification TagSpec =
5830 {
5831 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005832 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5833 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5834 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005835 };
5836
5837 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5838}
5839
5840
5841/*
5842 Public function, see header qcbor/qcbor_decode.h file
5843*/
5844void QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005845 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005846 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005847 int64_t *pnMantissa,
5848 int64_t *pnExponent)
5849{
5850 if(pMe->uLastError != QCBOR_SUCCESS) {
5851 return;
5852 }
5853
5854 QCBORItem Item;
5855 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5856 if(pMe->uLastError != QCBOR_SUCCESS) {
5857 return;
5858 }
5859
5860 const TagSpecification TagSpec =
5861 {
5862 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005863 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5864 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5865 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005866 };
5867
5868 ProcessMantissaAndExponent(pMe, TagSpec, &Item, pnMantissa, pnExponent);
5869}
5870
5871
5872/*
5873 Public function, see header qcbor/qcbor_decode.h file
5874*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005875void QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
5876 uint8_t uTagRequirement,
5877 UsefulBuf MantissaBuffer,
5878 UsefulBufC *pMantissa,
5879 bool *pbMantissaIsNegative,
5880 int64_t *pnExponent)
5881{
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005882 if(pMe->uLastError != QCBOR_SUCCESS) {
5883 return;
5884 }
5885
5886 QCBORItem Item;
5887 QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
5888 if(uError) {
5889 pMe->uLastError = (uint8_t)uError;
5890 return;
5891 }
5892
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005893 const TagSpecification TagSpec =
5894 {
5895 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005896 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5897 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5898 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005899 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005900
5901 ProcessMantissaAndExponentBig(pMe, TagSpec, &Item, MantissaBuffer, pMantissa, pbMantissaIsNegative, pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005902}
5903
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005904
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005905/*
5906 Public function, see header qcbor/qcbor_decode.h file
5907*/
5908void QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005909 int64_t nLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005910 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005911 UsefulBuf BufferForMantissa,
5912 UsefulBufC *pMantissa,
5913 bool *pbIsNegative,
5914 int64_t *pnExponent)
5915{
5916 if(pMe->uLastError != QCBOR_SUCCESS) {
5917 return;
5918 }
5919
5920 QCBORItem Item;
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005921 QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
5922 if(pMe->uLastError != QCBOR_SUCCESS) {
5923 return;
5924 }
5925
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005926 const TagSpecification TagSpec =
5927 {
5928 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005929 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5930 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5931 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005932 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005933
Laurence Lundblade93d89472020-10-03 22:30:50 -07005934 ProcessMantissaAndExponentBig(pMe,
5935 TagSpec,
5936 &Item,
5937 BufferForMantissa,
5938 pMantissa,
5939 pbIsNegative,
5940 pnExponent);
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005941}
5942
5943
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005944/*
5945 Public function, see header qcbor/qcbor_decode.h file
5946*/
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005947void QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005948 const char *szLabel,
Laurence Lundblade2f5e16d2020-08-04 20:35:23 -07005949 uint8_t uTagRequirement,
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005950 UsefulBuf BufferForMantissa,
5951 UsefulBufC *pMantissa,
5952 bool *pbIsNegative,
5953 int64_t *pnExponent)
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005954{
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005955 if(pMe->uLastError != QCBOR_SUCCESS) {
5956 return;
5957 }
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005958
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005959 QCBORItem Item;
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005960 QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
5961 if(pMe->uLastError != QCBOR_SUCCESS) {
Laurence Lundblade3cd26eb2020-06-29 23:33:13 -07005962 return;
5963 }
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005964
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005965 const TagSpecification TagSpec =
5966 {
5967 uTagRequirement,
Laurence Lundbladec384d4e2020-10-07 09:46:10 -07005968 {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
5969 QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
5970 {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
Laurence Lundbladefaec39f2020-08-02 21:53:53 -07005971 };
Laurence Lundbladeb3683da2020-08-02 17:44:54 -07005972
Laurence Lundblade93d89472020-10-03 22:30:50 -07005973 ProcessMantissaAndExponentBig(pMe,
5974 TagSpec,
5975 &Item,
5976 BufferForMantissa,
5977 pMantissa,
5978 pbIsNegative,
5979 pnExponent);
Laurence Lundblade91853ae2020-06-15 19:35:58 -07005980}
Laurence Lundbladed4cd7232020-07-03 19:30:48 -07005981
Laurence Lundbladedd6e76e2021-03-10 01:54:01 -07005982#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */